Fix laplacian dst format and simplify 24bit writes#3791
Conversation
Previously, the color gathered in acolor was mapped using the source surface's information, and then written into the destination surface. Since destination surfaces are restricted to the same depth, this did work most of the time, but would not work if two surfaces had the same depth but different pixel layouts. Except for in the 24 bit path, which would map RGB, then unmap with source format, then remap into channels in destination format. After this change, the color is correctly mapped using the destination's pixelformat, and the 24 bit write is simplified to just use the mapped color as is.
These are using mapped colors, they can be stored directly into the pixel buffer. There is no need to "unmap" them using the pixelformat and store them in the red, green, and blue channels separately.
📝 WalkthroughWalkthroughThis PR refactors 24-bpp pixel write logic to use fixed byte positions based on system byte order instead of per-format channel shifts, and corrects the laplacian function to map colors using the destination surface's format and palette. A regression test validates laplacian correctness when source and destination have different channel masks. Changes24-bpp pixel write and laplacian cross-format fix
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
test/transform_test.py (1)
1272-1304: ⚡ Quick winConsider asserting the surfaces have different channel masks before the laplacian call.
The test validates that laplacian works when source and destination have different channel layouts, but doesn't explicitly verify that the layouts are actually different before running the transform. Adding a precondition assertion would make the test more self-documenting and catch potential regressions in the test setup itself.
🔍 Suggested precondition check
s2 = pygame.Surface( (SIZE, SIZE), 0, 32, masks=(0xFF0000, 0xFF00, 0xFF, 0xFF000000), ) + # Verify the surfaces actually have different channel layouts + self.assertNotEqual(s1.get_masks(), s2.get_masks()) pygame.transform.laplacian(s1, s2)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/transform_test.py` around lines 1272 - 1304, Add a precondition assertion in test_laplacian__cross_format to ensure the source and destination actually have different channel layouts: check s1.get_masks() != s2.get_masks() (or compare masks tuples created when constructing s1/s2) before calling pygame.transform.laplacian so the test fails early if the surfaces end up with the same channel masks; place this assertion right after s2 is created and before the laplacian call.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@test/transform_test.py`:
- Around line 1272-1304: Add a precondition assertion in
test_laplacian__cross_format to ensure the source and destination actually have
different channel layouts: check s1.get_masks() != s2.get_masks() (or compare
masks tuples created when constructing s1/s2) before calling
pygame.transform.laplacian so the test fails early if the surfaces end up with
the same channel masks; place this assertion right after s2 is created and
before the laplacian call.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4c334018-a822-46b3-8ac0-a2a91dea887c
📒 Files selected for processing (3)
src_c/surface.csrc_c/transform.ctest/transform_test.py
This is a follow-up to #3790
CodeRabbit said the bugfix in that PR was lacking from laplacian, and it was wrong about that. However, going through laplacian found that it also has a bug with writing pixel data-- it is using the wrong surface's information about what to write.
For laplacian--
Previously, the color gathered in acolor was mapped using the source surface's information, and then written into the destination surface. Since destination surfaces are restricted to the same depth, this did work most of the time, but would not work if two surfaces had the same depth but different pixel layouts. Except for in the 24 bit path, which would map RGB, then unmap with source format, then remap into channels in destination format.
Simplified 24 bit writes--
These are using mapped colors, they can be stored directly into the pixel buffer. There is no need to "unmap" them using the pixelformat and store them in the red, green, and blue channels separately.
(This is related because simplifying the 24 bit writes broke the laplacian test, because of the aforementioned bug)