2007.08.07 14:41 "[Tiff] Indexed Images", by Christian Henning

2007.08.07 03:46 "[Tiff] bilevel image scrambling when size not divisible by 8", by Lee Cooper

I'm developing an image processing toolbox in C/C++ based on the TIFF library and I have one function that converts grayscale TIFF data to B&W by thresholding and another function to write the result to disk. When the number of pixels in the image isn't evenly divisible by 8 the result TIFF's contents are scrambled somewhere in the writing process.

 For example a 200x100 image of a single narrow vertical strip writes

OK, the same image at 201x100 appears as a series of diagonal bands and some seemingly random garbage at the bottom. The thresholding portion seems to be working OK, I have verified this by writing its result in ASCII and checking manually in Matlab.

Apparently I have some misunderstanding about how bilevel images are handled in TIFF but I can't find much info on the subject. When the number of pixels isn't a multiple of eight how is the remainder of the byte handled? I feel like this will probably be a simple answer but I'm stuck and really need to make some progress. I've included some code snippets below.

---------------------------------------------------------------------------------------------------------------------- int TIFFwriteBW(uint8* image, char* filename, uint32 width, uint32 height) {

        TIFF* out = TIFFOpen(filename, "w");

        TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);

TIFFSetField( TIFFTAG_IMAGELENGTH    , height              );out,

        TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
        TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
        TIFFSetField(out, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
        TIFFSetField(out, TIFFTAG_ORIENTATION,
ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_PLANARCONFIG,
PLANARCONFIG_CONTIG);
        TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);

        TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);

TIFFSetField( TIFFTAG_ROWSPERSTRIP   , height              ); out,

        TIFFWriteEncodedStrip(out, 0, image, (uint32)ceil((height * width) / 8.0);

        TIFFClose(out);

        return(1);
}

uint8* gray2BW(uint8* image, uint32 npixels, uint8 thresh) {
        uint8* bw = (uint8*) malloc((uint32) ceil(npixels / 8.0) * sizeof(uint8));
        if(bw != NULL) {
                uint8 *grayptr = image;

                int i, j;
                for(i = 0; i < npixels; i++) {
                        *(bw + i/8) <<= 1; //shift byte contents left by one
                        if(*grayptr >= thresh) { //test threshold each pixel
                                *(bw + i/8) |= 01;
                        }
                        grayptr++;
                }
                return(bw);
        }
        else {
                return(NULL);
        }
}