使用C#调用LibTiff(访问分块TIFF图像)

11
我想使用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上的帮助 [/编辑]
3个回答

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

https://bitmiracle.com/libtiff/

我们刚刚发布了它,所以可能会有一些错误。但是完整的源代码附带了许多测试,因此大多数明显的错误应该已经修复了。

谢谢。我的第一次测试看起来不错。虽然我找到了一个包装类,但它没有已知的作者,而且我迟早会遇到访问托管/非托管内存资源的问题。基准测试显示,在读取非压缩文件时具有相同的性能,并且在Adobe压缩的金字塔状平铺tiff上具有50%的性能损失。这对我来说是可以接受的。我可能决定不使用压缩,而是更好地使我的软件支持多核,而不是解决内存问题。 - Adriaan
谢谢,Adriaan。由于我们选择的编程语言不同,我们的实现肯定比原始版本慢。 - Bobrovsky
我不介意。对于我的项目,性能意味着功能/欧元。而开发时间占据了95%的成本。我可以轻松地投入一个四核处理器来弥补这一点。此外,当我避免压缩时,差异很小。而我的文件只压缩约10%,因此每个文件只有100兆字节而已;-) - Adriaan

4

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


1
你能添加一些链接吗?据我所见,TiffBitmapDecoder试图一次性在内存中加载图像。我做不到那样。大于1 GByte的图片在32位机器上由于碎片化而总是失败。你是指Windows7特定的内容吗(http://msdn.microsoft.com/en-us/library/ee720061%28VS.85%29.aspx)? - Adriaan
不,TBD 不存储图像。请从这里开始:http://msdn.microsoft.com/en-us/library/ms748873.aspx - Hans Passant
感谢您的帮助。不幸的是,我的经验与此不同。http://msdn.microsoft.com/en-us/library/ms748873.aspx中概述的步骤尝试使用位图1帧的大小分配单个内存块。我需要访问位图中的每个像素(因此没有适合屏幕的内存保存选项),但不一定在一个内存块中。当我尝试按照示例给出的方式运行tiff解码器时,它通常会在位图> 10k * 10k上失败。而这些只是我的“小测试文件”。我的目标是800MPixel x 16位。这就是为什么我寻找平铺的TIFF文件的原因。 - Adriaan
抱歉,你无法在32位操作系统上加载400 MB的图像。请切换到64位操作系统或分段读取图像。 - Hans Passant
是的。这就是为什么我在研究平铺技术。转换到64位操作系统可以解决部分问题,但在进行任何处理之前读取整个文件仍然会有很大的延迟。现在硬盘比CPU慢。此外,我喜欢金字塔式TIFF文件的可能性(即在同一文件中准备低分辨率图像以供预览等)。 - Adriaan
能否使用TiffBitmapDecoder读取一个大约3MB的“平铺式TIFF图像”,并将其转换为PDF格式,而不使用第三方库?我可以使用iTextSharp来创建PDF,但不能使用Lib2Tiff等其他第三方库。 - Murali Murugesan

1
我的初始解决方案是使用C#.NET包装LibTIFF DLL。我在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);   
    }
}

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


“LibTiff” 是处理分块 TIFF 的唯一方式吗?还是我们可以使用 .Net Framework 中的 TiffBitmapDecoder 类来完成相同的操作? - Murali Murugesan
据我所见,TiffBitMapDecoder没有提供选择性加载文件部分的功能(仅用于渲染完整帧)。http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.tiffbitmapdecoder(v=vs.110).aspx - Adriaan

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