【问题标题】:T6 Compressed Tiff imageT6 压缩 Tiff 图像
【发布时间】:2020-04-05 10:30:56
【问题描述】:

我正在尝试读取 JPG 格式的图像文件,将文本写入图像, 并将其以单条压缩 TIFF 图像格式保存到文件中。 我使用 Apache Commons 库进行压缩和编写 输出图像文件。我不知道为什么输出图像被绘制成两部分,第二部分首先绘制。如果有人可以帮助我解决这个问题或指出我在这里做错了什么。谢谢..

这是来自以下代码的示例输入和输出图像...

sample image

FileOutputStream      fos  = null;
BufferedOutputStream  os   = null;
ByteArrayOutputStream baos = null;

try {

    String          inputPath    = "D:\\Test\\input.jpg";
    File            inputFile    = new File(inputPath);

    BufferedImage   inputImage   = ImageIO.read(inputFile);

    int             width        = inputImage.getWidth();
    int             height       = inputImage.getHeight();

    BufferedImage   outputImage  = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);

    Font font = new Font("Arial", Font.BOLD, 40 );
    java.awt.Graphics2D g2 = outputImage.createGraphics();
    g2.setFont( font );
    g2.setColor ( Color.BLACK );
    g2.drawImage ( inputImage, 0, 0, width, height, Color.WHITE, null);
    g2.drawString("TEST TEXT", 20, 40);
    g2.dispose();

    PixelDensity        resolution   = PixelDensity.createFromPixelsPerInch ( 200, 200);
    double              resolutionX  = resolution.horizontalDensityInches();
    double              resolutionY  = resolution.verticalDensityInches();
    RationalNumber      rationalNumX = RationalNumber.valueOf ( resolutionX );
    RationalNumber      rationalNumY = RationalNumber.valueOf ( resolutionY );

    TiffOutputSet       outputSet    = new TiffOutputSet(ByteOrder.LITTLE_ENDIAN);
    TiffOutputDirectory directory    = outputSet.addRootDirectory();

    baos = new ByteArrayOutputStream(); 
    ImageIO.write(outputImage, "tif", baos); 
    byte[] bytes = baos.toByteArray();

    byte[] compressedBytes = T4AndT6Compression.compressT6(bytes, width, height);

    TiffImageData.Data data = new TiffImageData.Data(0, compressedBytes.length, compressedBytes);

    TiffElement.DataElement[] dataElements = new TiffElement.DataElement[]{ data };

    TiffImageData tiffImageData = new TiffImageData.Strips(dataElements, height);

    directory.add ( TiffTagConstants.TIFF_TAG_NEW_SUBFILE_TYPE,                   1    );
    directory.add ( TiffTagConstants.TIFF_TAG_PHOTOMETRIC_INTERPRETATION, (short) 1    );
    directory.add ( TiffTagConstants.TIFF_TAG_COMPRESSION,                (short) 4    );
    directory.add ( TiffTagConstants.TIFF_TAG_BITS_PER_SAMPLE,            (short) 1    );
    directory.add ( TiffTagConstants.TIFF_TAG_RESOLUTION_UNIT,            (short) 2    );
    directory.add ( TiffTagConstants.TIFF_TAG_ROWS_PER_STRIP,             height       );
    directory.add ( TiffTagConstants.TIFF_TAG_IMAGE_WIDTH,                width        );
    directory.add ( TiffTagConstants.TIFF_TAG_IMAGE_LENGTH,               height       );
    directory.add ( TiffTagConstants.TIFF_TAG_XRESOLUTION,                rationalNumX );
    directory.add ( TiffTagConstants.TIFF_TAG_YRESOLUTION,                rationalNumY );

    directory.setTiffImageData( tiffImageData );

    String outputPath = "D:\\Test\\output.tif";
    File outputFile = new File(outputPath);

    fos = new FileOutputStream(outputFile);
    os   = new BufferedOutputStream(fos);

    new TiffImageWriterLossy().write( os, outputSet );


} catch (IOException ex) {

    Logger.getLogger(JavaApplication7.class.getName()).log(Level.SEVERE, null, ex);

}   catch (ImageWriteException ex) {

    Logger.getLogger(JavaApplication7.class.getName()).log(Level.SEVERE, null, ex);

} finally {

    if ( baos != null ) {
        try { 
            baos.flush();   
            baos.close();   
        } catch ( IOException ex ) { }
    }
    if ( os != null ) {
        try { 
            os.flush();   
            os.close();   
        } catch ( IOException ex ) { }
    }
    if ( fos != null ) {
        try { 
            fos.flush();   
            fos.close();   
        } catch ( IOException ex ) { }
    }

}

【问题讨论】:

  • 您正在创建图像,然后将其保存,然后在某些查看器应用程序中查看保存的图像,例如 Windows 中的 Paint,对吗?如果是这样,那么我建议查看您在 Java 中创建的 BufferedImage 以查看创建的图像是否如您所愿。也许在JLabel 中显示图像。
  • 链接中的示例图像实际上是原始图像和从显示压缩图像输出的 JLabel 屏幕截图中截取的裁剪图像的组合。
  • 我觉得这有点奇怪,因为当我尝试一点一点地调整缓冲图像大小直到它开始以 0.0 点的位置绘制图像时,我得到了我想要的结果。整数宽度 = 输入图像。获取宽度();整数高度 = 输入图像。获取高度();宽度 += ( ( 宽度 \100 ) * 8 ) ; \\ 添加 8% 高度 += ( ( 高度 \100 ) * 8 ) ; \\ add 8% 但是当我尝试将其他输入图像文件的大小增加 8% 时,输出图像结果不正确。我不知道为什么压缩后看起来图像大小发生了变化。

标签: java tiff apache-commons javax.imageio


【解决方案1】:

您的代码的问题在于您首先使用 ImageIO 将 BufferedImage 存储为 TIFF 文件,然后将 整个文件 连同标题一起压缩为您传递给公共的图像的像素数据成像:

baos = new ByteArrayOutputStream(); 
ImageIO.write(outputImage, "tif", baos); 
byte[] bytes = baos.toByteArray(); // <-- This is not pixel data, but a complete TIFF file

byte[] compressedBytes = T4AndT6Compression.compressT6(bytes, width, height);

这实际上与您期望的图像相似的原因是 ImageIO 写入未压缩的图像数据。图片前面的垃圾线和偏移量是 TIFF 标头和显示为像素的标签...

相反,您可能打算执行以下操作:

// Cast is safe here, as you know outputImage is TYPE_BYTE_BINARY
byte[] bytes = ((DataBufferByte) outputImage.getRaster().getDataBuffer()).getData();
byte[] compressedBytes = T4AndT6Compression.compressT6(bytes, width, height);

这将只压缩像素,您的图像应该没问题。


您也可以仅使用 ImageIO 完成所有操作,并通过执行以下操作避免对公共映像的额外依赖:

try (ImageOutputStream stream = ImageIO.createImageOutputStream(outputFile)) {
    ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromRenderedImage(outputImage);
    ImageWriter writer = ImageIO.getImageWriters(imageTypeSpecifier, "TIFF").next();
    writer.setOutput(stream);

    ImageWriteParam param = writer.getDefaultWriteParam();
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    param.setCompressionType("CCITT T.6");

    IIOMetadata metadata = writer.getDefaultImageMetadata(imageTypeSpecifier, param);
    // TODO: Set 200 DPI, default is likely 72, and perhaps subfile type if needed, 
    // other tags will be set correctly for you

    writer.write(null, new IIOImage(outputImage, null, metadata), param);
}

【讨论】:

  • 非常感谢 HaraldK。你是我的救世主...我会学习您的建议并尝试使用它...再次感谢您...
  • 仅使用 ImageIO 的解决方案对我来说就像一个魅力!非常感谢!
猜你喜欢
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多