首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ImageIO写入特定tiff

ImageIO写入特定tiff
EN

Stack Overflow用户
提问于 2019-04-23 23:06:06
回答 1查看 1.5K关注 0票数 0

我尝试(使用ImageIO -> https://github.com/haraldk/TwelveMonkeys)将图像转换为特定的tiff,就像imagemagick所做的那样。我有一个输入图像,并想写一个特定的tiff,如下所示:

代码语言:javascript
复制
PLANAR_CONFIGURATION = 1
SAMPLES_PER_PIXEL = 1
BITS_PER_SAMPLE = 1
Y_RESOLUTION = 196
X_RESOLUTION = 204
IMAGE_WIDTH = 1728

你知道如何渲染输入流吗?目前,该图像只是转换为tiff。

代码语言:javascript
复制
BufferedImage image = ImageIO.read(inputstream)
ImageIO.write( image, "tiff", outputstream );
EN

回答 1

Stack Overflow用户

发布于 2019-04-24 16:14:27

正如@fmw42所说,制作1比特的图像是你自己做的。TIFFImageWriter插件将写入按原样传递的图像。幸运的是,这并不难做到。

这里有一个简单(但不是很复杂)的方法来将图像转换成二进制:

代码语言:javascript
复制
private static BufferedImage toBinary(BufferedImage original) {
    if (original.getType() == BufferedImage.TYPE_BYTE_BINARY) {
        return original;
    }

    // Quick and unsophisticated way to convert to B/W binary, using default dither and threshold (fixed, 50% I think)
    BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
    Graphics2D g = image.createGraphics();
    try {
        g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
        g.setComposite(AlphaComposite.Src);
        g.drawImage(original, 0, 0, null);
    }
    finally {
        g.dispose();
    }

    return image;
}

我将把它作为练习来编写更高级的解决方案,使用自适应阈值,误差扩散抖动等。

现在,您可以使用以下代码,并且您几乎可以做到这一点:

代码语言:javascript
复制
public static void main(String[] args) throws IOException {
    BufferedImage original = ImageIO.read(new File(args[0]));
    ImageIO.write(toBinary(original), "TIFF", new File("out.tif"));
}

不幸的是,这不会设置X和Y分辨率标签。如果您也需要这样做,那么您必须更深入地挖掘ImageIO应用程序接口,并弄清楚如何使用元数据来控制输出。注意,只有元数据中的一些值可以以这种方式设置。其他值将从传入的图像数据中计算,一些值可能由编写器填充默认值。

您可以使用以下代码( toBinary方法与上面相同):

代码语言:javascript
复制
public static void main(String[] args) throws IOException {
    BufferedImage original = ImageIO.read(new File(args[0]));

    BufferedImage image = toBinary(original);

    ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();

    try (ImageOutputStream stream = ImageIO.createImageOutputStream(new File("out.tif"))) {
        // You may use the param to control compression
        ImageWriteParam param = writer.getDefaultWriteParam();

        IIOMetadata metadata = writer.getDefaultImageMetadata(ImageTypeSpecifier.createFromRenderedImage(image), param);
        Node root = metadata.getAsTree("com_sun_media_imageio_plugins_tiff_image_1.0"); // "javax_imageio_tiff_image_1.0" will work in later versions
        Node ifd = root.getFirstChild();
        // Add X and Y resolution tags
        ifd.appendChild(createResTag("282", "XResolution", "204/1"));
        ifd.appendChild(createResTag("283", "YResolution", "196/1"));

        // Merge changes back to metadata
        metadata.mergeTree("com_sun_media_imageio_plugins_tiff_image_1.0", root);

        // Write full image, with metadata
        writer.setOutput(stream);
        writer.write(null, new IIOImage(image, null, metadata), param);
    }
    finally {
        writer.dispose();
    }
}

private static IIOMetadataNode createResTag(String tagNumber, String tagName, String tagValue) {
    IIOMetadataNode res = new IIOMetadataNode("TIFFField");
    res.setAttribute("number", tagNumber);
    res.setAttribute("name", tagName); // Tag name is optional

    IIOMetadataNode value = new IIOMetadataNode("TIFFRational");
    value.setAttribute("value", tagValue);

    IIOMetadataNode rationals = new IIOMetadataNode("TIFFRationals");
    rationals.appendChild(value);
    res.appendChild(rationals);

    return res;
}

PS: TwelveMonkeys的TIFF插件目前不写PlanarConfiguration: 1,因为这是默认值,没有办法强制它。但这无关紧要,因为在这种情况下,所有兼容的TIFF软件都必须使用默认值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55814194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档