Add configurable ResizeQuality for Resizetizer#34559
Add configurable ResizeQuality for Resizetizer#34559jfversluis wants to merge 8 commits intonet11.0from
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34559Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34559" |
There was a problem hiding this comment.
Pull request overview
This PR adds a configurable ResizeQuality option to Resizetizer so image resampling quality can be controlled via MSBuild metadata, while keeping existing behavior unchanged by default (Auto).
Changes:
- Introduces an internal
ResizeQualityenum and plumbs it throughResizeImageInfo→ tool creation → resize operations. - Replaces use of obsolete
SKPaint.FilterQualitywith explicitSKSamplingOptionsselection based onResizeQuality. - Adds unit + end-to-end tests validating parsing, sampling-option mapping, and output differences/regressions.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/SingleProject/Resizetizer/src/ResizeQuality.cs | Adds the ResizeQuality enum used to control resampling behavior. |
| src/SingleProject/Resizetizer/src/ResizeImageInfo.cs | Adds Quality property + parses ResizeQuality MSBuild metadata. |
| src/SingleProject/Resizetizer/src/SkiaSharpTools.cs | Adds quality-aware factory/ctor and maps ResizeQuality to SKSamplingOptions. |
| src/SingleProject/Resizetizer/src/SkiaSharpRasterTools.cs | Passes quality through constructor chain; raster draw uses SamplingOptions. |
| src/SingleProject/Resizetizer/src/SkiaSharpSvgTools.cs | Passes quality through; uses SamplingOptions for raster downscaling path. |
| src/SingleProject/Resizetizer/src/SkiaSharpImaginaryTools.cs | Updates base ctor call to include default quality. |
| src/SingleProject/Resizetizer/src/SkiaSharpAppIconTools.cs | Ensures app icon background/foreground tool creation respects info.Quality. |
| src/SingleProject/Resizetizer/src/Resizer.cs | Threads Info.Quality into tool creation. |
| src/SingleProject/Resizetizer/src/AndroidAdaptiveIconGenerator.cs | Threads Info.Quality into adaptive icon resizing. |
| src/SingleProject/Resizetizer/test/UnitTests/ResizeImageInfoTests.cs | Adds tests for defaulting + case-insensitive parsing + invalid value handling. |
| src/SingleProject/Resizetizer/test/UnitTests/SkiaSharpRasterToolsTests.cs | Adds sampling-option mapping tests and functional output comparisons for raster images. |
| src/SingleProject/Resizetizer/test/UnitTests/SkiaSharpSvgToolsTests.cs | Adds sampling-option mapping tests and functional output comparisons for SVG downscaling. |
| src/SingleProject/Resizetizer/test/UnitTests/ResizetizeImagesTests.cs | Adds end-to-end MSBuild task pipeline tests for ResizeQuality. |
You can also share your feedback on Copilot code review. Take the survey.
There was a problem hiding this comment.
Pull request overview
This PR adds a configurable ResizeQuality option to the Resizetizer pipeline so callers can control image resampling behavior (via MSBuild item metadata), while preserving the existing default output.
Changes:
- Introduces an internal
ResizeQualityenum and plumbs it throughResizeImageInfoparsing and all resizing/tooling entry points. - Switches resampling control to
SKSamplingOptions(removing the obsoleteSKPaint.FilterQualityusage) and mapsResizeQualityvalues to the desired sampling options. - Adds unit and end-to-end tests covering parsing, sampling option mapping, and output equivalence/differences.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/SingleProject/Resizetizer/src/ResizeQuality.cs | Adds the new ResizeQuality enum used to select resampling behavior. |
| src/SingleProject/Resizetizer/src/ResizeImageInfo.cs | Adds Quality with default, and parses ResizeQuality from MSBuild metadata. |
| src/SingleProject/Resizetizer/src/SkiaSharpTools.cs | Plumbs ResizeQuality into constructors/factories and maps it to SKSamplingOptions; removes obsolete FilterQuality. |
| src/SingleProject/Resizetizer/src/SkiaSharpRasterTools.cs | Threads quality through constructors so raster drawing uses the configured sampling. |
| src/SingleProject/Resizetizer/src/SkiaSharpSvgTools.cs | Threads quality through constructors so SVG downscaling uses the configured sampling. |
| src/SingleProject/Resizetizer/src/SkiaSharpImaginaryTools.cs | Updates base constructor call to provide a default ResizeQuality for manufactured images. |
| src/SingleProject/Resizetizer/src/Resizer.cs | Ensures ResizeQuality flows into SkiaSharpTools.Create(...) when resizing. |
| src/SingleProject/Resizetizer/src/SkiaSharpAppIconTools.cs | Ensures app icon background/foreground tool creation passes through ResizeQuality. |
| src/SingleProject/Resizetizer/src/AndroidAdaptiveIconGenerator.cs | Ensures adaptive icon background/foreground resizing passes through ResizeQuality. |
| src/SingleProject/Resizetizer/test/UnitTests/ResizeImageInfoTests.cs | Adds tests for defaulting and case-insensitive parsing of ResizeQuality metadata. |
| src/SingleProject/Resizetizer/test/UnitTests/SkiaSharpRasterToolsTests.cs | Adds tests validating sampling option mapping and output invariants/differences for raster resizing. |
| src/SingleProject/Resizetizer/test/UnitTests/SkiaSharpSvgToolsTests.cs | Adds tests validating sampling option mapping and output invariants/differences for SVG resizing. |
| src/SingleProject/Resizetizer/test/UnitTests/ResizetizeImagesTests.cs | Adds end-to-end MSBuild pipeline tests verifying metadata is respected and defaults preserve baseline behavior. |
You can also share your feedback on Copilot code review. Take the survey.
Code Review SummaryResizeQuality for Resizetizer — Adds Findings
Overall Assessment
Otherwise the design, test coverage, and backward compatibility story are solid. Review performed by Copilot CLI |
a438af9 to
28be2d7
Compare
Code Review — PR #34559Independent AssessmentWhat this changes: Adds configurable Target branch: Reconciliation with PR NarrativeAgreement: ✅ Code matches description. Addresses @mattleibow's feedback on #25686: uses custom enum (not deprecated Findings✅ Good — Correct SkiaSharp API usageThe old code relied on // SkiaSharpRasterTools.DrawUnscaled
canvas.DrawImage(img, 0, 0, SamplingOptions, Paint);
// SkiaSharpSvgTools.DrawUnscaled (downscale path)
canvas.DrawImage(img, 0, 0, SamplingOptions, Paint);SVG upscaling ( ✅ Good — Quality mappings are well-chosen
✅ Good — Backwards compatible
✅ Good — Clean constructor threadingQuality parameter added to all constructor chains consistently:
✅ Good — Incremental build support
✅ Good — Comprehensive tests (22 new)
💡 Observation —
|
Add a FilterQuality property to ResizeImageInfo with a default of SKFilterQuality.High (preserving existing behavior). The property is parsed from MSBuild item metadata and threaded through SkiaSharpTools, SkiaSharpRasterTools, SkiaSharpSvgTools, SkiaSharpImaginaryTools, Resizer, SkiaSharpAppIconTools, and AndroidAdaptiveIconGenerator. Users can now configure FilterQuality per image in their project file: <MauiImage Include="Resources\Images\photo.png" FilterQuality="None" /> Fixes #25750 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The original implementation only set Paint.FilterQuality which is deprecated and ignored by newer SkiaSharp. This fix maps FilterQuality to the actual SamplingOptions used by DrawImage, making the setting functional: - None -> Nearest/None (nearest neighbor, smallest file size) - Low -> Linear/None (bilinear, no mipmaps) - Medium -> Linear/Linear (bilinear + mipmaps) - High/default -> Linear/Linear (preserves original hardcoded behavior) Added 13 functional tests proving the feature works end-to-end: - Pixel differentiation: None vs High produce different output (proves it works) - Regression: default produces identical output to explicit High - End-to-end MSBuild pipeline: FilterQuality metadata flows through ResizetizeImages task - All quality levels produce correctly sized output for both raster and SVG Full regression: 605 passed (568 baseline + 37 new), 20 pre-existing failures, 0 regressions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per mattleibow's review on PR #25686, replace the obsolete SKFilterQuality enum with a clean MAUI-specific ResizeQuality enum that hides SkiaSharp internals: - Auto: Default behavior (bilinear + mipmaps, preserves backward compat) - Best: Mitchell cubic resampler (highest quality) - Fastest: Nearest neighbor (smallest file size, fastest processing) MSBuild metadata name changed from FilterQuality to ResizeQuality. All 25 new tests pass. 593 total passed (568 baseline + 25 new). Same 20 pre-existing failures. Zero regressions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Enum.TryParse now uses ignoreCase: true, matching MSBuild convention for metadata parsing (consistent with Resize, TintColor, etc.) - Added 3 case-insensitive parsing tests (auto, FASTEST, best) - Added Best vs Auto pixel differentiation test proving Mitchell cubic path is exercised and produces different output than bilinear 29 new tests, 597 total passed, 0 regressions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ke tests - Replace meaningless IsAntialias assertions with SamplingOptions correctness checks - Add per-quality SamplingOptions mapping tests (Auto→Linear/Linear, Best→Mitchell, Fastest→Nearest/None) - Add SVG pixel differentiation test (Fastest vs Auto on downscale) - Add Best quality smoke tests for both raster and SVG - Fix SVG tests to use BaseSize for exact dimension assertions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Assert pixel array lengths match before comparison loop to avoid IndexOutOfRangeException - Remove misleading 'smaller file sizes' claim from Fastest doc (PNG encoding is fixed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…alidation - Add missing </summary> closing tag on Best enum member XML doc - Add ResizeQuality to MSBuild inputs tracking so changing quality settings triggers a rebuild instead of serving stale cached images Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
28be2d7 to
6989901
Compare
🧪 PR Test EvaluationOverall Verdict: ✅ Tests are adequate This PR adds 37 new unit tests with excellent coverage of the core
📊 Expand Full EvaluationPR Test Evaluation ReportPR: #34559 — Add configurable ResizeQuality for Resizetizer Overall Verdict✅ Tests are adequate Strong unit test coverage of the core quality mapping, MSBuild metadata parsing, and pixel-level regression guarantees. Two minor gaps in coverage for the 1. Fix Coverage — ✅The tests trace directly to the changed code paths:
If the quality mapping 2. Edge Cases & Gaps —
|
| Test | Assertion | Quality |
|---|---|---|
| Sampling options mapping | Assert.Equal(new SKSamplingOptions(...), tools.SamplingOptions) |
✅ Exact match |
| Pixel identity (default == Auto) | Pixel-by-pixel loop Assert.Equal(pixel1, pixel2) |
✅ Very strong |
| Pixel difference | Assert.True(differentPixels > 0, ...) |
✅ Adequate with message |
| Output dimensions | Assert.Equal(256, resultImage.Width) |
✅ Specific |
| Enum parsing | Assert.Equal(expected, info.Quality) |
✅ Exact match |
Assertions are specific and meaningful throughout. The pixel-by-pixel equality for the regression test (DefaultQualityProducesIdenticalOutputToExplicitAuto) is particularly strong.
9. Fix-Test Alignment — ✅
Fix → Test mapping:
| Changed File | Test Coverage |
|---|---|
ResizeQuality.cs (new enum) |
Used in all test files ✅ |
ResizeImageInfo.cs (Quality property + parsing) |
ResizeImageInfoTests.ResizeQualityTests ✅ |
SkiaSharpTools.cs (sampling options switch) |
SkiaSharpRasterToolsTests.ResizeQualityTests, SkiaSharpSvgToolsTests.ResizeQualityTests ✅ |
SkiaSharpRasterTools.cs / SkiaSharpSvgTools.cs / SkiaSharpImaginaryTools.cs (constructors) |
Covered transitively ✅ |
Resizer.cs (passes quality through) |
Covered by E2E ResizetizeImagesTests ✅ |
SkiaSharpAppIconTools.cs (passes quality) |
|
AndroidAdaptiveIconGenerator.cs (passes quality) |
|
Microsoft.Maui.Resizetizer.After.targets (build invalidation) |
Recommendations
- (Nice-to-have) Add a quality test to
SkiaSharpAppIconToolsTests— Add a test that creates an app icon withResizeQuality=Fastestand verifies the output differs fromAuto. Since the existingSkiaSharpAppIconToolsTestsalready test pixel output, this would be a straightforward addition. - (Nice-to-have) Add SVG
BestvsAutopixel comparison — MirrorBestQualityProducesDifferentPixelOutputThanAutofromSkiaSharpRasterToolsTestsinSkiaSharpSvgToolsTeststo ensure SVG quality behaves as expected forBestmode. - (Low priority) Consider a
ResizeQualityE2E test for app icons — A test inResizetizeImagesTeststhat uses an app icon item withResizeQualityset would close the gap for theAndroidAdaptiveIconGeneratorcode path.
Warning
⚠️ Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
dc.services.visualstudio.com
To allow these domains, add them to the network.allowed list in your workflow frontmatter:
network:
allowed:
- defaults
- "dc.services.visualstudio.com"See Network Configuration for more information.
Note
🔒 Integrity filtering filtered 2 items
Integrity filtering activated and filtered the following items during workflow execution.
This happens when a tool call accesses a resource that does not meet the required integrity or secrecy level of the workflow.
- pr:Add configurable ResizeQuality for Resizetizer #34559 (
pull_request_read: Resource 'pr:Add configurable ResizeQuality for Resizetizer #34559' has lower integrity than agent requires. Agent would need to drop integrity tags [unapproved:all approved:all] to trust this resource.) - #25686 (
search_pull_requests: Resource 'pr:made FilterQuality configurable for Resizetizer #25686' has lower integrity than agent requires. Agent would need to drop integrity tags [approved:all] to trust this resource.)
🧪 Test evaluation by Evaluate PR Tests
Description
Adds a configurable
ResizeQualityoption to Resizetizer, allowing developers to control the image resampling quality when resizing images. This is a clean re-implementation of community PR #25686 (by @thisisthekap), rebased ontonet11.0and incorporating review feedback from @mattleibow.Key changes:
ResizeQualityenum with three values:Auto(default),Best,FastestSKSamplingOptions(not the deprecatedPaint.FilterQualitywhich is ignored by newer SkiaSharp)<MauiImage ResizeQuality="Fastest" ... />Autoproduces identical output to the previous hardcoded behaviorQuality mappings:
Auto(default)Linear+LinearmipmapsBestMitchellcubic resamplerFastestNearestneighbor, no mipmapsUsage:
Changes
9 source files across Resizetizer:
ResizeQuality.cs(new) — Custom enumResizeImageInfo.cs— Quality property + case-insensitive MSBuild metadata parsingSkiaSharpTools.cs— ResizeQuality → SKSamplingOptions mapping; removed obsoletePaint.FilterQualitySkiaSharpRasterTools.cs,SkiaSharpSvgTools.cs,SkiaSharpImaginaryTools.cs— Constructor chainsResizer.cs,SkiaSharpAppIconTools.cs,AndroidAdaptiveIconGenerator.cs— Pass quality through4 test files with 37 new tests:
Test results
Review notes
Addresses feedback from @mattleibow on #25686:
SKFilterQualitySKSamplingOptions(the actual rendering control, not the ignoredPaint.FilterQuality)BestusesSKCubicResampler.Mitchellas suggestedItems for reviewer consideration:
Auto/Best/Fastest) — open to alternatives likeDefault/High/LowFixes #25686