Java image resize, maintain aspect ratio

前端 未结 11 1425
盖世英雄少女心
盖世英雄少女心 2020-11-28 19:38

I have an image which I resize:

if((width != null) || (height != null))
{
    try{
        // scale image on disk
        BufferedImage originalImage = ImageI         


        
相关标签:
11条回答
  • 2020-11-28 19:54

    I have found the selected answer to have problems with upscaling, and so I have made (yet) another version (which I have 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 the 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 讨论(0)
  • 2020-11-28 19:56

    Here's a small piece of code that I wrote, it resizes the image to fit the container while keeping the image's original aspect ratio. It takes in as parameters the container's width, height and the image. You can modify it to fit your needs. It's 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 讨论(0)
  • 2020-11-28 19:59

    Here we go:

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

    Function to return the new size depending on the boundary

    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 anyone also needs the image resizing code, here is a decent solution.

    If you're unsure about the above solution there are different ways to achieve the same result.

    0 讨论(0)
  • 2020-11-28 20:00

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

    0 讨论(0)
  • 2020-11-28 20:00

    Load image:

    BufferedImage bufferedImage = ImageIO.read(file);   
    

    Resize it:

    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 Scalr library:

    <dependency>
        <groupId>org.imgscalr</groupId>
        <artifactId>imgscalr-lib</artifactId>
        <version>4.2</version>
    </dependency>
    
    0 讨论(0)
  • 2020-11-28 20:01

    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);
    
    0 讨论(0)
提交回复
热议问题