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

3
我们发现了一些TIFF图像是6型OJPEG压缩的,其中许多具有相同的BitsPerSample值“8 8 8”,并且可以正常工作。
然而,偶尔会看到一些BitsPerSample值为“8 25608 0”的图像。我想知道这是否可能,如果不是,那么它是否是生成TIFF文件的系统中的错误。如果是,他们能否通过简单地修改标签使BitsPerSample变为“8 8 8”来修复呢?
目前,我只找到了一个工具(LEAD)可以通过将它们转换为未压缩的TIFF格式来处理它们,但我不知道它是如何处理的,而且这仅仅是为了解决少数图像的问题所需要的大量开销。
有没有人遇到过这个问题或者对于解决这个问题比我更有经验的人呢?到目前为止,我在Libtiff.net代码中探索的尝试并没有取得太大的成果!
谢谢!
更新:使用Libtiff.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”的不同每样本值

未处理的异常:System.NullReferenceException:对象引用未设置为对象的实例。 在C:\ tiffstuff \ tifftest \ tifftest \ Program.cs的tifftest.Program.Main(String [] args)中:第15行 分段错误

我现在让它绕过检查并假设“BitsPerSample”为8,但现在我正在尝试使用bitmiracle网站上的示例提取图像以保存为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: Missing JPEG tables

结果图像只是100%的绿色。

在修复这个问题方面,我是否已经超出了自己的能力范围?我知道JPEG图片在其中,但似乎无法成功地获取并解压缩它 :-(


你是在处理彩色图像还是灰度图像?我猜如果_SamplesPerPixel_设置为1,你只需要读取一个值,它应该是“8”。这适用于灰度图像。彩色图像使用每个像素3个样本(RGB),每个通道都需要“8”位。你对图像做了什么,并且能否展示出代码中哪里出错了? - John Willemse
它们是RGB图像,我已经在原问题中更新了一些基本代码,问题是我甚至无法打开文件以更改BitsPerSample标签来测试是否将其更改为“8 8 8”会解决问题。一旦成功打开,我只想将其保存为JPEG格式。 - Simon
@Simon,8年过去了,我们现在有解决方案了吗?我的TIF图像采用24位深度的JPEG压缩,而且只能使用LEAD工具将其转换为jpg。任何指导都将是有帮助的。 - Ankit Dhadse
2个回答

1
似乎文件有些损坏。如@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])子句和相应的错误处理代码。我认为这将允许你打开文件(如果没有其他问题)。
你可能想要以某种方式转换或至少修补这些文件。

我得出了类似的结论,但仍然存在问题,请查看我的后续答案。我已相应地更新了问题。 - Simon

1
25608的位深度肯定是错误的。JPEG压缩从不使用每个像素超过8位的位深度。还有其他图像格式可以使用16甚至32位每个像素,但这已经是任何正常应用程序的最高值了。
在JPEG中有RGB图像,即“8 8 8”,CMYK图像,即“8 8 8 8”,以及单色图像,即“8”。
这些图像可能是CMYK格式,你使用的软件可能不支持此格式。在这种情况下,您需要将它们转换为RGB格式才能在该软件中使用它们。
如果这些图像是RGB格式,则标签只是损坏了,修复它将使图像正常工作。(当然,假设没有其他东西也被损坏了。)

太好了,谢谢。我相信它们是RGB图像,我一直在尝试调整Libtiff.net的源代码,因为我显然需要在那里进行更改,因为使用API时,在我有机会更改标签之前,它只是试图打开文件。你或其他人有没有任何指针可以告诉我应该在哪里添加一些代码以覆盖BitsPerSample(如果它损坏)?我承认到目前为止我一直在尝试并且失败了! - Simon
@Simon:抱歉,我从未使用过它,所以无法帮助你。 - Guffa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接