4

我得到的错误是我的缓冲区对于像素来说不够大。有什么建议吗?Bitmap b 应该与我试图将其像素放入的 gSaveBitmap 大小相同。

if(gBuffer == null)
        {
            Bitmap b = Bitmap.createScaledBitmap(gBitmap, mWidth, mHeight, false);
            //gBuffer = ByteBuffer.allocateDirect(b.getRowBytes()*b.getHeight()*4);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            b.compress(Bitmap.CompressFormat.PNG,  100,  stream);
            gBuffer = ByteBuffer.wrap(stream.toByteArray());
            b.recycle();
        }
        gSaveBitmap.copyPixelsFromBuffer(gBuffer);

更新:下面的代码给出了完全相同的错误,但不涉及任何压缩。

if(gBuffer == null)
        {
            Bitmap b = Bitmap.createScaledBitmap(gBitmap, mWidth, mHeight, false);

            int bytes = b.getWidth()*b.getHeight()*4;
            gBuffer = ByteBuffer.allocate(bytes);
            b.copyPixelsToBuffer(gBuffer);              
            b.recycle();
        }
        gSaveBitmap.copyPixelsFromBuffer(gBuffer);

更新:通过将 gBuffer 的大小加倍解决了这个问题。也许有人可以告诉我为什么这是正确的尺寸。另外...图片旋转错误,需要旋转90度。任何想法如何在 gBuffer 中重新排列数据?

gBuffer = ByteBuffer.allocate(b.getRowBytes()*b.getHeight()*2);
4

2 回答 2

3

我想我可能已经解决了这个问题——看看Bitmap::copyPixelsFromBuffer() 的源代码(版本 2.3.4_r1,上次 Bitmap 在 4.4 之前的 Grepcode 上更新)

public void copyPixelsFromBuffer(Buffer src) {

     checkRecycled("copyPixelsFromBuffer called on recycled bitmap");

     int elements = src.remaining();
     int shift;
     if (src instanceof ByteBuffer) {

         shift = 0;

     } else if (src instanceof ShortBuffer) {
         shift = 1;

     } else if (src instanceof IntBuffer) {
         shift = 2;

     } else {

         throw new RuntimeException("unsupported Buffer subclass");

     }

     long bufferBytes = (long)elements << shift;
     long bitmapBytes = (long)getRowBytes() * getHeight();

     if (bufferBytes < bitmapBytes) {

         throw new RuntimeException("Buffer not large enough for pixels");

     }

     nativeCopyPixelsFromBuffer(mNativeBitmap, src);

 }

错误的措辞有点不清楚,但代码澄清了 - 这意味着您的缓冲区被计算为没有足够的数据来填充位图的像素。这是因为他们使用缓冲区的 remaining() 方法来计算缓冲区的容量,其中考虑了其位置属性的当前值。如果在调用 copyPixelsFromBuffer() 之前在缓冲区上调用 rewind(),您应该会看到运行时异常消失。

于 2014-05-20T20:44:49.093 回答
0

我找到了这个问题的答案:

您应该始终设置,buffer size > bit map size因为不同 Android 版本上的位图总是更改。

您可以在下面记录代码以查看buffer size & bitmap size(Android API 应 >= 12 以使用以下日志)

Log.i("", "Bitmap size = " + mBitmap.getByteCount());
        Log.i("", "Buffer size = " + mBuffer.capacity());

它应该工作。

谢谢,

于 2014-07-12T09:54:11.680 回答