2006.03.13 16:35 "[Tiff] CCITT Group 4 images", by Philip Watkinson

2006.03.16 12:38 "Re: [Tiff] CCITT Group 4 images", by Gerben Vos

I have CCITT Group 4 compressed images that are not contained within TIFF files. Can I use Libtiff to decompress the images?

It is possible to drive the CCITT codec directly using a dummy TIFF
object. However, you will be using libtiff internals, which may change
in later versions, so you will have to check everytime you upgrade.
You could try this code, which works for libtiff version 3.5.7.

Gerben Vos.

{
    uint16 compression = /* e.g., COMPRESSION_CCITTFAX4 */;

// Use a dummy TIFF object to drive the codec.
TIFF tif;
_TIFFmemset(&tif, 0, sizeof(tif));
tif.tif_name = "";
tif.tif_mode = O_RDONLY;
tif.tif_dir.td_imagewidth = width;
tif.tif_dir.td_imagelength = height;
tif.tif_dir.td_bitspersample = 1;
tif.tif_dir.td_samplesperpixel = 1;
tif.tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
tif.tif_dir.td_fillorder = FILLORDER_MSB2LSB;
tif.tif_flags = tif.tif_dir.td_fillorder;
tif.tif_dir.td_compression = compression;
tif.tif_postdecode = _TIFFNoPostDecode;

bool result = true;
if (!TIFFSetCompressionScheme(&tif, compression))
    result = false;

// This is a compression-specific option, which can only be set after // setting the compression scheme, and only using TIFFSetField, because // these internals aren't defined in a header file.

/* if (compression == COMPRESSION_CCITTFAX3)
    TIFFSetField(&tif, TIFFTAG_GROUP3OPTIONS,

                     encodedByteAlign ? GROUP3OPT_FILLBITS : 0); */

// Code from TIFFFillStrip().

    tif.tif_rawdatasize = /* length of compressed data */;
    tif.tif_rawdata = /* pointer to compressed data */;

// Allocate new buffer.
long newsize = ((width + 7) / 8) * height;
tidata_t newbuf = (tidata_t)malloc(newsize);
if (newbuf == NULL)
    result = false;

// Code from TIFFStartStrip().
if (result && (tif.tif_flags & TIFF_CODERSETUP) == 0) {
    if (!(*tif.tif_setupdecode)(&tif))
        result = false;
    tif.tif_flags |= TIFF_CODERSETUP;
}
tif.tif_curstrip = 0;
tif.tif_row = 0;
tif.tif_rawcp = tif.tif_rawdata;
tif.tif_rawcc = tif.tif_rawdatasize;
if (result && !(*tif.tif_predecode)(&tif, (tsample_t)0))
    result = false;

// Code from TIFFReadEncodedStrip().
if (result && (*tif.tif_decodestrip)(&tif, newbuf, newsize, (tsample_t)0))
    (*tif.tif_postdecode)(&tif, newbuf, newsize);
else
    result = false;

if (result) {
    /* uncompressed data now in newbuf, with length newsize */
}
free(newbuf);

    // Code from TIFFClose().
    if (tif.tif_cleanup)
        (tif.tif_cleanup)(&tif);
    TIFFFreeDirectory(&tif);
    if (tif.tif_fieldinfo)
        _TIFFfree(tif.tif_fieldinfo);
}