在.NET中打开巨大的TIF并将部件复制到新图像

我正在寻找一个可以打开和复制大型TIFF文件部分的库。 我查看了LibTiff.Net ,它可以非常快速地打开文件,但它没有任何用于裁剪或复制图像部分的function。 我的图像向上是100,000 x 100,000像素并且创建该大小的System.Drawing.Bitmap会使应用程序崩溃,因此首先转换为Bitmap不是一个选项。

任何人都可以推荐.NET库吗?

如果您的文件在磁盘上小于4GB 我建议您再看一下LibTiff.Net。 即使有如此大的图像,你也有一些选择。

首先,检查您的图像是平铺还是剥离。 Tiff.IsTiled方法会给你答案。

如果您的图像是平铺的,那么您可能不应该使用ReadScanline方法读取它。 在这种情况下使用ReadEncodedTile方法可能更好。

如果图像被剥离,则可以使用ReadScanlineReadEncodedStrip方法进行读取。

如果你想使用期望System.Drawing.Bitmap不是尝试使用ReadRGBATileReadRGBAStrip 。 这些方法可用于从图像的某些部分创建位图。 没有这样的示例,但是将颜色TIFF转换为32位System.Drawing.Bitmap应该为您提供有关如何将图像的图块或条带转换为位图的几乎所有必需信息。

编辑:

LibTiff.Net 2.4.508增加了对BigTiff的支持,因此也支持大于4GB的文件。

您的图像必须采用BigTIFF格式,因为普通TIFF不能大于4 GB。

可以使用libtiff的修改版本(在BigTIFF网站中提供 )读取BigTIFF ,该库允许以您希望的方式处理此类图像,而无需在内存中加载所有像素数据。

我没有看到.NET的绑定,但它不应该太长。

Atalasoft dotImage具有内置于TIFF解码器的function。 解码实现了接口IRegionReadable,它允许您从Stream中的图像的给定页面读取矩形部分。

在TIFF中,此部分将使用方向标记,并且在剥离或平铺的tiff中使用最小的切片和条带集来填充矩形。

(免责声明,我为Atalasoft工作并编写了该界面并在TIFF解码器中实现了它)

正如Bobrovsky所提到的,你应该检查你的文件图像是否是平铺的。 在下文中,我已经提供了片段代码来读取流tiff并裁剪图像的左上部分。

 using (Tiff input = Tiff.Open(@"imageFile.tif", "r")) { // get properties to use in writing output image file int width = input.GetField(TiffTag.IMAGEWIDTH)[0].ToInt(); int height = input.GetField(TiffTag.IMAGELENGTH)[0].ToInt(); int samplesPerPixel = input.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt(); int bitsPerSample = input.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt(); int photo = input.GetField(TiffTag.PHOTOMETRIC)[0].ToInt(); int scanlineSize = input.ScanlineSize(); byte[][] buffer = new byte[height][]; for (int i = 0; i < height; ++i) { buffer[i] = new byte[scanlineSize]; input.ReadScanline(buffer[i], i); } using (Tiff output = Tiff.Open("splitedImage.tif", "w")) { output.SetField(TiffTag.SAMPLESPERPIXEL, samplesPerPixel); output.SetField(TiffTag.IMAGEWIDTH, width/2); output.SetField(TiffTag.IMAGELENGTH, height/2); output.SetField(TiffTag.BITSPERSAMPLE, bitsPerSample); output.SetField(TiffTag.ROWSPERSTRIP, output.DefaultStripSize(0)); output.SetField(TiffTag.PHOTOMETRIC, photo); output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG); int c = 0; byte[][] holder = new byte[height][]; for (int i = height/2; i < height; i++) //for (int j = 0; j < height/2 ; j++) { holder[i] = buffer[i].Skip(buffer[i].Length/2).ToArray(); output.WriteScanline(holder[i], c); c++; } } } System.Diagnostics.Process.Start("splitedImage.tif"); 

对于图像的其他部分,您可以在for循环中更改“i”的范围。