Question

My android app uses an external lib that makes some image treatments. The final output of the treatment chain is a monochrome bitmap but saved has a color bitmap (32bpp).

The image has to be uploaded to a cloud blob, so for bandwidth concerns, i'd like to convert it to 1bpp G4 compression TIFF. I successfully integrated libTIFF in my app via JNI and now i'm writing the conversion routine in C. I'm a little stuck here.

I managed to produce a 32 BPP TIFF, but impossible to reduce to 1bpp, the output image is always unreadable. Did someone succeded to do similar task ?

More speciffically :

  • What should be the value of SAMPLE_PER_PIXEL and BITS_PER_SAMPLE parameters ?
  • How to determine the strip size ?
  • How to fill each strip ? (i.e. : How to convert 32bpp pixel lines to 1 bpp pixels strips ?)

Many thanks !

UPDATE : The code produced with the precious help of Mohit Jain

int ConvertMonochrome32BppBitmapTo1BppTiff(char* bitmap, int height, int width, int resx, int resy, char const *tifffilename)
{
    TIFF *tiff;

    if ((tiff = TIFFOpen(tifffilename, "w")) == NULL)
    {
        return TC_ERROR_OPEN_FAILED;
    }

    // TIFF Settings
    TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
    TIFFSetField(tiff, TIFFTAG_XRESOLUTION, resx);
    TIFFSetField(tiff, TIFFTAG_YRESOLUTION, resy);
    TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); //Group4 compression
    TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1);
    TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 1);
    TIFFSetField(tiff, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);

    tsize_t tbufsize = (width + 7) / 8; //Tiff ScanLine buffer size for 1bpp pixel row

    //Now writing image to the file one row by one
    int x, y;
    for (y = 0; y < height; y++)
    {
        char *buffer = malloc(tbufsize);
        memset(buffer, 0, tbufsize);

        for (x = 0; x < width; x++)
        {
            //offset of the 1st byte of each pixel in the input image (is enough to determine is black or white in 32 bpp monochrome bitmap)
            uint32 bmpoffset = ((y * width) + x) * 4; 

            if (bitmap[bmpoffset] == 0) //Black pixel ?
            {
                uint32 tiffoffset = x / 8;
                *(buffer + tiffoffset) |= (0b10000000 >> (x % 8));
            }
        }

        if (TIFFWriteScanline(tiff, buffer, y, 0) != 1)
        {
            return TC_ERROR_WRITING_FAILED;
        }

        if (buffer)
        {
            free(buffer);
            buffer = NULL;
        }
    }

    TIFFClose(tiff);
    tiff = NULL;

    return TC_SUCCESSFULL;
}
Was it helpful?

Solution

To convert 32 bpp to 1 bpp, extract RGB and convert it into Y (luminance) and use some threshold to convert to 1 bpp.

Number of samples and bits per pixel should be 1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top