【问题标题】:decodeByteArray and copyPixelsToBuffer not working. SkImageDecoder::Factory returned nulldecodeByteArray 和 copyPixelsToBuffer 不起作用。 SkImageDecoder::Factory 返回 null
【发布时间】:2012-06-01 23:19:09
【问题描述】:

我有一个实现 Serializable 的类 TouchPoint,因为它包含位图,所以我为该类编写了 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 返回 null

那么我该如何解决它。我知道可能的解决方案是将 writeObject() 更改为

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

但是这种方法慢了将近 10 倍以上。

  • copyPixelsToBuffer ~14ms 用于写入图像
  • _bmp.compress ~ 160ms

更新 发现实际问题是在

之后
buffer.array();

所有byte[]数组元素为:0

【问题讨论】:

  • 您没有收到任何其他错误消息吗?也许,int bytes = _bmp.getRowBytes() * _bmp.getHeight() 可以解决您的问题。
  • 不,我没有收到其他消息。这并不能解决问题。但是,我找到了解决这个问题的方法。我稍后会发布答案。

标签: java android bitmap bytearray serializable


【解决方案1】:

最后,我找到了一种方法,让它既能工作又能更快。我使用这种方法遇到了两个问题:

  1. 我也应该传递 Bitmap.Config 参数,否则我无法解码字节数组
  2. _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;
    }
}

这对我来说已经足够快了——比 bmp.compress 方式快了大约 15 倍。希望这会有所帮助:)

【讨论】:

  • 嗯,它似乎比下面的方法慢得多。我是不是做错了什么?
【解决方案2】:

位图到字节[]:

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

使用 Bufferedstreams 以获得更好的性能。

【讨论】:

  • 我已经说过这个方法太慢了,因为它压缩Bitmap需要很多时间。我已经找到了工作速度快约 15 倍的方法。
猜你喜欢
  • 2012-06-07
  • 2012-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多