Programing

Android에서 올바른 크기로 비트 맵 디코딩

lottogame 2020. 12. 2. 07:46
반응형

Android에서 올바른 크기로 비트 맵 디코딩


를 사용하여 SD 카드에서 비트 맵을 디코딩 BitmapFactory.decodeFile합니다. 때로는 비트 맵이 애플리케이션에 필요하거나 힙이 허용하는 것보다 크므 BitmapFactory.Options.inSampleSize로 서브 샘플링 된 (더 작은) 비트 맵을 요청하는 데 사용 합니다.

문제는 플랫폼이 inSampleSize의 정확한 값을 적용하지 않고 때때로 비트 맵이 너무 작거나 사용 가능한 메모리에 비해 너무 크다는 것입니다.

에서 http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize :

참고 : 디코더는이 요청을 수행하려고 시도하지만 결과 비트 맵은 요청 된 것과 정확히 다른 차원을 가질 수 있습니다. 또한 2의 거듭 제곱은 디코더가 존중하기 위해 더 빠르고 / 쉽습니다.

디코딩을 위해 가능한 한 적은 메모리를 사용하면서 필요한 정확한 크기의 비트 맵을 얻으려면 SD 카드에서 비트 맵을 어떻게 디코딩해야합니까?

편집하다:

현재 소스 코드 :

BitmapFactory.Options bounds = new BitmapFactory.Options();
this.bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, bounds);
if (bounds.outWidth == -1) { // TODO: Error }
int width = bounds.outWidth;
int height = bounds.outHeight;
boolean withinBounds = width <= maxWidth && height <= maxHeight;
if (!withinBounds) {
    int newWidth = calculateNewWidth(int width, int height);
    float sampleSizeF = (float) width / (float) newWidth;
    int sampleSize = Math.round(sampleSizeF);
    BitmapFactory.Options resample = new BitmapFactory.Options();
    resample.inSampleSize = sampleSize;
    bitmap = BitmapFactory.decodeFile(filePath, resample);
}

올바른 방향으로 가고 있지만 한 번에 두 가지 작업을 수행하려고합니다. 파일을 읽고 적절한 크기로 조정합니다.

첫 번째 단계는 BitmapFactory.Options.inSampleSize를 사용하여 필요한 것보다 약간 더 큰 Bitmap으로 파일을 읽어서 작은 썸네일 또는 화면 해상도 이미지 만 원하는 경우 큰 비트 맵을 읽는 데 과도한 메모리를 사용하지 않도록하는 것입니다.

두 번째 단계는 Bitmap.createScaledBitmap ()을 호출하여 필요한 정확한 해상도로 새 비트 맵을 만드는 것입니다.

메모리를 회수하려면 임시 비트 맵 후에 정리해야합니다. (변수가 범위를 벗어나게하고 GC가 처리하도록하거나 많은 이미지를로드하고 메모리가 부족한 경우에는 .recycle ()을 호출하십시오.)


을 사용할 수 있습니다 inJustDecodeBounds. 로 설정 TRUE하고 파일을있는 그대로로드합니다.

이미지는 메모리에로드되지 않습니다. 그러나 outheightoutwidth 의 특성 BitmapFactory.Options는 지정된 이미지의 실제 크기 PARAMS 포함됩니다. 얼마나 서브 샘플링 할 것인지 계산하십시오. 즉, 1/2 또는 1/4 또는 1/8 등을 입력하고 inSampleSize 에 따라 2/4/8 등을 할당합니다 .

이제 설정 inJustDecodeBoundsFALSE하고 호출 BitmapFactory.decodeFile()위의 계산으로 정확한 크기의 이미지를로드 할 수 있습니다.


먼저 이미지를 가장 가까운 샘플링 값으로 샘플링하여 비트 맵이 메모리 효율적이되도록해야합니다. 완료되면 화면에 맞게 확장 할 수 있습니다.

// This function taking care of sampling
backImage =decodeSampledBitmapFromResource(getResources(),R.drawable.back, width, height);

// This will scale it to your screen width and height. you need to pass screen width and height.
backImage = Bitmap.createScaledBitmap(backImage, width, height, false); 

API에 이미 샘플 크기가 적용되거나 적용되지 않을 수 있다고 명시되어 있기 때문입니다. 그래서 나는을 사용하는 동안 운이 좋지 않은 것 같습니다 BitmapFactory.

그러나 탈출구는 자신의 비트 맵 리더를 사용하는 것입니다. 그러나 상당히 잘 테스트되고 표준화 된 BitmapFactory를 고수하는 것이 좋습니다.

나는 약간의 추가 메모리 소비에 대해 너무 걱정하지 않고 그 값을 존중하지 않는 이유를 찾으려고 노력할 것입니다. 슬프게도 나는 그것에 대해 모른다 :(


ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filesPath), THUMBSIZE, THUMBSIZE))

요구 사항에 따라 THUMBSIZE를 직접 설정할 수 있지만 하위 수준 구현 세부 정보, 출력 이미지 품질 및 성능에 대해 잘 모르겠지만 일반적으로 축소판을 표시해야 할 때 선호합니다.


리소스에서 정확한 크기의 이미지를 찾는 사람들을 위해.

정확한 너비의 경우 reqHight = 0을 전달하고 정확한 높이의 경우 reqWidth = 0을 전달합니다.

public static Bitmap decodeBitmapResource(Context context, int resId, int reqWidth, int reqHeight)
{
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(context.getResources(), resId, options);
    float scale = 1;
    if (reqWidth != 0 && reqHeight == 0)
    {
        options.inSampleSize = (int) Math.ceil(options.outWidth / (float) reqWidth);
        scale = (float) options.outWidth / (float) reqWidth;
    }
    else if (reqHeight != 0 && reqWidth == 0)
    {
        options.inSampleSize = (int) Math.ceil(options.outHeight / (float) reqHeight);
        scale = (float) options.outHeight / (float) reqHeight;
    }
    else if (reqHeight != 0 && reqWidth != 0)
    {
        float x = (float) options.outWidth / (float) reqWidth;
        float y = (float) options.outHeight / (float) reqHeight;
        scale = x > y ? x : y;
    }
    reqWidth = (int) ((float) options.outWidth / scale);
    reqHeight = (int) ((float) options.outHeight / scale);
    options.inJustDecodeBounds = false;
    Bitmap tmp = BitmapFactory.decodeResource(context.getResources(), resId, options);
    Bitmap out = Bitmap.createScaledBitmap(tmp, reqWidth, reqHeight, false);
    tmp.recycle();
    tmp = null;
    return out;
}

inSampleSize를 사용하기 때문에 더 이상 메모리 문제에 직면하지 않습니다. 그래서 inSampleSize는 저에게 매우 안정적으로 작동합니다. 문제를 다시 확인하는 것이 좋습니다. 크기가 요청한 것과 정확히 일치하지 않을 수 있습니다. 그러나 어쨌든 줄여야하며 더 이상 "메모리 부족"이 없어야합니다. 또한 여기에 코드 스 니펫을 게시하는 것이 좋습니다. 문제가있을 수 있습니다.


As the100rabh said, if you use BitmapFactory you don't really have much choice. However, bitmap decoding is really simple, and depending on the scaling algorithm you want to use, it's usually fairly simple to scale it on-the-fly without having to read large parts of the original bitmap into memory (in general, you'll only need double the memory required for 1-2 lines of the original bitmap).


When inScaled flag is set (by default it is TRUE), if inDensity and inTargetDensity are not 0, the bitmap will be scaled to match inTargetDensity when loaded, rather than relying on the graphics system scaling it each time it is drawn to a Canvas. So simply set the inScaled to false will do.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;

I was able to approximately get the "right size" by rescaling the decoded image file to 70% its bitmap size.

Bitmap myBitmap = BitmapFactory.decodeFile(path);
if(myBitmap != null)
{
  //reduce to 70% size; bitmaps produce larger than actual image size
  Bitmap rescaledMyBitmap = Bitmap.createScaledBitmap(
                                                  myBitmap, 
                                                  myBitmap.getWidth()/10*7, 
                                                  myBitmap.getHeight()/10*7, 
                                                  false);

  image.setImageBitmap(rescaledMyBitmap);
}                

I hope this helps you out somehow! Peace!

참고URL : https://stackoverflow.com/questions/2641726/decoding-bitmaps-in-android-with-the-right-size

반응형