Skip to content

fix(hide): read the preview's pixels at 8 bits a channel - #987

Merged
KnifeLemon merged 1 commit into
KnifeLemon:mainfrom
lightscape-jm:fix/hide-preview-depth
Nov 2, 2026
Merged

KnifeLemon merged 1 commit into
KnifeLemon:mainfrom
lightscape-jm:fix/hide-preview-depth

Conversation

@lightscape-jm

Copy link
Copy Markdown
Contributor

What does this change?

The small preview fix from #877 (#3 in the plan), on its own before Annotate.

The Pixelate / blur window turns its preview into a bitmap from ImageMagick's MagickFormat.Bgra output, which keeps the picture's own depth. A PNG stored at 1 bit a channel (a flat screenshot, a diagram, a two-colour palette) gives an eighth of the bytes. The bitmap reads four bytes a pixel from the pinned buffer, so it reads past the end, which can show wrong pixels or crash.

Measured on current main through HideService.LoadPreviewAsync, for a plain white 40 × 30 PNG and a two-colour palette PNG (both saved by ImageMagick at depth 1):

Picture Bytes from ToByteArray(MagickFormat.Bgra) Bytes the bitmap reads
white.png (GrayscaleAlpha, depth 1) 600 4,800
palette.png (PaletteAlpha, depth 1) 600 4,800

The pixels are now read from the pixel collection (GetPixels().ToByteArray(PixelMapping.BGRA)), which is 8 bits a channel whatever depth the picture was stored with, and their count is checked before the bitmap is made, so a mismatch is an error instead of a read past the end.

I looked for the same pattern elsewhere: PdfCompressor.EncodeFlate also writes raw pixels, but it sets Depth = 8 first and checks the length, so it's fine.

Type of change

  • Bug fix
  • New feature or improvement
  • New format or engine
  • Translation
  • Documentation
  • Build, CI or dependencies

How was it tested?

  • dotnet format --verify-no-changes
  • dotnet test: the App Pixelate / blur tests (33, including the new one) pass.
  • Tried it in the app (what you converted or clicked, and on which OS): macOS 26.6.2, Apple silicon. The table above is from the real preview loader on main; with this change the same pictures give 4,800 bytes in their real colours.

New test (tests/Filee.App.Tests/HidePreviewPixelsTests.cs):

Test Checks
A_one_bit_and_a_palette_png_give_four_bytes_a_pixel_in_their_colours a 1-bit white PNG and a palette PNG with a blue square, saved and read back: four bytes a pixel, white as white, and the blue square's BGRA bytes in the top left with white beside it

Screenshots (UI changes)

None.

Checklist

  • New UI strings are in all src/Filee.App/Assets/i18n/*.json files (none)
  • New third-party code or binaries are listed in THIRD-PARTY-NOTICES.md (none)
  • The PR does one thing (unrelated changes go in a separate PR)

🤖 Generated with Claude Code

The Pixelate / blur window turned its preview into a bitmap from
ImageMagick's "BGRA" output, which keeps the picture's own depth: a 1-bit
grey or palette PNG (a flat screenshot, a diagram) gave an eighth of the
bytes, and the bitmap, reading four bytes a pixel, ran past their end
and could crash Filee.

The pixels are now read from the picture's pixel data, 8 bits a
channel whatever depth it was stored with, and their count is checked
before the bitmap is made.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the bug Something isn't working label Nov 1, 2026

@KnifeLemon KnifeLemon left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @lightscape-jm. A clear catch, with numbers that show it:

  • ToByteArray(MagickFormat.Bgra) keeps the stored depth, so a 1-bit PNG gave an eighth of the bytes, and the bitmap read past the end of the buffer;
  • GetPixels().ToByteArray(PixelMapping.BGRA) is 8 bits a channel whatever the depth;
  • the length check turns any future mismatch into an error instead of a bad read.

Checking PdfCompressor.EncodeFlate for the same pattern was a good extra. CI is green. Merging.

@KnifeLemon
KnifeLemon merged commit 4ff6b3e into KnifeLemon:main Nov 2, 2026
10 checks passed
@lightscape-jm lightscape-jm mentioned this pull request Nov 2, 2026
7 of 12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants