Libtiff-不同的BitsPerSample-有效或有缺陷的tiff标记

本文关键字:有缺陷 tiff 标记 BitsPerSample- Libtiff- 有效 | 更新日期: 2023-09-27 17:57:51

我们遇到了一些经过类型6 OJPEG压缩的TIFF图像,许多图像的BitsPerSample相同,为"8 8 8",工作正常。

然而,我们偶尔会看到BitsPerSample值为"8 25608 0"的示例。我想知道这是否可能,如果不可能,是否是生成TIFF的系统中的错误。如果是这样的话,可以通过简单地修改标签使BitsPerSample为"8 8 8"来修复它们吗?

目前,我只找到了一个工具(LEAD),可以通过将它们转换为未压缩的TIFF来处理它们,显然我不知道它是如何做到这一点的,而且仅仅解决少数图像的问题是一个很大的开销。

有没有人遇到过这个问题,或者比我更了解这个问题的解决方法是简单还是复杂,到目前为止,我在Libtiff.net代码中的尝试并没有很有成效!

干杯

更新:将litiff.net与一起使用

    static void Main(string[] args)
    {
        using (Tiff image = Tiff.Open(args[0], "r"))
        {
            FieldValue[] value = image.GetField(TiffTag.IMAGEWIDTH);
            int width = value[0].ToInt();
            Console.WriteLine(string.Format("Width = {0}", width));
        }
    }

结果(显然跳过了异常处理!):

ReadDirectory:警告,10.TIF:遇到标记为33000(0x80e8)的未知字段10.TIF:无法为字段"BitsPerSample"处理不同的每个样本值

未处理的异常:系统。NullReferenceException:对象引用未设置为对象的实例。在tifftest。程序C:''tiffstuf''tifftest''tifftest''Program.cs:line 15中的Main(String[]args)分段故障

我现在让它绕过检查,假设"BitsPerSample"为8,但我现在正试图提取图像以保存为BMP,使用比特奇迹网站上的示例:

            using (Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb))
            {
                Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                byte[] bits = new byte[bmpdata.Stride * bmpdata.Height];
                for (int y = 0; y < bmp.Height; y++)
                {
                    int rasterOffset = y * bmp.Width;
                    int bitsOffset = (bmp.Height - y - 1) * bmpdata.Stride;
                    for (int x = 0; x < bmp.Width; x++)
                    {
                        int rgba = raster[rasterOffset++];
                        bits[bitsOffset++] = (byte)((rgba >> 16) & 0xff);
                        bits[bitsOffset++] = (byte)((rgba >> 8) & 0xff);
                        bits[bitsOffset++] = (byte)(rgba & 0xff);
                    }
                }
                System.Runtime.InteropServices.Marshal.Copy(bits, 0, bmpdata.Scan0, bits.Length);
                bmp.UnlockBits(bmpdata);
                bmp.Save("c:''tiffstuff''TiffTo24BitBitmap.bmp");
            }

我显然收到了OJPEG警告,然后收到了以下信息:OJPEGReadHeaderInfoSecTablesQTable:缺少JPEG表

生成的图像只有100%的绿色。

我是不是太力不从心了?我知道JPEG在那里的某个地方,似乎无法成功地对其进行解压缩:-(

Libtiff-不同的BitsPerSample-有效或有缺陷的tiff标记

25608的位深度绝对是错误的。JPEG压缩从不使用每像素8位以外的位深度。还有其他图像格式可以使用每像素16位甚至32位,但这与任何正常应用程序一样高。

在JPEG中,有RGB图像,即"8 8 8",CMYK图像,即8 8 8 8,单色图像。

图像可能是CMYK,而您使用的软件不支持这种情况。在这种情况下,您需要将它们转换为RGB才能与该软件一起使用。

如果图像是RGB,那么标签就是损坏的,修复它会使图像正常工作。(当然,假设没有其他事情发生。)

文件似乎是半损坏的。如@Guffa所述,对于OJPEG文件,每个样本值的位应为8 8 8(RGB)或8 8 8 8(CMYK)

不幸的是,LibTiff。Net没有机会修复像BITSPERSAMPLE这样的重要标签。

我看到的唯一选项是将此类文件的自动更正代码添加到库中。

给出错误的代码在Tiff_DirRead.cs文件中(如下所示的三个位置)。

private bool fetchPerSampleShorts(TiffDirEntry dir, out short pl)
{
    ...
    for (ushort i = 1; i < check_count; i++)
    {
        if (v[i] != v[0])
        {
            ErrorExt(this, m_clientdata, m_name,
                "Cannot handle different per-sample values for field '"{0}'"",
                FieldWithTag(dir.tdir_tag).Name);
            failed = true;
            break;
        }
    }
    ...
}
private bool fetchPerSampleLongs(TiffDirEntry dir, out int pl)
{
    ...
    for (ushort i = 1; i < check_count; i++)
    {
        if (v[i] != v[0])
        {
            ErrorExt(this, m_clientdata, m_name,
                "Cannot handle different per-sample values for field '"{0}'"",
                FieldWithTag(dir.tdir_tag).Name);
            failed = true;
            break;
        }
    }
    ...
}
private bool fetchPerSampleAnys(TiffDirEntry dir, out double pl)
{
    ...
    for (ushort i = 1; i < check_count; i++)
    {
        if (v[i] != v[0])
        {
            ErrorExt(this, m_clientdata, m_name,
                "Cannot handle different per-sample values for field '"{0}'"",
                FieldWithTag(dir.tdir_tag).Name);
            failed = true;
            break;
        }
    }
    ...
}

您可以尝试删除if (v[i] != v[0])子句和相应的错误处理代码。我想这会让你打开文件(如果没有其他问题的话)。

您可能希望以某种方式转换或至少修补此类文件。