// 詳細偽代碼(以註釋形式包含在文件頂部):
// 1. 定義方法 SplitImage:
// - 輸入: inputPath (圖片完整路徑), cols (列數), rows (行數), outputDir (輸出目錄), format, quality
// - 驗證 inputPath 是否存在, 創建 outputDir(如果不存在)
// - 使用 SkiaSharp 解碼輸入圖片為 SKBitmap
// - 計算每列基礎寬度 baseTileWidth = bitmap.Width / cols
// - 計算每行基礎高度 baseTileHeight = bitmap.Height / rows
// - 對於每個行 r 從 0 到 rows-1:
// - 計算 top = r * baseTileHeight
// - 計算 height = (r == rows-1) ? bitmap.Height - top : baseTileHeight // 處理餘數
// 對於每個列 c 從 0 到 cols-1:
// - 計算 left = c * baseTileWidth
// - 計算 width = (c == cols-1) ? bitmap.Width - left : baseTileWidth // 處理餘數
// - 新建 SKBitmap tile (width, height) 使用與原圖相同的顏色類型和 alpha 類型
// - 使用 bitmap.ExtractSubset(tile, new SKRectI(left, top, left + width, top + height))
// - 將 tile 轉為 SKImage, 然後 Encode 為字節數據 (JPEG/PNG)
// - 將數據寫入到 outputDir, 文件名使用模式: originalname_row{r}_col{c}.jpg
// - 釋放所有 SkiaSharp 資源並返回已寫入文件列表或異常信息
//
// 2. 在 Main 中調用 SplitImage,參數:
// - inputPath: @"C:\Users\malia\linda_server\src\assets\international.jpg"
// - cols: 3, rows: 4
// - outputDir: 同一目錄下的 "tiles" 子文件夾
// 3. 輸出處理結果到控制枱,處理異常並返回非零退出碼(如果失敗)
//
// 説明:
// - 處理寬高無法被整除的情況,最後一行/最後一列會包含餘下像素,保證不丟失圖像內容。
// - 使用 SkiaSharp 的託管資源模式 (using) 以確保正確釋放資源。
// - 輸出使用 JPEG(可修改為 PNG),質量默認設置為 90。using System;
using System.IO;
using System.Collections.Generic;
using SkiaSharp;namespace ConsoleApp26
{
internal static class Program
{
private static int Main(string[] args)
{
// 輸入圖片路徑(硬編碼為題目要求路徑)
string inputPath = @"C:\Users\malia\linda_server\src\assets\international.jpg";
int cols = 3;
int rows = 4;
string outputDir = Path.Combine(Path.GetDirectoryName(inputPath) ?? ".", "tiles"); try
{
var savedFiles = SplitImage(inputPath, cols, rows, outputDir, SKEncodedImageFormat.Jpeg, 90);
Console.WriteLine("分割完成,共生成 {0} 張圖片,目錄: {1}", savedFiles.Count, outputDir);
foreach (var f in savedFiles)
{
Console.WriteLine(" " + f);
} return 0;
}
catch (Exception ex)
{
Console.Error.WriteLine("處理失敗: " + ex.Message);
return 1;
}
} private static List<string> SplitImage(
string inputPath,
int cols,
int rows,
string outputDir,
SKEncodedImageFormat format,
int quality)
{
if (string.IsNullOrWhiteSpace(inputPath))
{
throw new ArgumentException("輸入路徑為空", nameof(inputPath));
} if (!File.Exists(inputPath))
{
throw new FileNotFoundException("找不到輸入圖片", inputPath);
} if (cols <= 0 || rows <= 0)
{
throw new ArgumentOutOfRangeException("cols/rows 必須大於 0");
} Directory.CreateDirectory(outputDir);
var savedFiles = new List<string>();
string baseName = Path.GetFileNameWithoutExtension(inputPath);
string ext = format == SKEncodedImageFormat.Png ? "png" : "jpg"; using var original = SKBitmap.Decode(inputPath);
if (original is null)
{
throw new InvalidOperationException("無法解碼輸入圖片: " + inputPath);
} int baseTileWidth = original.Width / cols;
int baseTileHeight = original.Height / rows; for (int r = 0; r < rows; r++)
{
int top = r * baseTileHeight;
int tileHeight = (r == rows - 1) ? original.Height - top : baseTileHeight;
if (tileHeight <= 0) tileHeight = Math.Max(1, baseTileHeight); for (int c = 0; c < cols; c++)
{
int left = c * baseTileWidth;
int tileWidth = (c == cols - 1) ? original.Width - left : baseTileWidth;
if (tileWidth <= 0) tileWidth = Math.Max(1, baseTileWidth); var subsetRect = new SKRectI(left, top, left + tileWidth, top + tileHeight);
using var tileBitmap = new SKBitmap(tileWidth, tileHeight, original.ColorType, original.AlphaType);
bool ok = original.ExtractSubset(tileBitmap, subsetRect);
if (!ok)
{
// 作為後備,使用畫布拷貝區域
using var canvasBmp = new SKBitmap(tileWidth, tileHeight, original.ColorType, original.AlphaType);
using var canvas = new SKCanvas(canvasBmp);
var srcRect = new SKRectI(left, top, left + tileWidth, top + tileHeight);
var destRect = new SKRectI(0, 0, tileWidth, tileHeight);
canvas.DrawBitmap(original, srcRect, destRect);
canvas.Flush(); SaveBitmapToFile(canvasBmp, outputDir, baseName, r, c, format, quality, savedFiles, ext);
}
else
{
SaveBitmapToFile(tileBitmap, outputDir, baseName, r, c, format, quality, savedFiles, ext);
}
}
} return savedFiles;
} private static void SaveBitmapToFile(
SKBitmap bitmap,
string outputDir,
string baseName,
int row,
int col,
SKEncodedImageFormat format,
int quality,
List<string> savedFiles,
string ext)
{
using var image = SKImage.FromBitmap(bitmap);
using var data = image.Encode(format, quality);
if (data is null)
{
throw new InvalidOperationException("編碼圖像數據失敗");
} string fileName = $"{baseName}_r{row}_c{col}.{ext}";
string outPath = Path.Combine(outputDir, fileName);
using var fs = File.OpenWrite(outPath);
data.SaveTo(fs);
savedFiles.Add(outPath);
}
}
}
本文章為轉載內容,我們尊重原作者對文章享有的著作權。如有內容錯誤或侵權問題,歡迎原作者聯繫我們進行內容更正或刪除文章。