我有几个文件,其中包含一个特定的标题,后面跟着TIFF图像数据。如何将这些TIFF图像数据写入TIFF文件?谢谢你的帮助。
编辑:下面是我测试的内容:
InputStream is = new FileInputStream(filePath);
is.skip(252);
BufferedImage bufferedImage = ImageIO.read(is);
File fileOut = new File(fileOutPath);
ImageIO.write(bufferedImage,"TIFF", fileOut);我跳过文件的特定头(252 bytes )以获得Tiff Image数据字节。但是bufferedImage是空的,所以我得到一个java.lang.IllegalArgumentException: im == null!异常。
在简历中,我有一个没有TIFF头的TIFF文件。TIFF头已被特定的头替换,但图像字节与TIFF文件中的图像字节完全相同。
编辑:多亏了haraldK,我终于可以创建一个TIFF头了。但我无法打开图像,可能是因为压缩:"M2 =修改的读代码II (MRII),即传真组4“。
下面是我创建的标题:
SubFileType (1 Long): Zero
ImageWidth (1 Long): 210
ImageLength (1 Long): 297
BitsPerSample (3 Short): 8, 8, 8
Compression (1 Short): Group 4 Fax (aka CCITT FAX4)
Photometric (1 Short): RGB
StripOffsets (1 Long): 306
SamplesPerPixel (1 Short): 3
RowsPerStrip (1 Short): 297
StripByteCounts (1 Long): 187110
ResolutionUnit (1 Short): None
XResolution (72 Rational):
YResolution (1 Rational): Unexpected numeric
DateTime (20 ASCII): 2014:07:12 10:51:51
Software (28 ASCII): Put your software name here
ImageDescription (30 ASCII): Put an image description here 在合并标头和图像数据之前,我应该解压缩图像数据吗?
发布于 2014-08-09 13:05:34
免责声明:这不是一个完全有效的例子(在这种情况下,我需要一些示例文件来验证),而是概述了这个想法。
首先,打开文件的流,跳过专有的头(您的代码假设您总是可以跳过任意数量的字节,但情况并不总是这样):
InputStream is = new FileInputStream(filePath);
int toSkip = 252;
int skipped = 0;
while (toSkip > 0 && (skipped = is.skip(toSkip)) >= 0) {
toSkip -= skipped;
}然后,根据TIFF规范重新创建一个有效的、最小的TIFF头。这其实并不难:
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(bytes);
dataOut.write('M');
dataOut.write('M'); // "Motorola" (network) byte order
dataOut.writeShort(42); // TIFF magic identifier (42)
dataOut.writeUnsignedInt(8); // Offset to 1st IFD
// ... write IFD, containing minimal info as per the spec由于您的输入数据似乎是双层或黑白传真格式(参考)。注释),请参见规范中的两层图像(第17页)中所需的字段和允许的值。有关普通RGB图像,请参见第6节: RGB全色图像(第24页)。
注意,规范中的short在Java中是(无符号的) int,而LONG是(无符号的)int。还请注意,字段必须以增加的标签顺序写入。RATIONAL可以写成两个长(即两个未签名的ints)。对于XResolution和YResolution,只需编写72/1,因为这是默认的72 DPI。StripOffsets将是IFD +8的长度,用于在IFD之前写入的字节。如果没有条带,将RowsPerStrip设置为ImageLength,而StripByteCounts设置为整个(压缩)图像数据的长度。
对标头进行编码后,合并标头和图像数据,并读取它:
ByteArrayInputStream header = new ByteArrayInputStream(bytes.toByteArray());
InputStream stream = new SequenceInputStream(header, is); // Merge header and image data现在,您可以读取图像:
BufferedImage image = ImageIO.read(stream); // Read image
// TODO: Test that image is non-null before attempting to write但是,如果只将TIFF写回文件,则可以将数据从stream复制到新文件,并尝试在外部工具中打开它。这种方法比用Java解码图像并将其编码回TIFF (ImageIO不需要JAI或其他TIFF插件)要快得多,所需内存也更少:
OutputStream os = new FileOutputStream(new File(...));
byte[] buffer = new byte[1024];
int read;
while ((read = stream.read(buffer) >= 0) {
os.write(0, read, buffer);
}发布于 2014-08-07 10:32:39
您可以尝试使用这样的javax.imageio.ImageIO读/写操作:
ImageIO.write(img, "TIFF", new File('fileName'));或者你可以使用Java高级成像API。
https://stackoverflow.com/questions/25179381
复制相似问题