Skip to content

Image Resize & Watermark — C# source

Batch-resize images by width, height or percentage and stamp a text watermark with position, opacity and size control — entirely in your browser, nothing uploaded.

This is the C# implementation — the same logic the interactive tool runs, in a shareable, citable form.

// Image Resize & Watermark — C# (.NET 8, System.Drawing) port of the image-resize-and-watermark tool.

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace CosmoDev.ImageResizeAndWatermark;

public static class ImageResizeAndWatermark
{
    // Mirrors the TS resizeAndWatermark: aspect-preserving resize, then a
    // bottom-right watermark — white fill at 70% alpha over a dark outline
    // (strokeText + fillText), both via one GraphicsPath.
    public static Bitmap Run(Image src, int targetWidth, string watermark)
    {
        int h = (int)Math.Round((double)src.Height / src.Width * targetWidth, MidpointRounding.AwayFromZero);
        var bmp = new Bitmap(targetWidth, h, PixelFormat.Format32bppArgb);
        using (var g = Graphics.FromImage(bmp))
        {
            g.InterpolationMode = InterpolationMode.HighQualityBicubic; // imageSmoothingQuality 'high'
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            g.DrawImage(src, new Rectangle(0, 0, targetWidth, h));

            int fs = (int)Math.Round(Math.Min(targetWidth, h) * 6.0 / 100.0);
            // Bold ≈ the TS 600 weight; GenericSansSerif ≈ system-ui, sans-serif.
            using var font = new Font(FontFamily.GenericSansSerif, fs, FontStyle.Bold, GraphicsUnit.Pixel);
            var fmt = StringFormat.GenericTypographic; // unpadded measure, like measureText
            var box = g.MeasureString(watermark, font, PointF.Empty, fmt);
            // TS anchors the baseline at h-8; the path box top sits ~one ascent higher.
            var origin = new PointF(targetWidth - box.Width - 8, h - 8f - font.Height);

            var path = new GraphicsPath();
            path.AddString(watermark, font.FontFamily, (int)FontStyle.Bold, fs, origin, fmt);
            g.PixelOffsetMode = PixelOffsetMode.Default; // DrawPath centers the pen on the outline
            using (var pen = new Pen(Color.FromArgb(140, 0, 0, 0), Math.Max(1f, fs / 14f))) // 0.55 alpha
                g.DrawPath(pen, path); // strokeText
            using var brush = new SolidBrush(Color.FromArgb(178, 255, 255, 255)); // 0.7 alpha
            g.FillPath(brush, path); // fillText
        }
        return bmp;
    }

    public static void Main()
    {
        using var src = Image.FromFile("input.jpg");
        using var result = Run(src, 1280, "CosmoDev");
        // WebP needs ImageSharp/WPF on .NET 8; JPEG keeps the stdlib demo short.
        result.Save("output.jpg", ImageFormat.Jpeg);
    }
}

Also available in 8 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →