当前位置: 首页 > 面试题库 >

encodeByteArray和copyPixelsToBuffer无法正常工作。SkImageDecoder :: Factory返回null

董子平
2023-03-14
问题内容

我有一个实现了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


问题答案:

最终,我找到了一种使其同时运行并更快的方法。使用此方法遇到两个问题:

  1. 我也应该通过Bitmap.Config参数,否则我无法解码字节数组
  2. _bmp.compress和_bmp.copyPixelsToBuffer给出了不同的数组,所以我不能使用解码字节数组。

我这样解决了

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倍。希望这可以帮助 :)



 类似资料:
  • 问题内容: 目标是将a转换为a ,将其在数据的a个活动之间传递,然后在以后的阶段将其重新转换回a 以便显示在中。 问题是,每当我尝试这样做时,我只会得到一个空位图和无描述性,无用的日志输出: (特别是因为在这种情况下没有必要)。 我已经运行了以下测试案例,该案例肯定将问题缩小为转换和还原代码。根据我的调试,解码正确,字节数组的大小正确且已满,位图配置被强制设置为相同,只是失败了: 前正确显示图像,

  • 我正在用Laravel 8制作一个论坛,基本上每当用户在这个论坛上提问时,它应该被重定向到这个问题。 我还想使重定向过程基于问题的字段。 因此,为了做到这一点,我在方法的末尾添加了以下内容: 下面是看问题的路线: 然后我在控制器编码: 但现在的问题是,当我尝试添加新问题时,该问题将成功添加,但它会将我重定向到页面。重定向后的URL也如下所示: 正如你所看到的问题没有正确添加! 那么这里出了什么问题

  • 问题内容: 我有一个正在使用的。我以前用过但从未遇到过这个问题。 当我上下滚动时,某些项目消失,而某些消失的项目再次出现在底部。 码: : : 问题答案: 重用Views,因此可以说是第一次调用is 。这将导致该行的可见度为。 当又被称为绑定一个新行,该行的观点依然是-没有什么是复位之间势必行。 因此,您的if语句应完全重置状态: 这将确保正确设置每一行的可见性。

  • 问题内容: 我在HashSet上调用Iterator.remove()遇到问题。 我有一组带有时间戳的对象。在将新项目添加到Set之前,我将遍历Set,确定该数据对象的旧版本并将其删除(在添加新对象之前)。时间戳包含在hashCode和equals()中,但不包含equalsData()。 奇怪的是,对于集合中的某些项目,i.remove()默默失败(也不例外)。我已经核实了 实际上会调用i.re

  • 问题内容: 因此,我的设置无法按我想要的方式工作。因此,每当我运行该程序时,它就会立即从0变为100。我尝试使用,任务,并尝试了,但没有任何尝试。 这是我的程序: @MadProgrammer这是我尝试做一名摆动工作人员并将每个名称写入文档并更新进度栏的尝试。该程序将达到86%左右并停止运行,永远不会创建完成的文档。该程序将创建一个空白文档。这是我首先创建的SwingWorker对象,这是两种方法

  • 问题内容: 我在JLayeredpane上有两个JPanels。其中一个显示pdf,重叠的一个具有透明背景(我使用过setOpaque(false))。现在,我可以将图形添加到透明面板中,这样看来我实际上是在注释pdf。我想要一个橡皮擦工具来删除这些注释。我尝试使用以下代码 其中path是由多条线构成的形状。现在,不是在先前的图形上绘制 透明线 ,而是绘制 黑线 。我要去哪里错了? 问题答案: 请