Ao trabalhar com o processamento de imagem em .NET, uma necessidade comum é a fusão de múltiplas imagens – muitas vezes de diferentes tamanhos – em uma única saída. Casos de uso típicos incluem colagens, folhas de sprite, follas de contato, ou banners de marketing. Este tutorial mostra como combinar imagens usando Aspose.Imaging para .Net com controle preciso sobre o layout: eixo (horizontal/vertical), alinhamento (top/center/bottom e esquerda/centro/direita), padding exterior, e espaçamento entre imagens. Graphics
O fogo.
O que você vai construir
*Layout: horizontal ou vertical
- Apresentação : *
Layout horizontal → alinhamento vertical:
Top
,Middle
,Bottom
Layout vertical → alinhamento horizontal:
Left
,Center
,Right
Padding: outer padding e inter-item spacing
Background: Fim de cor sólida
Formatos: carregar formatos mistos (JPG, PNG, etc.), exceto para Png/JPEG
Exemplo completo
using System;
using System.Collections.Generic;
using System.IO;
using Aspose.Imaging;
using Aspose.Imaging.ImageOptions;
namespace ImagingMergeDemo
{
public enum MergeAxis { Horizontal, Vertical }
public enum VAlign { Top, Middle, Bottom }
public enum HAlign { Left, Center, Right }
public static class ImageMerger
{
/// <summary>
/// Merges input images into a single image with alignment and padding.
/// </summary>
/// <param name="inputPaths">List of source image file paths.</param>
/// <param name="axis">Horizontal or Vertical stacking.</param>
/// <param name="outerPadding">Padding around the whole collage (in pixels).</param>
/// <param name="spacing">Spacing between images (in pixels).</param>
/// <param name="bgColor">Background color for the canvas.</param>
/// <param name="verticalAlign">Only used when axis == Horizontal (Top/Middle/Bottom inside the row).</param>
/// <param name="horizontalAlign">Only used when axis == Vertical (Left/Center/Right inside the column).</param>
/// <param name="outputPath">Destination file path. Extension determines encoder (e.g., .png, .jpg).</param>
public static void Merge(
IReadOnlyList<string> inputPaths,
MergeAxis axis,
int outerPadding,
int spacing,
Color bgColor,
VAlign verticalAlign,
HAlign horizontalAlign,
string outputPath)
{
if (inputPaths is null || inputPaths.Count == 0)
throw new ArgumentException("No input images provided.");
// Load all images first so we can compute canvas size.
var loaded = new List<Image>(inputPaths.Count);
try
{
foreach (var p in inputPaths)
{
var img = Image.Load(p);
loaded.Add(img);
}
// Compute canvas size.
// For horizontal axis: width = sum(widths) + spacings + 2*outerPadding
// height = max(heights) + 2*outerPadding
// For vertical axis: height = sum(heights) + spacings + 2*outerPadding
// width = max(widths) + 2*outerPadding
int totalWidth, totalHeight;
if (axis == MergeAxis.Horizontal)
{
int sumWidths = 0, maxH = 0;
for (int i = 0; i < loaded.Count; i++)
{
sumWidths += loaded[i].Width;
maxH = Math.Max(maxH, loaded[i].Height);
}
totalWidth = sumWidths + ((loaded.Count - 1) * spacing) + 2 * outerPadding;
totalHeight = maxH + 2 * outerPadding;
}
else
{
int sumHeights = 0, maxW = 0;
for (int i = 0; i < loaded.Count; i++)
{
sumHeights += loaded[i].Height;
maxW = Math.Max(maxW, loaded[i].Width);
}
totalHeight = sumHeights + ((loaded.Count - 1) * spacing) + 2 * outerPadding;
totalWidth = maxW + 2 * outerPadding;
}
// Create canvas (use PNG by default for lossless output; you can switch to JPEGOptions)
using var canvas = Image.Create(new PngOptions(), totalWidth, totalHeight);
// Draw on canvas
using var g = new Graphics(canvas);
g.Clear(bgColor);
int cursorX = outerPadding;
int cursorY = outerPadding;
for (int i = 0; i < loaded.Count; i++)
{
var img = loaded[i];
int drawX, drawY;
if (axis == MergeAxis.Horizontal)
{
// X flows left -> right
drawX = cursorX;
// Y depends on vertical alignment vs tallest height
drawY = verticalAlign switch
{
VAlign.Top => outerPadding,
VAlign.Middle => outerPadding + (totalHeight - 2 * outerPadding - img.Height) / 2,
VAlign.Bottom => outerPadding + (totalHeight - 2 * outerPadding - img.Height),
_ => outerPadding
};
// Draw and move X cursor
g.DrawImage(img, new Rectangle(drawX, drawY, img.Width, img.Height));
cursorX += img.Width + spacing;
}
else
{
// Y flows top -> bottom
drawY = cursorY;
// X depends on horizontal alignment vs widest width
drawX = horizontalAlign switch
{
HAlign.Left => outerPadding,
HAlign.Center => outerPadding + (totalWidth - 2 * outerPadding - img.Width) / 2,
HAlign.Right => outerPadding + (totalWidth - 2 * outerPadding - img.Width),
_ => outerPadding
};
// Draw and move Y cursor
g.DrawImage(img, new Rectangle(drawX, drawY, img.Width, img.Height));
cursorY += img.Height + spacing;
}
}
// Save with encoder that matches extension
SaveByExtension(canvas, outputPath);
}
finally
{
// Dispose loaded images
foreach (var img in loaded)
img.Dispose();
}
}
private static void SaveByExtension(Image image, string outputPath)
{
var ext = Path.GetExtension(outputPath).ToLowerInvariant();
ImageOptionsBase opts = ext switch
{
".jpg" or ".jpeg" => new JpegOptions { Quality = 90 },
".png" => new PngOptions(),
_ => new PngOptions() // default to PNG
};
image.Save(outputPath, opts);
}
}
// Example usage
public class Program
{
public static void Main()
{
var inputs = new List<string>
{
"image1.jpg",
"image2.png",
"image3.jpg"
};
// Horizontal strip, vertically centered, with padding/spacing
ImageMerger.Merge(
inputPaths: inputs,
axis: MergeAxis.Horizontal,
outerPadding: 20,
spacing: 10,
bgColor: Color.White,
verticalAlign: VAlign.Middle,
horizontalAlign: HAlign.Center, // ignored for horizontal axis
outputPath: "merged_horizontal.png"
);
// Vertical stack, horizontally right-aligned
ImageMerger.Merge(
inputPaths: inputs,
axis: MergeAxis.Vertical,
outerPadding: 20,
spacing: 12,
bgColor: Color.FromArgb(255, 245, 245, 245),
verticalAlign: VAlign.Middle, // ignored for vertical axis
horizontalAlign: HAlign.Right,
outputPath: "merged_vertical.jpg"
);
}
}
}
Guia passo a passo
Passo 1: Carregar imagens
Carregue todas as imagens com Image.Load(path)
Mantenha-os vivos até depois de desenhar, depois dissolve.
Passo 2: Determine o tamanho da saída
- Layout horizontal: largura = soma de larguras + espaços + paddling exterior; altura = altura máxima + Padding exterior.
- Layout vertical: altura = soma de alturas + espaços + paddling externo; largura = max width + outer padding.
Passo 3: Crie o canvas de saída
Criar usando Image.Create(new PngOptions(), width, height)
(ou JpegOptions
Se você preferir o rendimento perdido). claro com uma cor de fundo.
Passo 4: Configure Alignment & Padding
- A fusão horizontal é calculada por
Top / Middle / Bottom
. - Combinação vertical → calcular X por
Left / Center / Right
. - Apply
outerPadding
espacing
de forma consistente.
Passo 5: desenhar cada imagem
Utilização Graphics.DrawImage(image, new Rectangle(x, y, image.Width, image.Height))
.
Passo 6: Salve o resultado
Escolha o codificador com base na extensão de nome de saída (por exemplo, .png
→ PngOptions
, .jpg
→ JpegOptions { Quality = … }
).
Melhores Práticas
- Formatos normalizados: Se você precisa de fundos transparentes, salve como PNG. Para arquivos menores sem transparência, use JPEG e tune
Quality
. - Guardrails: Valide a lista de entrada, gerencie arquivos desaparecidos e considere as dimensões máximas de canvas para evitar OOM.
- Disponível em:
Image
,Graphics
disponível - usousing
outry/finally
.
- Disponível em:
- Consistência de cores: Se as entradas tiverem tipos de cor misturados, confie em padrões de Aspose ou converse explicitamente quando necessário.
- Batching: Para grandes conjuntos, fluxo de saídas enquanto você vai ou crie múltiplas folhas/páginas.
More in this category
- Otimizar GIFs animados em .NET usando Aspose.Imaging
- Otimize TIFFs multi-páginas para arquivo em .NET com Aspose
- Animações de dados em .NET com Aspose.Imaging
- Compare compressão de imagem sem perda em .NET usando Aspose.Imaging
- Compressão de imagem sem perda e de qualidade definida em .NET com Aspose.Imaging