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

发布于 2024-12-29 10:03:33 字数 1539 浏览 6 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦醒灬来后我 2025-01-05 10:03:33

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

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

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

如果您的图像被剥离,则可以使用 ReadScanline 和 ReadEncodedStrip 方法来读取它。

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

编辑:

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

If your file is less than 4GB on disk than I recommend you to take another look at LibTiff.Net. Even with such large images you have some options.

First of all, check whether your image is tiled or stripped. Tiff.IsTiled method will give you the answer.

If your image is tiled, than you probably shouldn't read it using ReadScanline method. It might be better to use ReadEncodedTile method in that case.

If your images is stripped, than you can use ReadScanline and ReadEncodedStrip methods to read it.

If you want to use something that expects System.Drawing.Bitmap than try using ReadRGBATile or ReadRGBAStrip. These methods can be used to create bitmaps from portions of your image. There is no sample for this, but Convert color TIFF to a 32-bit System.Drawing.Bitmap should give you almost all required information about how to convert tile or strip of an image to a bitmap.

EDIT:

LibTiff.Net 2.4.508 adds support for BigTiff so files larger than 4GB are also supported.

生来就爱笑 2025-01-05 10:03:33

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

BigTIFF 可以使用 libtiff 的修改版本来读取(可在 BigTIFF 网站 中找到),该库允许处理这些图像可以按照您想要的方式显示,而无需将所有像素数据加载到内存中。

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

Your image must be in BigTIFF format, since normal TIFF can't be larger than 4 GB.

BigTIFF can be read with a modified version of libtiff (available in BigTIFF website), this library allows to handle such images the way you want without loading all pixel data in memory.

I didn't see bindings for .NET but it shouldn't be too long to do it.

近箐 2025-01-05 10:03:33

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

在 TIFF 中,此部分将遵循方向标签,而在条带或平铺 tiff 中,使用最小的平铺和条带集来填充矩形。

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

Atalasoft dotImage has this ability built-in to the TIFF decoder. The decode implements the interface IRegionReadable, which lets you read a rectangular section from a given page of an image in a Stream.

In a TIFF, this section will honor the orientation tag and in stripped or tiled tiffs uses the minimum set of tiles and strips to fill the rectangle.

(disclaimer, I work for Atalasoft and wrote that interface and implemented it in the TIFF decoder)

吾家有女初长成 2025-01-05 10:03:33

正如 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”的范围。

As Bobrovsky mentioned you should check if your file image is tiled or not. In the following, I've presented the snippet code to read a stream tiff and crop the upper left part of the image.

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 other parts of the image, you can change the range of "i" in for loop.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文