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

本文关键字:零件 复制 图像 新图像 NET 巨大 TIF | 更新日期: 2023-09-27 18:21:18

我正在寻找一个可以打开和复制大型TIFF文件部分的库。我看过LibTiff.Net,它能很快打开文件,但它没有任何裁剪或复制图像部分的功能。我的图像是100000 x 100000像素以上,创建这样大小的System.Drawing.Bitmap会使应用程序崩溃,因此首先转换为Bitmap不是一种选择。

有人能推荐一个.NET库吗?

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

如果你的文件在磁盘上的大小小于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。

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

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

Atalasoft dotImage在TIFF解码器中内置了此功能。解码实现了接口IRegionReadable,它允许您从流中图像的给定页面读取矩形部分。

在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");

对于图像的其他部分,可以更改循环中"i"的范围。