当我第一次问这个问题时,我尽可能多地提供了信息,因为我永远不知道如果某人能给我一个解决方案,什么会对他们有帮助,但从答案来看,我似乎没有阐明我的观点。
我将把原文放在底部,并将其缩短。我希望这能说明问题。
我正在处理从另一个程序返回给我的图像。例如,我可以在72 DPI下获得8x10的图像,或者在16x20下也可以在72 DPI下获得相同的图像。
我在Java工作。我想做的是拍摄16x20图像并调整其大小。如果可能的话,我只想更改文件,使其在72DPI时不是16x20,而是在144DPI时是8x10。
我知道它的像素数仍然是一样的,但观众会说一张图像有多大,DPI是多少,还有一些人会把图像打开到它的全尺寸,所以我宁愿他们把16x20当作一张更小、分辨率更高的图像。
我能用Java做这件事吗?我会丢失任何数据吗?我该怎么做?我可以更改png或jpg文件中的元数据吗?
-----(以下为原始问题)-----
我看到了一些与此接近的问题,但这有点不同。
我知道你可以用Java中的图像来降低图像分辨率(也在这里)。我做过的任何搜索都是为了降低图像的分辨率。
我有相反的问题。我正在处理一张72DPI的图像。优点是我可以增加图片的大小,这样我就可以使大小达到100%、200%、400%等等。所有图像都是72DPI,所以如果我使用200%进行缩放,然后在查看器中打开图像,使其与100%图像的大小相同,我会看到更好的分辨率。
为了清晰起见,我从其他人那里得到了一张图像,它可以从PDF或图片中生成,但我得到了另一个程序的图像。无论我做什么,这张图片都是72DPI。我不能改变这一点,但我可以指定200%的大小,它仍然是72DPI,只是两倍大,而且有更多细节。
我不是图形专家,这是我第一次做任何使用图形的编程。输出可以是jpg或png,所以格式没有那么重要。(如果需要,我可能也可以使用其他格式。)
假设原始图像是一张照片-8"x 10",分辨率为72 DPI。如果我要求200%的变焦,我会得到一张72DPI的16"x 20"图像。
在Java中,我可以在不丢失数据的情况下将较大的16"x 20"72DPI图像更改为8"x 10"的144DPI图像吗?换句话说,将DPI增加一倍,但将大小减半?
最重要的是,我能在不失去决心的情况下做到这一点吗?(我认为这是可以做到的。)
否,如果您拍摄8x10 72dpi的图像并要求200%的变焦,您将获得36dpi的16x20。你无法神奇地提高图像分辨率。
重要的是图像中的像素总数。所述DPI正是特定大小下的DPI。以72dpi拍摄8x10图像。它有576x720像素。如果你放大到200%,你仍然有相同数量的像素,但现在它们将分布在两倍的线性维度上,这意味着单个像素将更大。一些软件将尝试通过插值像素来提高分辨率,即通过对最近的邻居进行平均来创建新的像素。这可以给人以更高分辨率的印象,但图像不包含任何更多的数据。它总是有软化图像的效果,尤其是任何尖锐的边缘或线条。
如果在不重新采样的情况下缩小图像的大小,则会增加打印或显示的分辨率,但图像会变小。对于相同的图像,将DPI增加到144将使图像大小减小到4x5。
这很棘手,因为与Java中的许多内容一样,您不能以简单的方式访问某些内容。Java不跟踪DPI,但它确实使用每毫米点数。此外,另一个令人困惑的部分是,您无法更改图像或BufferedImage中的此类信息。只有在通过ImageWriter写入BufferedImage时,才能更改此信息。
我能够做到这一点。正如我所说,我可以指定返回给我的图像的缩放。无论缩放级别如何,输出都是72 DPI。我的目标是300DPI。我指定了400%的缩放级别。因此,在一张8英寸宽、72 DPI的图像上,我看到的是一张32英寸宽的72 DPI图像。我所要做的就是指定288(72 x 4)的DPI来覆盖我正在处理的默认72 DPI,然后当它被写出来时,图像具有相同的像素数,但被认为是以288 DPI而不是72 DPI完成的。
下面是一个代码片段:
//假设已经有ImageWriter iw
ImageWriteParam writeParam = writer.getDefaultWriteParam();
ImageTypeSpecifier typeSpecifier =
ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
continue;
}
//设置参数和信息
int DPI = 72 * scaling/100;
double dotsPerMilli = 1.0 * DPI / 10 / 2.54;
double checkDots = 1.0 * 144 / 10 / 2.54;
System.out.println("Dots per inch: " + DPI + ", DotsPerMilli: " + dotsPerMilli + ",
CheckDots = " + checkDots);
IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
horiz.setAttribute("value", Double.toString(dotsPerMilli));
IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
vert.setAttribute("value", Double.toString(dotsPerMilli));
IIOMetadataNode dim = new IIOMetadataNode("Dimension");
dim.appendChild(horiz);
dim.appendChild(vert);
root.appendChild(dim);
metadata.mergeTree("javax_imageio_1.0", root);
//从这里,只需使用ImageOutputStream 写出文件
final ImageOutputStream stream = ImageIO.createImageOutputStream(outFile);
System.out.println("Output file: " + outFile);
try {
writer.setOutput(ImageIO.createImageOutputStream(outFile));
writer.write(metadata, new IIOImage(image_to_save, null, metadata),
writeParam);
} catch (Exception e) {
System.out.println("Caught exception " + e + " when trying to write out
file.");
System.exit(0);
} finally {
stream.close();
}