decodeByteArray и copyPixelsToBuffer не работают. SkImageDecoder::Factory вернул ноль
У меня есть класс TouchPoint, который реализует Serializable и, поскольку он содержит Bitmap, я написал writeObject и readObject для этого класса:
private void writeObject(ObjectOutputStream oos) throws IOException {
long t1 = System.currentTimeMillis();
oos.defaultWriteObject();
if(_bmp!=null){
int bytes = _bmp.getWidth()*_bmp.getHeight()*4;
ByteBuffer buffer = ByteBuffer.allocate(bytes);
_bmp.copyPixelsToBuffer(buffer);
byte[] array = buffer.array();
oos.writeObject(array);
}
Log.v("PaintFX","Elapsed Time: "+(System.currentTimeMillis()-t1));
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
ois.defaultReadObject();
byte[] data = (byte[]) ois.readObject();
if(data != null && data.length > 0){
_bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
}
}
Проблема в том, что я получаю
SkImageDecoder::Factory вернул ноль
Так как я могу это исправить. Я знаю, что возможное решение состоит в том, чтобы изменить writeObject() на
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
_bmp.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
oos.writeObject(byteStream.toByteArray);
НО этот метод медленнее почти в 10+ раз.
- copyPixelsToBuffer ~ 14ms для записи изображения
- _bmp.compress ~ 160 мс
ОБНОВЛЕНИЕ Узнайте, что актуальная проблема заключается в том, что после
buffer.array();
Все элементы массива byte[]: 0
2 ответа
Наконец я нахожу способ заставить его работать и быть быстрее одновременно. Я столкнулся с двумя проблемами, используя этот метод:
- Я должен также передать параметр Bitmap.Config, без этого я не могу декодировать байтовый массив
- _bmp.compress и _bmp.copyPixelsToBuffer дают разные массивы, поэтому я не могу использовать decodeByteArray.
Я решил их таким образом
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
if(_bmp!=null){
int bytes = _bmp.getWidth()*_bmp.getHeight()*4;
ByteBuffer buffer = ByteBuffer.allocate(bytes);
_bmp.copyPixelsToBuffer(buffer);
byte[] array = new byte[bytes]; // looks like this is extraneous memory allocation
if (buffer.hasArray()) {
try{
array = buffer.array();
} catch (BufferUnderflowException e) {
e.printStackTrace();
}
}
String configName = _bmp.getConfig().name();
oos.writeObject(array);
oos.writeInt(_bmp.getWidth());
oos.writeInt(_bmp.getHeight());
oos.writeObject(configName);
} else {
oos.writeObject(null);
}
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
ois.defaultReadObject();
byte[] data = (byte[]) ois.readObject();
if (data != null) {
int w = ois.readInt();
int h = ois.readInt();
String configName = (String) ois.readObject();
Bitmap.Config configBmp = Bitmap.Config.valueOf(configName);
Bitmap bitmap_tmp = Bitmap.createBitmap(w, h, configBmp);
ByteBuffer buffer = ByteBuffer.wrap(data);
bitmap_tmp.copyPixelsFromBuffer(buffer);
_bmp = bitmap_tmp.copy(configBmp,true);
bitmap_tmp.recycle();
} else {
_bmp = null;
}
}
Это достаточно быстро для меня - примерно в 15 раз быстрее, чем способ bmp.compress. надеюсь это поможет:)
Растровое изображение в байт []:
Bitmap bmp; // your bitmap
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Используйте Bufferedstreams для лучшей производительности.