首页 文章

有没有办法控制在比特深度= 1(黑白)的TIFF-PNG转换中哪些像素变黑(阈值)

提问于
浏览
0

好吧,在将图像从TIFF转换为PNG格式的过程中,我真的希望最终图像尽可能小,所以我将位深度设置为1(黑白),我正在使用签名图像 . 我的问题是我“丢失”一些像素,因为在原始图像中“太白”并且转换过程忽略了它们 .

我想要的是一种告诉PNG编码器在图像中应用threshold的方法,例如,如果灰度级大于240,那么它是白色的,如果不是黑色的话 . 或者也许任何其他方式,图像不会丢失很多像素,因为图像是签名,我必须在浏览器中显示它 . 这是一个示例:

sample signature

这是我用来将图像从TIFF转换为PNG格式的代码:

public byte[]tiffToPng(byte[]tiffBytes) throws IOException {

    SeekableStream stream = new ByteArraySeekableStream(tiffBytes);
    ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", stream, null);
    RenderedImage renderedImage = decoder.decodeAsRenderedImage(0);

    PNGEncodeParam pngEncodeParam = PNGEncodeParam.getDefaultEncodeParam(renderedImage);
    pngEncodeParam.setBitDepth(1);

    ByteArrayOutputStream pngBytesStream = new ByteArrayOutputStream();
    ImageEncoder encoder = ImageCodec.createImageEncoder("png", pngBytesStream, pngEncodeParam);
    encoder.encode(renderedImage);
    pngBytesStream.flush();
    return pngBytesStream.toByteArray();
}

2 回答

  • 1

    好吧,过了一段时间,我首先制作了conversion of the RenderedImage to a BufferedImage,然后在RGB值上循环并完成阈值处理 . 最后,我将得到的图像编码为PNG(比特深度= 1) . 就是这个:

    public byte[]tiffToPng(byte[]tiffBytes) throws IOException {
        SeekableStream stream = new ByteArraySeekableStream(tiffBytes);
        ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", stream, null);
        RenderedImage tiffRenderedImage = decoder.decodeAsRenderedImage(0);
    
        BufferedImage tiffBufferedImage = toBufferedImage(tiffRenderedImage);
        for (int y = 0; y < tiffBufferedImage.getHeight(); y++) {
            for (int x = 0; x < tiffBufferedImage.getWidth(); x++) {
                int rgb = tiffBufferedImage.getRGB(x, y);
                int a = (rgb>>24)&0xFF;
                int r = (rgb>>16)&0xFF;
                int g = (rgb>>8)&0xFF;
                int b = (rgb>>0)&0xFF;
                if(a == 0xFF && r == g && g == b) {
                    if(r < 254) {
                        tiffBufferedImage.setRGB(x, y, 0xFF000000);
                    } else {
                        tiffBufferedImage.setRGB(x, y, 0xFFFFFFFF);
                    }
                }
            }
        }
    
        PNGEncodeParam pngEncodeParam = PNGEncodeParam.getDefaultEncodeParam(tiffBufferedImage);
        pngEncodeParam.setBitDepth(1);
        ByteArrayOutputStream pngBytesStream = new ByteArrayOutputStream();
        ImageEncoder encoder = ImageCodec.createImageEncoder("png", pngBytesStream, pngEncodeParam);
        encoder.encode(tiffBufferedImage);
        pngBytesStream.flush();
        return pngBytesStream.toByteArray();
    }
    
    public BufferedImage toBufferedImage(RenderedImage img) {
            if (img instanceof BufferedImage) {
                return (BufferedImage) img;
            }
            ColorModel cm = img.getColorModel();
            int width = img.getWidth();
            int height = img.getHeight();
            WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
            boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
            Hashtable properties = new Hashtable();
            String[] keys = img.getPropertyNames();
            if (keys != null) {
                for (int i = 0; i < keys.length; i++) {
                    properties.put(keys[i], img.getProperty(keys[i]));
                }
            }
            BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties);
            img.copyData(raster);
            return result;
        }
    

    这是最终的形象:

    signature succesfully converted PNG 1 bit depth

  • 0

    你想要做的更多的是图像预处理,我不希望编码器允许这样做 . 只需预处理图像(亮度/对比度和/或伽玛)并保存即可 .

相关问题