【问题标题】:How to resize Image in Java with same or lower DPI如何使用相同或更低的 DPI 在 Java 中调整图像大小
【发布时间】:2021-12-02 16:02:51
【问题描述】:

我正在尝试在 Java 中调整 jpg 图像文件的大小。为此,我正在使用 Scalr。 我有大约 16MB 的图像,分辨率为 6000x4000 和 350 dpi。

当我将其调整为 4500 宽度时,它会将 DPI 也缩小到 96。

这是我正在使用的代码:

    Scalr.resize(img, Scalr.Method.ULTRA_QUALITY, 4500, Scalr.OP_ANTIALIAS);

我在没有任何库的情况下尝试过,代码如下:

    private static BufferedImage resizeImageWithHint(BufferedImage originalImage, int type, int IMG_WIDTH,
        int 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();
    g.setComposite(AlphaComposite.Src);

    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    return resizedImage;
}

但结果是一样的。那么如果可能的话,我如何调整 dpi 大约 150 的图像大小,如果不可能的话,我该如何调整 350 dpi 的大小。

【问题讨论】:

  • 在 Java 中,图像没有“dpi”。事实上,除了可能的调色板之外,图像没有其他元数据。
  • @MarkJeronimus 那么如何将图像的大小调整为较低的分辨率但又不会丢失 DPI 并将其保持为原始 350。我在 c# .net 中做到了这一点,所以我知道这是可能的,只是想知道在 Java 中是如何实现的。
  • 顺便看看我改进后的多线程image resizer

标签: java image-resizing imgscalr


【解决方案1】:

将 DPI 存储在图像中意味着您要保存图像。 (这在您的问题中并不清楚。)您需要直接在编码器中指定元数据。这是JPEG版本。我看到 PNG 也可以,它需要不同的元数据树节点。

[编辑] 我找到了一种不依赖专有类的方法。

import org.w3c.dom.Element;

ImageWriter     writer = ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriteParam param    = writer.getDefaultWriteParam();

param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.95f);

IIOMetadata metadata = writer.getDefaultImageMetadata(ImageTypeSpecifier.createFromRenderedImage(image), param);
Element     tree     = (Element)metadata.getAsTree("javax_imageio_jpeg_image_1.0");
Element     jfif     = (Element)tree.getElementsByTagName("app0JFIF").item(0);
jfif.setAttribute("Xdensity", Integer.toString(350));
jfif.setAttribute("Ydensity", Integer.toString(350));
jfif.setAttribute("resUnits", "1"); // In pixels-per-inch units
metadata.mergeTree("javax_imageio_jpeg_image_1.0", tree);

try (FileImageOutputStream output = new FileImageOutputStream(new File(filename))) {
    writer.setOutput(output);
    IIOImage iioImage = new IIOImage(image, null, metadata);
    writer.write(metadata, iioImage, param);
    writer.dispose();
}

改编自source

PNG 版本here

【讨论】:

  • 谢谢。我在元素树上遇到错误。我应该为此“元素”导入哪个库?
  • 导入的那个
【解决方案2】:

为我工作,jpg 72 -> 300

public static void handleDpi(File file, int xDensity, int yDensity) {
        try {
            BufferedImage image = ImageIO.read(file);
            JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(new FileOutputStream(file));
            JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(image);
            jpegEncodeParam.setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
            jpegEncoder.setJPEGEncodeParam(jpegEncodeParam);
            jpegEncodeParam.setQuality(0.75f, false);
            jpegEncodeParam.setXDensity(xDensity);
            jpegEncodeParam.setYDensity(yDensity);
            jpegEncoder.encode(image, jpegEncodeParam);
            image.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
  • 2013-03-11
  • 2014-01-21
  • 2015-04-16
  • 2012-11-01
  • 1970-01-01
相关资源
最近更新 更多