2013.04.16 09:55 "[Tiff] How 16bits-RGBA image pixels are interlaced ?", by Rémy_Abergel

2013.04.16 09:55 "[Tiff] How 16bits-RGBA image pixels are interlaced ?", by Rémy_Abergel

Hello,

I'm trying to deal with 16-bits per channel RGBA TIFF images through C language, I could not find a lot of information about 16-bits images in the specifications.

In case of a 8-bits per channel RGBA image, I understand that a pixel is stored as a uint32, and can be deinterlaced by grouping the 32 bits into 4 groups (R,G,B,A) of 8 bits.

Then to deal with 8-bits per channel RGBA images, I'm doing the following (see also enclosed source code):

  1. I store the image data as a uint32 tab (using TIFFReadRGBAImageOriented) that I call data_tiff
  2. I deinterlace pixels using the following commands: (uint8) TIFFGetR(*data_tiff),(uint8) TIFFGetG(*data_tiff), (uint8) TIFFGetB(*data_tiff)& (uint8) TIFFGetA(*data_tiff)

*In case of a 16 bits per channel RGBA image, could you tell me how can I deinterlace pixels? *

if I could retreive image data as a uint64 tab, then I could do the following:

#define    TIFF16GetR(abgr)    ((abgr) & 0xffff)
#define    TIFF16GetG(abgr)    (((abgr) >> 16) & 0xffff)
#define    TIFF16GetB(abgr)    (((abgr) >> 32) & 0xffff)
#define    TIFF16GetA(abgr)    (((abgr) >> 48) & 0xffff)

  1. I read the image data as a uint64 tab
  2. I deinterlace pixels using (uint16) TIFF16GetR(*data_tiff),(uint16) TIFF16GetG(*data_tiff), (uint16) TIFF16GetB(*data_tiff)& (uint16) TIFF16GetA(*data_tiff)

but it seems that data are not natively stored in a uint64 tab, so I wonder how are interlaced 16-bits per channel images into a uint32 pixel tab.

I'm also facing difficulties dealing with *16-bits grayscaled images* in the same way (using TIFFReadRGBAImageOriented to get image data and trying to convert each pixel into a uint16)

More generally, *do you have any piece of documentation about 16 bits grayscale and color images?*

Thank you,
Best Regards,

Rémy A.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tiffio.h>

static uint8 *read_8bits_tiff_rgba_raw(fname,nx,ny,nc)
        const char *fname;
        size_t *nx,*ny,*nc;
{
        TIFF *tiffp = NULL;

        uint32 width = 0, height = 0, nbsamples = 0;
        uint32 *data_tiff = NULL;
        uint32 *ptr_in, *ptr_end;

        uint8 *data = NULL;
        uint8 *ptr_r, *ptr_g, *ptr_b;

        /* check the pointers */
        if ((NULL == nx) || (NULL == ny) || (NULL == nc))
                return NULL;

        /* no warning messages */
        (void) TIFFSetWarningHandler(NULL);

        /* open the TIFF file and structure */
        if (NULL == (tiffp = TIFFOpen(fname, "r")))
                return NULL;

        /* read width and height and allocate the storage raster */
        if (1 != TIFFGetField(tiffp, TIFFTAG_IMAGEWIDTH, &width)

                        || 1 != TIFFGetField(tiffp, TIFFTAG_IMAGELENGTH, &height)
                        || 1 != TIFFGetField(tiffp, TIFFTAG_SAMPLESPERPIXEL, &nbsamples)
                        || NULL == (data_tiff = (uint32 *) malloc(width * height * sizeof(uint32))))

        {
                TIFFClose(tiffp);
                return NULL;
        }

        /* read the image data */
        if (1 != TIFFReadRGBAImageOriented(tiffp, width, height, data_tiff,
                                ORIENTATION_TOPLEFT, 1))
        {
                free(data_tiff);
                TIFFClose(tiffp);
                return NULL;
        }

        /* close the TIFF file and structure */
        TIFFClose(tiffp);

        *nx = (size_t) width;        /* nx=number of columns */
        *ny = (size_t) height;       /* ny=number of rows */
        *nc = (size_t) nbsamples;    /* nc=number of channels */

        /* allocate the RGB deinterlaced array */

        if (NULL == (data = (uint8 *) malloc(*nx * *ny * 3 * sizeof(uint8))))

        {
                free(data_tiff);
                return NULL;
        }

        /*
         * deinterlace the TIFF raw array (ptr_in)
         * into three arrays (ptr_r, ptr_g, ptr_b)
         */

        ptr_in = data_tiff;
        ptr_end = ptr_in + *nx * *ny;
        ptr_r = data;

        ptr_g = ptr_r + *nx * *ny;
        ptr_b = ptr_g + *nx * *ny;
        while (ptr_in < ptr_end)

        {

                *ptr_r++ = (uint8) TIFFGetR(*ptr_in);
                *ptr_g++ = (uint8) TIFFGetG(*ptr_in);
                *ptr_b++ = (uint8) TIFFGetB(*ptr_in);

                ptr_in++;
        }
        free(data_tiff);

        /* select the correct number of channels to report */
        if ((3 == *nc)              /* RGB */

                        || (3 < *nc))       /* RGB + alpha + ... */

                *nc = 3;

        else if ((1 == *nc)         /* grayscale */

                        || (2 == *nc))      /* grayscale + alpha */

        {
                *nc = 1;

                /* truncate the deinterlaced array */
                data = (uint8 *) realloc(data, *nx * *ny * *nc * sizeof(uint8));

        }
        else /* 0 == *nc?? */
        {
                free(data);
                return NULL;
        }
        return data;
}