I have a truecolour image with 16 bits per channel (created by ImageMagick), which I'd like to read into separate R, G, B planes. The problem is that the resulting 16-bit pixel value simply duplicates the low and high bytes in the result. If the red component has an approximate value of 0x42, for example, my libpng code actually returns a value of 0x4242.
My first problem is that I'm not quite convinced that the input actually has 16-bit pixels. This is what identify -verbose
returns:
Type: TrueColor
Endianess: Undefined
Colorspace: RGB
Depth: 16/8-bit
Channel depth:
red: 8-bit
green: 8-bit
blue: 8-bit
Channel statistics:
Red:
min: 0 (0)
max: 65535 (1)
Properties:
PNG:IHDR.bit_depth : 16
PNG:IHDR.color_type : 2
Does this image actually have 16-bit data that I can extract? If so, how? My libpng read code basically does this (after confirming that png_get_color_type
returns 2, and png_get_bit_depth
returns 16):
png_uint_32 rowbytes = png_get_rowbytes(png, info);
image = (png_byte *) xmalloc(height * rowbytes);
row_pointers = (png_bytep*) xmalloc(sizeof(png_bytep) * height);
for(int i = 0; i < (int)height; i++)
row_pointers[i] = image + (i*rowbytes);
png_read_image(png, row_pointers);
And my code which splits image
into RGB planes does this:
uint16_t *src = (uint16_t*) image; // libpng composite image
uint16_t *rplane, *gplane, *bplane; // separate planar channels
...
for(size_t i=0; i<nrows; i++) {
for(size_t j=0; j<ncols; j++) {
*rplane++ = *src++;
*gplane++ = *src++;
*bplane++ = *src++;
}
}
So this assumes that the 48-bit pixel data returned by libpng is 16b R, then 16b B, then 16b G.
If I read the image into Matlab it reports that it's only reading 8-b pixels because of limitations in ImageMagick. If Matlab reports that pixel (x,y) has a red component of 0x42, for example, the libpng code above reports that it has a value of 0x4242. However, Matlab and the libpng code above agree on the RGB values of all pixels, except that Matlab reports them all as single 8-bit components, and the libpng code duplicates this value twice in each 16-bit component.
Any ideas? Thanks.
EDIT
non-verbose identify
output:
> identify in.png
in.png PNG 2776x2776 2776x2776+0+0 16-bit DirectClass 14.35MB 0.000u 0:00.000