Perf: Convert only the required source region in DrawImage#407
Perf: Convert only the required source region in DrawImage#407christianrondeau wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR optimizes DrawingCanvas<TPixel>.DrawImage(Image, ...) when drawing from a source Image whose pixel format differs from the canvas pixel format by converting only the actually-sampled (clipped) source region instead of converting the entire source image up-front. As part of that refactor, it also ensures temporary converted images are disposed when the draw operation short-circuits early (fixing the reported leak).
Changes:
- Pre-compute the effective clipped source/destination rectangles and, for foreign pixel formats, crop in the source format before converting to
TPixel. - Centralize source/destination clipping logic into
TryGetDrawImageClip(...)and reuse it from both the public and internal draw paths. - Add tests asserting that “convert clipped region then draw” matches “convert whole image then draw” across multiple clipping/transform scenarios (including a projective transform).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| tests/ImageSharp.Drawing.Tests/Processing/DrawingCanvasTests.DrawImage.cs | Adds regression tests ensuring foreign-format, clipped-region conversion produces identical output to full-image conversion across several scenarios. |
| src/ImageSharp.Drawing/Processing/DrawingCanvas{TPixel}.cs | Crops before conversion for foreign pixel formats, factors clipping into TryGetDrawImageClip, and disposes owned temporary images on early-exit. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #407 +/- ##
===================================
- Coverage 86% 86% -1%
===================================
Files 109 109
Lines 9059 9071 +12
Branches 1087 1091 +4
===================================
+ Hits 7826 7833 +7
- Misses 982 985 +3
- Partials 251 253 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
6e136c3 to
844c332
Compare
Prerequisites
Description
While testing for performance improvement opportunities, I noticed that using the Draw API with an Image onto an Image, ALL pixels of the source image were converted before drawing (https://github.com/SixLabors/ImageSharp.Drawing/blob/main/src/ImageSharp.Drawing/Processing/DrawingCanvas%7BTPixel%7D.cs#L665).
This PR crops the source first and converts the cropped region after.
Impact
Measured on a 22.9 MP image (5700×4014), drawing a 1/8-area region using a custom MemoryAllocator for measuring:
Before: 103MB, 24.4ms (4.3x less memory)
After: 24MB, 14.4 ms (1.7x faster)
NOTE: This also fixes a small leak, this clone was never disposed: https://github.com/SixLabors/ImageSharp.Drawing/blob/main/src/ImageSharp.Drawing/Processing/DrawingCanvas%7BTPixel%7D.cs#L665