0

私はこれで3日間立ち往生しています。ドキュメントのヘッダーと画像の生データからいくつかの情報を返すバッファリングされたリーダーで解析する必要がある Dicom ファイルを取得しました。その後、RAW に LUT を適用してバイトをグレースケールに変換し、Bitmap.create. 小さな画像には最適でしたが、今は 13Mo の画像をロードする必要があり、それを開くのに時間がかかるだけでなく (約 20 秒)、ビットマップ メソッドで LUT を適用しているときに、Android がエラー About Bitmap をスローします29052480-byte external allocation too large for this process. java.lang.OutOfMemoryError: bitmap size exceeds VM budget。このエラーについて多くのスレッドがあることは知っていますが、私の場合は、1 つの画像しか開きたくないので、少し独創的です (したがって、多くのビットマップをスタックすることではありません)。私はあなたにいくつかのコードを示すことができます:

RefreshBmp :

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は、ポストビニングです (それが実際の名前かどうかはわかりません)。それは、すべてのピクセルを交互に取ることにあります。これを行うには、1 つのピクセルを読み取り、1 つをスキップし、別のピクセルを読み取り、1 つをスキップして、行の終わりに到達するまでこれを続けます。次に、行をスキップして、このプロセスをデータ バッファーの最後まで続けます。

それが他の誰かを助けることができることを願っています。

于 2012-06-25T06:59:01.153 に答える