我有一百张 JPG 图像,想将它们合并为一个大 JPG。为了实现这一点,我使用以下代码:
using (var combinedBitmap = new Bitmap(combinedWidth, combinedHeights)) {
combinedBitmap.SetResolution(96, 96);
using (var g = Graphics.FromImage(combinedBitmap))
{
g.Clear(Color.White);
foreach (var imagePiece in imagePieces)
{
var imagePath = Path.Combine(slideFolderPath, imagePiece.FileName);
using (var image = Image.FromFile(imagePath))
{
var x = columnXs[imagePiece.Column];
var y = rowYs[imagePiece.Row];
g.DrawImage(image, new Point(x, y));
}
}
}
combinedBitmap.Save(combinedImagePath, ImageFormat.Jpeg);
}
Run Code Online (Sandbox Code Playgroud)
一切都很好,直到尺寸(combinedWidth,combinedHeights)超过窗帘阈值,就像这里所说的 /sf/answers/2042313381/
尺寸为 23170 x 23170 像素的合并 JPG 文件大约为 50MB — 不会太大而无法占用内存。
但是位图不能用更大的维度创建——只是因为错误的参数异常而中断。
有没有其他方法可以使用 C# 将 JPG 图像块合并到一个尺寸大于 23170 x 23170 的大 JPG 中?
这是使用libvips的解决方案。这是一个流式图像处理库,因此它不是在内存中操作巨大的对象,而是构建管道,然后并行运行它们,在一系列小区域中流式传输图像。
此示例使用net-vips,即libvips的 C# 绑定。
using System;
using System.Linq;
using NetVips;
class Merge
{
static void Main(string[] args)
{
if (args.Length < 2)
{
Console.WriteLine("Usage: [output] [images]");
return;
}
var image = Image.Black(60000, 60000);
var random = new Random();
foreach (var filename in args.Skip(1))
{
var tile = Image.NewFromFile(filename, access: Enums.Access.Sequential);
var x = random.Next(0, image.Width - tile.Width);
var y = random.Next(0, image.Height - tile.Height);
image = image.Insert(tile, x, y);
}
image.WriteToFile(args[0]);
}
}
Run Code Online (Sandbox Code Playgroud)
我制作了一组 1000 张 jpg 图像,每张 1450 x 2048 RGB 使用:
for ($i = 0; $i -lt 1000; $i++)
{
# https://commons.wikimedia.org/wiki/File:Taiaroa_Head_-_Otago.jpg
Copy-Item "$PSScriptRoot\..\Taiaroa_Head_-_Otago.jpg" -Destination "$PSScriptRoot\$i.jpg"
}
Run Code Online (Sandbox Code Playgroud)
为了测量执行上述代码所需的时间,我使用了 PowerShell 内置的“Measure-Command”(类似于 Bash 的“time”命令):
$fileNames = (Get-ChildItem -Path $PSScriptRoot -Recurse -Include *.jpg).Name
$results = Measure-Command { dotnet Merge.dll x.jpg $fileNames }
$results | Format-List *
Run Code Online (Sandbox Code Playgroud)
使用准备好的图像和上面的脚本,我看到了:
C:\merge>.\merge.ps1
Ticks : 368520029
Days : 0
Hours : 0
Milliseconds : 852
Minutes : 0
Seconds : 36
TotalDays : 0.000426527811342593
TotalHours : 0.0102366674722222
TotalMilliseconds : 36852.0029
TotalMinutes : 0.614200048333333
TotalSeconds : 36.8520029
Run Code Online (Sandbox Code Playgroud)
因此,在我的第 8 代 Intel Core i5 Windows PC 上,它在 36 秒内将 1000 张 jpg 图像合并为 60k x 60k jpg 大图像。
| 归档时间: |
|
| 查看次数: |
1468 次 |
| 最近记录: |