Le but est de convertir une Bitmap
en byte []
, de la transmettre entre les activités dans une Bundle
de données, puis de la reconvertir en une Bitmap
à un stade ultérieur pour affichage dans une Imageview
.
Le problème est que chaque fois que j'essaie, j'obtiens simplement un bitmap nul et une sortie de journal non descriptive et inutile:
12-07 17:01:33.282: D/skia(2971): --- SkImageDecoder::Factory returned null
J'ai examiné les solutions suivantes:
Solution fournit le bitmap en octet [] code utilisé
Souligne que copyPixelsToBuffer () est essentiel pour .compress
(Surtout vu que ce n'est pas nécessaire dans ce cas).
J'ai lancé le scénario de test suivant, qui limite définitivement le problème à la conversion et à la restauration du code. Sur la base de mon débogage, le décodage est correct, le tableau d'octets est de taille correcte et complet, les configurations Bitmap sont forcées d'être identiques, decodeByteArray
échoue:
package com.example.debug;
import Java.nio.ByteBuffer;
import Android.os.Bundle;
import Android.app.Activity;
import Android.graphics.Bitmap;
import Android.graphics.Bitmap.Config;
import Android.graphics.BitmapFactory;
import Android.util.Log;
import Android.view.Menu;
import Android.widget.ImageView;
import Android.widget.RelativeLayout;
public class MainActivity extends Activity {
RelativeLayout rl = null;
RelativeLayout.LayoutParams rlp = null;
ImageView ivBef = null;
ImageView ivAft = null;
Bitmap bmBef = null;
Bitmap bmAft = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TEST
BitmapFactory.Options bmo = new BitmapFactory.Options();
bmo.inPreferredConfig = Config.ARGB_8888;
bmBef = BitmapFactory.decodeFile("/mnt/sdcard/Debug/001.png", bmo);
byte[] b = bitmapToByteArray(bmBef);
bmAft = BitmapFactory.decodeByteArray(b, 0, b.length, bmo);
LinearLayout ll = new LinearLayout(this);
ivBef = new ImageView(this);
ivBef.setImageBitmap(bmBef);
ivAft = new ImageView(this);
ivAft.setImageBitmap(bmAft);
ll.addView(ivBef);
ll.addView(ivAft);
setContentView(ll);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public static byte[] bitmapToByteArray(Bitmap bm) {
// Create the buffer with the correct size
int iBytes = bm.getWidth() * bm.getHeight() * 4;
ByteBuffer buffer = ByteBuffer.allocate(iBytes);
// Log.e("DBG", buffer.remaining()+""); -- Returns a correct number based on dimensions
// Copy to buffer and then into byte array
bm.copyPixelsToBuffer(buffer);
// Log.e("DBG", buffer.remaining()+""); -- Returns 0
return buffer.array();
}
}
Before Imageview
affiche correctement l'image, after after ImageView
ne montre rien (comme on peut s'y attendre avec un bitmap null
Vous transmettez Bitmap à Intent et obtenez bitmap dans l'activité suivante de l'ensemble, mais le problème est que si votre taille Bitmap/Image est grande à ce moment, l'image n'est pas chargée dans l'activité suivante.
Utilisez ci-dessous 2 solutions pour résoudre ce problème.
1) Commencez par convertir une image en tableau d’octets, puis passez à l’intention. Dans l’activité suivante, obtenez un tableau d’octets provenant de l’ensemble et convertissez en image (bitmap) et définissez-le dans ImageView.
Convertir un bitmap en tableau d'octets: -
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Passer un tableau d'octets dans l'intention: -
Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("picture", byteArray);
startActivity(intent);
Obtenir le tableau d'octets du paquet et convertir en image bitmap: -
Bundle extras = getIntent().getExtras();
byte[] byteArray = extras.getByteArray("picture");
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
ImageView image = (ImageView) findViewById(R.id.imageView1);
image.setImageBitmap(bmp);
2) Commencez par enregistrer une image dans la carte SD puis, dans l’activité suivante, définissez cette image dans ImageView.
L'envoi d'un bitmap dans une Bundle
de données est une très mauvaise idée et une très mauvaise implémentation. En outre, la taille des données d'une Bundle
est 1 MB
, comme l'a déclaré Dianne Hackborn (ingénieur de structure Android).
La méthode suivante fonctionne parfaitement avec moi, essayez-la ..
public byte[] convertBitmapToByteArray(Context context, Bitmap bitmap) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream(bitmap.getWidth() * bitmap.getHeight());
bitmap.compress(CompressFormat.PNG, 100, buffer);
return buffer.toByteArray();
}
essaye ça:
bmBef = BitmapFactory.decodeFile("/mnt/sdcard/Debug/001.png", bmo);
ByteArrayOutputStream baos= new ByteArrayOutputStream();
bmBef .compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] byteArray = baos.toByteArray();