Resizing a bitmap to a fixed value but without changing the aspect ratio
Try this, calculate the ratio and then rescale.
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 float ratio = (float) width / maxWidth; width = maxWidth; height = (int)(height / ratio); } else if (height > width) { // portrait float ratio = (float) height / maxHeight; height = maxHeight; width = (int)(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;}
The answer by Coen Damen doesn't always respect Max Height and Max Width.Here's an answer that does:
private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) { if (maxHeight > 0 && maxWidth > 0) { int width = image.getWidth(); int height = image.getHeight(); float ratioBitmap = (float) width / (float) height; float ratioMax = (float) maxWidth / (float) maxHeight; int finalWidth = maxWidth; int finalHeight = maxHeight; if (ratioMax > 1) { finalWidth = (int) ((float)maxHeight * ratioBitmap); } else { finalHeight = (int) ((float)maxWidth / ratioBitmap); } image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true); return image; } else { return image; }}
I have stumbled upon the same problem a number of times in my projects and each time due to lack of time (and laziness) I would be satisfied with a less than optimum solution. But recently I found some time to crack down this particular issue. Here is my solution and I hope it helps someone down the line.
Bitmap scaleDownLargeImageWithAspectRatio(Bitmap image) { int imageVerticalAspectRatio,imageHorizontalAspectRatio; float bestFitScalingFactor=0; float percesionValue=(float) 0.2; //getAspect Ratio of Image int imageHeight=(int) (Math.ceil((double) image.getHeight()/100)*100); int imageWidth=(int) (Math.ceil((double) image.getWidth()/100)*100); int GCD=BigInteger.valueOf(imageHeight).gcd(BigInteger.valueOf(imageWidth)).intValue(); imageVerticalAspectRatio=imageHeight/GCD; imageHorizontalAspectRatio=imageWidth/GCD; Log.i("scaleDownLargeImageWIthAspectRatio","Image Dimensions(W:H): "+imageWidth+":"+imageHeight); Log.i("scaleDownLargeImageWIthAspectRatio","Image AspectRatio(W:H): "+imageHorizontalAspectRatio+":"+imageVerticalAspectRatio); //getContainer Dimensions int displayWidth = getWindowManager().getDefaultDisplay().getWidth(); int displayHeight = getWindowManager().getDefaultDisplay().getHeight(); //I wanted to show the image to fit the entire device, as a best case. So my ccontainer dimensions were displayWidth & displayHeight. For your case, you will need to fetch container dimensions at run time or you can pass static values to these two parameters int leftMargin = 0; int rightMargin = 0; int topMargin = 0; int bottomMargin = 0; int containerWidth = displayWidth - (leftMargin + rightMargin); int containerHeight = displayHeight - (topMargin + bottomMargin); Log.i("scaleDownLargeImageWIthAspectRatio","Container dimensions(W:H): "+containerWidth+":"+containerHeight); //iterate to get bestFitScaleFactor per constraints while((imageHorizontalAspectRatio*bestFitScalingFactor <= containerWidth) && (imageVerticalAspectRatio*bestFitScalingFactor<= containerHeight)) { bestFitScalingFactor+=percesionValue; } //return bestFit bitmap int bestFitHeight=(int) (imageVerticalAspectRatio*bestFitScalingFactor); int bestFitWidth=(int) (imageHorizontalAspectRatio*bestFitScalingFactor); Log.i("scaleDownLargeImageWIthAspectRatio","bestFitScalingFactor: "+bestFitScalingFactor); Log.i("scaleDownLargeImageWIthAspectRatio","bestFitOutPutDimesions(W:H): "+bestFitWidth+":"+bestFitHeight); image=Bitmap.createScaledBitmap(image, bestFitWidth,bestFitHeight, true); //Position the bitmap centre of the container int leftPadding=(containerWidth-image.getWidth())/2; int topPadding=(containerHeight-image.getHeight())/2; Bitmap backDrop=Bitmap.createBitmap(containerWidth, containerHeight, Bitmap.Config.RGB_565); Canvas can = new Canvas(backDrop); can.drawBitmap(image, leftPadding, topPadding, null); return backDrop; }