【问题标题】:Using LibTiff from C# (to access tiled TIFF images)使用 C# 中的 LibTiff(访问平铺的 TIFF 图像)
【发布时间】:2020-08-07 18:57:41
【问题描述】:

我想使用 LibTiff 访问非常大的 TIFF 文件。我需要多个页面和图块之类的功能,因此 LibTiff 似乎是正确的方法。任何人都可以帮助我如何使用 C# 中的 LibTiff 吗?我找到了一些链接(例如包含部分代码的blog.bee-ee。但我无法获得一个版本。我查看了FreeImage,但发现它不合适(图片约为 800 MPixel 8 或 16位灰度 --> 800-1600 MByte) 大小,我无法在 32 位环境中将其加载到内存中)

我在 C/C++ 方面非常有经验,但在 C# 方面还没有。谁能帮我做一个包装或一些提示?

注意:我需要页面来访问 tiff 中的金字塔平面(多分辨率),以及 256x256 的图块,以便快速访问图像的不同部分而无需立即加载。

[编辑]LibTIFF.NET 解决方案对我来说似乎最实用。我现在将它集成到产品开发中,它可能会为我省去很多关于进出托管内存的麻烦。我还没有尝试过“回调”功能,这似乎可以通过 .net 方式很好地解决。 感谢您对 stackoverflow 的帮助 [/编辑]

【问题讨论】:

    标签: c# .net libtiff libtiff.net


    【解决方案1】:

    您可以尝试我们的 LibTiff.Net。它是使用托管 C# 编写的 LibTiff 的免费和开源版本。我们实现的 API 与原来的非常相似。

    https://bitmiracle.com/libtiff/

    我们刚刚发布了它,所以可能存在错误。但是完整的源代码带有一些测试,所以最明显的错误应该被修复。

    【讨论】:

    • 谢谢。我的第一次测试看起来不错。虽然我找到了一个包装类,但它没有已知的作者,我迟早会遇到访问托管/非托管内存资源的一些问题。基准测试向我展示了读取非压缩文件的同等性能,并且在 Adob​​e 压缩的金字塔平铺 tiff 上的性能达到了 50%。这对我来说是可以接受的。我可能决定不使用压缩,而且我最好让我的软件多核友好而不是解决内存问题。
    • 谢谢,Adriaan,我们的实现肯定比原来选择的语言要慢 :-)
    • 我不介意。对于我的项目性能意味着功能/欧元。开发时间占成本的 95%。我可以很容易地投入一个四核来弥补这一点。此外,当我远离压缩时,差异很小。而且我的文件只压缩了大约 10%,所以每个文件只有糟糕的 100MByte ;-)
    【解决方案2】:

    WIC 支持非常大的图像文件。 .NET 框架中有一个很好的包装器:TiffBitmapDecoder。

    【讨论】:

    • 你能添加一些链接吗?从我所见,TiffBitmapDecoder 尝试一次将图像加载到内存中。我不能那样做。由于碎片,大于 1 GB 的图片在 32 位机器上总是会失败。你指的是 windows7-specifics (msdn.microsoft.com/en-us/library/ee720061%28VS.85%29.aspx)?
    • 不,待定不存储图像。从这里开始:msdn.microsoft.com/en-us/library/ms748873.aspx
    • 感谢您的帮助。不幸的是,我的经历不同。 msdn.microsoft.com/en-us/library/ms748873.aspx 中概述的步骤确实尝试分配具有位图 1 帧大小的单个内存块。我需要访问位图中的每个像素(因此没有适合屏幕的内存保存选项),只是不一定在一块内存中。当我尝试运行示例中给出的 tiff 解码器时,它通常在位图 > 10k * 10k 上失败。这些只是我的“小测试文件”。我的目标是 800MPixel x 16 位。这就是我寻找平铺 TIFF 文件的原因。
    • Hmya,您无法在 32 位操作系统上加载 400 MB 的图像。切换到 64 位操作系统或分段读取图像。
    • 是的。这就是我研究瓷砖的原因。切换到 64 位操作系统将解决部分问题,但在进行任何处理之前读取整个文件仍然会有很大的延迟。现在硬盘比cpu慢。我也喜欢金字塔 tiff 文件的可能性(即在同一个文件中准备好低分辨率图像以供预览等)
    【解决方案3】:

    我最初的解决方案是为 LibTIFF DLL 使用 C#.NET 包装器。我在libtiff ftp 上找到了它。它似乎包含了 LIBTiff 库的所有重要方法。它将内存保存在非托管的 LibTIFF 内存中;这意味着 C# 代码需要意识到这一点,并在需要以安全代码处理数据时复制数据。

    我的“瓷砖阅读代码”来测试它的阅读方式

    if (LibTIFF.IsTiled(tiff))
    {
        if (LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_TILEWIDTH, out tileWidth) &&
            LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_TILELENGTH, out tileLength))
        {
            uint tiles = 0;
            IntPtr pTile = LibTIFF._malloc((int)(tileLength*tileWidth*bitsPerSample/2));
            for (uint y = 0; y < imageLength; y += tileLength)
            {
                for (uint x = 0; x < imageWidth; x += tileWidth)
                {
                    LibTIFF.ReadTile(tiff, pTile, x, y, 0, 0);
                    tiles++;
                }
            }                        
            LibTIFF._free(pTile);   
        }
    }
    

    虽然我会选择 LibTIFF 的 .NET 端口,但这个解决方案可能适合其他人,所以我将它留在 StackOverflow 上。

    【讨论】:

    • LibTiff 是处理 Tiled TIFF 的唯一方法吗?或者我们可以对 .Net Framework 中的 TiffBitmapDecoder 类做同样的事情吗?
    • 据我所知,TiffBitMapDecoder 不提供选择性加载文件部分的功能(仅用于渲染完整帧)。 msdn.microsoft.com/en-us/library/…
    猜你喜欢
    • 1970-01-01
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    相关资源
    最近更新 更多