안드로이드에서 비트 맵의 ​​크기를 조정하는 방법?


336

원격 데이터베이스에서 Base64 문자열의 비트 맵을 가져 왔습니다 ( encodedImageBase64로 이미지를 나타내는 문자열 임).

profileImage = (ImageView)findViewById(R.id.profileImage);

byte[] imageAsBytes=null;
try {
    imageAsBytes = Base64.decode(encodedImage.getBytes());
} catch (IOException e) {e.printStackTrace();}

profileImage.setImageBitmap(
    BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
);

profileImage는 내 ImageView입니다

좋아,하지만 ImageView내 레이아웃 에 표시하기 전에이 이미지의 크기를 조정해야 합니다. 120x120으로 크기를 조정해야합니다.

누군가 크기를 조정하는 코드를 말해 줄 수 있습니까?

내가 찾은 예제는 얻은 base64 문자열에 비트 맵을 적용 할 수 없습니다.


답변:


550

변화:

profileImage.setImageBitmap(
    BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)

에:

Bitmap b = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
profileImage.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));

1200x1200과 같은 큰 해상도 이미지가 있다고 가정하고 이미지를 표시하면 이미지가 가득 찼습니다. 이미지 크기를 75 %로 낮추고 화면이 이미지보기에 크기가 조정 된 이미지를 완전히 표시 할 수 있도록하려면 해당 화면에 대해 어떻게해야합니까?
— jxgn

5
createScaledBitmap은 Galaxy Tab2에서 메모리 부족 예외를 발생시킵니다. 메모리가 많고 다른 특정 앱이 실행되고 있지 않기 때문에 매우 이상합니다. 매트릭스 솔루션은 작동합니다.
— Ludovic

28
종횡비를 저장하려면 어떻게해야합니까 ??
— 버그는

3
이것에 대한 dpi 스케일링은 어떻습니까? 스케일 된 비트 맵은 장치 화면 높이와 너비를 기반으로해야한다고 생각합니까?
— Doug Ray

2
Bitmap.createScaledBitmap ()을 사용하여 이미지를 원래 크기의 절반 이상으로 축소하면 앨리어싱 아티팩트가 생성 될 수 있습니다. 내가 대안을 제안하고 품질과 성능을 비교 하는 필자가 작성한 게시물을 살펴볼 수 있습니다 .
— Petrakeas

288
import android.graphics.Matrix
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
    int width = bm.getWidth();
    int height = bm.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    // CREATE A MATRIX FOR THE MANIPULATION
    Matrix matrix = new Matrix();
    // RESIZE THE BIT MAP
    matrix.postScale(scaleWidth, scaleHeight);

    // "RECREATE" THE NEW BITMAP
    Bitmap resizedBitmap = Bitmap.createBitmap(
        bm, 0, 0, width, height, matrix, false);
    bm.recycle();
    return resizedBitmap;
}

편집 : @aveschini가 제안한대로 bm.recycle();메모리 누수를 추가 했습니다. 다른 목적으로 이전 개체를 사용하는 경우 적절하게 처리하십시오.


6
bitmap.createscaledbitmap 과이 매트릭스 접근법을 모두 시도했습니다. 매트릭스 접근 방식으로 이미지가 훨씬 명확하다는 것을 알았습니다. 그것이 일반적인지 또는 전화 대신 시뮬레이터를 사용하고 있기 때문에 모르겠습니다. 나와 같은 문제를 일으키는 사람을위한 힌트.
— Anson Yao

2
더 나은 메모리 성능을 위해 bm.recycle ()을 추가해야합니다
— aveschini

2
솔루션에 감사하지만 매개 변수를 다시 정렬하면 더 좋습니다. public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight). 나는 그것을 알아내는 데 시간을 낭비했다. ; P
— Attacktive

1
Matrix의 올바른 가져 오기는 android.graphics.Matrix입니다.
— Lev

11
이것은 Bitmap.createScaledBitmap () 호출과 동일합니다. 참조 android.googlesource.com/platform/frameworks/base/+/refs/heads/...
— BamsBamx

122

비트 맵이 이미있는 경우 다음 코드를 사용하여 크기를 조정할 수 있습니다.

Bitmap originalBitmap = <original initialization>;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(
    originalBitmap, newWidth, newHeight, false);

1
@beginner 이미지의 크기를 조정하면 비트 맵을 잘못된 비율로 변환하거나 일부 비트 맵 정보를 제거하는 다른 차원을 기준으로 크기를 조정할 수 있습니다.
— ZenBalance

비례에 따라 비트 맵의 ​​크기를 조정하려고 시도했지만이 오류가 발생했습니다. 원인 : java.lang.RuntimeException : 캔버스 : 재활용 비트 맵을 사용하려고합니다 android.graphics.Bitmap@2291dd13
— 초보자

@beginner는 비트 맵의 ​​크기를 조정할 때마다 수행중인 작업에 따라 기존 비트 맵의 ​​크기를 조정하는 대신 새로운 크기의 사본을 만들어야합니다 (이 경우 비트 맵에 대한 참조처럼 보입니다) 이미 메모리에서 재활용되었습니다).
— ZenBalance

1
올바른 .. 나는 그것을 시도하고 지금 제대로 작동합니다. 고마워
— 초보자

39

종횡비 에 따른 스케일 :

float aspectRatio = yourSelectedImage.getWidth() / 
    (float) yourSelectedImage.getHeight();
int width = 480;
int height = Math.round(width / aspectRatio);

yourSelectedImage = Bitmap.createScaledBitmap(
    yourSelectedImage, width, height, false);

너비의 기본 intead로 높이를 사용하려면 다음으로 변경하십시오.

int height = 480;
int width = Math.round(height * aspectRatio);

24

종횡비를 유지하면서 대상 최대 크기 및 너비로 비트 맵을 스케일링하십시오.

int maxHeight = 2000;
int maxWidth = 2000;    
float scale = Math.min(((float)maxHeight / bitmap.getWidth()), ((float)maxWidth / bitmap.getHeight()));

Matrix matrix = new Matrix();
matrix.postScale(scale, scale);

bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);

7

이 코드를 사용해보십시오 :

BitmapDrawable drawable = (BitmapDrawable) imgview.getDrawable();
Bitmap bmp = drawable.getBitmap();
Bitmap b = Bitmap.createScaledBitmap(bmp, 120, 120, false);

도움이 되길 바랍니다.


7

이 상황에서 가로 세로 비율을 유지하는 방법을 누군가가 물었습니다.

스케일링에 사용중인 요인을 계산하고 두 차원 모두에 사용하십시오. 이미지의 높이가 화면의 20 %가 되길 원한다고하자

int scaleToUse = 20; // this will be our percentage
Bitmap bmp = BitmapFactory.decodeResource(
    context.getResources(), R.drawable.mypng);
int sizeY = screenResolution.y * scaleToUse / 100;
int sizeX = bmp.getWidth() * sizeY / bmp.getHeight();
Bitmap scaled = Bitmap.createScaledBitmap(bmp, sizeX, sizeY, false);

화면 해상도를 얻는 방법은 다음과 같습니다. 화면 크기를 픽셀 단위 로 가져옵니다.


3

이것을보십시오 :이 함수는 비례 적으로 비트 맵의 ​​크기를 조정합니다. 마지막 매개 변수가 "X" newDimensionXorY로 설정되면 새 너비로 처리되고 "Y"로 설정되면 새 높이로 처리됩니다.

public Bitmap getProportionalBitmap(Bitmap bitmap, 
                                    int newDimensionXorY, 
                                    String XorY) {
    if (bitmap == null) {
        return null;
    }

    float xyRatio = 0;
    int newWidth = 0;
    int newHeight = 0;

    if (XorY.toLowerCase().equals("x")) {
        xyRatio = (float) newDimensionXorY / bitmap.getWidth();
        newHeight = (int) (bitmap.getHeight() * xyRatio);
        bitmap = Bitmap.createScaledBitmap(
            bitmap, newDimensionXorY, newHeight, true);
    } else if (XorY.toLowerCase().equals("y")) {
        xyRatio = (float) newDimensionXorY / bitmap.getHeight();
        newWidth = (int) (bitmap.getWidth() * xyRatio);
        bitmap = Bitmap.createScaledBitmap(
            bitmap, newWidth, newDimensionXorY, true);
    }
    return bitmap;
}

3
profileImage.setImageBitmap(
    Bitmap.createScaledBitmap(
        BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length), 
        80, 80, false
    )
);

3
  public Bitmap scaleBitmap(Bitmap mBitmap) {
        int ScaleSize = 250;//max Height or width to Scale
        int width = mBitmap.getWidth();
        int height = mBitmap.getHeight();
        float excessSizeRatio = width > height ? width / ScaleSize : height / ScaleSize;
         Bitmap bitmap = Bitmap.createBitmap(
                mBitmap, 0, 0,(int) (width/excessSizeRatio),(int) (height/excessSizeRatio));
        //mBitmap.recycle(); if you are not using mBitmap Obj
        return bitmap;
    }

나를 위해 그것은 float reSizeping overflowSizeRatio = width> height 후에 작동했습니다. (float) ((float) width / (float) ScaleSize) : (float) ((float) height / (float) ScaleSize) ;;
— Csabi

3
public static Bitmap resizeBitmapByScale(
            Bitmap bitmap, float scale, boolean recycle) {
        int width = Math.round(bitmap.getWidth() * scale);
        int height = Math.round(bitmap.getHeight() * scale);
        if (width == bitmap.getWidth()
                && height == bitmap.getHeight()) return bitmap;
        Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap));
        Canvas canvas = new Canvas(target);
        canvas.scale(scale, scale);
        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
        canvas.drawBitmap(bitmap, 0, 0, paint);
        if (recycle) bitmap.recycle();
        return target;
    }
    private static Bitmap.Config getConfig(Bitmap bitmap) {
        Bitmap.Config config = bitmap.getConfig();
        if (config == null) {
            config = Bitmap.Config.ARGB_8888;
        }
        return config;
    }


2

모든 디스플레이 크기에 따른 비트 맵 크기 조정

public Bitmap bitmapResize(Bitmap imageBitmap) {

    Bitmap bitmap = imageBitmap;
    float heightbmp = bitmap.getHeight();
    float widthbmp = bitmap.getWidth();

    // Get Screen width
    DisplayMetrics displaymetrics = new DisplayMetrics();
    this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
    float height = displaymetrics.heightPixels / 3;
    float width = displaymetrics.widthPixels / 3;

    int convertHeight = (int) hight, convertWidth = (int) width;

    // higher
    if (heightbmp > height) {
        convertHeight = (int) height - 20;
        bitmap = Bitmap.createScaledBitmap(bitmap, convertWidth,
                convertHighet, true);
    }

    // wider
    if (widthbmp > width) {
        convertWidth = (int) width - 20;
        bitmap = Bitmap.createScaledBitmap(bitmap, convertWidth,
                convertHeight, true);
    }

    return bitmap;
}

1

허용되는 답변은 맞지만 Bitmap동일한 가로 세로 비율 을 유지하여 크기를 조정하지는 않습니다 . Bitmap동일한 종횡비를 유지하여 크기를 조정하는 방법을 찾고 있다면 다음 유틸리티 기능을 사용할 수 있습니다. 기능에 대한 사용법과 설명은 이 링크에 있습니다.

public static Bitmap resizeBitmap(Bitmap source, int maxLength) {
       try {
           if (source.getHeight() >= source.getWidth()) {
               int targetHeight = maxLength;
               if (source.getHeight() <= targetHeight) { // if image already smaller than the required height
                   return source;
               }

               double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
               int targetWidth = (int) (targetHeight * aspectRatio);

               Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
               if (result != source) {
               }
               return result;
           } else {
               int targetWidth = maxLength;

               if (source.getWidth() <= targetWidth) { // if image already smaller than the required height
                   return source;
               }

               double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
               int targetHeight = (int) (targetWidth * aspectRatio);

               Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
               if (result != source) {
               }
               return result;

           }
       }
       catch (Exception e)
       {
           return source;
       }
   }

0
/**
 * Kotlin method for Bitmap scaling
 * @param bitmap the bitmap to be scaled
 * @param pixel  the target pixel size
 * @param width  the width
 * @param height the height
 * @param max    the max(height, width)
 * @return the scaled bitmap
 */
fun scaleBitmap(bitmap:Bitmap, pixel:Float, width:Int, height:Int, max:Int):Bitmap {
    val scale = px / max
    val h = Math.round(scale * height)
    val w = Math.round(scale * width)
    return Bitmap.createScaledBitmap(bitmap, w, h, true)
  }

0

종횡비를 유지하면서

  public Bitmap resizeBitmap(Bitmap source, int width,int height) {
    if(source.getHeight() == height && source.getWidth() == width) return source;
    int maxLength=Math.min(width,height);
    try {
        source=source.copy(source.getConfig(),true);
        if (source.getHeight() <= source.getWidth()) {
            if (source.getHeight() <= maxLength) { // if image already smaller than the required height
                return source;
            }

            double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
            int targetWidth = (int) (maxLength * aspectRatio);

            return Bitmap.createScaledBitmap(source, targetWidth, maxLength, false);
        } else {

            if (source.getWidth() <= maxLength) { // if image already smaller than the required height
                return source;
            }

            double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
            int targetHeight = (int) (maxLength * aspectRatio);

            return Bitmap.createScaledBitmap(source, maxLength, targetHeight, false);

        }
    }
    catch (Exception e)
    {
        return source;
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.