在 Java 中提高图像的分辨率和减小图像的大小 [英] Increasing Resolution and Reducing Size of an Image in Java

查看:61
本文介绍了在 Java 中提高图像的分辨率和减小图像的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我第一次问这个问题时,我尽可能多地提供了信息,因为我永远不知道如果他们能给出解决方案,对某人有什么帮助,但从答案来看,我似乎没有把我的观点说清楚.

When I first asked this, I included as much information as I could, since I never know what will help someone if they can give m a solution, but from the answers, it seems I didn't make my point clear.

我将原始文本留在底部并缩短它.我希望这能说清楚.

I'm leaving the original text at the bottom and shortening this. I hope that makes it clear.

我正在处理从另一个程序返回给我的图像.例如,我可以在 72 DPI 下获得 8x10 的图像,或者在 16x20 和 72DPI 下获得相同的图像.

I am working with images returned to me from another program. I can get an image that's, for example, 8x10 at 72 DPI or the same image at 16x20, also at 72DPI.

我在 Java 工作.我想做的是获取 16x20 图像并调整其大小.如果可能,我只想更改文件,而不是 72DPI 下的 16x20,而是 144DPI 下的 8x10.

I'm working in Java. What I'd like to do is take the 16x20 image and resize it. If possible, I'd like to just change the file so instead of being 16x20 at 72DPI, it's 8x10 at 144DPI.

我知道它仍然是相同数量的像素,但观众会说图像有多大以及 DPI 是多少,还有一些人会以全尺寸打开图像,所以我宁愿他们将 16x20 视为分辨率更高的小图像.

I know that it's still the same number of pixels, but viewers will say how big an image is and what the DPI is and also some open an image to its full size, so I'd rather them treat the 16x20 as a smaller image with a higher resolution.

我可以在 Java 中做到这一点吗?我会丢失任何数据吗?我该怎么做 - 我可以只更改 png 或 jpg 文件中的元数据吗?

Can I do that in Java? Will I lose any data? How would I do it - can I just change the metadata in the png or jpg file?

-----(下面的原始问题)-----

-----(original question below here)-----

我看到了一些与此接近的问题,但这有点不同.

I've seen a few questions that come close to this, but this is a little different.

我知道您可以使用 Java 中的图像降低图像分辨率(也在这里).我所做的任何搜索都与降低图像分辨率有关.

I know you can decrease image resolution with an image in Java (also here). Any searches I've done have been concerned with decreasing the resolution of an image.

我有相反的问题.我正在处理以 72DPI 恢复的图像.优点是我可以增加图片的大小,所以我可以把大小设置为100%、200%、400%等等.所有图像的分辨率均为 72DPI,因此如果我使用 200% 进行缩放,然后在查看器中打开图像并使其与 100% 图像的大小相同,我会看到更好的分辨率.

I have the opposite problem. I'm working with an image that I'm getting back in 72DPI. The advantage is I can increase the size of the picture, so I could make the size 100%, 200%, 400% and so on. All images are at 72DPI, so if I use 200% for the zoom, then open the image in a viewer and make it the same size as the 100% image, I am seeing a better resolution.

为清楚起见 - 我从其他人那里获取图像,它可以从 PDF 或图片生成,但我从另一个程序给出的图像.不管我做什么,这张图片都是 72DPI.我无法改变它,但我可以将大小指定为 200%,它仍然以 72DPI 返回,只是两倍大,细节更多.

For clarity - I am getting an image from someone else, it could be generate from a PDF or picture, but I am given the image from another program. No matter what I do, this image is at 72DPI. I can't change that, but I can specify the size at 200% and it still comes back at 72DPI, just twice as big and with more detail.

我不是图形专家,这是我第一次完成任何使用图形的编程.输出可以是 jpg 或 png,所以格式不是那么重要.(如果需要,我可能也可以使用其他格式.)

I'm no graphics expert and this is the first time I've done any programming that uses graphics. The output could be jpg or png, so the format isn't that important. (I could probably also use other formats if needed.)

假设原始图像是一张照片 - 8" x 10",72 DPI.如果我要求 200% 缩放,我会得到 72DPI 的 16" x 20" 图像.

Let's say the original image is a photo - 8" x 10", and at 72 DPI. If I ask for a 200% zoom, I get a 16" x 20" image at 72DPI.

我可以在 Java 中将较大的 16" x 20" 72DPI 图像更改为 8" x 10" 的 144DPI 图像而不会丢失数据吗?换句话说,DPI 加倍,但大小减半?

Can I, within Java, change that larger 16" x 20" 72DPI image to a 144DPI image that's 8" x 10" without losing data? In other words, double the DPI, but cut the size in half?

而且,最重要的是,我可以在不丢失分辨率的情况下做到这一点吗?(我认为可以做到.)

And, most importantly, can I do it without losing resolution? (I would think that can be done.)

推荐答案

这很棘手,因为与 Java 中的许多情况一样,您不能仅以简单的方式访问某些内容.Java 不跟踪 DPI,但它确实使用每毫米点数.此外,另一个令人困惑的部分是您无法更改图像或 BufferedImage 中的此类信息.只有在通过 ImageWriter 写出 BufferedImage 时才能更改此信息.

This is tricky because, like so much in Java, you can't just access something in a simple way. Java does not keep track of DPI, but it does use dots per millimeter. Also, another part that is confusing is that you cannot change this kind of information in an image, or in a BufferedImage. You can only change this information when you are writing a BufferedImage out through an ImageWriter.

我能够做到这一点.正如我所说,我可以指定返回给我的图像的缩放比例.无论缩放级别如何,输出都是 72 DPI.我的目标是 300DPI.我指定了 400% 的缩放级别.因此,在 72 DPI 的 8" 宽图像上,返回给我的是 72 DPI 的 32" 图像.我所要做的就是指定 288 (72 x 4) 的 DPI 来覆盖我正在处理的默认 72 DPI,然后当它被写出时,图像具有相同数量的像素,但被认为是在288 DPI 而不是 72 DPI.

I was able to do this. As I said, I could specify the zoom on the image that was returned to me. No matter what zoom level, the output was 72 DPI. My goal was 300DPI. I specified a zoom level of 400%. So, on an 8" wide image of 72 DPI, that returned to me a 32" image of 72 DPI. All I had to do was specify a DPI of 288 (72 x 4) to override the default 72 DPI I was dealing with and then when it was written out, the image had the same number of pixels, but was considered to be done at 288 DPI rather than 72 DPI.

这是一个代码片段:

//假设已经有一个ImageWriter iw

//Assumed there's already an 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 写出文件

// From here, just write out file using an 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();
}

这篇关于在 Java 中提高图像的分辨率和减小图像的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆