8

I have a class TouchPoint which implements Serializable and because it contains Bitmap I wrote writeObject and readObject for that class:

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);
    }
}

The problem is that I get

SkImageDecoder::Factory returned null

So how can I fix it. I know that possible solution is to change writeObject() to

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
_bmp.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
oos.writeObject(byteStream.toByteArray);

BUT this method is slower almost 10+ times.

  • copyPixelsToBuffer ~14ms for writing image
  • _bmp.compress ~ 160ms

UPDATE Find out that the actual problem is that after

buffer.array();

All byte[] array elements are: 0

Cyberon
  • 289
  • 1
  • 4
  • 16
  • Don't you get any other error messages? Perhaps, `int bytes = _bmp.getRowBytes() * _bmp.getHeight()` would solve your problem. – a.ch. May 30 '12 at 10:59
  • no, I don't get other messages. that doesn't fixed the problem. However, I find the way to solve this. I'll post an answer later. – Cyberon May 30 '12 at 14:32

2 Answers2

7

Finally I find a way to make it work and be faster at the same time. I was encountered two issues using this method:

  1. I should pass the Bitmap.Config param also, without that I can't decode the byte array
  2. _bmp.compress and _bmp.copyPixelsToBuffer give different arrays so I couldn't use decodeByteArray.

I solved them this way

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;
    }
}

This is enough fast for me - about 15x faster then the bmp.compress way. hope this helps :)

Community
  • 1
  • 1
Cyberon
  • 289
  • 1
  • 4
  • 16
  • well it seems like its much slower than the below method. Am i doing some mistake? – Ana Apr 22 '14 at 05:28
1

Bitmap to byte[]:

Bitmap bmp; // your bitmap
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();

Use Bufferedstreams for better performance.

Klaasvaak
  • 5,634
  • 15
  • 45
  • 68
  • 2
    I already said that this method is too slow, because it compress the Bitmap which takes a lot of time. I already find the way which works ~15x faster. – Cyberon Jun 01 '12 at 08:42