Skip to content
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

Allow for intra-byte bits_per_sample. #218

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

Conversation

samsieber
Copy link

Specifically, correctly read stripped tifs for any bits_per_sample sized up to the normal maximum bits_per_sample limit. Also, correctly read tiled tiffs that have bit padding in the last tile of each row. Bit padding in more than one tile per row is not supported.

Future work could include error reporting about gaps in coverage, tests, and a separate newtype for buffer indexing (vs usize for bytes)

Addresses #217; here are the caveats/support:

  • 32 bits and below should work for unsigned chunky stripped images
    • I haven't tested it with planar images, but it should work
    • This supports rgb(a) tiffs as well
  • Tiled tifs have the additional restriction that the only the final tile per row of tiles can have bit padding at the end. So this means that (samples*bits_per_sample*tile_width)%byte_len must be 0. Since tile dimensions are supposed to be multiples of 16, that means 1,2 and 4 bits_per_sample should always work. Other values may work correctly depending on the tile size and samples_per_pixel combination.
  • No validation was added or altered, except noting that horizontal prediction doesn't work for any non-byte-aligned bits_per_sample size for grayscale.
  • I think good future work would be to add a newtype wrapper around usize meant to index into DecodingBuffer, and then move most of the bit-padding calculation conversion logic into there.

Specifically, correctly read stripped tifs for any bits_per_sample sized up to the normal maximum bits_per_sample limit.
Also, correctly read tiled tiffs that have bit padding in the last tile of each row. Bit padding in more than one tile per row is not supported.

Future work could include error reporting about gaps in coverage, tests, and a separate newtype for buffer indexing (vs usize for bytes)
fn usize_div_ceil(numerator: usize, denominator: usize) -> usize {
(numerator + denominator - 1) / denominator
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add a comment here explaining what a "buffer unit" is? Though a shorter name might be better. Maybe call them "elements"?

if output_width == data_dims.0 as usize && padding_right == 0 {
let total_samples = data_dims.0 as usize * data_dims.1 as usize * samples;
let tile = &mut buffer.as_bytes_mut()[..total_samples * byte_len];
let row_buffer_units: usize = usize_div_ceil(data_dims.0 as usize * samples * self.bits_per_sample as usize, byte_len * 8);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm nervous about overflowing a usize here. I know the old code isn't careful here either, but it would be good to address. (Especially now that there's an additional multiplication by bits_per_sample that makes it even easier to overflow on a 32-bit system).

Probably the right thing to do would be to do most of the arithmetic using u64's and then use try_into when converting back.

/// If we leave in per-tile bit padding, then we cannot do it without knowing the number of tiles across this image is.
///
/// We have two options basically for precise allocation without knowing the number of tiles across:
/// * Ban tiles where tile_dim % (bits_per_sample * samples) == 0
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add a check if this condition isn't met, and return an unsupported error in that case?

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