我正在寻找一个可以打开和复制大型 TIFF 文件部分的库。我查看了LibTiff.Net,它可以非常快速地打开文件,但它没有任何用于裁剪或复制图像部分的功能。我的图像为 100,000 x 100,000 像素以上,创建System.Drawing.Bitmap
该尺寸的图像会使应用程序崩溃,因此不能转换为Bitmap
第一个图像。
任何人都可以推荐一个 .NET 库吗?
我正在寻找一个可以打开和复制大型 TIFF 文件部分的库。我查看了LibTiff.Net,它可以非常快速地打开文件,但它没有任何用于裁剪或复制图像部分的功能。我的图像为 100,000 x 100,000 像素以上,创建System.Drawing.Bitmap
该尺寸的图像会使应用程序崩溃,因此不能转换为Bitmap
第一个图像。
任何人都可以推荐一个 .NET 库吗?
如果您的文件在磁盘上小于 4GB,我建议您再看看 LibTiff.Net。即使有如此大的图像,您也有一些选择。
首先,检查您的图像是平铺还是剥离。Tiff.IsTiled
方法会给你答案。
如果您的图像是平铺的,那么您可能不应该使用ReadScanline
方法读取它。在这种情况下使用ReadEncodedTile
方法可能会更好。
如果您的图像被剥离,那么您可以使用ReadScanline
和ReadEncodedStrip
方法来阅读它。
如果您想使用期望的东西,请System.Drawing.Bitmap
尝试使用ReadRGBATile
or ReadRGBAStrip
。这些方法可用于从图像的某些部分创建位图。没有这方面的示例,但将彩色 TIFF 转换为 32 位 System.Drawing.Bitmap应该为您提供有关如何将图像的平铺或条带转换为位图的几乎所有必需信息。
编辑:
LibTiff.Net 2.4.508 增加了对 BigTiff 的支持,因此也支持大于 4GB 的文件。
您的图像必须是BigTIFF格式,因为普通 TIFF 不能大于 4 GB。
BigTIFF 可以使用 libtiff 的修改版本(可在BigTIFF 网站上获得)读取,该库允许以您想要的方式处理此类图像,而无需将所有像素数据加载到内存中。
我没有看到 .NET 的绑定,但它应该不会太长。
Atalasoft dotImage具有内置于 TIFF 解码器的此功能。解码器实现接口 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”的范围。