大缓冲区导致Android内存不足

时间:2012-06-13 08:26:54

标签: java android optimization memory-leaks bitmap

我被困3天了。我得到了一个Dicom文件,我需要使用缓冲读取器进行解析,该读取器从文档的标题和图像的原始数据中返回一些信息。之后,我在raw上应用LUT将字节转换为灰度,然后将其抛入Bitmap.create。这对于小图片来说是完美的,但是现在,我必须加载13Mo图像,不仅需要花费很长时间才能打开它(大约20秒),而且,在应用位图方法的LUT时,Android会抛出关于Bitmap的错误{ {1}} 29052480-byte external allocation too large for this process.。我知道有很多线程关于这个错误,但在我的情况下,它有点原始,因为我只想打开一个图像(所以它不是关于堆叠多位图)。我可以给你看一些代码:

RefreshBmp:

java.lang.OutOfMemoryError: bitmap size exceeds VM budget

哪个叫我的LUT:

private void refreshBmp(int windowWidth, int windowCentre) {
    int[] colorArray = process.transformBuffer(myDicomObject.getRawData(),
            myDicomObject.isInverted(), windowWidth, windowCentre,
            myDicomObject.getnBits());

    Bitmap bmp = Bitmap.createBitmap(colorArray,
            myDicomObject.getColumns(), myDicomObject.getRows(),
            Bitmap.Config.ARGB_8888);
    dicomImageView.setImageBitmap(bmp);
}

希望有人知道一种节省内存分配的方法,特别是LUT方法。

2 个答案:

答案 0 :(得分:0)

如果你不需要它,你应该尝试直接修改rawData。像这样:

public void transformBuffer(int[] rawData, boolean inverted,
        int windowWidth, int windowCenter, int nBits) {
/*
change rowData instead resultBuffer
*/
}

public void methodThatCallsTransformBuffer(...) {
    transformBuffer(data, inverted, ...);
    //now data is transformed
}

另外,使用lutBuffer,您可以为每个像素计算colorValue。你会节省一些内存会慢一点:

int colorValue = 0;
if (inverted) {
   if (rawData[i] < min) {
      colorValue = 255;
   } else {
      if (rawData[i] < max) {
         double value = doubleGrayScale * ((i - dmin + 1) / (dmax - dmin + 1));
         colorValue  = (int) (doubleGrayScale - value) >> intDivisionFactor;         
      }
   }
} else {
   if (rawData[i] >= min && rowData[i] < max) {
      double value = doubleGrayScale * ((i - dmin + 1) / (dmax - dmin + 1));
      colorValue  = (int) (doubleGrayScale - value) >> intDivisionFactor;      
   } else if (rowData[i] > max) {
      colorValue = 255;
   }
}

答案 1 :(得分:0)

当我最终找到解决方案时,我决定回答自己。使用那些大的Bitmap数据可以避免这个OutOfMemory错误的唯一方法是进行分箱后(如果它是实际名称,我就不知道了)。它包括拍摄每个替代像素。您可以通过读取一个像素,跳过一个,读取另一个像素,跳过一个并继续执行此操作直到到达行尾,然后跳过一行并继续此过程到数据缓冲区的末尾来执行此操作。

我希望它可以帮助别人。