首页 > 解决方案 > 当我想用 C# 合并两个大的 tiff 图像时为什么会出错?

问题描述

我想合并两个大 Tiff。我尝试了很多方法。但每次都会出错。例如:我使用了 ImageMagic 和 System.Drowing.Graphics 和 ImageProcessor 等。

OneDriveFiles:https ://1drv.ms/u/s!AlD9jC3hP9FTcEB2J2rKgp8Lw_E?e=JFVewK

已共享四个文件。

原始文件名:_1.tif 和 _11.tif

使用 Magick.NET-Q16-x64 V7.14.3 创建:dotnet.tif

使用 ImageMagick Q16 v 7.0.8 创建:magickcmd.tif

系统信息: OP:win 10 x64 Ram:64Gig Cpu:I7 GPU:8Gig FreeSpace:400Gig

Tif 格式:

像素格式:Format1bppIndexed

大小:2Gig

模式:位图

压缩:lzw

像素顺序:交错

字节顺序:lsb

宽度:95752px

高度:295464px

水平分辨率:800dpi

垂直分辨率:2400dpi

位深:1

分辨率单位:2

谢谢您的帮助...

/// Use ImageMagick
                using (MagickImageCollection images = new MagickImageCollection())
                {

                    MagickNET.SetTempDirectory(@"d:\");

                    images.Add(new MagickImage(txtAddress2.Text, new MagickReadSettings { Endian = Endian.LSB }));
                    images.Add(new MagickImage(txtAddress1.Text, new MagickReadSettings { Endian = Endian.LSB }));

                    using (IMagickImage image = images.AppendHorizontally())
                    {
                        image.Endian = Endian.LSB;
                        image.Settings.SetDefine("tiff:endian", "lsb");
                        image.Write(@"d:\output" + new Random().Next() + ".tif");
                    }

                }

//////使用 System.Drowing

 public static Bitmap MergeTwoImages(Image firstImage, Image secondImage)
    {


        int outputImageWidth = firstImage.Width > secondImage.Width ? firstImage.Width : secondImage.Width;

        int outputImageHeight = firstImage.Height + secondImage.Height + 1;

        Bitmap outputImage = new Bitmap(outputImageWidth, outputImageHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        using (Graphics graphics = Graphics.FromImage(outputImage))
        {
            graphics.DrawImage(firstImage, new Rectangle(new Point(), firstImage.Size),
                new Rectangle(new Point(), firstImage.Size), GraphicsUnit.Pixel);
            graphics.DrawImage(secondImage, new Rectangle(new Point(0, firstImage.Height + 1), secondImage.Size),
                new Rectangle(new Point(), secondImage.Size), GraphicsUnit.Pixel);
        }

        return outputImage;
    }

对于这个问题,我建议...

标签: c#image-processingbitmapimagemagick

解决方案


我查看了您的输出图像,它们看起来都很好。如果您无法查看它们,可能是因为它们对于您正在使用的任何程序来说都太大了。它们在libvips GUI nip2中为我显示,尽管它们需要几分钟才能打开。

您的图像很大:15,000 像素和 180,000 像素。它们以每像素 1 位的形式存储在 TIFF 文件中,但 ImageMagick6 会将它们解压缩到五个通道和每通道 16 位进行处理,因此每个通道为 25GB。ImageMagick7 将使用每个通道 32 位,因此每个图像 50GB。这已经接近您计算机的极限——它可能相当慢。

libvips可以执行这样的操作,而无需将整个图像加载到内存中:它将图像从输入流式传输到一系列小区域中的输出。它将为您计算机上的每个核心运行一个流,所以它也很快。

它有一个很好的 C# 绑定:net-vips。我实际上并没有在这台笔记本电脑上安装它,所以我尝试使用 Python。

import sys
import pyvips

left = pyvips.Image.new_from_file(sys.argv[2], access='sequential')
right = pyvips.Image.new_from_file(sys.argv[1], access='sequential')
join = left.join(right, 'horizontal', expand=True)
join.tiffsave(sys.argv[3], predictor='none', compression='lzw', squash=True)

绑定非常相似——您应该能够轻松地转换为 C#。

在这个双核 2015 笔记本电脑上,我看到:

$ /usr/bin/time -f %M:%e python3 join.py _1.tif _11.tif vips.tif
65832:26.55

所以它运行时间为 26 秒,需要 65MB 的内存。

你试过放气压缩吗?它比 LZW 慢,但效果更好。将保存行更改为:

join.tiffsave(sys.argv[3], compression='deflate', squash=True)

运行时间上升到 57 秒,但输出文件小了 25%。

libvips 也有一个 CLI,你也可以输入:

vips join _1.tif _11.tif vips.tif[compression=deflate,squash] horizontal --expand

推荐阅读