UWP Win2D应用中按比例调整图像大小的问题
Hey there, let's fix that stretching issue with your Win2D CanvasAnimatedControl! The problem here is that when you call DrawImage(_bitmap) directly, it stretches the image to fill the entire control bounds regardless of its original aspect ratio. Same goes for the text—without accounting for the control's resized dimensions relative to your content's natural size, it'll get warped too.
Step 1: Calculate Aspect Ratio & Target Drawing Bounds
First, we need to compare your bitmap's original aspect ratio to the control's current aspect ratio. This lets us calculate a scaled, non-stretched rectangle that fits neatly within the control (with optional letterbox/pillarbox bars if needed).
Update your Draw method with this logic:
private void Draw(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args) { if (!IsLoadInProgress()) { // Get aspect ratios for the image and current control size float imageAspectRatio = _bitmap.Size.Width / _bitmap.Size.Height; float controlAspectRatio = sender.Size.Width / sender.Size.Height; float scale; float xOffset = 0; float yOffset = 0; // Determine scaling factor and offsets to maintain proportionality if (controlAspectRatio > imageAspectRatio) { // Control is wider than the image—add pillarbox bars left/right scale = sender.Size.Height / _bitmap.Size.Height; xOffset = (sender.Size.Width - (_bitmap.Size.Width * scale)) / 2; } else { // Control is taller than the image—add letterbox bars top/bottom scale = sender.Size.Width / _bitmap.Size.Width; yOffset = (sender.Size.Height - (_bitmap.Size.Height * scale)) / 2; } // Create the scaled, non-stretched drawing rectangle Rect drawRect = new Rect(xOffset, yOffset, _bitmap.Size.Width * scale, _bitmap.Size.Height * scale); // Draw the image to this safe rectangle args.DrawingSession.DrawImage(_bitmap, drawRect); // Pass the scaled bounds to your text drawing method DrawText(args, drawRect, "...TESTING TEXT..."); } }
Step 2: Adjust Text to Match Scaled Content
Modify your DrawText method to use the scaled bounds, so text scales proportionally with the image and stays properly aligned:
private void DrawText(CanvasAnimatedDrawEventArgs args, Rect drawRect, string text) { // Scale text size relative to the image's scaling factor float scaledTextSize = 24 * (drawRect.Width / _bitmap.Size.Width); // Center text over the scaled image (adjust positioning as needed) args.DrawingSession.DrawText( text, drawRect.X + (drawRect.Width / 2), drawRect.Y + (drawRect.Height / 2), Colors.Black, new CanvasTextFormat { FontSize = scaledTextSize, HorizontalAlignment = CanvasHorizontalAlignment.Center, VerticalAlignment = CanvasVerticalAlignment.Center }); }
Optional: Add DPI Scaling for Crisper Rendering
If you want sharp content across different display DPIs, factor in the control's DPI value when calculating sizes:
float dpi = sender.Dpi; // Adjust bitmap size to account for DPI float dpiAdjustedImageWidth = _bitmap.Size.Width * dpi / 96; float dpiAdjustedImageHeight = _bitmap.Size.Height * dpi / 96; float imageAspectRatio = dpiAdjustedImageWidth / dpiAdjustedImageHeight; // Rest of the scaling logic remains similar
Why This Works
By calculating a uniform scaling factor based on aspect ratios, we ensure the image never gets stretched—only scaled up/down proportionally. The text uses the same scaling factor to maintain its relative size to the image, and positioning it based on the scaled image bounds keeps everything aligned correctly.
内容的提问来源于stack exchange,提问作者Maximus

