如何正确调整图像大小?

时间:2019-06-28 07:55:10

标签: java image

获取正确尺寸的图像时出现问题。

为此,我有这种方法可以调整图像的大小,并且逻辑上需要进行一些小的更改以获取正确的图像大小:

private final Integer width = 170;
private final Integer height = 140;
private final Integer maxFeatImageHeight = 600;
private final Integer maxFeatImageWidth = 600;
   /**
 * @param featureImage .
 * @return byte[]
 * @throws Exception
 */
private byte[] resizeFeatureImage(MultipartFile featureImage) throws Exception
{
    try
    {
        BufferedImage originalImage = ImageIO.read(featureImage.getInputStream());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        double featImageWidth = originalImage.getWidth();
        double featImageHeight = originalImage.getHeight();

        if (featImageHeight > maxFeatImageHeight || featImageWidth > maxFeatImageWidth)
        {
         // Sanity check on the input (division by zero, infinity):
            if (featImageWidth <= 1 || featImageHeight <= 1) {
                throw new IllegalArgumentException("Error ..." + featureImage);
            }

            // The scaling factors to reach to maxima on width and height:
            double xScale = maxFeatImageWidth   / featImageWidth;
            double yScale = maxFeatImageHeight  / featImageHeight;

            // Proportional (scale width and height by the same factor):
            double scale = Math.min(xScale, yScale);

            // (Possibly) Do not enlarge:
            scale = Math.min(1.0, scale);

            int finalWidth = Math.min((int) Math.round(scale * featImageWidth), maxFeatImageWidth);
            int finalHeight = Math.min((int) Math.round(scale * featImageHeight), maxFeatImageHeight);
            double ratio = featImageWidth / featImageHeight;
            // width is bigger then height
            if (ratio > 1)
            {
                finalWidth = maxFeatImageWidth;
                finalHeight = (int) Math.round(maxFeatImageHeight / ratio);
            }
            // height is bigger then width
            else if (ratio < 1)
            {
                finalWidth = (int) Math.round(maxFeatImageWidth / ratio);
                finalHeight = maxFeatImageHeight;
            }
            // width and height are equal
            else
            {
                finalHeight = maxFeatImageHeight;
                finalWidth = maxFeatImageWidth;
            }

            logger.info("[resizeFeatureImage] [FEATURE IMAGE RESIZE] Starting to resize feature Image");
            Graphics2D g2d;
            BufferedImage resizedImage;

            if (featureImage.getContentType().contains("png"))
            {
                resizedImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_ARGB);
            }
            else
            {
                resizedImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_3BYTE_BGR);
            }

            g2d = resizedImage.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.drawImage(ImageIO.read(featureImage.getInputStream()), 0, 0, finalWidth, finalHeight,
                    null);
            g2d.dispose();

            ImageIO.write(resizedImage, featureImage.getContentType().split("/")[1], baos);
            logger.info("[resizeFeatureImage] [FEATURE IMAGE RESIZE] Feature image resized!");
            return baos.toByteArray();
        }
        else
        {
            ImageIO.write(originalImage, featureImage.getContentType().split("/")[1], baos);
            return baos.toByteArray();
        }
    }
    catch (Exception e)
    {
        logger.warn("[resizeFeatureImage] [STATUS] - ERROR ");
        logger.warn("[resizeFeatureImage] [EXCEPTION] " + e.getMessage(), e);
        throw new IOException("The file you uploaded can be damaged or has incorrect encoding.");
    }
}

因此,显示的每个图像都小于其所拥有的空间 在下图中,您可以看到有很多空白未被使用,这肯定意味着我的方法做错了,导致这种情况,我已经检查了很多次这种方法,而我没有我真的不知道为什么或会发生这种情况,如果有需要,谁能帮助我编辑此方法,我将非常感激。 图像显示如下: enter image description here

3 个答案:

答案 0 :(得分:2)

private static final int MAX_FEAT_IMAGE_WIDTH = 600;
private static final int MAX_FEAT_IMAGE_WIDTH = 600;

double featImageWidth = originalImage.getWidth();
double featImageHeight = originalImage.getHeight();

// Sanity check on the input (division by zero, infinity):
if (featImageWidth <= 1 || featImageHeight <= 1) {
    throw new IllegalArgumentException("..." + featureImage);
}

// The scaling factors to reach to maxima on width and height:
double xScale = MAX_FEAT_IMAGE_WIDTH / featImageWidth;
double yScale = MAX_FEAT_IMAGE_HEIGHT / featImageHeight;

// Proportional (scale width and height by the same factor):
double scale = Math.min(xScale, yScale);

// (Possibly) Do not enlarge:
scale = Math.min(1.0, scale);

int finalWidth = Math.min((int) Math.round(scale * featImageWidth), MAX_FEAT_IMAGE_WIDTH);
int finalHeight = Math.min((int) Math.round(scale * featImageHeigth), MAX_FEAT_IMAGE_HEIGHT);
  • 如您所见,我扭转了两件事,以保持比例缩放。在精神上使用比率(/而不是比例因子(*)似乎会更难。

  • 分别确定宽度和高度的缩放比例,让我们选择最小缩放比例。

  • 也可以决定放大小图片。

答案 1 :(得分:2)

您仅考虑方向(对于垂直,ratio <1,否则为水平或正方形)。这还不够;您必须考虑目标宽度/高度:

        int sw = originalImage.getWidth();
        int sh = originalImage.getHeight();
        int swdh = sw * maxFeatImageHeight;
        int shdw = sh * maxFeatImageWidth;
        if (swdh < shdw) {
            finalWidth = swdh / sh;
            finalHeight = maxFeatImageHeight;
        } else {
            finalWidth = maxFeatImageWidth;
            finalHeight = shdw / sw;
        }

更新:

好的,让我们从秤开始:

        double xScale = maxFeatImageWidth/featImageWidth;
        double yScale = maxFeatImageHeight/featImageHeight;

您可以写:

在yScale

finalWidth = featImageWidth*yScale = featImageWidth*maxFeatImageHeight/featImageHeight;
finalHeight = maxFeatImageHeight;

否则,我们可以使用xScale:

finalWidth = maxFeatImageWidth;
finalHeight = featImageHeight*xScale = featImageHeight*maxFeatImageWidth/featImageWidth;

由于所有宽度和高度都> = 0,因此yScale

yScale*featImageWidth*featImageHeight < xScale*featImageWidth*featImageHeight

如此

maxFeatImageHeight*featImageWidth < maxFeatImageHeight*featImageWidth

我将这两个值另存为swdh和shdw,因为以后可以重用它们。

它避免了从intdouble以及从doubleint的转换。

答案 2 :(得分:1)

很可能您应该知道要调整大小的图像的大小,在该值之后,if and else语句应该起作用,并调用resize函数就可以调整大小。希望对您有所帮助。并且在调整大小时,请确保也能够按照用户定义减小像素。