0

我在这个问题上被困了 3 天。我得到了一个 Dicom 文件,我需要使用缓冲阅读器对其进行解析,该阅读器从文档的标题和图像的原始数据返回一些信息。之后,我在 raw 上应用 LUT 将字节转换为灰度,然后将其放入Bitmap.create. 它非常适合小图像,但现在,我必须加载 13Mo 图像,不仅需要很长时间才能打开它(大约 20 秒),而且在应用 LUT int 位图方法时,Android 会抛出关于 Bitmap 的错误29052480-byte external allocation too large for this process. java.lang.OutOfMemoryError: bitmap size exceeds VM budget。我知道有很多关于这个错误的线索,但就我而言,它有点原始,因为我只想打开一个图像(所以它不是关于堆叠很多位图)。我可以给你看一些代码:

刷新Bmp:

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:

public int[] transformBuffer(int[] rawData, boolean inverted,
        int windowWidth, int windowCenter, int nBits) {
    System.gc();

    int min = windowCenter - (windowWidth/2);       
    int max = windowCenter + (windowWidth/2);       
    int intGrayscale = (int) Math.pow(2, nBits);    
    int intDivisionFactor = nBits-8;                

    double dmin = (double) min;                     
    double dmax = (double) max;                     
    double doubleGrayScale = (double) intGrayscale; 

    int rawDataLength = rawData.length;             

    int[] resultBuffer = new int[rawDataLength];    
    lutBuffer = new int[intGrayscale];              

    if(inverted){

        for(int i = 0 ; i < min ; i++){
            lutBuffer[i] = 255;
        }

        for(int i = min ; i < max ; i++){
            double value = doubleGrayScale * ((i - dmin + 1) / (dmax - dmin + 1));
            lutBuffer[i] = (int) (doubleGrayScale - value) >> intDivisionFactor;
        }

        for(int i = max ; i < intGrayscale ; i++){
            lutBuffer[i] = 0;
        }

    }else{
        for(int i = 0 ; i < min ; i++){
            lutBuffer[i] = 0;
        }

        for(int i = min ; i < max ; i++){
            double value = ((i - dmin + 1) / (dmax - dmin + 1));
            lutBuffer[i] = (int) (value) << intDivisionFactor;
        }

        for(int i = max ; i < intGrayscale ; i++){
            lutBuffer[i] = 255;
        }
    }

    for(int i = 0 ; i < rawDataLength ; i++){
        int colorValue = lutBuffer[rawData[i]];
        resultBuffer[i] = Color.argb(255, colorValue, colorValue, colorValue);
    }

    System.out.println(resultBuffer.length);
    return resultBuffer;
}

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

4

2 回答 2

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;
   }
}
于 2012-06-13T08:36:55.813 回答
0

当我最终找到解决方案时,我决定回答自己。使用这些大位图数据避免此错误的唯一方法 OutOfMemory是后期分箱(我不确定它是否是实际名称)。它包括获取每个交替的像素。您可以通过读取一个像素、跳过一个像素、读取另一个像素、跳过一个像素并继续执行此操作直到到达行尾,然后跳过一行并继续此过程直到数据缓冲区的末尾。

我希望它可以帮助别人。

于 2012-06-25T06:59:01.153 回答