1

The image size desire:

private static final int WIDTH = 640;
private static final int HEIGHT = 480;

Main method for scalling:

    public byte[] getScaledCustomImageByteArray(byte[] imageBytes, int width, int height) throws IOException {
      if (imageBytes == null) {
        return null; //NOSONAR
      }
      try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
           ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(imageBytes)) {
        BufferedImage before = ImageIO.read(byteArrayInputStream);
        if (before == null) {
          throw new ImageProcessingException("ByteArray is not an image!");
        }
        BufferedImage after = getScaledInstance(before, width, height);
        ImageIO.write(after, "png", byteArrayOutputStream);
        byteArrayOutputStream.flush();
        return byteArrayOutputStream.toByteArray();
      }
  }

This method works properly, it scale keeping the ratio.

    private Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
      int originalWidth = imgSize.width;
      int originalHeight = imgSize.height;
      int boundWidth = boundary.width;
      int boundHeight = boundary.height;
      int newWidth = originalWidth;
      int newHeight = originalHeight;
      if (originalWidth > boundWidth) {
        newWidth = boundWidth;
        newHeight = (newWidth * originalHeight) / originalWidth;
      }
      if (newHeight > boundHeight) {
        newHeight = boundHeight;
        newWidth = (newHeight * originalWidth) / originalHeight;
      }
      return new Dimension(newWidth, newHeight);
  }

Here is where I do not understand properly what is the problem when resizing the image.

    private BufferedImage getScaledInstance(BufferedImage image, int maxWidth, int maxHeight) {
      int width = image.getWidth();
      int height = image.getHeight();
    // if the image is already scaled, no further scaling is needed
      if (width <= maxWidth && height <= maxHeight) {
        return image;
      }

      int type = (image.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : 
  BufferedImage.TYPE_INT_ARGB;
      BufferedImage result = image;
      BufferedImage scratchImage = null;
      Graphics2D graphics2D = null;
      int prevWidth = result.getWidth();
      int prevHeight = result.getHeight();
      Dimension targetDimensions = getScaledDimension(new Dimension(image.getWidth(), 
            image.getHeight()), new Dimension(maxWidth, maxHeight));
      int targetWidth = (int) targetDimensions.getWidth();
      int targetHeight = (int) targetDimensions.getHeight();
      do {
        if (width > targetWidth) {
          width /= 2;
          if (width < targetWidth) {
            width = targetWidth;
          }
        }

        if (height > targetHeight) {
          height /= 2;
          if (height < targetHeight) {
            height = targetHeight;
          }
        }
        if (scratchImage == null) {
          scratchImage = new BufferedImage(width, height, type);
          graphics2D = scratchImage.createGraphics();
          graphics2D.setComposite(AlphaComposite.Clear);
          graphics2D.fillRect(0, 0, width, height);
        }
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
                                  RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.setComposite(AlphaComposite.Src);
        graphics2D.drawImage(result, 0, 0, width, height, 0, 0, prevWidth, prevHeight, null);
        prevWidth = width;
        prevHeight = height;
        result = scratchImage;
      } while (width != targetWidth || height != targetHeight);
      graphics2D.dispose();
      if (targetWidth != result.getWidth() || targetHeight != result.getHeight()) {
        scratchImage = new BufferedImage(targetWidth, targetHeight, type);
        graphics2D = scratchImage.createGraphics();
        graphics2D.setComposite(AlphaComposite.Clear);
        graphics2D.fillRect(0, 0, targetWidth, targetHeight);
        graphics2D.setComposite(AlphaComposite.Src);
        graphics2D.drawImage(result, 0, 0, null);
        graphics2D.dispose();
        result = scratchImage;
      }
      return result;
  }

Google width 1856pixels && hegiht 886pixel I have this issue enter image description here enter image description here

But when the image it is width 750pixel && height 497pixel all looks good enter image description here enter image description here

Legacy code. I don't see where the issue is.

Harald K
  • 26,314
  • 7
  • 65
  • 111
Eduard A
  • 370
  • 3
  • 9
  • 1
    I had a same issue, With the difference that I lost orientation. the problem is that when you scale an image, it losses the **EXIF** data, the solution is to save the **EXIF** data of the image before scale it. and then create the new image with the Previous **EXIF** data. see also this post : https://stackoverflow.com/questions/56798393/why-image-is-rotated-and-resized-instead-of-resized-only/67955535#67955535 – Issa Khodadadi Sep 07 '21 at 11:18
  • Your input is a JPEG (probably, in both cases) and is internally encoded as YCbCr. However, for the Google screenshot, the ImageIO JPEG plugin mis-interprets this as RGB, making the colors all wrong (the unscaled Google image would also be inverted, if displayed in Java). An easy fix is probably to use my [JPEG plugin](https://github.com/haraldk/TwelveMonkeys#file-formats-supported) for ImageIO. – Harald K Sep 07 '21 at 12:10
  • 1
    Come to think of it, it could also be that you input is a format with transparency (alpha channel), and that you store it unchanged as a 4 channel JPEG. This works in older versions of Java, but most software will interpret this as CMYK JPEGs. However, none of these explanations makes sense if both your input and output is PNG... – Harald K Sep 10 '21 at 11:07
  • I fixed it by changing ImageIO.write(after, "png", byteArrayOutputStream); png to jpg :)) – Eduard A Sep 16 '21 at 09:01

0 Answers0