将一张图片切分为3*4的文件列表

// 详细伪代码(以注释形式包含在文件顶部):
// 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);
}
}
}

posted on 2025-12-23 16:22  漫思  阅读(3)  评论(0)    收藏  举报

导航