Java 扩展图像支持库 TwelveMonkeys ImageIO

2022-05-17 14:22:53 浏览数 (1)

TwelveMonkeys ImageIO 通过 javax.imageio.* 包的插件为 Java 平台提供扩展图像文件格式支持。

注意,GIF、 PNG 和 WBMP 格式已经通过 ImageIO API 支持,使用的是 JDK 标准插件。对于 BMP、 JPEG 和 TIFF 格式,TwelveMonkeys 插件提供了扩展格式支持和其他特性。

Basic usage

大多数时候,你所需要做的只是在你的项目中包含插件,然后写下:

代码语言:javascript复制
BufferedImage image = ImageIO.read(file);

这将把文件的第一个图像完全加载到内存中。

最基本和最简单的书写形式是:

代码语言:javascript复制
if (!ImageIO.write(image, format, file)) {
   // Handle image not written case
}

这将使用给定格式的默认设置将整个图像写入单个文件。

这些插件在运行时会被自动发现。查看 FAQ 了解更多关于这种机制如何工作的信息。

Maven dependency example To depend on the JPEG and TIFF plugin using Maven, add the following to your POM:

代码语言:javascript复制
...
<dependencies>
    ...
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-jpeg</artifactId>
        <version>3.8.1</version>
    </dependency>
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-tiff</artifactId>
        <version>3.8.1</version>
    </dependency>

    <!--
    Optional dependency. Needed only if you deploy ImageIO plugins as part of a web app.
    Make sure you add the IIOProviderContextListener to your web.xml, see above.
    -->
    <dependency>
        <groupId>com.twelvemonkeys.servlet</groupId>
        <artifactId>servlet</artifactId>
        <version>3.8.1</version>
    </dependency>

    <!--
    Or Jakarta version, for Servlet API 5.0
    -->
    <dependency>
        <groupId>com.twelvemonkeys.servlet</groupId>
        <artifactId>servlet</artifactId>
        <version>3.8.1</version>
        <classifier>jakarta</classifier>
    </dependency>
</dependencies>

最终我的 MyImageIO 增强类。其实也是为了解决某些情况下 jpg 图片 ImageIO.read() 方法报错的问题。我寻找原因,发现用 jdk 自带的 jpeg 解析器不能解析所有的jpeg格式文件(如cmyk)。出现 unsupported formate 错误。之后使用 createJPEG4 解决了此问题,但是最终生成的图片有红屏现象,最终使用 TwelveMonkeys ImageIO 是无入侵且完美解决,这个值得点赞。

代码语言:javascript复制
    static class MyImageIO {

        public static BufferedImage read(File input) throws IOException {
            if (input == null) {
                throw new IllegalArgumentException("input == null!");
            }
            if (!input.canRead()) {
                throw new IIOException("Can't read input file!");
            }

            ImageInputStream stream = ImageIO.createImageInputStream(input);
            if (stream == null) {
                throw new IIOException("Can't create an ImageInputStream!");
            }
            BufferedImage bi = read(stream);
            if (bi == null) {
                stream.close();
            }
            return bi;
        }

        private static BufferedImage read(ImageInputStream stream)
                throws IOException {
            if (stream == null) {
                throw new IllegalArgumentException("stream == null!");
            }

            Iterator<ImageReader> iter = ImageIO.getImageReaders(stream);
            if (!iter.hasNext()) {
                return null;
            }

            final ImageReader reader = iter.next();
            ImageReadParam param = reader.getDefaultReadParam();
            reader.setInput(stream, true, true);
            BufferedImage bi;
            try {
                bi = reader.read(0, param);
            } catch (IIOException e) {
                Raster raster = reader.readRaster(0, null);
                bi = createJPEG4(raster);
            } finally {
                reader.dispose();
                stream.close();
            }
            return bi;
        }

        private static BufferedImage createJPEG4(Raster raster) {
            int w = raster.getWidth();
            int h = raster.getHeight();
            byte[] rgb = new byte[w * h * 3];
            // 彩色空间转换
            float[] Y = raster.getSamples(0, 0, w, h, 0, (float[]) null);
            float[] Cb = raster.getSamples(0, 0, w, h, 1, (float[]) null);
            float[] Cr = raster.getSamples(0, 0, w, h, 2, (float[]) null);
            float[] K = raster.getSamples(0, 0, w, h, 3, (float[]) null);

            for (int i = 0, imax = Y.length, base = 0; i < imax; i  , base  = 3) {
                float k = 220 - K[i], y = 255 - Y[i], cb = 255 - Cb[i], cr = 255 - Cr[i];

                double val = y   1.402 * (cr - 128) - k;
                val = (val - 128) * .65f   128;
                rgb[base] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff
                        : (byte) (val   0.5);

                val = y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128) - k;
                val = (val - 128) * .65f   128;
                rgb[base   1] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff
                        : (byte) (val   0.5);

                val = y   1.772 * (cb - 128) - k;
                val = (val - 128) * .65f   128;
                rgb[base   2] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff
                        : (byte) (val   0.5);
            }

            raster = Raster.createInterleavedRaster(new DataBufferByte(rgb,
                    rgb.length), w, h, w * 3, 3, new int[] { 0, 1, 2 }, null);

            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
            ColorModel cm = new ComponentColorModel(cs, false, true,
                    Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
            return new BufferedImage(cm, (WritableRaster) raster, true, null);
        }
    }

参考

haraldk/TwelveMonkeys: TwelveMonkeys ImageIO: Additional plug-ins and extensions for Java's ImageIO https://github.com/haraldk/TwelveMonkeys

0 人点赞