3

我们遇到了一些 TIFF 图像,它们是类型 6 OJPEG 压缩的,许多具有相同的 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”的不同每个样本值

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

我现在让它绕过检查并假设“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 就在某个地方似乎无法获取并成功解压缩:-(

4

2 回答 2

1

25608 的位深度绝对是错误的。JPEG 压缩从不使用每像素 8 位以外的位深度。还有其他图像格式可以使用每像素 16 位甚至 32 位,但对于任何普通应用程序来说,这已经是最高的了。

在JPEG中有RGB图像,即“8 8 8”,CMYK图像,即“8 8 8 8”,和单色图像,即。“8”。

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

如果图像是 RGB,那么标签就是损坏了,修复它会使图像正常工作。(当然假设没有其他任何东西也被破坏了。)

于 2013-02-06T13:21:57.257 回答
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])子句和相应的错误处理代码。我认为这将让您打开文件(如果其中没有其他问题)。

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

于 2013-02-06T16:19:16.333 回答