T6 压缩 Tiff 图像
T6 Compressed Tiff image
我正在尝试读取 JPG 格式的图像文件,在图像中写入文本,
并将其保存为单条压缩 TIFF 图像格式的文件。
我使用 Apache Commons 库来压缩和编写
输出图像文件。我不知道为什么输出图像被绘制成分成两部分,第二部分先绘制。如果有人可以帮助我解决这个问题或指出我在这里做错了什么。谢谢..
这是来自以下代码的示例输入和输出图像...
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 ) { }
}
}
您的代码存在问题,您首先使用 ImageIO 将 BufferedImage
存储为 TIFF 文件,然后压缩 整个文件 以及 header s作为你传递给commons imaging的图像的像素数据:
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 header 和显示为像素的标签...
相反,您可能打算做类似的事情:
// 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);
}
我正在尝试读取 JPG 格式的图像文件,在图像中写入文本, 并将其保存为单条压缩 TIFF 图像格式的文件。 我使用 Apache Commons 库来压缩和编写 输出图像文件。我不知道为什么输出图像被绘制成分成两部分,第二部分先绘制。如果有人可以帮助我解决这个问题或指出我在这里做错了什么。谢谢..
这是来自以下代码的示例输入和输出图像...
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 ) { }
}
}
您的代码存在问题,您首先使用 ImageIO 将 BufferedImage
存储为 TIFF 文件,然后压缩 整个文件 以及 header s作为你传递给commons imaging的图像的像素数据:
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 header 和显示为像素的标签...
相反,您可能打算做类似的事情:
// 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);
}