// 詳細偽代碼(以註釋形式包含在文件頂部):
// 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);
        }
    }
}