8000 Re-use `UnpredictImageU8` and implement for 16bpp by palszasz · Pull Request #53 · syoyo/tinydng · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Re-use UnpredictImageU8 and implement for 16bpp #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: release
Choose a base branch
from

Conversation

palszasz
Copy link
Contributor
@palszasz palszasz commented Jun 9, 2025

We had issues using tinydng to load 16bit TIFF files: the files are loaded, but the data seems to be 8000 garbage.

We suspect the issue with 16bit tiff files are related to the predictor. In the case where the loader fails, the tiff file uses the LZW compression and predictor==2. It seems that in 16bit mode the predictor still assumes 8bit data, and hence the bug.

As a first step we rewrite the code to use the UnpredictImageU8 function in more places, so we can fix the issue in less places.

Then implemented UnpredictImageU8 for 16bpp images as well.


I'm not 100% happy that I had to use templates, since templates were not used before in the code. If you want, I can just create duplicated functions (i.e. one function for uint8_t case and another for uint16_t case)... or use C macros ;-)

Here is a test image to reprodoce the issue:

test_image_00.tiff.zip

(I patched locally test_loader.cc to dump the pixel values to verify it... and we can see the fix in our own image viewer using tinydng).

@syoyo syoyo requested a review from Copilot June 9, 2025 11:49
Copy link
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the TIFF loader’s predictor logic by introducing a generic UnpredictImageU8Impl template, centralizing horizontal differencing (predictor 2) into a single function, and extending support to 16-bit samples. Key changes:

  • Added UnpredictImageU8Impl<T> and unified UnpredictImageU8 to handle both 8 bpp and 16 bpp.
  • Replaced in-place loops in DecompressZIPedTile and LoadDNGFromMemory with calls to UnpredictImageU8.
  • Removed duplicated prediction code blocks and consolidated failure paths.
Comments suppressed due to low confidence (3)

tiny_dng_loader.h:2865

  • [nitpick] The function name UnpredictImageU8 implies 8-bit only, but it now handles 16-bit samples too. Consider renaming (e.g., UnpredictImage) to accurately reflect its capabilities.
static bool UnpredictImageU8(std::vector<uint8_t>& dst,  // inout

tiny_dng_loader.h:2876

  • No automated tests cover the 16-bpp predictor path. Please add a unit test for LZW + predictor==2 on 16-bit images to prevent regressions.
} else if (bps == 16) {

tiny_dng_loader.h:2847

  • Neither UnpredictImageU8Impl nor UnpredictImageU8 have doc comments explaining parameters, behavior, and supported bps values. Adding brief function headers would improve readability.
static void UnpredictImageU8Impl(T* dst,  // inout

Comment on lines 2848 to 2849
int predictor, const size_t width,
const size_t rows, const size_t spp) {
Copy link
Preview
Copilot AI Jun 9, 2025

Choos 8000 e a reason for hiding this comment

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

The parameter predictor is accepted by UnpredictImageU8Impl but never used; consider removing it or asserting its expected value (e.g., predictor == 2) to avoid confusion.

Suggested change
int predictor, const size_t width,
const size_t rows, const size_t spp) {
const size_t width, const size_t rows,
const size_t spp) {

Copilot uses AI. Check for mistakes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point! Will fix it!

UnpredictImageU8Impl(dst.data(), predictor, width, rows, spp);
return true;
} else if (bps == 16) {
UnpredictImageU8Impl(reinterpret_cast<uint16_t*>(dst.data()), predictor, width, rows, spp);
Copy link
Preview
Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

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

Reinterpreting a vector<uint8_t> buffer as uint16_t* can lead to unaligned accesses on platforms that require 2-byte alignment. Consider copying into a properly aligned vector<uint16_t> or processing bytes directly.

Copilot uses AI. Check for mistakes.

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 codebase already contains similar cases (e.g. in read2), so fixing this I think would not have any benefit, but would impact the performance negatively.

@palszasz
Copy link
Contributor Author

[nitpick] The function name UnpredictImageU8 implies 8-bit only, but it now handles 16-bit samples too. Consider renaming (e.g., UnpredictImage) to accurately reflect its capabilities.

Good point, will fix it.

We suspect the issue with 16bit tiff files are related to the predictor.
In the case where the loader fails, the tiff file uses the LZW
compression and predictor==2. It seems that in 16bit mode the predictor
still assumes 8bit data, and hence the bug.

As a first step we rewrite the code to use the `UnpredictImageU8`
function in more places, so we can fix the issue in less places.

Then implemented `UnpredictImageU8` for 16bpp images as well.
@palszasz palszasz force-pushed the feature/fix_16bps_predictor branch from 0903961 to 8258cc0 Compare June 10, 2025 12:05
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
0