Skip to content

Decode theme thumbnails with SkiaSharp so WebP themes work - #700

Open
rmbakker88 wants to merge 2 commits into
t1m0thyj:mainfrom
rmbakker88:feat/webp-thumbnails
Open

Decode theme thumbnails with SkiaSharp so WebP themes work#700
rmbakker88 wants to merge 2 commits into
t1m0thyj:mainfrom
rmbakker88:feat/webp-thumbnails

Conversation

@rmbakker88

Copy link
Copy Markdown

Relates to #690 , and to #696 .

In #690 you mentioned WDD should already handle previewing .png and .webp. Preview does — Skia/ImageCache.cs decodes through SKCodec, which reads WebP fine. Thumbnail generation was missed by the 5.7.0 Skia change though: ThemeThumbLoader still decodes with System.Drawing, and GDI+ cannot read WebP at all. Image.FromFile on a .webp throws:

System.Runtime.InteropServices.ExternalException: An object could not be created, possibly due to
a lack of memory, but most likely due to invalid input.

So a WebP theme previews but has no thumbnail — and before #NNN is fixed, that exception hangs the import dialog outright.

What this changes

Decode thumbnails with SKCodec (first commit). Same decoder and the same SKCubicResampler.Mitchell sampling the preview renderer already uses, then a pixel copy into a Bitmap for the ListView image list. ScaleImage(Image, Size) is gone since every caller now starts from a path or a stream. No new package — SkiaSharp is already referenced.

Reuse cached thumbnails that do not match the requested size (second commit). GetThumbnailImage only reused a cached thumbnail when its size matched exactly, and otherwise disposed it and regenerated from the theme images. That meant a thumbnail.png supplied with a theme was silently ignored unless it happened to be exactly 192x108, and on any display not at 100% scaling — where the requested size is e.g. 256x144 — even the bundled thumbnails were discarded and regenerated on every single load. It now scales the cached thumbnail, and falls back to generating a new one if the file cannot be read.

I did not re-save the scaled result to thumbnail.png, so a thumbnail shipped with a theme stays as the author made it rather than being overwritten by the cache. Happy to change that if you would rather the cache always hold the display-sized version.

Testing

  • dotnet test --filter "type!=system" — 7 passed, unchanged from main.
  • Decoder checked directly against 1920x1080 .jpg, .png and .webp files, scaling to 192x108 and upscaling 192x108 to 256x144. Verified the output is the requested size and that four known-colour quadrants land in the right place with the right values, which catches both channel-order and orientation mistakes. .webp fails on main with the exception above and passes here; .jpg and .png pass on both.
  • Manually: a WebP theme that hangs the import on main now imports with a real generated thumbnail and previews correctly.

Note on scope

This is only about WDD reading WebP theme images. It does not touch how wallpaper is handed to Windows, so it is not the whole of #690 if that also means writing .webp to the desktop on builds that support it natively — happy to leave that part alone or look at it separately.

rmbakker88 and others added 2 commits July 26, 2026 01:19
Thumbnails were decoded with System.Drawing, which cannot read WebP, so
generating one for a WebP theme threw ExternalException even though the
preview renderer added in 5.7.0 already decodes WebP through SKCodec.

Decode through SKCodec here as well and scale with the same Mitchell
resampler the preview uses, then copy the pixels into a Bitmap for the
ListView image list.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A cached thumbnail was only used when its size matched exactly, so a
thumbnail.png supplied with a theme, or one cached before the display
scaling changed, was thrown away and regenerated from the theme images
on every load.

Scale the cached thumbnail to the requested size instead, and fall back
to generating a new one if it cannot be read.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant