Skip to content

Commit

Permalink
convert inputs with < 4 bits to 8 bits correctly (#1080)
Browse files Browse the repository at this point in the history
  • Loading branch information
farindk committed Dec 26, 2023
1 parent 1d411c6 commit d7f125c
Showing 1 changed file with 26 additions and 4 deletions.
30 changes: 26 additions & 4 deletions libheif/color-conversion/hdr_sdr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* along with libheif. If not, see <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include "hdr_sdr.h"


Expand Down Expand Up @@ -80,7 +81,7 @@ Op_to_hdr_planes::convert_colorspace(const std::shared_ptr<const HeifPixelImage>
int output_bits = target_state.bits_per_pixel;

int shift1 = output_bits - input_bits;
int shift2 = 2 * input_bits - 16;
int shift2 = 2 * input_bits - output_bits;

const uint8_t* p_in;
int stride_in;
Expand Down Expand Up @@ -189,8 +190,29 @@ Op_to_sdr_planes::convert_colorspace(const std::shared_ptr<const HeifPixelImage>
return nullptr;
}

int shift = 8 - input_bits;
int roundingShift = 2 * input_bits - 8;
// We also want to support converting inputs with < 4 bits per pixel covering the whole output range.
// E.g. a 1-bit input should map to the output 0x00 / 0xFF.
// We do so by constructing a fixed-point multiplication factor that effectively shifts and combines the input to
// a string of bits that completely fills the output.
//
// Example: input 3 bit.
// Factor (binary): 00100100|10010010
// Input copies: AAABBBCC|CDDDEEE0
// \ /
// output

assert(input_bits > 0 && input_bits < 8);
uint16_t bit = static_cast<uint16_t>(1 << (16 - input_bits));
uint16_t mulFactor = bit;

for (;;) {
bit >>= input_bits;
if (!bit) {
break;
}

mulFactor |= bit;
}

int stride_in;
const uint8_t* p_in = input->get_plane(channel, &stride_in);
Expand All @@ -201,7 +223,7 @@ Op_to_sdr_planes::convert_colorspace(const std::shared_ptr<const HeifPixelImage>
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) {
int in = p_in[y * stride_in + x];
p_out[y * stride_out + x] = (uint8_t) ((in << shift) | (in >> roundingShift));
p_out[y * stride_out + x] = (uint8_t) ((in * mulFactor) >> 8);
}
} else {
outimg->copy_new_plane_from(input, channel, channel);
Expand Down

0 comments on commit d7f125c

Please sign in to comment.