Skip to content

Pure integer arithmetic#2904

Open
mpospelova wants to merge 3 commits intoimage-rs:mainfrom
mpospelova:pure-integer-arithmetic
Open

Pure integer arithmetic#2904
mpospelova wants to merge 3 commits intoimage-rs:mainfrom
mpospelova:pure-integer-arithmetic

Conversation

@mpospelova
Copy link
Copy Markdown
Contributor

This PR replaces floating-point arithmetic with pure integer arithmetic for CMYK-to-RGB conversion in the TIFF decoder. Fixes Precision Errors:

  • Eliminates off-by-one pixel values caused by floating-point truncation. Now this behaves similarly to libtiff
  • Added tiff/testsuite/cmyk_u8_edge_case.tif (edge case with a 1x1 pixel with CMYK [0, 0, 0, 65]) to test this
  • Old Logic: floor(255 * (1 - 65/255)) = floor(189.9998) = 189
  • New Logic: (255 * 190) // 255 = 190

Copy link
Copy Markdown
Member

@197g 197g left a comment

Choose a reason for hiding this comment

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

Just a question, integer arithmetic with fixed divisors sounds preferable in either case—most of the time at least.

Comment on lines +563 to +565
(((255 - c) * k_inv) / 255) as u8,
(((255 - m) * k_inv) / 255) as u8,
(((255 - y) * k_inv) / 255) as u8,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's making a good point that as used floor semantics but wouldn't we prefer rounding here? Then a bias term for 127 should be added here before.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you! Adding a bias term is mathematically more accurate for rounding, but it again introduced pixel differences when testing against libtiff (which uses truncation by default). I have added another test case for this specific truncation behavior:

  • CMYK: [1, 1, 1, 128] with intermediate values (255 - c) = 254 and k_inv = 127
  • New logic without bias term: (254 * 127) / 255 = 32258 / 255 = 126 (integer division naturally truncates to 126)
  • With bias term: (254 * 127 + 127) / 255 = 32385 / 255 = 127 (rounds up to 127)

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