Jun 17, 2015

Using libfreeimage to create a TIFF file

Recently, I wrote a monochrome image captured from a image sensor into a TIFF file using the opencv highgui module.  While convenient, this module could not add custom TIFF tags.  So this time, I explore an alternative TIFF file creation method using freeimage library.

Saving raw data in memory into a TIFF file

In a previous blog post, I pushed a monochrome 16-bit image from my Zedboard FPGA into the designated DRAM.  In freeimage, all images are represented as FIBITMAP type.  To form such a bitmap from the raw memory location--which I call BSP_dma in my Linux application--without copying memory, the following code snippet worked:

#include <FreeImage.h>//To save image to TIFF file
        FIBITMAP* bmp = FreeImage_ConvertFromRawBitsEx(
                    FALSE,//do not copy src
                    (BYTE*)BSP_dma, FIT_UINT16,
                    me->imgParam.width, me->imgParam.height,
                    2*me->imgParam.width,//pitch
                    16, //bits per pixel
                    0, 0, 0);//RGB masks

To write out the bitmap as a TIFF file, this short snippet does the job:

FreeImage_Save(FIF_TIFF, bmp, fname.toLatin1().data(), TIFF_NONE);

Finally, release the memory (I do NOT mean free, since we did NOT allocate anything on the heap):

FreeImage_Unload(bmp);

Adding custom tag to TIFF

libfreeimage supports many metadata model.  Of these, I am interested in the Adobe XMP model, which is enumerated as FIMD_XMP in libfreeimage.  I can put ANY STRING I want into this single key named "XMLPacket".  Assuming I have a QString called profile that contains that free-form string, here is the code snippet to write that TIFF tag:

        FITAG* tag = FreeImage_CreateTag();
        Q_ALLEGE(tag);
        // note that the FIMD_XMP model accept a single key named “XMLPacket”
        FreeImage_SetTagKey(tag, "XMLPacket");
        FreeImage_SetTagLength(tag, profile.length());
        FreeImage_SetTagCount(tag, profile.length());
        FreeImage_SetTagType(tag, FIDT_ASCII);
        //The tag value must be stored after the tag data type, tag count and
        //tag length have been filled.
        FreeImage_SetTagValue(tag, profile.toLatin1().data());

        Q_ALLEGE(FreeImage_SetMetadata(FIMD_XMP, bmp, FreeImage_GetTagKey(tag), tag));

After saving the file, the tag should be freed:

        FreeImage_DeleteTag(tag);