Android: BitmapFactory.decodeByteArray donne bitmap pixélisé
Je suis en train de travailler sur une application Android qui permet d'afficher les photos qui sont téléchargés à partir de Flickr. Je obtenir un objet bitmap à partir d'un tableau d'octets, qui est lu par le Flickr de l'URL, comme suit:
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inDither = true;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt);
Je puis dessiner l'image sur une toile de dans la méthode onDraw de Vue de l'objet:
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint);
Le problème est que l'image est pixélisée, et je ne peux pas comprendre pourquoi; j'ai essayé un certain nombre de variations de l'opt et de la peinture des objets avec pas de chance. La différence entre l'image affichée dans mon application et de l'image à l'URL d'origine est à peu près démontré par le texte suivant:
Bonne image, c'est le résultat attendu http://homepages.inf.ed.ac.uk/s0677975/good.jpg
Look par exemple, à regarder les nuages dans le coin en haut à gauche pour voir la différence.
Noter que les images JPEG qui sont chargés de les ressources du projet et élaboré de manière similaire, afficher amende, c'est à dire pas de pixelisation.
Quelqu'un peut-il me donner un indice pour expliquer ce qui se passe?
Développer un peu, le tableau d'octets est obtenu à partir de Flickr comme suit; c'est basé sur le code de la Photostream application par 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();
PS: j'ai aussi posté une variante de cette question sur l'android.développeur Google groupe.
Merci beaucoup pour votre suggestion -- maintenant, je suis vraiment perplexe! J'ai fait comme vous l'avez suggéré, et a constaté que l'image résultant directement de l'téléchargé tableau d'octets est en effet pixélisé. Cependant, ce qui est téléchargé à partir d'exactement la même URL, ce qui, lors de l'accès sur mon ordinateur, n'est PAS pixélisé. Ici, c'est le correspondant de Flickr URL:
http://farm3.static.flickr.com/2678/4315351421_54e8cdb8e5.jpg
Encore plus étrange, quand je lance la même application dans le simulateur, plutôt que sur mon téléphone (HTC Hero), il n'y a pas de pixelisation.
Comment diable est-ce possible?
Ci-dessous le code que j'ai utiliser pour le chargement d'une image bitmap à partir d'une URL-il est basé sur le Photostream application par Romain Guy, et il intègre Aura une suggestion d'écrire brutes tableau d'octets dans le fichier:
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);
}
}
}
Suis-je fou ici?
Mieux,
Michael.
source d'informationauteur Michael Pedersen
Vous devez vous connecter pour publier un commentaire.
Écrire les octets brutes extraites à partir de l'URL à
/sdcard/tmp.jpg
et de les afficher sur votre PC.JPEG les images sont compressées en 8x8 (ou 16x16) tuiles. La "pixellisation", comme vous le décrire, il est en fait dans ces tuiles, ce qui suggère que le "mauvais" de l'image est au format JPEG qui est plus agressive compressé que les autres.
Alors j'aimerais anticiper que le problème réel est que l'image téléchargée est une très faible qualité de la version, par exemple, l'une destinée thumbnailing/aperçu de cas d'utilisation.
Ok, j'ai donc enfin l'obtenir: il semble que mon réseau mobile ne de compression d'image pour économiser de la bande passante.
Donc une image téléchargée à partir de mon téléphone est de qualité inférieure à celle de la même image téléchargée à partir de mon ordinateur.
Qui est une déception pour mon application, mais je ne crois pas qu'il y a quelque chose que je peux faire à ce sujet. Soupir.
Merci encore pour vos commentaires!
Meilleur,
Michael.
Certaines versions d'Android ont un bug dans la classe Bitmap et de convertir l'image à RGB_565 lors de certaines opérations. Cela se traduit par des artefacts similaires à ceux sur votre image. Cela expliquerait aussi le cerclage de ciel bleu.
Aussi, ayez à l'esprit que android des tentatives pour "optimiser" l'image en les convertissant en rgb_565 lors du chargement et même de la compilation sur fichiers de ressources. Jetez un oeil à:
http://android.nakatome.net/2010/04/bitmap-basics.html