Image resizing in Java, maintaining aspect ratio

I have an image that I am resizing:

if((width != null) || (height != null)) { try{ // scale image on disk BufferedImage originalImage = ImageIO.read(file); int type = originalImage.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImage.getType(); BufferedImage resizeImageJpg = resizeImage(originalImage, type, 200, 200); ImageIO.write(resizeImageJpg, "jpg", file); } catch(IOException e) { System.out.println(e.getMessage()); } } 

This is how I resize the image:

 private static BufferedImage resizeImage(BufferedImage originalImage, int type, Integer img_width, Integer img_height) { BufferedImage resizedImage = new BufferedImage(img_width, img_height, type); Graphics2D g = resizedImage.createGraphics(); g.drawImage(originalImage, 0, 0, img_width, img_height, null); g.dispose(); return resizedImage; } 

Now the problem is that I also need to maintain aspect ratio. That is, I need the new 200/200 image to contain the new scaled image. More or less like this: enter image description here

I tried some things, but they did not work as expected. Any help is appreciated. Thank you very much.

+62
java image
Apr 20 '12 at 11:20
source share
11 answers

Here we go:

 Dimension imgSize = new Dimension(500, 100); Dimension boundary = new Dimension(200, 200); 

Function to return a new size depending on the border

 public static Dimension getScaledDimension(Dimension imgSize, Dimension boundary) { int original_width = imgSize.width; int original_height = imgSize.height; int bound_width = boundary.width; int bound_height = boundary.height; int new_width = original_width; int new_height = original_height; // first check if we need to scale width if (original_width > bound_width) { //scale width to fit new_width = bound_width; //scale height to maintain aspect ratio new_height = (new_width * original_height) / original_width; } // then check if we need to scale even with the new height if (new_height > bound_height) { //scale height to fit instead new_height = bound_height; //scale width to maintain aspect ratio new_width = (new_height * original_width) / original_height; } return new Dimension(new_width, new_height); } 

In case someone also needs an image resizing code, here is a decent solution .

If you are not sure about the above solution, there are different ways to achieve the same result.

+91
Apr 20 2018-12-12T00:
source share

Translated from here :

 Dimension getScaledDimension(Dimension imageSize, Dimension boundary) { double widthRatio = boundary.getWidth() / imageSize.getWidth(); double heightRatio = boundary.getHeight() / imageSize.getHeight(); double ratio = Math.min(widthRatio, heightRatio); return new Dimension((int) (imageSize.width * ratio), (int) (imageSize.height * ratio)); } 

You can also use imgscalr to resize images while maintaining aspect ratio:

 BufferedImage resizeMe = ImageIO.read(new File("orig.jpg")); Dimension newMaxSize = new Dimension(255, 255); BufferedImage resizedImg = Scalr.resize(resizeMe, Method.QUALITY, newMaxSize.width, newMaxSize.height); 
+10
Sep 20 '15 at 12:09
source share

You need to check Image.getScaledInstance () and much more in this answer: How to improve the performance of the g.drawImage () method for resizing images

+5
Apr 20 2018-12-12T00:
source share

try it

 float rateX = (float)jpDisplayImagen.getWidth()/(float)img.getWidth(); float rateY = (float)jpDisplayImagen.getHeight()/(float)img.getHeight(); if (rateX>rateY){ int W=(int)(img.getWidth()*rateY); int H=(int)(img.getHeight()*rateY); jpDisplayImagen.getGraphics().drawImage(img, 0, 0,W,H, null); } else{ int W=(int)(img.getWidth()*rateX); int H=(int)(img.getHeight()*rateX); jpDisplayImagen.getGraphics().drawImage(img, 0, 0,W,H, null); } 
+1
Nov 27 '13 at 3:32
source share

Upload image:

 BufferedImage bufferedImage = ImageIO.read(file); 

Change its size:

 private BufferedImage resizeAndCrop(BufferedImage bufferedImage, Integer width, Integer height) { Mode mode = (double) width / (double) height >= (double) bufferedImage.getWidth() / (double) bufferedImage.getHeight() ? Scalr.Mode.FIT_TO_WIDTH : Scalr.Mode.FIT_TO_HEIGHT; bufferedImage = Scalr.resize(bufferedImage, Scalr.Method.ULTRA_QUALITY, mode, width, height); int x = 0; int y = 0; if (mode == Scalr.Mode.FIT_TO_WIDTH) { y = (bufferedImage.getHeight() - height) / 2; } else if (mode == Scalr.Mode.FIT_TO_HEIGHT) { x = (bufferedImage.getWidth() - width) / 2; } bufferedImage = Scalr.crop(bufferedImage, x, y, width, height); return bufferedImage; } 

Using the Scalr library:

 <dependency> <groupId>org.imgscalr</groupId> <artifactId>imgscalr-lib</artifactId> <version>4.2</version> </dependency> 
+1
Jan 12 '17 at 9:14 on
source share
 public class ImageTransformation { public static final String PNG = "png"; public static byte[] resize(FileItem fileItem, int width, int height) { try { ResampleOp resampleOp = new ResampleOp(width, height); BufferedImage scaledImage = resampleOp.filter(ImageIO.read(fileItem.getInputStream()), null); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(scaledImage, PNG, baos); return baos.toByteArray(); } catch (Exception ex) { throw new MapsException("An error occured during image resizing.", ex); } } public static byte[] resizeAdjustMax(FileItem fileItem, int maxWidth, int maxHeight) { try { BufferedInputStream bis = new BufferedInputStream(fileItem.getInputStream()); BufferedImage bufimg = ImageIO.read(bis); //check size of image int img_width = bufimg.getWidth(); int img_height = bufimg.getHeight(); if(img_width > maxWidth || img_height > maxHeight) { float factx = (float) img_width / maxWidth; float facty = (float) img_height / maxHeight; float fact = (factx>facty) ? factx : facty; img_width = (int) ((int) img_width / fact); img_height = (int) ((int) img_height / fact); } return resize(fileItem,img_width, img_height); } catch (Exception ex) { throw new MapsException("An error occured during image resizing.", ex); } } 

}

0
Sep 07 '15 at 7:15
source share

This is my decision:

 /* Change dimension of Image */ public static Image resizeImage(Image image, int scaledWidth, int scaledHeight, boolean preserveRatio) { if (preserveRatio) { double imageHeight = image.getHeight(); double imageWidth = image.getWidth(); if (imageHeight/scaledHeight > imageWidth/scaledWidth) { scaledWidth = (int) (scaledHeight * imageWidth / imageHeight); } else { scaledHeight = (int) (scaledWidth * imageHeight / imageWidth); } } BufferedImage inputBufImage = SwingFXUtils.fromFXImage(image, null); // creates output image BufferedImage outputBufImage = new BufferedImage(scaledWidth, scaledHeight, inputBufImage.getType()); // scales the input image to the output image Graphics2D g2d = outputBufImage.createGraphics(); g2d.drawImage(inputBufImage, 0, 0, scaledWidth, scaledHeight, null); g2d.dispose(); return SwingFXUtils.toFXImage(outputBufImage, null); } 
0
Mar 30 '16 at 11:04
source share

All the other answers show how to calculate the new height of the image depending on the width of the new image or vice versa and how to resize the image using the Java Image API. For those people who are looking for a direct solution, I recommend any java image processing infrastructure that can do this on one line.

The following is an example of the Marvin Framework :

 // 300 is the new width. The height is calculated to maintain aspect. scale(image.clone(), image, 300); 

Import Required:

 import static marvin.MarvinPluginCollection.* 
0
Aug 26 '16 at 13:16
source share

I found the selected answer to have problems with scaling, and so I made (yet) another version (which I tested):

 public static Point scaleFit(Point src, Point bounds) { int newWidth = src.x; int newHeight = src.y; double boundsAspectRatio = bounds.y / (double) bounds.x; double srcAspectRatio = src.y / (double) src.x; // first check if we need to scale width if (boundsAspectRatio < srcAspectRatio) { // scale width to fit newWidth = bounds.x; //scale height to maintain aspect ratio newHeight = (newWidth * src.y) / src.x; } else { //scale height to fit instead newHeight = bounds.y; //scale width to maintain aspect ratio newWidth = (newHeight * src.x) / src.y; } return new Point(newWidth, newHeight); } 

Written in Android terminology :-)

as for tests:

 @Test public void scaleFit() throws Exception { final Point displaySize = new Point(1080, 1920); assertEquals(displaySize, Util.scaleFit(displaySize, displaySize)); assertEquals(displaySize, Util.scaleFit(new Point(displaySize.x / 2, displaySize.y / 2), displaySize)); assertEquals(displaySize, Util.scaleFit(new Point(displaySize.x * 2, displaySize.y * 2), displaySize)); assertEquals(new Point(displaySize.x, displaySize.y * 2), Util.scaleFit(new Point(displaySize.x / 2, displaySize.y), displaySize)); assertEquals(new Point(displaySize.x * 2, displaySize.y), Util.scaleFit(new Point(displaySize.x, displaySize.y / 2), displaySize)); assertEquals(new Point(displaySize.x, displaySize.y * 3 / 2), Util.scaleFit(new Point(displaySize.x / 3, displaySize.y / 2), displaySize)); } 
0
Aug 27 '17 at 7:13
source share

Here is a small piece of code that I wrote, it resizes the image to fit the container, while preserving the original aspect ratio of the image. It takes as parameters the width of the container, height and image. You can change it according to your needs. This is simple and works fine for my applications.

 private Image scaleimage(int wid, int hei, BufferedImage img){ Image im = img; double scale; double imw = img.getWidth(); double imh = img.getHeight(); if (wid > imw && hei > imh){ im = img; }else if(wid/imw < hei/imh){ scale = wid/imw; im = img.getScaledInstance((int) (scale*imw), (int) (scale*imh), Image.SCALE_SMOOTH); }else if (wid/imw > hei/imh){ scale = hei/imh; im = img.getScaledInstance((int) (scale*imw), (int) (scale*imh), Image.SCALE_SMOOTH); }else if (wid/imw == hei/imh){ scale = wid/imw; im = img.getScaledInstance((int) (scale*imw), (int) (scale*imh), Image.SCALE_SMOOTH); } return im; } 
0
Dec 31 '19 at 6:14
source share

Just add another block to your Ozzy code to make it look like this:

 public static Dimension getScaledDimension(Dimension imgSize,Dimension boundary) { int original_width = imgSize.width; int original_height = imgSize.height; int bound_width = boundary.width; int bound_height = boundary.height; int new_width = original_width; int new_height = original_height; // first check if we need to scale width if (original_width > bound_width) { //scale width to fit new_width = bound_width; //scale height to maintain aspect ratio new_height = (new_width * original_height) / original_width; } // then check if we need to scale even with the new height if (new_height > bound_height) { //scale height to fit instead new_height = bound_height; //scale width to maintain aspect ratio new_width = (new_height * original_width) / original_height; } // upscale if original is smaller if (original_width < bound_width) { //scale width to fit new_width = bound_width; //scale height to maintain aspect ratio new_height = (new_width * original_height) / original_width; } return new Dimension(new_width, new_height); } 
-one
Mar 23 '16 at 3:10
source share



All Articles