Skip to content

Conversation

@nico
Copy link
Contributor

@nico nico commented Nov 14, 2025

This makes it possible to give a halftone region a reference image
instead of a grid of indices. If that's done, the grid of indices is
computed by finding the best-matching pattern for each covered region
in the reference image.

This can be used with a pattern dictionary that uses unique_image_tiles
from #26299 to make exact test images that have fewer tiles than
distinct_image_tiles and identity_tile_indices.

It should also be possible to use this with a regular halftone dot
pattern dictionary to get actual halftone images, but I haven't tried
that yet.

The matching is done in the writer instead of jbig2-from-image because
jbig2-from-image does not have access to referred-to segments, and
because this will eventually have to learn to deal with interesting
grid vectors, and that logic is also all in the writer. (For now,
interesting grid vectors are not supported, though.)

Then use this to add a basic halftone test, and tests for templates 1-3 (in both pattern dictionary and halftone region).

nico added 6 commits November 14, 2025 18:51
When I renamed the halftone region halftone keys, I forgot to update
their spelling in some diagnostic messages. Update the diagnostics
to use the right spellings.
This will allow putting a non-default-constructible field in
HalftoneRegionSegmentData.

No behavior change.
This makes it possible to give a halftone region a reference image
instead of a grid of indices. If that's done, the grid of indices is
computed by finding the best-matching pattern for each covered region
in the reference image.

This can be used with a pattern dictionary that uses unique_image_tiles
from SerenityOS#26299 to make exact test images that have fewer tiles than
distinct_image_tiles and identity_tile_indices.

It should also be possible to use this with a regular halftone dot
pattern dictionary to get actual halftone images, but I haven't tried
that yet.

The matching is done in the writer instead of jbig2-from-image because
jbig2-from-image does not have access to referred-to segments, and
because this will eventually have to learn to deal with interesting
grid vectors, and that logic is also all in the writer. (For now,
interesting grid vectors are not supported, though.)
This follows up on SerenityOS#26299 to create a test image that stores just
88 tiles instead of the 625 in bitmap-halftone-10bpp.json.
@github-actions github-actions bot added the 👀 pr-needs-review PR needs review from a maintainer or community member label Nov 14, 2025
Comment on lines +2005 to +2015
for (u32 y = 0; y < halftone_region.grayscale_height; ++y) {
for (u32 x = 0; x < halftone_region.grayscale_width; ++x) {
// Find best tile in pattern dictionary that matches reference best.
// FIXME: This is a naive, inefficient implementation.
u32 best_pattern_index = 0;
u32 best_pattern_difference = UINT32_MAX;
for (u32 pattern_index = 0; pattern_index <= pattern_dictionary.gray_max; ++pattern_index) {
u32 pattern_x = pattern_index * pattern_dictionary.pattern_width;
u32 pattern_difference = 0;
for (u32 py = 0; py < pattern_dictionary.pattern_height; ++py) {
for (u32 px = 0; px < pattern_dictionary.pattern_width; ++px) {
Copy link
Contributor

Choose a reason for hiding this comment

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

casual n^5 algo?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The halftone region is a tiling of the reference image, so the outer x/y walks the reference image in tile increments and the inner walks the tile data. So in a way this does O(number of patterns) work per pixel (to find the best pattern to match each tile). I'd call this O(n^3).

Still, as the comment says, yes, this is inefficient. (It's not super duper slow in practice though, just regular slow: I tried covering Tests/LibGfx/test-inputs/jpg/big_image.jpg, a 4000x3000 image, with 16 possible 4x4 tiles, and that took less than a second.)

@nico nico merged commit b7418e7 into SerenityOS:master Nov 15, 2025
14 checks passed
@nico nico deleted the jbig2-halftone branch November 15, 2025 13:09
@github-actions github-actions bot removed the 👀 pr-needs-review PR needs review from a maintainer or community member label Nov 15, 2025
nico added a commit to nico/serenity that referenced this pull request Nov 19, 2025
nico added a commit that referenced this pull request Nov 20, 2025
A lossless_halftone_region segment got added in #26399.
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.

2 participants