Android: BitmapFactory.decodeByteArray proporciona un mapa de bits pixelado

Estoy trabajando en una aplicación de Android que muestra fotos que se descargan de Flickr. Obtengo un objeto de mapa de bits de una matriz de bytes, que a su vez se lee de la URL de Flickr relevante, de la siguiente manera:

BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inDither = true;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt);

Luego dibujo el mapa de bits en un lienzo en el método onDraw de un objeto View:

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint); 

El problema es que la imagen resultante está pixelada y no puedo entender por qué; He intentado una serie de variaciones de los objetos optar y pintar sin suerte. La diferencia entre la imagen que se muestra en mi aplicación y la imagen en la URL original se demuestra más o menos de la siguiente manera:

Mala imagen, vea pixelación en la esquina superior izquierda http://homepages.inf.ed.ac.uk/s0677975/bad.jpg

Buena imagen, este es el resultado esperado http://homepages.inf.ed.ac.uk/s0677975/good.jpg

Mira por ejemplo en las nubes en la esquina superior izquierda para ver la diferencia.

Tenga en cuenta que las imágenes JPEG que se cargan desde los recursos del proyecto y se dibujan de manera similar se muestran muy bien, es decir, no tienen pixelación.

¿Alguien puede darme una pista de por qué sucede esto?

Para elaborar un poco, la matriz de bytes se obtiene de Flickr de la siguiente manera; Esto se basa en el código de la aplicación Photostream de Romain Guy:

InputStream in = new BufferedInputStream(url.openStream(), IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
copy(in, out);
out.flush();
final byte[] data = dataStream.toByteArray();

PD: También publiqué una variante de esta pregunta en el grupo de Google android.developer.

Muchas gracias por su sugerencia, ¡ahora estoy realmente perplejo! Hice lo que sugirió y descubrí que la imagen que resulta directamente de la matriz de bytes descargada está pixelada. Sin embargo, esto se descarga exactamente de la misma URL que, cuando se accede en mi computadora, NO está pixelada. Aquí está la URL de Flickr correspondiente:

http://farm3.static.flickr.com/2678/4315351421_54e8cdb8e5.jpg

Aún más extraño, cuando ejecuto la misma aplicación en el simulador en lugar de en mi teléfono (un HTC Hero), no hay pixelación.

¿Cómo es esto posible?

A continuación se muestra el código que uso para cargar un mapa de bits desde una URL: está basado en la aplicación Photostream de Romain Guy e incorpora la sugerencia de Will de escribir la matriz de bytes sin procesar en el archivo:

Bitmap loadPhotoBitmap(URL url) {
    Bitmap bitmap = null;
        InputStream in = null;
        BufferedOutputStream out = null;

        try {

            FileOutputStream fos = new FileOutputStream("/sdcard/photo-tmp.jpg");
            BufferedOutputStream bfs = new BufferedOutputStream(fos);

            in = new BufferedInputStream(url.openStream(),
                    IO_BUFFER_SIZE);

            final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
            out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
            copy(in, out);                    
            out.flush();
            final byte[] data = dataStream.toByteArray();

            bfs.write(data, 0, data.length);
            bfs.flush();

            BitmapFactory.Options opt = new BitmapFactory.Options();
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt);

        } catch (IOException e) {
            android.util.Log.e(LOG_TAG, "Could not load photo: " + this, e);
        } finally {
            closeStream(in);
            closeStream(out)
            closeStream(bfs);
        }

        return bitmap;
    }

private static void copy(InputStream in, OutputStream out) throws IOException {
    byte[] b = new byte[IO_BUFFER_SIZE];
    int read;
    while ((read = in.read(b)) != -1) {
        out.write(b, 0, read);
    }
}

private static void closeStream(Closeable stream) {
    if (stream != null) {
        try {
            stream.close();
        } catch (IOException e) {
            android.util.Log.e(LOG_TAG, "Could not close stream", e);
        }
    }
}

¿Me estoy volviendo loco aquí? Lo mejor, Michael.

Respuestas a la pregunta(3)

Su respuesta a la pregunta