c# - 当我想用 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;
}
对于这个问题,我建议...
解决方案
我查看了您的输出图像,它们看起来都很好。如果您无法查看它们,可能是因为它们对于您正在使用的任何程序来说都太大了。它们在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
推荐阅读
- ios - Safari iOS 收藏夹/书签图标未更新 apple-touch-icon.png
- php - 如何将标签从我的 PHP Web 应用程序打印到 Epson USB 收据打印机
- c++ - Visual Studio Code 终端和 G++
- python - PyQt5 的 QStackedLayout 中的常用按钮和定位
- reactjs - 如何使用 webpack4 禁用块(代码拆分)?
- python - 如何使用递归但不使用 for 或 while 循环来获得不重复的字符串排列?
- javascript - 调试 forEach 循环以了解其工作原理
- c++ - 如何从可执行文件中删除所有调试和个人信息?
- django - 在 ModelChoiceField 或 ModelMultipleChoiceField 中搜索的最简单方法是什么?
- android - Windows 10 上的颤振医生错误:CreateProcessW 失败 5