0

我最近开发了一个在 Tomcat7 上运行的 Java Servlet,它应该接受来自不同格式(PNG、JPG、BMP)的图片的 POST。并执行以下任务:

  • 如果大于 2000 像素,请缩小它们
  • 缓存其他维度(如果允许)
  • 运行散列算法来识别相似的图像
  • 将它们全部存储并缓存为 JPG

作为最快的解决方案,我依赖 ImageIO,它在我遇到更多“新”格式之前产生了不错的结果。有两个主要问题我找不到有效的解决方案:

  • 渐进式 JPEG
  • 包含 EXIF 元数据的 JPEG

我评估了不同的解决方案,但似乎都没有解决这两种解决方案(我将列出最好的两个):

  • Apache Imaging(读取 EXIF,无法读取/写入 JPEG速度很慢
  • JMagick (接受 JPEG & Progressive JPEG,不关心 EXIF )

你们中是否有人能够实施适用于这两种格式的解决方案?

4

1 回答 1

0

您可以尝试im4java,它也像JMagick一样使用ImageMagick。但它不是作为原生库的包装器,而是使用命令行与ImageMagick进行通信。

ImageMagick具有-auto-orient自动将图像转换为“正确”方向的操作。有关详细信息,请查看文档

优点

  • 非常快,特别是如果ImageMagick是用libjpeg-turbo等优化库编译的(例如在Debian发行版中的标准)
  • 支持比Debian等发行版中包含的JMagick版本更多的ImageMagick操作(截至撰写时)。

缺点

  • 使用命令行界面与ImageMagick进行通信,由于安全限制,这可能是不允许的。

Maven 依赖

    <dependency>
        <groupId>org.im4java</groupId>
        <artifactId>im4java</artifactId>
        <version>1.4.0</version>
    </dependency>

示例 1(带文件)

        // prepare operations
        final int width = 2000;
        final double quality = 85.0;
        final IMOperation op = new IMOperation();
        op.addImage("/path/to/input/image.jpg"); // input
        op.autoOrient();
        op.resize(width);
        op.quality(quality);
        op.addImage("/path/to/output/image.jpg"); // output (rotated image @ 85% quality)

        // create and execute command
        final ConvertCmd convertCmd = new ConvertCmd();
        convertCmd.run(op);

示例 2(带有输入/输出流)

        // prepare operations
        final String outputFormat = "jpeg";
        final int width = 2000;
        final double quality = 85.0;
        final IMOperation op = new IMOperation();
        op.addImage("-"); // input: stdin
        op.autoOrient();
        op.resize(width);
        op.quality(quality);
        op.addImage(outputFormat + ":-"); // output: stdout

        // create and execute command
        final ConvertCmd convertCmd = new ConvertCmd();
        final Pipe inPipe = new Pipe(inputStreamWithOriginalImage,
                null); // no output stream, using stdin
        convertCmd.setInputProvider(inPipe);
        final Pipe outPipe = new Pipe(null, // no input stream, using stdout
                outputStreamForConvertedImage);
        convertCmd.setOutputConsumer(outPipe);
        convertCmd.run(op);

示例 3(图像信息)

        final boolean baseInfoOnly = true;
        final Info info = new Info("/path/to/input/image.jpg",
                baseInfoOnly);
        System.out.println("Geometry: " + info.getImageGeometry());

表现

您还可以查看此问题以进行性能优化(但请注意,有一个-colorspace rgb和一个不必要的,因为不支持 JPEG 图像,-coalesce这两个操作都增加了处理时间)。

文档

在这里,您可以找到包含更多示例的开发人员指南。

于 2018-06-15T11:00:29.040 回答