ارائه تصاویر در یک شبکه (موزیک) یک الزام رایج برای گالری ها، ورق های تماس و پانل ها است. Aspose.Imaging برای .NET همه چیزهایی را فراهم می کند که شما نیاز دارید تا تصاویر را بارگذاری کنید، آنها را بر روی یک کانوا بسازید و یک ترکیب نهایی را ذخیره کنید.
این راهنمای نشان می دهد که چگونه برای ساخت یک ترکیب شبکه قابل استفاده با ** خطوط / ستون ها**، ** خارج از پدینگ**, ** بین سلول های فضایی** ، ** رنگ پس زمینه (از جمله شفاف)** و ** حالت های مناسب** (محتویات / پوشش / چسب) به علاوه هماهنگی در داخل هر سلولی.
نمونه کامل و خودکفایی
using System;
using System.Collections.Generic;
using System.IO;
using Aspose.Imaging;
using Aspose.Imaging.ImageOptions;
namespace ImagingGridDemo
{
public enum FitMode { Contain, Cover, Stretch }
public enum HAlign { Left, Center, Right }
public enum VAlign { Top, Middle, Bottom }
public sealed class GridOptions
{
// Required layout
public int Rows { get; init; }
public int Columns { get; init; }
// Optional cell size. If null, computed from max source dimensions.
public int? CellWidth { get; init; }
public int? CellHeight { get; init; }
// Spacing/padding
public int Spacing { get; init; } = 8; // space between cells
public int Padding { get; init; } = 16; // outer canvas padding
// Drawing behavior
public FitMode Fit { get; init; } = FitMode.Contain;
public HAlign AlignX { get; init; } = HAlign.Center;
public VAlign AlignY { get; init; } = VAlign.Middle;
// Background
public Color Background { get; init; } = Color.White;
// Output
public string OutputPath { get; init; } = "grid.png"; // encoder inferred by extension
public void Validate()
{
if (Rows <= 0 || Columns <= 0)
throw new ArgumentException("Rows and Columns must be positive.");
if (Spacing < 0 || Padding < 0)
throw new ArgumentException("Spacing and Padding cannot be negative.");
if (!OutputPath.EndsWith(".png", StringComparison.OrdinalIgnoreCase) &&
!OutputPath.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) &&
!OutputPath.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase))
throw new ArgumentException("OutputPath must end with .png or .jpg/.jpeg.");
}
}
public static class ImageGridComposer
{
/// <summary>
/// Builds a grid/mosaic from the given image file paths.
/// </summary>
public static void Compose(IReadOnlyList<string> imagePaths, GridOptions options)
{
if (imagePaths is null || imagePaths.Count == 0)
throw new ArgumentException("No input images provided.");
options.Validate();
// 1) Load the images
var images = new List<Image>(imagePaths.Count);
try
{
foreach (var path in imagePaths)
images.Add(Image.Load(path));
// 2) Determine cell size (if not supplied) from the max width/height of sources
int cellW = options.CellWidth ?? GetMaxWidth(images);
int cellH = options.CellHeight ?? GetMaxHeight(images);
// 3) Compute canvas size
int w = options.Padding * 2
+ (options.Columns * cellW)
+ ((options.Columns - 1) * options.Spacing);
int h = options.Padding * 2
+ (options.Rows * cellH)
+ ((options.Rows - 1) * options.Spacing);
// 4) Create canvas. Use PNG by default (lossless & supports transparency).
ImageOptionsBase canvasOptions = options.OutputPath.EndsWith(".png", StringComparison.OrdinalIgnoreCase)
? new PngOptions()
: new JpegOptions { Quality = 90 };
using var canvas = Image.Create(canvasOptions, w, h);
// If you want transparent background, set Background = Color.Transparent and save as PNG
using var g = new Graphics(canvas);
g.Clear(options.Background);
// 5) Draw each image into its cell
int idx = 0;
for (int r = 0; r < options.Rows; r++)
{
for (int c = 0; c < options.Columns; c++)
{
if (idx >= images.Count) break;
var img = images[idx++];
var cellRect = CellRect(r, c, cellW, cellH, options);
// Determine source and destination rectangles according to FitMode
GetDrawRects(img.Width, img.Height, cellRect, options, out Rectangle srcRect, out Rectangle dstRect);
// Draw scaled/cropped as needed
g.DrawImage(img, dstRect, srcRect);
// (Optional) draw cell borders for debugging:
// g.DrawRectangle(new Pen(Color.LightGray), cellRect);
}
}
// 6) Save by extension
SaveByExtension(canvas, options.OutputPath);
}
finally
{
foreach (var img in images)
img.Dispose();
}
}
private static int GetMaxWidth(List<Image> imgs)
{
int m = 1;
foreach (var i in imgs) m = Math.Max(m, i.Width);
return m;
}
private static int GetMaxHeight(List<Image> imgs)
{
int m = 1;
foreach (var i in imgs) m = Math.Max(m, i.Height);
return m;
}
private static Rectangle CellRect(int row, int col, int cellW, int cellH, GridOptions opt)
{
int x = opt.Padding + col * (cellW + opt.Spacing);
int y = opt.Padding + row * (cellH + opt.Spacing);
return new Rectangle(x, y, cellW, cellH);
}
/// <summary>
/// Computes source and destination rectangles for DrawImage based on fit & alignment.
/// </summary>
private static void GetDrawRects(
int srcW, int srcH, Rectangle cell, GridOptions opt,
out Rectangle srcRect, out Rectangle dstRect)
{
srcRect = new Rectangle(0, 0, srcW, srcH);
if (opt.Fit == FitMode.Stretch)
{
// Stretch to fill the entire cell.
dstRect = cell;
return;
}
// Aspect ratios
double imgAR = (double)srcW / srcH;
double cellAR = (double)cell.Width / cell.Height;
if (opt.Fit == FitMode.Contain)
{
// Scale down so the whole image fits inside the cell (letterboxing possible).
double scale = (imgAR > cellAR)
? (double)cell.Width / srcW
: (double)cell.Height / srcH;
int drawW = (int)Math.Round(srcW * scale);
int drawH = (int)Math.Round(srcH * scale);
int dx = AlignX(cell.X, cell.Width, drawW, opt.AlignX);
int dy = AlignY(cell.Y, cell.Height, drawH, opt.AlignY);
dstRect = new Rectangle(dx, dy, drawW, drawH);
return;
}
// FitMode.Cover:
// Crop source to match cell aspect, then scale to fill cell completely.
if (opt.Fit == FitMode.Cover)
{
if (imgAR > cellAR)
{
// Image too wide; crop left/right
int newSrcW = (int)Math.Round(srcH * cellAR);
int sx = (srcW - newSrcW) / 2;
srcRect = new Rectangle(sx, 0, newSrcW, srcH);
}
else
{
// Image too tall; crop top/bottom
int newSrcH = (int)Math.Round(srcW / cellAR);
int sy = (srcH - newSrcH) / 2;
srcRect = new Rectangle(0, sy, srcW, newSrcH);
}
dstRect = cell; // fill the cell exactly
return;
}
// Default fallback (shouldn't hit)
dstRect = cell;
}
private static int AlignX(int cellX, int cellW, int drawW, HAlign ax)
{
return ax switch
{
HAlign.Left => cellX,
HAlign.Center => cellX + (cellW - drawW) / 2,
HAlign.Right => cellX + (cellW - drawW),
_ => cellX
};
}
private static int AlignY(int cellY, int cellH, int drawH, VAlign ay)
{
return ay switch
{
VAlign.Top => cellY,
VAlign.Middle => cellY + (cellH - drawH) / 2,
VAlign.Bottom => cellY + (cellH - drawH),
_ => cellY
};
}
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()
};
image.Save(outputPath, opts);
}
}
// Demo usage
public static class Program
{
public static void Main()
{
var inputs = new List<string>
{
"img1.jpg", "img2.png", "img3.jpg",
"img4.jpg", "img5.png", "img6.jpg"
};
var opts = new GridOptions
{
Rows = 2,
Columns = 3,
// Leave CellWidth/CellHeight null to auto-fit to largest source,
// or set fixed cell size (e.g., 640x480):
// CellWidth = 640, CellHeight = 480,
Spacing = 10,
Padding = 20,
Fit = FitMode.Contain, // Contain | Cover | Stretch
AlignX = HAlign.Center, // used by Contain
AlignY = VAlign.Middle, // used by Contain
Background = Color.White, // use Color.Transparent with PNG for transparent canvas
OutputPath = "grid.png"
};
ImageGridComposer.Compose(inputs, opts);
Console.WriteLine("Grid created: " + opts.OutputPath);
}
}
}
راهنمای گام به گام
تولید ورودی ها
Image.Load(path)
برای هر فایل، آنها را در حافظه نگه دارید تا زمانی که ترکیب ذخیره شود، سپس آن را رها کنید.- اندازه سلولی *
در غیر این صورت، محاسبه
cellWidth
وcellHeight
به عنوان max عرض / ارتفاع در سراسر منابع.یا یک اندازه سلول خاص را برای شبکه های یکنواخت تعیین کنید.
تغییر اندازه
width = 2*Padding + Columns*cellW + (Columns-1)*Spacing
height = 2*Padding + Rows*cellH + (Rows-1)*Spacing
تغییرمسیر Canvas
Image.Create(new PngOptions(), width, height)
(یاJpegOptions
اگر می خواهید از دست دادن، فایل های کوچکتر).پس زمینه های روشن :g.Clear(Color.White)
یاColor.Transparent
PNG )** جایگزین هر تصویر*
مستقیم سلولی را برای (سنگ، ستون) محاسبه کنید.
برای محتویات: مقیاس برای انطباق در داخل سلول، سپس هماهنگ (چپ / مرکز / راست، بالا / متوسط / پایین).
برای Cover: منبع محصول به ظاهر سلولی، سپس سلول را به طور کامل پر کنید.
برای Stretch: پر کردن سلول بدون در نظر گرفتن نسبت جنبه.
- نجات *کدگذاری را با گسترش خروجی انتخاب کنید:
.png
→new PngOptions()
.jpg
/.jpeg
→new JpegOptions { Quality = 90 }
بهترین شیوهها
- ** شفافیت**: برای پس زمینه های شفاف، استفاده
Color.Transparent
به عنوان PNG ذخیره می شود. - بسیار بزرگ شبکه ها: محاسبه کل پیکسل برای جلوگیری از OOM؛ پردازش در صفحات در صورت لزوم.
- Mixed DPI/Color Types: اجازه دهید Aspose به صورت تصادفی با تبدیل ها برخورد کند یا اگر خط لوله شما این کار را انجام دهد، از قبل استاندارد شود.
- ** اعتباربخشی**: اطمینان
Rows * Columns >= images.Count
(و یا تصمیم بگیرید که چگونه برای مقابله با جریان بیش از حد مهربان). - نمایش مشخصی: اصلاح شده
CellWidth/CellHeight
برای پیاده سازی لوله های یکنواخت، به ویژه برای تکه های UI.
More in this category
- بهینه سازی GIF های متحرک در .NET با استفاده از Aspose.Imaging
- بهینه سازی TIFF های چند صفحه ای برای آرشیو در .NET با Aspose
- HEIC به JPEG/PNG تبدیل با Aspose.Imaging برای .NET
- استخراج تصاویر محصول برای پلتفرم های تجارت الکترونیک با استفاده از Aspose.Imaging برای .NET
- انیمیشن های مبتنی بر داده در .NET با Aspose.Imaging