Interleaved mode reading confusion with heif_image_get_bits_per_pixel_range > 8
I am attempting to implement interleaved (heif_chroma_interleaved_R*) reading mode in GraphicsMagick. I am successful with heif_image_get_bits_per_pixel_range <= 8, but the implementation I provided for 9-16 bits is crashing half way through as if it is striding twice as fast as it should be (I did not see that in the debugger), or heif_image_get_plane_readonly2() returned a buffer half the size as was expected. I feel like I must be doing something dumb, but still have not figured it out.
For the input file, the original preferred colorspace is heif_colorspace_RGB, and original preferred chroma is heif_chroma_444. For purpose of decode (heif_decode_image), colorspace is heif_colorspace_RGB and chroma_decode is heif_chroma_interleaved_RRGGBB_BE.
This is the related implementation code. What might I be doing wrong for the "else if (bits_per_pixel_range <= 16)" case? The code intends to parse each sample value as a native 'uint16_t'.
```
{
/*
Decode RGB(A) interleaved pixels
This requires set-up in advance to request the desired RGB(A) sub-format.
heif_chroma_interleaved_RGB
heif_chroma_interleaved_RGBA
heif_chroma_interleaved_RRGGBB_BE
heif_chroma_interleaved_RRGGBBAA_BE
heif_chroma_interleaved_RRGGBB_LE
heif_chroma_interleaved_RRGGBBAA_LE
*/
typedef union
{
const uint8_t *u8;
const uint16_t *u16;
} magick_pixels_t;
magick_pixels_t
pixels;
size_t
row_stride;
unsigned long
x,
y;
int
bits_per_pixel,
bits_per_pixel_range;
enum heif_channel
heif_channel;
const MagickBool
matte = image->matte;
if (image->logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"Chroma format: %s", heif_chroma_format_str);
heif_channel = heif_channel_interleaved;
heif_channel_str = HEIF_channel_to_string(heif_channel);
bits_per_pixel = heif_image_get_bits_per_pixel(heif_image,
heif_channel);
bits_per_pixel_range = heif_image_get_bits_per_pixel_range(heif_image,
heif_channel);
pixels.u8 = heif_image_get_plane_readonly2(heif_image,
heif_channel,
&row_stride);
if (pixels.u8 == (const uint8_t*) NULL)
{
if (image->logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"heif_image_get_plane_readonly2() returned NULL"
" (channel %s)!",heif_channel_str);
ThrowHEIFThrowReadImageFrameException(CorruptImageError,
AnErrorHasOccurredReadingFromFile, image);
}
/* interleaved row stride 1536 (8 bits in 24 bit quantum) */
/* interleaved row stride 3072 (16 bit samples in 48 bit packet) */
if (image->logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" %s row stride %zu (%d bit samples in %d bit packet)",
heif_channel_str, row_stride,
bits_per_pixel_range,
bits_per_pixel);
/* FIXME: TODO */
if (bits_per_pixel_range <= 8)
{
const uint8_t
*p;
for (y=0; y < image->rows; y++)
{
p=pixels.u8+y*row_stride;
q=SetImagePixelsEx(image,0,y,image->columns,1,exception);
if (q == (PixelPacket *) NULL)
{
HEIFReadImageFrameCleanup();
return MagickFail;
}
for (x=0; x < image->columns; x++)
{
SetRedSample(q,ScaleCharToQuantum(*p++));
SetGreenSample(q,ScaleCharToQuantum(*p++));
SetBlueSample(q,ScaleCharToQuantum(*p++));
if (matte)
SetOpacitySample(q,MaxRGB-ScaleCharToQuantum(*p++));
else
SetOpacitySample(q,OpaqueOpacity);
q++;
}
if (!SyncImagePixelsEx(image,exception))
{
HEIFReadImageFrameCleanup();
return MagickFail;
}
}
}
else if (bits_per_pixel_range <= 16)
{
const uint16_t
*p;
for (y=0; y < image->rows; y++)
{
p=pixels.u16+y*row_stride;
q=SetImagePixelsEx(image,0,y,image->columns,1,exception);
if (q == (PixelPacket *) NULL)
{
HEIFReadImageFrameCleanup();
return MagickFail;
}
for (x=0; x < image->columns; x++)
{
SetRedSample(q,ScaleShortToQuantum(*p++));
SetGreenSample(q,ScaleShortToQuantum(*p++));
SetBlueSample(q,ScaleShortToQuantum(*p++));
if (matte)
SetOpacitySample(q,MaxRGB-ScaleShortToQuantum(*p++));
else
SetOpacitySample(q,OpaqueOpacity);
q++;
}
if (!SyncImagePixelsEx(image,exception))
{
HEIFReadImageFrameCleanup();
return MagickFail;
}
}
}
}
```
关闭于 2026-04-11 4 条评论