如何从TIFF图像数据创建TIFF文件 [英] How to create a TIFF file from TIFF image data

查看:471
本文介绍了如何从TIFF图像数据创建TIFF文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个文件包含一个特定的标题,后跟TIFF图像数据。
如何将这些TIFF图像数据写入TIFF文件?
感谢您的帮助。

I have got several files that contains a specific header follows by TIFF image data. How can I write those TIFF image data into a TIFF file ? Thanks for your help.

编辑:这是我测试的:

InputStream is = new FileInputStream(filePath);
is.skip(252);
BufferedImage bufferedImage = ImageIO.read(is);
File fileOut = new File(fileOutPath);
ImageIO.write(bufferedImage,"TIFF", fileOut);

我跳过文件的特定标题(252Bytes)以获取Tiff图像数据字节。
但是bufferedImage为null所以我得到了一个java.lang.IllegalArgumentException:im == null!例外。

I skip the specific header of the file (252Bytes) to get the Tiff Image data bytes. But the bufferedImage is null so I get a java.lang.IllegalArgumentException: im == null! exception.

在简历中,我有一个没有TIFF标题的TIFF文件。 TIFF标题已替换为特定的一个,但图像字节与TIFF文件完全相同。

In resume, I have a TIFF file without a TIFF header. The TIFF header has been replace by a specific one but the image bytes are exactly the same as in a TIFF file.

编辑:
感谢haraldK,我最后可以创建一个TIFF标题。但我无法打开图像,可能是因为压缩:M2 =修改后的读码II(MRII),即传真组4。

EDIT : Thanks to haraldK, I can finally create a TIFF header. But I can't open the image, maybe it is because of the compression : "M2 = Modified Read Code II (MRII), i.e., fax group 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 

我应该在合并标题和图像数据之前解压缩图像数据吗?

Should I uncompress the image data before merging the header and the image data ?

推荐答案

免责声明:这不是一个完全有效的例子(在这种情况下我需要一些示例文件来验证),但ra概述了这个想法。

Disclaimer: This isn't a fully working example (I would need some sample files to verify in that case), but rather outlines the idea.

首先,打开一个文件流,然后跳过专有标题(你的代码假定你总是可以跳过你喜欢的字节数,但是情况并非总是如此):

First, open a stream to the file, and skip the proprietary header (your code assumes that you can always skip as many bytes you like, but that's not always the case):

InputStream is = new FileInputStream(filePath);

int toSkip = 252;
int skipped = 0;

while (toSkip > 0 && (skipped = is.skip(toSkip)) >= 0) {
    toSkip -= skipped;
}

然后,根据<重新创建有效的最小TIFF标头a href =https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf =nofollow> TIFF规范。这实际上并不太难:

Then, re-create a valid, minimal TIFF header, according to the TIFF specification. This is actually not too hard:

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

由于您的输入数据似乎是双层或黑/白传真格式(参考注释),请参阅规范中的第3节:双层图像(第17页),了解所需字段和允许值。有关普通RGB图像,请参阅第6节:RGB全彩色图像(第24页)。

As your input data seems to be in bilevel or black/white fax format (ref. comments), see Section 3: Bilevel Images (page 17) in the spec for the required fields and allowed values. For normal RGB images, see Section 6: RGB Full Color Images (page 24).

请注意,规范中的SHORT是(无符号)在Java中,但LONG是(无符号) int 。另请注意,必须按增加的标记顺序写入字段。 RATIONAL可以写成两个LONG(即两个未签名的 int s)。对于 XResolution YResolution ,只需写入72/1,因为这是默认的72 DPI。 StripOffsets 将是在IFD之前写入的字节的IFD + 8的长度。如果您没有条带,请设置 RowsPerStrip 等于 ImageLength StripByteCounts 等于整个(压缩)图像数据的长度。

Note that SHORT in the spec is (unsigned) short in Java, but LONG is (unsigned) int. Also note that fields must be written in increasing tag order. RATIONAL can be written as two LONGs (i.e., two unsigned ints). For XResolution and YResolution, just write 72/1 as this is default 72 DPI. StripOffsets will be the length of the IFD + 8 for the bytes written before the IFD. If you don't have strips, set RowsPerStrip equal to ImageLength and StripByteCounts equal to the length of the entire (compressed) image data.

完成对标题的编码后,合并标题和图像数据,然后读取它:

When done encoding the header, merge the header and the image data, and read it:

ByteArrayInputStream header = new ByteArrayInputStream(bytes.toByteArray());
InputStream stream = new SequenceInputStream(header, is); // Merge header and image data

现在,您可以阅读图像:

Now, you could read the image:

BufferedImage image = ImageIO.read(stream); // Read image

// TODO: Test that image is non-null before attempting to write

但是,如果您只将TIFF写回文件,则只需将 stream 中的数据复制到新文件中,然后尝试打开它在外部工具中。与在Java中解码图像,然后将其编码回TIFF(并且不需要JAI或ImageIO的其他TIFF插件)相比,这种方法将更快,所需内存更少:

However, if you are only writing the TIFF back to a file, you could just copy the data from stream to a new file, and try to open it in an external tool. This approach will be much faster and require less memory than decoding the image in Java, and then encoding it back to TIFF (and doesn't need JAI or other TIFF plugin for ImageIO):

OutputStream os = new FileOutputStream(new File(...));

byte[] buffer = new byte[1024];
int read;

while ((read = stream.read(buffer) >= 0) {
   os.write(0, read, buffer);
}

这篇关于如何从TIFF图像数据创建TIFF文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆