如何使用相同或更低的 DPI 调整 Java 中的图像大小
How to resize Image in Java with same or lower DPI
我正在尝试调整 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。
将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
这对我有用,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();
}
}
我正在尝试调整 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。
将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
这对我有用,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();
}
}