Atunci când lucrează cu prelucrarea imaginii în .NET, o necesitate comună este de a combina mai multe imagini – adesea de diferite dimensiuni – într-o singură ieșire. cazuri de utilizare tipice includ collage, frunze sprite, panouri de contact sau bannere de marketing. Acest tutorial arată cum să combinați imaginile folosind Aspose.Imagining pentru .Net cu control precis asupra layout-ului: axis (orizontal/vertical), aliniere (top/center/bottom și stânga/centrul/dreapta), exterior padding, și spațiu între imagine. Graphics şi focul.

Ce vei construi

  • *Layout: orizontal sau vertical

  • • Alimentare: *

  • Layout orizontal → aliniere verticală: Top, Middle, Bottom

  • Layout vertical – aliniere orizontală: Left, Center, Right

  • Padding: exterior pading și inter-item spacing

  • Background: încărcătura de culoare solidă

  • Formate: formate amestecate de încărcare (JPG, PNG, etc.), cu excepția formatelor Png/JPEG

Exemplu complet

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"
            );
        }
    }
}

Ghidul pas cu pas

Pasul 1: Încărcați imagini

Încărcați toate imaginile cu Image.Load(path)Păstrați-le în viață până după desenare, apoi eliminați.

Pasul 2: Determinați dimensiunea de ieșire

  • Layout-ul orizontal: lățime = sumă de widths + spații + padding exterior; înălțimea = înaltă maxă + Padding exterior.
  • Layout vertical: înălțime = sumă de înaltăți + spații + padding exterior; latitudine = max width + outer padding.

Pasul 3: Creați canvasul de ieșire

Creați folosind Image.Create(new PngOptions(), width, height) (sau JpegOptions dacă preferați o ieșire pierdută). clar cu o culoare de fundal.

Pasul 4: Configurați Alignment & Padding

  • Furnizarea orizontală se calculează prin Top / Middle / Bottom.
  • Combinarea verticală se calculează prin Left / Center / Right.
  • Apply outerPadding şi spacing în mod consecvent.

Pasul 5: Descrieți fiecare imagine

Utilizarea Graphics.DrawImage(image, new Rectangle(x, y, image.Width, image.Height)).

Pasul 6: Salvați rezultatul

Selectați coderul bazat pe extinderea denumirii de ieșire (de exemplu, .pngPngOptions, .jpgJpegOptions { Quality = … }).

Cele mai bune practici

  • Formate normalizate: Dacă aveți nevoie de fundal transparent, salvați ca PNG. Pentru fișierele mai mici fără transparență, utilizați JPEG și tune Quality.
  • Guardrails: Validați lista de intrări, gestionați fișierele lipsite și luați în considerare dimensiunile maxime ale canvasului pentru a evita OOM.
  • *Disponibilă pentru: Image, Graphics sunt disponibile - utilizare using sau try/finally.
  • Color consistență: În cazul în care intrările au tipuri de culori mixte, se bazează pe defectele Aspose sau se convertează explicit atunci când este necesar.
  • Batching: Pentru seturi mari, flux outputs pe măsură ce mergeți sau creați mai multe plăci / pagini.

More in this category