Scaled Bitmap maintaining aspect ratio

后端 未结 12 856
-上瘾入骨i
-上瘾入骨i 2020-11-30 23:49

I would like to scale a Bitmap to a runtime dependant width and height, where the aspect ratio is maintained and the Bitmap fills the entire width

相关标签:
12条回答
  • 2020-12-01 00:31

    It can also be done by calculating the ratio yourself, like this.

    private Bitmap scaleBitmap(Bitmap bm) {
        int width = bm.getWidth();
        int height = bm.getHeight();
    
        Log.v("Pictures", "Width and height are " + width + "--" + height);
    
        if (width > height) {
            // landscape
            int ratio = width / maxWidth;
            width = maxWidth;
            height = height / ratio;
        } else if (height > width) {
            // portrait
            int ratio = height / maxHeight;
            height = maxHeight;
            width = width / ratio;
        } else {
            // square
            height = maxHeight;
            width = maxWidth;
        }
    
        Log.v("Pictures", "after scaling Width and height are " + width + "--" + height);
    
        bm = Bitmap.createScaledBitmap(bm, width, height, true);
        return bm;
    }
    
    0 讨论(0)
  • 2020-12-01 00:34

    My solution was this, which maintains aspect ratio, and requires only one size, for example if you have a 1920*1080 and an 1080*1920 image and you want to resize it to 1280, the first will be 1280*720 and the second will be 720*1280

    public static Bitmap resizeBitmap(final Bitmap temp, final int size) {
            if (size > 0) {
                int width = temp.getWidth();
                int height = temp.getHeight();
                float ratioBitmap = (float) width / (float) height;
                int finalWidth = size;
                int finalHeight = size;
                if (ratioBitmap < 1) {
                    finalWidth = (int) ((float) size * ratioBitmap);
                } else {
                    finalHeight = (int) ((float) size / ratioBitmap);
                }
                return Bitmap.createScaledBitmap(temp, finalWidth, finalHeight, true);
            } else {
                return temp;
            }
        }
    
    0 讨论(0)
  • 2020-12-01 00:37

    What about this:

    Bitmap background = Bitmap.createBitmap((int)width, (int)height, Config.ARGB_8888);
    
    float originalWidth = originalImage.getWidth(); 
    float originalHeight = originalImage.getHeight();
    
    Canvas canvas = new Canvas(background);
    
    float scale = width / originalWidth;
    
    float xTranslation = 0.0f;
    float yTranslation = (height - originalHeight * scale) / 2.0f;
    
    Matrix transformation = new Matrix();
    transformation.postTranslate(xTranslation, yTranslation);
    transformation.preScale(scale, scale);
    
    Paint paint = new Paint();
    paint.setFilterBitmap(true);
    
    canvas.drawBitmap(originalImage, transformation, paint);
    
    return background;
    

    I added a paint to filter the scaled bitmap.

    0 讨论(0)
  • 2020-12-01 00:37

    None of the above answers were worked for me and I just created a method which sets all of the dimensions into the desired ones with painting the empty area to black. Here is my method:

    /**
     * Scale the image preserving the ratio
     * @param imageToScale Image to be scaled
     * @param destinationWidth Destination width after scaling
     * @param destinationHeight Destination height after scaling
     * @return New scaled bitmap preserving the ratio
     */
    public static Bitmap scalePreserveRatio(Bitmap imageToScale, int destinationWidth,
            int destinationHeight) {
        if (destinationHeight > 0 && destinationWidth > 0 && imageToScale != null) {
            int width = imageToScale.getWidth();
            int height = imageToScale.getHeight();
    
            //Calculate the max changing amount and decide which dimension to use
            float widthRatio = (float) destinationWidth / (float) width;
            float heightRatio = (float) destinationHeight / (float) height;
    
            //Use the ratio that will fit the image into the desired sizes
            int finalWidth = (int)Math.floor(width * widthRatio);
            int finalHeight = (int)Math.floor(height * widthRatio);
            if (finalWidth > destinationWidth || finalHeight > destinationHeight) {
                finalWidth = (int)Math.floor(width * heightRatio);
                finalHeight = (int)Math.floor(height * heightRatio);
            }
    
            //Scale given bitmap to fit into the desired area
            imageToScale = Bitmap.createScaledBitmap(imageToScale, finalWidth, finalHeight, true);
    
            //Created a bitmap with desired sizes
            Bitmap scaledImage = Bitmap.createBitmap(destinationWidth, destinationHeight, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(scaledImage);
    
            //Draw background color
            Paint paint = new Paint();
            paint.setColor(Color.BLACK);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
    
            //Calculate the ratios and decide which part will have empty areas (width or height)
            float ratioBitmap = (float)finalWidth / (float)finalHeight;
            float destinationRatio = (float) destinationWidth / (float) destinationHeight;
            float left = ratioBitmap >= destinationRatio ? 0 : (float)(destinationWidth - finalWidth) / 2;
            float top = ratioBitmap < destinationRatio ? 0: (float)(destinationHeight - finalHeight) / 2;
            canvas.drawBitmap(imageToScale, left, top, null);
    
            return scaledImage;
        } else {
            return imageToScale;
        }
    }
    

    For example;

    Let's say you have an image as 100 x 100 but the desired size is 300x50, then this method will convert your image to 50 x 50 and paint it into a new image which has dimensions as 300 x 50 (and empty fileds will be black).

    Another example: let's say you have an image as 600 x 1000 and the desired sizes are 300 x 50 again, then your image will be converted into 30 x 50 and painted into a newly created image which has sizes as 300 x 50.

    I think this is what it must be, Rs.

    0 讨论(0)
  • 2020-12-01 00:38

    This is an awesome library from ArthurHub to handle the image crops both programmatically and interactively if you don't want to reinvent the wheel.

    But if you prefer a non bloated version like me.., the internal function shown here is a rather sophisticated to perform Image Scaling with few standard options

    /**
     * Resize the given bitmap to the given width/height by the given option.<br>
     */
    
    enum RequestSizeOptions {
        RESIZE_FIT,
        RESIZE_INSIDE,
        RESIZE_EXACT
    }
    
    static Bitmap resizeBitmap(Bitmap bitmap, int reqWidth, int reqHeight, RequestSizeOptions options) {
        try {
            if (reqWidth > 0 && reqHeight > 0 && (options == RequestSizeOptions.RESIZE_FIT ||
                    options == RequestSizeOptions.RESIZE_INSIDE ||
                    options == RequestSizeOptions.RESIZE_EXACT)) {
    
                Bitmap resized = null;
                if (options == RequestSizeOptions.RESIZE_EXACT) {
                    resized = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, false);
                } else {
                    int width = bitmap.getWidth();
                    int height = bitmap.getHeight();
                    float scale = Math.max(width / (float) reqWidth, height / (float) reqHeight);
                    if (scale > 1 || options == RequestSizeOptions.RESIZE_FIT) {
                        resized = Bitmap.createScaledBitmap(bitmap, (int) (width / scale), (int) (height / scale), false);
                    }
                }
                if (resized != null) {
                    if (resized != bitmap) {
                        bitmap.recycle();
                    }
                    return resized;
                }
            }
        } catch (Exception e) {
            Log.w("AIC", "Failed to resize cropped image, return bitmap before resize", e);
        }
        return bitmap;
    }
    
    0 讨论(0)
  • 2020-12-01 00:42

    Added RESIZE_CROP to Gowrav's answer.

       enum RequestSizeOptions {
        RESIZE_FIT,
        RESIZE_INSIDE,
        RESIZE_EXACT,
        RESIZE_CENTRE_CROP
    }
    static Bitmap resizeBitmap(Bitmap bitmap, int reqWidth, int reqHeight, RequestSizeOptions options) {
        try {
            if (reqWidth > 0 && reqHeight > 0 && (options == RequestSizeOptions.RESIZE_FIT ||
                    options == RequestSizeOptions.RESIZE_INSIDE ||
                    options == RequestSizeOptions.RESIZE_EXACT || options == RequestSizeOptions.RESIZE_CENTRE_CROP)) {
    
                Bitmap resized = null;
                if (options == RequestSizeOptions.RESIZE_EXACT) {
                    resized = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, false);
                } else {
                    int width = bitmap.getWidth();
                    int height = bitmap.getHeight();
                    float scale = Math.max(width / (float) reqWidth, height / (float) reqHeight);
                    if (scale > 1 || options == RequestSizeOptions.RESIZE_FIT) {
                        resized = Bitmap.createScaledBitmap(bitmap, (int) (width / scale), (int) (height / scale), false);
                    }
                    if (scale > 1 || options == RequestSizeOptions.RESIZE_CENTRE_CROP) {
                        int smaller_side = (height-width)>0?width:height;
                        int half_smaller_side = smaller_side/2;
                        Rect initialRect = new Rect(0,0,width,height);
                        Rect finalRect = new Rect(initialRect.centerX()-half_smaller_side,initialRect.centerY()-half_smaller_side,
                                initialRect.centerX()+half_smaller_side,initialRect.centerY()+half_smaller_side);
                        bitmap = Bitmap.createBitmap(bitmap,  finalRect.left, finalRect.top, finalRect.width(), finalRect.height(), null, true);
                        //keep in mind we have square as request for cropping, otherwise - it is useless
                        resized = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, false);
                    }
    
                }
                if (resized != null) {
                    if (resized != bitmap) {
                        bitmap.recycle();
                    }
                    return resized;
                }
            }
        } catch (Exception e) {
            Log.w("AIC", "Failed to resize cropped image, return bitmap before resize", e);
        }
        return bitmap;
    }
    
    0 讨论(0)
提交回复
热议问题