导读:本期聚焦于小伙伴创作的《C#图片处理完整指南:裁剪、缩放、锐化与水印的实用代码示例》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#图片处理完整指南:裁剪、缩放、锐化与水印的实用代码示例》有用,将其分享出去将是对创作者最好的鼓励。

C#图片处理示例:裁剪、缩放、清晰度与水印

在桌面应用或Web后端开发中,图片处理是一项常见需求。C#提供了丰富的API(如System.Drawing)来处理图片,包括裁剪、缩放、调整清晰度以及添加水印。本文将通过完整的示例代码演示这些操作,帮助开发者快速掌握核心技巧。

准备工作

本文使用System.Drawing.Common命名空间(适用于Windows平台)。在项目中添加引用System.Drawing.Common(如使用.NET 6+,需要手动安装NuGet包)。此外,请确保项目目标平台支持GDI+。

图片裁剪

裁剪是从原图中截取指定矩形区域。关键方法是Graphics.DrawImage配合源图像的目标矩形。

using System.Drawing;

public static Bitmap CropImage(Image sourceImage, Rectangle cropArea)
{
    Bitmap result = new Bitmap(cropArea.Width, cropArea.Height);
    using (Graphics g = Graphics.FromImage(result))
    {
        // 将源图像的指定区域绘制到新位图上
        g.DrawImage(sourceImage, new Rectangle(0, 0, result.Width, result.Height),
                    cropArea, GraphicsUnit.Pixel);
    }
    return result;
}

// 使用示例
using (var src = Image.FromFile("input.jpg"))
{
    Rectangle crop = new Rectangle(50, 50, 200, 150);
    using (var cropped = CropImage(src, crop))
    {
        cropped.Save("cropped.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
    }
}

上述代码中,cropArea定义了要保留的矩形区域,新生成的位图尺寸与该区域一致。注意DrawImage方法的重载参数:目标矩形、源矩形和度量单位。

图片缩放

缩放图片时需保持宽高比或强制拉伸。推荐使用高质量插值模式避免锯齿。

public static Bitmap ScaleImage(Image sourceImage, int newWidth, int newHeight, bool keepAspectRatio = true)
{
    int destWidth = newWidth;
    int destHeight = newHeight;

    if (keepAspectRatio)
    {
        float ratio = Math.Min((float)newWidth / sourceImage.Width, (float)newHeight / sourceImage.Height);
        destWidth = (int)(sourceImage.Width * ratio);
        destHeight = (int)(sourceImage.Height * ratio);
    }

    Bitmap result = new Bitmap(destWidth, destHeight);
    using (Graphics g = Graphics.FromImage(result))
    {
        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        g.DrawImage(sourceImage, 0, 0, destWidth, destHeight);
    }
    return result;
}

// 使用示例
using (var src = Image.FromFile("input.jpg"))
{
    using (var scaled = ScaleImage(src, 800, 600, true))
    {
        scaled.Save("scaled.jpg", ImageFormat.Jpeg);
    }
}

设置InterpolationModeHighQualityBicubic可获得平滑缩放效果。若需要固定尺寸且不保持比例,将keepAspectRatio设为false

调整清晰度(锐化)

清晰度调整通常通过锐化滤镜实现,例如3x3卷积核(拉普拉斯算子或自定义内核)。下面实现一个简单的锐化函数:

public static Bitmap SharpenImage(Bitmap sourceImage, float strength = 1.0f)
{
    // 创建锐化卷积核
    float[,] kernel = new float[,]
    {
        {  0, -1,  0 },
        { -1,  5, -1 },
        {  0, -1,  0 }
    };
    // 强度调整
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            kernel[i, j] *= strength;

    Bitmap result = new Bitmap(sourceImage.Width, sourceImage.Height);
    System.Drawing.Imaging.BitmapData srcData = sourceImage.LockBits(
        new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
        System.Drawing.Imaging.ImageLockMode.ReadOnly,
        System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    System.Drawing.Imaging.BitmapData dstData = result.LockBits(
        new Rectangle(0, 0, result.Width, result.Height),
        System.Drawing.Imaging.ImageLockMode.WriteOnly,
        System.Drawing.Imaging.PixelFormat.Format32bppArgb);

    int stride = srcData.Stride;
    int offset = stride - sourceImage.Width * 4;
    System.IntPtr srcPtr = srcData.Scan0;
    System.IntPtr dstPtr = dstData.Scan0;

    unsafe
    {
        byte* src = (byte*)srcPtr.ToPointer();
        byte* dst = (byte*)dstPtr.ToPointer();

        // 遍历每个像素(忽略边缘)
        for (int y = 1; y < sourceImage.Height - 1; y++)
        {
            for (int x = 1; x < sourceImage.Width - 1; x++)
            {
                int idx = y * stride + x * 4;
                float b = 0, g = 0, r = 0, a = 0;
                // 3x3卷积
                for (int ky = -1; ky <= 1; ky++)
                {
                    for (int kx = -1; kx <= 1; kx++)
                    {
                        int pixelIdx = (y + ky) * stride + (x + kx) * 4;
                        float weight = kernel[ky + 1, kx + 1];
                        b += src[pixelIdx] * weight;
                        g += src[pixelIdx + 1] * weight;
                        r += src[pixelIdx + 2] * weight;
                        a += src[pixelIdx + 3] * weight;
                    }
                }
                // 限制到[0,255]
                dst[idx] = ClampToByte(b);
                dst[idx + 1] = ClampToByte(g);
                dst[idx + 2] = ClampToByte(r);
                dst[idx + 3] = ClampToByte(a);
            }
        }
    }

    sourceImage.UnlockBits(srcData);
    result.UnlockBits(dstData);
    return result;
}

private static byte ClampToByte(float value)
{
    return (byte)(value < 0 ? 0 : (value > 255 ? 255 : value));
}

// 使用示例
using (var src = (Bitmap)Image.FromFile("input.jpg"))
{
    using (var sharp = SharpenImage(src, 1.2f))
    {
        sharp.Save("sharpened.jpg", ImageFormat.Jpeg);
    }
}

以上代码通过不安全代码(unsafe)直接操作像素,效率较高。若项目不允许unsafe,可使用Bitmap.GetPixel/SetPixel但速度较慢。锐化强度通过strength参数控制。

添加图片水印

水印可以是文字或另一张图片。以下示例分别演示文字水印和图片水印。

文字水印

public static Bitmap AddTextWatermark(Image sourceImage, string text, Font font, Color color, Point position, float opacity = 0.5f)
{
    Bitmap result = new Bitmap(sourceImage);
    using (Graphics g = Graphics.FromImage(result))
    {
        // 设置透明度
        ColorMatrix cm = new ColorMatrix();
        cm.Matrix33 = opacity; // Alpha通道比例
        System.Drawing.Imaging.ImageAttributes attr = new System.Drawing.Imaging.ImageAttributes();
        attr.SetColorMatrix(cm);

        // 绘制文本
        using (SolidBrush brush = new SolidBrush(color))
        {
            // 使用Graphics.DrawString直接绘制(不支持透明度控制,但一般可用)
            g.DrawString(text, font, brush, position);
        }
    }
    return result;
}

// 使用示例
using (var src = Image.FromFile("input.jpg"))
{
    using (Font f = new Font("Arial", 24))
    {
        var watermarked = AddTextWatermark(src, "ipipp.com", f, Color.FromArgb(128, 255, 255, 255), new Point(20, 20), 0.6f);
        watermarked.Save("watermarked_text.jpg", ImageFormat.Jpeg);
    }
}

注意:直接使用DrawString无法完美实现透明度(绘制的文字颜色本身包含Alpha值),更好的方法是使用TextRenderer或手动创建Graphics并设置CompositingMode。此处示例简化,实际项目中建议结合ImageAttributes控制。

图片水印

public static Bitmap AddImageWatermark(Image sourceImage, Image watermarkImage, Point position, float opacity = 0.5f)
{
    Bitmap result = new Bitmap(sourceImage);
    using (Graphics g = Graphics.FromImage(result))
    {
        ColorMatrix cm = new ColorMatrix();
        cm.Matrix33 = opacity;
        System.Drawing.Imaging.ImageAttributes attr = new System.Drawing.Imaging.ImageAttributes();
        attr.SetColorMatrix(cm);

        // 绘制水印图片(支持透明度)
        g.DrawImage(watermarkImage,
            new Rectangle(position.X, position.Y, watermarkImage.Width, watermarkImage.Height),
            0, 0, watermarkImage.Width, watermarkImage.Height,
            GraphicsUnit.Pixel, attr);
    }
    return result;
}

// 使用示例
using (var src = Image.FromFile("input.jpg"))
using (var logo = Image.FromFile("logo.png"))
{
    using (var result = AddImageWatermark(src, logo, new Point(src.Width - logo.Width - 10, 10), 0.4f))
    {
        result.Save("watermarked_image.jpg", ImageFormat.Jpeg);
    }
}

图片水印通过ImageAttributes控制Alpha通道,实现半透明叠加。可根据需要调整位置和透明度。

完整示例

以下是一个综合示例,依次执行裁剪、缩放、锐化和添加水印:

static void ProcessImage(string inputPath, string outputPath)
{
    using (var src = Image.FromFile(inputPath))
    {
        // 1. 裁剪(取中心区域)
        int cropSize = Math.Min(src.Width, src.Height);
        int x = (src.Width - cropSize) / 2;
        int y = (src.Height - cropSize) / 2;
        using (var cropped = CropImage(src, new Rectangle(x, y, cropSize, cropSize)))
        {
            // 2. 缩放至指定尺寸
            using (var scaled = ScaleImage(cropped, 500, 500, true))
            {
                // 3. 锐化
                using (var sharp = SharpenImage((Bitmap)scaled, 1.0f))
                {
                    // 4. 添加水印
                    using (Font f = new Font("Arial", 20))
                    {
                        var result = AddTextWatermark(sharp, "Sample", f, Color.FromArgb(100, 255, 255, 255), new Point(10, 10));
                        result.Save(outputPath, ImageFormat.Jpeg);
                    }
                }
            }
        }
    }
}

注意事项

  • 内存管理BitmapGraphics对象必须及时释放,使用usingDispose

  • 平台兼容性System.Drawing.Common在Windows上原生支持,在Linux/macOS需安装libgdiplus,且功能受限。跨平台建议使用ImageSharp(NuGet包SixLabors.ImageSharp)。

  • 性能优化:大批量处理时避免使用GetPixel/SetPixel,优先使用LockBits和指针操作。

  • 编码格式:保存时可根据需要选择合适的ImageFormat(JPEG、PNG、BMP等),注意JPEG是有损压缩。

总结

本文展示了C#中使用System.Drawing进行图片裁剪、缩放、锐化和添加水印的完整Demo。开发者可以根据实际需求组合这些操作,实现更复杂的图像处理流水线。对于生产环境,建议进一步封装错误处理和资源管理,并考虑使用更现代的跨平台库(如ImageSharp)以提升可移植性。

C图片处理 System.Drawing 图片裁剪 图片缩放 图片水印

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。