Repository navigation
Replace ImageSharp with SkiaSharp in the thumbnail generator - #6598
Conversation
ImageSharp's only consumer was tools/MeshWeaver.ThumbnailGenerator. Every version up to 4.1.1 carries three high-severity advisories and the patched line requires a paid licence, so the generator now scales its captures with SkiaSharp (MIT), already shipped by the portal. - ThumbnailResizer: box fitting (unchanged maths) + bicubic (Catmull-Rom) PNG scale to the exact thumbnail size, matching ImageSharp's default Resize sampler family. - Drop SixLabors.ImageSharp from Directory.Packages.props and its Dependabot ignore block. - New test/MeshWeaver.ThumbnailGenerator.Test: an 800x450 fixture capture becomes a 400x225 PNG. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Validation misidentifies invalid heights, and the repeated dependency rationale incorrectly includes patched ImageSharp 3.2.0 among vulnerable releases.
4 open findings
What changed in this PR
Replaces ImageSharp with the existing SkiaSharp stack in the standalone thumbnail generator.
Changes:
- Adds SkiaSharp-based PNG resizing and aspect fitting.
- Adds focused resizing tests and fixture coverage.
- Removes ImageSharp dependency and Dependabot configuration.
| File | Description |
|---|---|
.github/dependabot.yml |
Removes the ImageSharp ignore rule. |
Directory.Packages.props |
Removes the ImageSharp version pin. |
MeshWeaver.slnx |
Adds the thumbnail test project. |
tools/MeshWeaver.ThumbnailGenerator/ThumbnailResizer.cs |
Implements SkiaSharp resizing. |
tools/MeshWeaver.ThumbnailGenerator/ThumbnailGenerator.cs |
Uses the new resizer. |
tools/MeshWeaver.ThumbnailGenerator/MeshWeaver.ThumbnailGenerator.csproj |
Replaces package references. |
tools/MeshWeaver.ThumbnailGenerator/README.md |
Documents thumbnail generation. |
test/MeshWeaver.ThumbnailGenerator.Test/ThumbnailResizerTest.cs |
Tests dimensions, format, pixels, and failures. |
test/MeshWeaver.ThumbnailGenerator.Test/MeshWeaver.ThumbnailGenerator.Test.csproj |
Defines the test project. |
test/MeshWeaver.ThumbnailGenerator.Test/Fixtures/screenshot-800x450.png |
Supplies the resize fixture. |
test/MeshWeaver.Documentation.Test/HandWovenGateRatchetGuard.cs |
Updates the sanctioned-tool rationale. |
test/Directory.Build.props |
Excludes the dependency-free test from messaging imports. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| var distinct = new HashSet<SKColor>(); | ||
| for (var y = 0; y < bitmap.Height; y += 15) | ||
| for (var x = 0; x < bitmap.Width; x += 20) | ||
| distinct.Add(bitmap.GetPixel(x, y)); | ||
| Assert.True(distinct.Count > 1, "The thumbnail is a single flat colour — nothing of the capture survived."); |
There was a problem hiding this comment.
Fair point on convention, but not a defect worth a new review round: the set is a method-local, single-threaded scratch value inside a test assertion and never escapes it; the immutable-collections rule targets state that is shared or held. The assertion's result (more than one distinct sampled colour) is the same either way. Leaving it as is under this PR's converge rule (push only for a wrong result, security hole, data loss or broken build/test).
| <!-- Image scaling: SkiaSharp (MIT), the stack the portal already ships for share cards and | ||
| favicons. Replaced SixLabors.ImageSharp — every version up to 4.1.1 carries high-severity | ||
| advisories and the patched line is pay-to-use. The Linux natives let the tool (and its | ||
| test) run on a Linux runner; macOS and Windows natives come with SkiaSharp itself. --> |
There was a problem hiding this comment.
Agreed the phrase "every version up to 4.1.1" is loose: the 3.x line's patched backport is 3.2.0, so precisely the vulnerable set is < 3.2.0 and 4.0.0–4.1.1, with 3.2.0 and 4.1.2 patched but licence-enforcing. The PR body states that precisely, and the decision does not change: both patched releases enforce a paid licence in MSBuild, which is why the package goes. This is wording in a comment/README, not behaviour, so it is not pushed on its own under this PR's converge rule; it can be tightened in a follow-up touching the tool.
| the same stack the portal ships for share cards and favicons. It replaced SixLabors.ImageSharp: | ||
| every ImageSharp version up to 4.1.1 carries high-severity advisories, and the patched releases | ||
| need a paid licence. `test/MeshWeaver.ThumbnailGenerator.Test` pins the output size and format. No newline at end of file |
There was a problem hiding this comment.
Agreed the phrase "every version up to 4.1.1" is loose: the 3.x line's patched backport is 3.2.0, so precisely the vulnerable set is < 3.2.0 and 4.0.0–4.1.1, with 3.2.0 and 4.1.2 patched but licence-enforcing. The PR body states that precisely, and the decision does not change: both patched releases enforce a paid licence in MSBuild, which is why the package goes. This is wording in a comment/README, not behaviour, so it is not pushed on its own under this PR's converge rule; it can be tightened in a follow-up touching the tool.
| /// ships for its share cards and favicons; SixLabors.ImageSharp was dropped because every version up | ||
| /// to 4.1.1 carries high-severity advisories and the patched line needs a paid licence. |
There was a problem hiding this comment.
Agreed the phrase "every version up to 4.1.1" is loose: the 3.x line's patched backport is 3.2.0, so precisely the vulnerable set is < 3.2.0 and 4.0.0–4.1.1, with 3.2.0 and 4.1.2 patched but licence-enforcing. The PR body states that precisely, and the decision does not change: both patched releases enforce a paid licence in MSBuild, which is why the package goes. This is wording in a comment/README, not behaviour, so it is not pushed on its own under this PR's converge rule; it can be tightened in a follow-up touching the tool.
Test Results 25 files + 1 25 suites +1 57m 4s ⏱️ -3s Results for commit 6258336. ± Comparison against base commit 5ba08db. This pull request removes 40 and adds 47 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
main replaced SixLabors.ImageSharp with SkiaSharp (#6598), so the ImageSharp hold this branch carried in Directory.Packages.props and .github/dependabot.yml is dropped with the package. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Maintainer decision: replace ImageSharp in core.
SixLabors.ImageSharphad exactly one consumer,tools/MeshWeaver.ThumbnailGenerator. Every version up to 4.1.1 carries three high-severity advisories (GHSA-j3p4-wp97-rph4, GHSA-j9gm-c75j-xc9q, GHSA-jjfr-hcj7-qf5w), and the only patched releases (4.1.2, and the 3.2.0 backport) enforce a paid licence in MSBuild. So the package goes, rather than being held.What changes
ThumbnailResizer(new, in the tool): the box-fitting maths moved here unchanged, and the scale-down is now SkiaSharp (MIT), already shipped by the portal for share cards and favicons. It still scales the 2x Playwright capture to exactly the fitted size, using a bicubic (Catmull-Rom) sampler from the same family as ImageSharp's defaultResize, and writes a PNG. Output size, format and filter family are unchanged.SkiaSharp+SkiaSharp.NativeAssets.Linux.NoDependencies, both already centrally pinned.SixLabors.ImageSharpis removed fromDirectory.Packages.props, and its Dependabot ignore block is removed from.github/dependabot.yml.test/MeshWeaver.ThumbnailGenerator.Test(new): an 800x450 fixture capture becomes a 400x225 PNG. The test checks the encoded format, the dimensions, and that the pixels are not a single flat colour. It also covers aspect fitting (wider, taller, same aspect) and refuses an undecodable source by name. The project is inMeshWeaver.slnx, soshard-assign.shpicks it up at the default weight, and it is excluded from the globalMeshWeaver.Messagingusing, since it references no messaging.HandWovenGateRatchetGuard: the reason text for the tool's sanctioned entry now names SkiaSharp. The tool still references no MeshWeaver assembly, so the entry's premise still holds.Nothing in CI invokes the generator. It is run from source (
dotnet run --project tools/MeshWeaver.ThumbnailGenerator), per NuGetPackageRetirement, and that command is unchanged.Coordination with #6549
Dependabot's group PR #6549 bumps ImageSharp 3.1.12 → 3.2.0 and moves its ignore to
>=3.2.0. This PR supersedes that ImageSharp part: once this merges, both the pin and the ignore block are gone, and Dependabot's rebase of #6549 drops the ImageSharp bump. Its Testcontainers/xunit bumps are unaffected.Verification (local, CI flags)
dotnet build -c Release -warnaserror test/MeshWeaver.ThumbnailGenerator.Test/...(builds the tool too): 0 warnings, 0 errors.dotnet teston it: 5 of 5 passed.dotnet build -c Release -warnaserror test/MeshWeaver.Documentation.Test/...: 0/0.HandWovenGate*: 4 of 4 passed.Satellite-pins: SixLabors.ImageSharp — git grep of origin/main in MeshWeaver.Plugins, .Education, .Reinsurance, .SocialMedia, .Manufacturing, .Crm, .FundReporting and Memex: no csproj/props/targets references it versionless. Memex declares its own
PackageVersion(3.1.12) in its own Directory.Packages.props and references it from no project; MeshWeaver.Plugins mentions it only in prose (src/MeshWeaver.AI/Data/Skill/package-versions.md).Pairs-with: none — the removed package was referenced only by a standalone tool; no public type or member leaves
src/.🤖 Generated with Claude Code