Android: Bitmap to Byte Array и обратно: SkImageDecoder:: Factory возвращен null
Цель состоит в том, чтобы преобразовать a Bitmap
в byte []
, передать его между действиями в Bundle
данных, а затем переконвертировать его обратно к Bitmap
на более позднем этапе для отображения в Imageview
.
Проблема в том, что всякий раз, когда я пытаюсь это сделать, я просто получаю нулевое растровое изображение и не описательный, бесполезный вывод журнала:
12-07 17:01:33.282: D/skia(2971): --- SkImageDecoder::Factory returned null
Я рассмотрел следующие решения:
Решение поставляет битмап в байт [] используемый код
Подчеркнул, что copyPixelsToBuffer() необходим для .compress
(Особенно учитывая, что в этом случае это не обязательно).
Я запустил следующий тестовый пример, который определенно сужает проблему для преобразования и восстановления кода. Основываясь на моей отладке, есть правильное декодирование, массив байтов - правильный размер и полный, конфигурации Bitmap вынуждены быть одинаковыми, decodeByteArray
просто терпит неудачу:
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();
}
}
Прежде чем Imageview
правильно отобразит изображение, после Imageview
ничего не отображается (как вы ожидали бы с нулевым растровым изображением
Ответы
Ответ 1
Вы передаете Bitmap в Intent и получаете растровое изображение в следующей активности из пакета, но проблема в том, что размер вашего Bitmap/Image большой в то время, когда изображение не загружается в следующем действии.
Используйте ниже 2 Решения для решения этой проблемы.
1) Сначала преобразуйте изображение в байт-массив, а затем перейдите в Intent и в следующем действии получите массив байтов из Bundle и Convert into Image (Bitmap) и установите в ImageView.
Преобразование битмапа в байт-массив: -
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Передать массив байтов в цель: -
Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("picture", byteArray);
startActivity(intent);
Получить байт-массив из Bundle и преобразовать в растровое изображение: -
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) Сначала сохраните изображение в SDCard и в следующем действии установите это изображение в ImageView.
Ответ 2
Отправка растрового изображения в Bundle
данных - настоящая плохая идея и будет реальной плохой реализацией. Кроме того, размер данных Bundle
равен 1 MB
, как указано Dianne Hackborn (разработчиком инфраструктуры Android).
Ответ 3
Следующий метод отлично работает со мной, дайте ему попробовать.
public byte[] convertBitmapToByteArray(Context context, Bitmap bitmap) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream(bitmap.getWidth() * bitmap.getHeight());
bitmap.compress(CompressFormat.PNG, 100, buffer);
return buffer.toByteArray();
}
Ответ 4
попробуйте следующее:
bmBef = BitmapFactory.decodeFile("/mnt/sdcard/Debug/001.png", bmo);
ByteArrayOutputStream baos= new ByteArrayOutputStream();
bmBef .compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] byteArray = baos.toByteArray();