2012-11-20 3 views
3

디스크에 1280x1280 JPG가 있는데 ImageView에 표시 할 이미지의 영역을 디코딩 할 때 (측면이 잘리는) 다음 코드를 사용하고 있습니다. 이미지에서 위쪽과 아래쪽을 잘라내는 것과 비슷한 문제가 있습니다. 에이서 ICONIA A100 (4.0.3) 코드가 완벽하게 작동 및 힙에는 메모리를 할당하지 제공된 경우 재순환 비트 맵으로 지역 디코딩에 왜 BitmapRegionDecoder가 많은 양의 메모리를 할당합니까?

private Bitmap decodeBitmapRegion(InputStream in, Rect region, Bitmap recycleBitmap) { 
    LOGD(TAG, "decodeBitmapRegion region=" + region + ", recycleBitmap=" + recycleBitmap); 

    Bitmap bitmap = null; 
    BitmapRegionDecoder decoder = null; 

    BitmapFactory.Options options = new BitmapFactory.Options();   
    options.inSampleSize = 1; 
    options.inBitmap = recycleBitmap; 

    try { 
     decoder = BitmapRegionDecoder.newInstance(in, false); 
     bitmap = decoder.decodeRegion(region, options); 
    } catch (IllegalArgumentException e){ 
     LOGE(TAG, "Failed to recycle bitmap for rect=" + region, e); 
    } catch (IOException e) { 
     LOGE(TAG, "Failed to decode into rect=" + region, e); 
    } finally { 
     if (decoder != null) decoder.recycle(); 
    } 

    return bitmap; 
} 

. logcat에는 GC가 없거나 힙 메시지가 증가합니다. 또한 4.2.0을 실행하는 Nexus 7에서도 올바르게 작동합니다.

Motorola Xoom (4.0.4)에서이 코드는 다음 logcat을 생성합니다. 첫번째 dalvikvm-heap grow (4738256 바이트)은 아마도 BitmapRegionDecoder의 데이터 용이고 두 번째 (3603216 바이트)는 이미지를 저장하는 데 필요한 메모리 양 (800x1126x4)과 일치합니다. 스키 아 오류가 있습니다.

8522 LocationImageLoader D decodeBitmapRegion region=Rect(240, 77 - 1040, 1203), [email protected] 
    8522    dalvikvm D GC_FOR_ALLOC freed 8213K, 28% free 22782K/31623K, paused 34ms 
    8522   dalvikvm-heap I Grow heap (frag case) to 26.808MB for 4738256-byte allocation 
    8522    dalvikvm D GC_CONCURRENT freed 6K, 14% free 27403K/31623K, paused 3ms+7ms 
    8522     skia D WARNING: One-shot allocator has already allocated (alloc count = 1) 
    8522    dalvikvm D GC_FOR_ALLOC freed 0K, 14% free 27403K/31623K, paused 33ms 
    8522   dalvikvm-heap I Grow heap (frag case) to 30.238MB for 3603216-byte allocation 
    8522    dalvikvm D GC_FOR_ALLOC freed 0K, 3% free 30922K/31623K, paused 41ms 

설정 options.inPreferredConfig = Bitmap.Config.RGB_565; 비트 맵이 올바르게 재활용 된 것처럼 Xoom의 두 번째 할당을 무효화하는 것으로 보이지만 여전히 디코더에 할당 된 메모리가 있습니다.

전체 이미지 (1280x1280) 및 BitmapFactory를 사용한 재활용 작업은 영역에서 요구하는 것보다 전체 이미지를 저장하는 데 훨씬 많은 메모리가 사용되지만 작동합니다.

왜 Xoom이 작동하지 않지만 Acer은 모두 Android 4.0.x를 실행 중일 때 이해할 수 없습니다.

+0

...? – auval

+0

Xoom이 GPU에서 디코 딘/자르기/인코딩을 수행하지 않는 것 같습니다. – auval

+0

@uval hardwareAccelerated가 true로 설정되어 있지만 불행히도 GPU에서 수행되지 않는 작업에 대한 이론은 의미가 있지만 차이는 없습니다. –

답변

1

recycleBitmap을 재활용하고 있습니까?

주목할만한 점은, 재활용 된 비트 맵이 일부 작업에서 반환 된 실제 비트 맵이기 때문에 재활용하지 않을 수도 있다는 점입니다. 그러나 다른 경우에는 새로운 비트 맵이 인스턴스화되어 원래의 비트 맵을 재활용하려고합니다. 더 이상이 메서드의 범위 밖에서는 필요하지 않다고 가정합니다.

+0

비트 맵이 다시 사용되었는지 확인하기 위해 두 객체 ID를 비교 한 코드가 있지만 recycleBitmap에서 recycle을 호출하지 않습니다. Xoom에는 두 개의 다른 개체가 있지만 검은 색 비트 맵을 사용하면 재활용이 가능합니다! 이 경우 Xoom의 또 다른 특징은 Nexus 기기가 객체 평등을 보여 주므로 메모리가 다시 사용된다는 것입니다. –

+0

나는 Xoom에 손을 넣고 내 프로젝트 중 하나에서 비슷한 코드를 테스트 해보고 다시 돌아올 것입니다. –

2

내 Archos G9 80 (4.0.4)에서 RGB656을 요청했지만 반환 된 비트 맵이 RGB8888을 사용하고 있음을 확인했습니다. 1024x1024 사각형을 디코딩하고 결과 비트 맵에서 getByteCount()를 호출하면 4MB가 반환됩니다. RGB8888을 사용하여 비트 맵을 전달하더라도 새 공간을 할당합니다.

설명서를 참고하면 inSampleSize에 옵션이 사용되지만 작동하는 것처럼 보이지만 inPreferredConfig 및 inBitmap은 특별히 언급하지 않았습니다. 나는 inPreferredConfig와 inBitmap을 기리는 수단이 제조업체에 달려 있거나 4.1 이상으로 추가되었다는 것을 의미한다고 생각합니다.

+0

일부 출처에 링크하는 것이 도움이 될 수 있습니다. – JSuar

+0

4444 및 656 모드는 "더 이상 사용되지 않습니다."bitmapdecoder는 항상 최근 안드로이드 버전에서 8888을 말합니다. 지금 개발자가 가이드와 동영상을 만들 때 Google이 옵션으로 사용하여 메모리를 쉽게 절약 할 수 있다고 말하는 것을 막을 수 있습니까?당연히 아니지. –

관련 문제