java - 如何在java中重新采样图像并保持其物理尺寸?

标签 java imagemagick

假设我有一个 144x144 像素的图像,ppi(每英寸像素)为 144。所以我的图像实际上是一个 1x1 英寸的正方形。现在我想将其像素密度降低到 72 ppi,但仍保留其 1x1 英寸见方的物理尺寸。为了实现这一点,现在需要将图像的像素尺寸设置为 72x72 像素。我想仅通过以下可用输入来实现此目的:

  • 图像
  • 目标 ppi

这与 ImageMagick 中所做的非常相似如下

convert -units PixelsPerInch original_144by144.jpg -resample resampled_72 72by72.jpg

上面的 ImageMagick 命令在进行重新采样时在内部保留图像的物理尺寸。

我想用 Java 来做到这一点。关于如何去做有什么建议吗?

最佳答案

我只是希望人们认识到每英寸像素 (PPI) 与每英寸点数 (DPI) 不同。尽管这些术语经常用于指代同一事物,但它们是不同的 Read here for more insight

我个人只会使用ImageMagick (免费且 open source )通过 Java 应用程序,因为 ImageMagick 作为命令行应用程序运行得很好,例如:

String imageMagickLocation = "D:\\ImageMagick-7.0.8-Q16\\magick.exe";
String sourceImagePath = "C:\\Users\\DevilsHnd\\Pictures\\MyImage.png";
String destinationPath = "C:\\Users\\DevilsHnd\\Pictures\\New_MyImage.png"; 
int desiredPPI = 72;
String commandLineString = imageMagickLocation + " convert -units PixelsPerInch \"" 
                         + sourceImagePath + "\" -resample " + desiredPPI + " \"" 
                         + destinationPath + "\""; 

List<String> list = runCMD(commandLineString);

/* Display any results from the call to the runCMD() 
   method. If ImageMagick is successful then there 
   should be nothing (the List should be empty).  */
if (!list.isEmpty()) {
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
}

下面提供的runCMD()方法允许您的应用程序像通过Windows“命令提示符”窗口一样运行命令行应用程序:

/**
 * This method is specifically designed for running the Microsoft Windows CMD 
 * command prompt and having the results that would normally be displayed within 
 * a Command Prompt Window placed into a string List Interface instead.<br><br>
 * <p>
 * <b>Example Usage:</b><pre>
 *       {@code 
 *          List<String> list = runCMD("/C dir");
 *          for (int i = 0; i < list.size(); i++) {
 *              System.out.println(list.get(i));
 *          }
 *       } </pre>
 *
 * @param commandString (String) The command string to pass to the Command
 *                      Prompt. You do not need to place "cmd" within your
 *                      command string because it is applied automatically.
 *                      As a matter of fact if you do it is automatically
 *                      removed.<br> 
 *
 * @return (List&lt;String&gt;) A string List containing the results of
 *         the processed command.
 */
public List<String> runCMD(String commandString) {
    if (commandString.toLowerCase().startsWith("cmd ")) {
        commandString = commandString.substring(4);
    }
    List<String> result = new ArrayList<>();
    try {
        Process p = Runtime.getRuntime().exec("cmd /C " + commandString);
        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(p.getInputStream()))) {
            String line;
            while ((line = in.readLine()) != null) {
                result.add(line);
            }
        }
        p.destroy(); // Kill the process
        return result;
    }
    catch (IOException e) {
        JOptionPane.showMessageDialog(null, "<html>IO Error during processing of runCMD()!"
                                    + "<br><br>" + e.getMessage() + "</html>",
                                      "runCMD() Method Error", JOptionPane.WARNING_MESSAGE);
        return null;
    }
}

使用 ImageMagick 将图像转换为每英寸 72 像素 (PPI) 的速度相对较快,但将 PPI 设置为高于原始源 PPI 可能需要更长的时间,具体取决于差异。无论你做什么,都不要做一些疯狂的事情,比如将图像转换为 2000 PPI,除非你有一台具有大量内存的 super 计算机(ImageMagick 将尝试这样做)。事实上,您需要安装保护措施来防止不合理的 PPI 值的转换。

ImageMagick 对特定图像重新采样以表示 72 PPI 的典型命令行操作是:

D:\ImagMagick\magick.exe convert -units PixelsPerInch "C:\Pictures\MyImageName1.png" -resample 72 "C:\Pictures\MyImageName2.png"

                            O R

D:\ImagMagick\magick.exe convert -units PixelsPerInch "C:\Pictures\MyImageName1.png" -resample 72 "C:\Pictures\MyImageName2.jpg"

注意两次转换调用之间目标文件扩展名发生变化。源文件路径和目标文件路径和/或文件名括在引号内,以防其中包含一个或多个空格。

此外,您还可以轻松修改内容以执行批量图像文件转换。我相信 ImageMagick 也具有通过命令行进行批处理的功能。

关于java - 如何在java中重新采样图像并保持其物理尺寸?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56833107/

相关文章:

java - 最正确地利用了 SOLID 原则的 OSS .net/java 项目有哪些?

c++ - 使用 g++ 编译并将 GraphicsMagick++ 作为静态库

java - Android Studio 数据绑定(bind)中此处不允许使用元素数据

java - 如何将相似的 Java 函数合并为一个(在 C++ 中我会使用模板)

java - 如何在使用 Spring 和 JAX-RS 构建的 REST Api 中处理 Unicode 字符...?

php - 使用 imagemagick 设置质量?

java - 给定一个.jpg或.png,以及一个URL,如何生成 "LogoQ"类型的二维码?

java - g.addV().property(T.label, "SomeLabel") 与 g.addV ("SomeLabel")

ruby - Ubuntu 12.10 - Ruby gem rmagick 缺少依赖问题

imagemagick - 转换 : non-conforming drawing primitive definition `text'