如何在Android中调整位图的大小?


336

我从我的远程数据库中获取了一个Base64字符串的位图,(encodedImage是用Base64表示图像的字符串):

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字符串位图。


Answers:


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,则在显示该图像时,它在imageview中将已满。如果我按比例缩小75%,并且屏幕能够在imageview中完全显示按比例缩放的图像,那么此类屏幕应该怎么做?
jxgn

5
createScaledBitmap在我的Galaxy Tab2上抛出了内存不足异常,这对我来说很奇怪,因为内存很大,并且没有其他特定的应用程序在运行。Matrix解决方案虽然有效。
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 2015年

2
感谢您的解决方案,但是最好对参数重新排序;public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight)。我花了很多时间弄清楚它。; P
进攻性的

1
请注意,适用于Matrix的正确导入是android.graphics.Matrix。
列夫

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);

要将高度用作宽度的基本单位,请更改为:

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其视为s新的宽度,而将其设置为“ 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;
    }

对我来说,它工作了一点重新键入浮点extraSizeRatio = width> height吗?(float)((float)width /(float)ScaleSize):(float)((float)height /(float)ScaleSize);
卡萨比(Csabi)2013年

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;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.