Mercurial > octave-libtiff
changeset 31144:8ba9f2326ee9
Tiff writeEncodedStrip: added support for BiLevel images
* __tiff__.cc(write_strip): implemented the case for BiLevel images.
author | magedrifaat <magedrifaat@gmail.com> |
---|---|
date | Sun, 31 Jul 2022 01:26:02 +0200 |
parents | a68f2dadafee |
children | 2e11f9cb30b8 |
files | libinterp/dldfcn/__tiff__.cc |
diffstat | 1 files changed, 46 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/dldfcn/__tiff__.cc Sun Jul 31 00:13:04 2022 +0200 +++ b/libinterp/dldfcn/__tiff__.cc Sun Jul 31 01:26:02 2022 +0200 @@ -948,12 +948,52 @@ // LibTIFF uses zero-based indexing as opposed to Octave's 1-based strip_no--; - // Can't rely in LibTIFF's TIFFStripSize because boundary strips - // can be smaller in size - tsize_t strip_size = strip_data.numel () * image_data->bits_per_sample / 8; - if (TIFFWriteEncodedStrip (tif, strip_no, - strip_data.fortran_vec (), strip_size) == -1) - error ("Failed to write strip data to image"); + void *data_vec = strip_data.fortran_vec (); + if (image_data->bits_per_sample == 8 + || image_data->bits_per_sample == 16 + || image_data->bits_per_sample == 32 + || image_data->bits_per_sample == 64) + { + // Can't rely on LibTIFF's TIFFStripSize because boundary strips + // can be smaller in size + tsize_t strip_size = strip_data.numel () + * image_data->bits_per_sample / 8; + if (TIFFWriteEncodedStrip (tif, strip_no, data_vec, strip_size) == -1) + error ("Failed to write strip data to image"); + + } + else if (image_data->bits_per_sample == 1) + { + if (image_data->samples_per_pixel != 1) + error ("Bi-Level images must have one channel only"); + + // Create a buffer to hold the packed strip data + // Unique pointers are faster than vectors for constant size buffers + std::unique_ptr<uint8_t []> strip_ptr + = std::make_unique<uint8_t []> (TIFFStripSize (tif)); + uint8_t *strip_buf = strip_ptr.get (); + uint8_t *data_u8 = reinterpret_cast<uint8_t *> (data_vec); + // According to the format specification, the row should be byte + // aligned so the number of bytes is rounded up to the nearest byte + uint32_t padded_width = (image_data->width + 7) / 8; + // Packing the pixel data into bits + for (uint32_t row = 0; row < rows_in_strip; row++) + { + for (uint32_t col = 0; col < image_data->width; col++) + { + uint8_t shift = 7 - col % 8; + strip_buf[row * padded_width + col / 8] |= data_u8[col] << shift; + } + data_u8 += image_data->width; + } + tsize_t strip_size = padded_width * rows_in_strip; + if (TIFFWriteEncodedStrip (tif, strip_no, strip_buf, strip_size) == -1) + error ("Failed to write strip data to image"); + } + else + { + error ("Unsupported bit depth"); + } } #endif @@ -1244,7 +1284,6 @@ else error ("Expected logical matrix for BiLevel image"); break; - case 4: case 8: if (args(2).is_uint8_type ()) write_strip<uint8NDArray> (tif, strip_no,