如何从JPEG压缩的TIFF文件中提取图像?Jpeg from Tiff(jpeg-compressed)
我已经根据StripOffests和StripBytesCount字段读取字节,但我无法从它们加载图像。
如何从JPEG压缩的TIFF文件中提取图像?Jpeg from Tiff(jpeg-compressed)
我已经根据StripOffests和StripBytesCount字段读取字节,但我无法从它们加载图像。
旧式TIFF-JPEG(压缩类型6)基本上在TIFF包装器内填充了一个普通的JFIF文件。新型TIFF-JPEG(压缩类型7)允许将JPEG表格数据(Huffman,量化)存储在单独的标签(0x015B JPEGTables)中。这允许您在文件中放入带有SOI/EOI标记的JPEG数据条,而无需重复Huffman和Quantization表。这可能是你看到你的文件。单条开始于序列FFD8,但缺少霍夫曼和量化表。这是Photoshop产品通常写入文件的方式。
我试图在图像数据的开头添加量化表,但它没有帮助。我必须在哪里插入该表格? – user393679 2011-04-21 22:21:57
霍夫曼表怎么样?图像是否分成多个条。你想每个带1 JPEG文件?添加更多细节。 – BitBank 2011-04-22 04:34:21
有1个JPEG分成多个条。 – user393679 2011-04-22 05:28:20
如果您试图从TIFF,JPEG或其他文件中提取实际图像,最好使用库如libtiff这样做。 TIFF是一个非常复杂的规范,虽然你自己也可以做到这一点,并获得一到两类图像,但你可能无法处理经常出现的其他情况,特别是“旧式”JPEG是在TIFF中加入的子格式,并且不适合整体。
我的公司,Atalasoft,使.NET产品,包括一个非常好的TIFF编解码器。如果您只需要担心单页图像,我们的免费产品将适合您。
在.NET领域,你也可以看看Bit Miracle的libtiff的托管版本。这是一个相当不错的图书馆港口。
谢谢你的回答。我无法使用任何库。我只在解析新式JPEG压缩的TIFF时很有趣。你能告诉我,根据StripOffests和StripBytesCount字段,我从TIFF文件中检索到的JPEG压缩数据有什么问题? – user393679 2011-04-21 13:17:37
我看到它包含jpeg的开始标记:X0FFD8,但为什么它不能打开。我必须用这些数据来操作什么来获得图像? – user393679 2011-04-21 13:25:17
使用JAI:
int TAG_COMPRESSION = 259;
int TAG_JPEG_INTERCHANGE_FORMAT = 513;
int COMP_JPEG_OLD = 6;
int COMP_JPEG_TTN2 = 7;
SeekableStream stream = new ByteArraySeekableStream(imageData);
TIFFDirectory tdir = new TIFFDirectory(stream, 0);
int compression = tdir.getField(TAG_COMPRESSION).getAsInt(0);
// Decoder name
String decoder2use = "tiff";
if (compression == COMP_JPEG_OLD) {
// Special handling for old/unsupported JPEG-in-TIFF format:
// {@link: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4929147 }
stream.seek(tdir.getField(TAG_JPEG_INTERCHANGE_FORMAT).getAsLong(0));
decoder2use = "jpeg";
}
// Decode image
ImageDecoder dec = ImageCodec.createImageDecoder(decoder2use, stream, null);
RenderedImage img = dec.decodeAsRenderedImage();
的最佳解决方案,对我帮助很大。 只需添加,如果您在TIFF中有多个页面,则必须重复读取流,并在TIFFDirectory
对象中定义不同的目录号,然后重复上述所有操作。
TIFFDirectory tdir = new TIFFDirectory(stream, 1);
非凡。谢谢你的救星。 – Adrian 2014-10-14 12:11:56
与提到的库的libtiff的问题是,它提取图像和然后将其保存再压缩,这意味着在JPG的情况下的另一质量损失。这就是说,即使不使用第三方库,也可以通过调用NET Framework的GDI +方法来完成相同的任务。
此线程的初始作者尝试获取jpeg二进制文件而无需重新压缩它,这正是我所要做的。
这是一个可能的解决方案,如果你能提供优质的损失住,不想使用干啥,但.NET类库:
public static int SplitMultiPage(string sourceFileName, string targetPath)
{
using (Image multipageTIFF = Image.FromFile(sourceFileName))
{
int pageCount = multipageTIFF.GetFrameCount(FrameDimension.Page);
if (pageCount > 1)
{
string sFileName = Path.GetFileNameWithoutExtension (sourceFileName);
for (int i = 0; i < pageCount; i++)
{
multipageTIFF.SelectActiveFrame(FrameDimension.Page, i);
// ein einzelner Frame könnte auch ein anderes Format haben, z.B. JPG, PNG, BMP, etc.
// Damit die Datei die korrekte Endung bekommt, holen wir uns eine Endung aus der Beschreibung des Codecs
// Interessanterweise liefert uns das RawFormat im Fall TIFF (der einzige Multiframefall) immer den Codec für TIFF,
// statt den des Frames
ImageCodecInfo codec = Helpers.GetEncoder(multipageTIFF.RawFormat);
string sExtension = codec.FilenameExtension.Split(new char[] { ';' })[0];
sExtension = sExtension.Substring(sExtension.IndexOf('.') + 1);
string newFileName = Path.Combine(targetPath, string.Format("{0}_{1}.{2}", sFileName, i + 1, sExtension));
EncoderParameters encoderParams = new EncoderParameters(2);
encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.LastFrame);
// für TIF 1 Bit machen wir CompressionCCITT4 Kompression, da das die besten Ergebnisse liefert
switch (GetCompressionType(multipageTIFF))
{
case 1: // No compression -> BMP?
encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionNone);
break;
case 2: // CCITT modified Huffman RLE 32773 = PackBits compression, aka Macintosh RLE
encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionRle);
break;
case 3: // CCITT Group 3 fax encoding
encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT3);
break;
case 4: // CCITT Group 4 fax encoding
encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT4);
break;
case 5: // LZW
encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW);
break;
case 6: //JPEG ('old-style' JPEG, later overriden in Technote2)
case 7: // Technote2 overrides old-style JPEG compression, and defines 7 = JPEG ('new-style' JPEG)
{
codec = Helpers.GetEncoder(ImageFormat.Jpeg);
encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90);
}
break;
}
multipageTIFF.Save(newFileName, codec, encoderParams);
}
}
return pageCount;
}
}
所使用的辅助方法:
public static ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
读压缩标志:
public static int GetCompressionType(Image image)
{
/* TIFF Tag Compression
IFD Image
Code 259 (hex 0x0103)
Name Compression
LibTiff name TIFFTAG_COMPRESSION
Type SHORT
Count 1
Default 1 (No compression)
Description
Compression scheme used on the image data.
The specification defines these values to be baseline:
1 = No compression
2 = CCITT modified Huffman RLE
32773 = PackBits compression, aka Macintosh RLE
Additionally, the specification defines these values as part of the TIFF extensions:
3 = CCITT Group 3 fax encoding
4 = CCITT Group 4 fax encoding
5 = LZW
6 = JPEG ('old-style' JPEG, later overriden in Technote2)
Technote2 overrides old-style JPEG compression, and defines:
7 = JPEG ('new-style' JPEG)
Adobe later added the deflate compression scheme:
8 = Deflate ('Adobe-style')
The TIFF-F specification (RFC 2301) defines:
9 = Defined by TIFF-F and TIFF-FX standard (RFC 2301) as ITU-T Rec. T.82 coding, using ITU-T Rec. T.85 (which boils down to JBIG on black and white).
10 = Defined by TIFF-F and TIFF-FX standard (RFC 2301) as ITU-T Rec. T.82 coding, using ITU-T Rec. T.43 (which boils down to JBIG on color).
*/
int compressionTagIndex = Array.IndexOf(image.PropertyIdList, 0x103);
PropertyItem compressionTag = image.PropertyItems[compressionTagIndex];
return BitConverter.ToInt16(compressionTag.Value, 0);
}
此方法:public static int GetCompressionType(Image image)应以“返回BitConverter.ToUInt16(compressionTag.Value,0);”结尾因为您不需要由于返回的16位数组而产生有符号整数。 – 2013-03-08 18:36:54
您是否在寻找压缩图片的数据,或者您正在寻找真实图片? – plinth 2011-04-20 17:24:09
我在寻找实际的图片 – user393679 2011-04-20 18:33:16