首页 > 解决方案 > 解压 TIF 文件中的 LZW 图像数据 - 图像数据不是以清晰的代码开头

问题描述

我正在编写一个 C# 库来解释和显示 TIF 文件中的图像,其中图像数据条使用 LZW 压缩进行压缩。我正在使用由另一个应用程序生成的一组 21 个 TIF 文件对其进行测试,我无法控制这些文件。

我在某处读到图像数据应该以清晰的代码开头,但它不在 Adob​​e TIFF6 规范中,我现在找不到它的来源。

在14个测试文件中,图像数据以LZW Clear码值256开头(图像数据中的第一个字节为0x8000,因此1000 0000 0000 0000的前9位为1 0000 0000 = 256十进制)。我可以解压并显示这些没问题。

然而在 7 个文件中,LZW 压缩数据的前两个字节是 0x06FA、0x0712 或 0x097A。显然,这些不是会触发我初始化 LZW 字符串表的清晰代码。即使使用初始 256 值初始化 LZW 字符串表,我也很快遇到 LZW 压缩数据中的代码在字符串表中没有相应的条目,从而导致错误。

0x06FA = 0000 0110 1111 1010 first 9 bits = 0 0000 1101 = 0x0D = 13 decimal
0x0712 = 0000 0111 0001 0010 first 9 bits = 0 0000 1110 = 0x0E = 14 decimal
0x097A = 0000 1001 0111 1010 first 9 bits = 0 0001 0010 = 0x12 = 18 decimal

这些值是否有一些我还没有发现的特殊含义?是否应该将它们视为字符串表中的常规代码?如果是这样,为什么我随后会遇到尚未在字符串表中获得条目的代码?还是我遇到问题的 7 个文件不符合规范?它们在 IrfanView 中显示良好,所以我认为它们确实符合要求。

这是我的解压代码,我尽可能地接近 TIFF6 规范中的算法。

        public byte[] DecompressToBytes()
        {
            List<byte> decompressed = new List<byte>();
            int oldCode = 0;
            int code = 0;
            string entry;

            // Just in case the first code we encounter isn't the clearcode.
            initializeDictionary();

            // getNextCode decides whether to read a 9, 10, 11 or 12 bit value
            // based on size of string table Dictionary.
            while(((code = getNextCode()) != EndOfInformation))     // EndOfInformation = 257
            {
                if(code == ClearCode)                               // ClearCode = 256
                {
                    initializeDictionary();
                    code = getNextCode();
                    if(code == EndOfInformation)
                        break;
                    entry = Dictionary[code];
                    // convert string (eg "0A0B0C") to bytes and add to output.
                    addBytes(decompressed, entry);                  
                    oldCode = code;
                }
                else
                {
                    if(Dictionary.ContainsKey(code))
                    {
                        entry = Dictionary[code];
                        addBytes(decompressed, entry);
                        Dictionary.Add(Dictionary.Count, stringFromCode(oldCode) + stringFromCode(code).Substring(0, 2));
                        oldCode = code;
                    }
                    else
                    {
                        entry = stringFromCode(oldCode) + stringFromCode(oldCode).Substring(0, 2);
                        addBytes(decompressed, entry);
                        Dictionary.Add(Dictionary.Count, entry);
                        oldCode = code;
                    }
                }
            }
            return decompressed.ToArray();
        }

标签: c#compressiontifflzw

解决方案


只是为了关闭它,我误解了规范。导致我出现问题的文件具有多个条带中的图像数据。我认为图像数据的开始实际上是各个条带偏移的开始。


推荐阅读