Generating Text Overlays and Compositing Images in C#
Dynamic image generation in C# relies on the System.Drawing namespace to handle typography rendering, bitmap scaling, and layered composition. The following implementation provides a structured approach to creating text-based bitmaps, resizing assets with high-quality interpolation, and merging foreground elements onto a background canvas.
Core Utility Implementation
The utility class encapsulates three primary operations: rendering string content to a bitmap, scaling an existing image, and overlaying a foreground image onto a background with precise positioning and optional framing.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
public static class ImageCompositionEngine
{
public static Bitmap RenderTextToBitmap(string content, int pointSize, bool useBold = false)
{
int canvasWidth = 400;
int canvasHeight = 200;
FontStyle style = useBold ? FontStyle.Bold : FontStyle.Regular;
using var typeface = new Font("Arial", pointSize, style);
using var paintBrush = new SolidBrush(Color.Black);
using var layoutFormat = new StringFormat(StringFormatFlags.NoClip)
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
var canvas = new Bitmap(canvasWidth, canvasHeight);
using (var ctx = Graphics.FromImage(canvas))
{
ctx.Clear(Color.White);
ctx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
var bounds = new RectangleF(0, 0, canvasWidth, canvasHeight);
ctx.DrawString(content, typeface, paintBrush, bounds, layoutFormat);
}
return canvas;
}
public static Bitmap ScaleBitmap(Image source, int targetWidth, int targetHeight)
{
var resized = new Bitmap(targetWidth, targetHeight);
using var ctx = Graphics.FromImage(resized);
ctx.InterpolationMode = InterpolationMode.HighQualityBicubic;
ctx.PixelOffsetMode = PixelOffsetMode.HighQuality;
ctx.CompositingQuality = CompositingQuality.HighQuality;
var destRect = new Rectangle(0, 0, targetWidth, targetHeight);
var srcRect = new Rectangle(0, 0, source.Width, source.Height);
ctx.DrawImage(source, destRect, srcRect, GraphicsUnit.Pixel);
return resized;
}
public static Bitmap OverlayImageOnBackground(Image background, Image foreground, int offsetX = 0, int offsetY = 0)
{
var composite = new Bitmap(background.Width, background.Height);
using var ctx = Graphics.FromImage(composite);
ctx.Clear(Color.Transparent);
ctx.DrawImage(background, 0, 0, background.Width, background.Height);
int posX = (background.Width / 2) - (foreground.Width / 2) + offsetX;
int posY = (background.Height / 2) - (foreground.Height / 2) + offsetY;
var borderRect = new Rectangle(posX - 1, posY - 1, foreground.Width + 2, foreground.Height + 2);
ctx.FillRectangle(Brushes.White, borderRect);
ctx.DrawImage(foreground, posX, posY, foreground.Width, foreground.Height);
return composite;
}
}
Execution Pipeline
Running the composition workflow involves initializing the base layer, optionally generating or resizing the overlay, and merging them with coordinate adjustments.
public void ExecuteCompositionPipeline()
{
string bgPath = @"C:\assets\background.jpg";
string fgPath = @"C:\assets\foreground.png";
string outputPath = @"C:\output\final_composite.jpg";
using var baseImage = Image.FromFile(bgPath);
using var overlayImage = Image.FromFile(fgPath);
// Alternative: Generate text layer dynamically
// using var textLayer = ImageCompositionEngine.RenderTextToBitmap("X7K9 M2P4", 14, true);
// using var scaledOverlay = ImageCompositionEngine.ScaleBitmap(textLayer, 200, 100);
using var result = ImageCompositionEngine.OverlayImageOnBackground(baseImage, overlayImage, 0, -100);
result.Save(outputPath, ImageFormat.Jpeg);
}
Technical Considerations
- Unmanaged Resource Disposal:
Graphics,Font,Brush, andBitmapinstances wrap GDI+ handles. Utilizingusingdeclarations or explicitDispose()calls prevents handle exhaustion in high-throughput scenarios. - Interpolation and Quality Flags: Scaling operations default to lower-quality algorithms for performance. Explicitly assigning
InterpolationMode.HighQualityBicubic,PixelOffsetMode.HighQuality, andCompositingQuality.HighQualityeliminates jagged edges and preserves detail during resolution changes. - Coordinate Mathematics: Centering logic calculates the midpoint of the background and subtracts half the foreground dimensions. Applying offsets after this baseline calculasion ensures adjustments shift the element relative to the exact center rather than the origin.
- Typography Rendering: Activating
TextRenderingHint.AntiAliassmooths character edges. TheStringFormatconfiguration withStringAlignment.Centerfor both horizontal and vertical axes guarantees precise text placement within the definedRectangleFbounds.