1994.06.16 20:17 "RGB to TIFF", by Mitesh Mehta

1994.06.16 23:08 "Re: RGB to TIFF", by Dan McCoy

. . . I have used TIFFReadRGBAImage and the TIFFGetR/G/B routines to read a tiff file into a RGBA format. Now after the processing is done I need to restore it to the original TIFF form from the RGBA format. I could not find any obvious routine to do this.

Following is the routine we use around here when we get lazy.

Dan McCoy       Pixar           mccoy@pixar.com

PS. Sam, do you want this one?

----------------save.c----------------

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

/*
 * TIFFSaveRGBImage is a utility routine that will write an image
 * array out as a TIFF file.  It is meant for programs that don't
 * want to deal with a lot of options.   All TIFF options will be
 * set to "reasonable" defaults.
 *
 * filename will be the name of the created file.
 * inorder specifies the location of the color fields in the uint32.
 *    0: abgr where a is the most significant byte.
 *    1: rgba where r is the most significant byte.
 *    2: argb where a is the most significant byte.
 *    3: bgra where b is the most significant byte.
 * sendalpha controls whether the alpha channel is written.
 *    0: only r, g, and b are written.
 *    1: alpha is written as well.
 * orientation specifies how the scanlines are arranged in the array.
 *    0: top of image is first in the array.
 *    1: bottom of image is first in the array.
 * width the width of the image in pixels.
 * height the height of the image in pixels.
 * image is a pointer to width*height uint32's containing the pixels 
 *    of the image in scanline order.
 *
 * The file will be LZW compressed.
 *
 * Returns 1 for success, o for failure.
 */

int
TIFFSaveRGBImage(filename, inorder, sendalpha, orientation, width, height, image)
    char *filename;
    int  inorder;       /* 0: abgr,  1: rgba, 2: argb, 3: bgra */
    int  sendalpha;     /* 0: rgb,   1: rgba */
    int  orientation;   /* 0: top to bottom, 1: bottom to top */
    int  width;
    int  height;
    uint32 *image;
{
    int            bytesperscan;
    int            rows;
    int            samples;
    unsigned char *scan;
    TIFF          *tif;

    rows = 1;
    scan = (unsigned char *) &rows;
    if (*scan) {
        /* Little endian machine, reverse sense of inorder. */
        switch (inorder) {
        case 0: inorder = 1; break;
        case 1: inorder = 0; break;
        case 2: inorder = 3; break;
        case 3: inorder = 2; break;
        }
    }

    if (sendalpha)
        samples = 4;
    else
        samples = 3;

    bytesperscan = width * samples;
    scan = (unsigned char *) malloc(bytesperscan);
    if (scan == NULL)
        return 0;

    tif = TIFFOpen(filename, "w");

    if (tif == NULL)
    {
        free(scan);
        return 0;
    }

    TIFFSetField(tif, TIFFTAG_SUBFILETYPE, (uint32) 0);
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); 
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) width);
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) height);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);

    if (sendalpha)
        TIFFSetField(tif, TIFFTAG_MATTEING, 1);

    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samples);
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);


    rows = 8192 / bytesperscan;
    if (rows < 1) rows = 1;

    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, (uint32) rows);


    /*
     * The file is open, all parameters are set,
     * write the image array into the file a scan at a time.
     */

    {
        register int npixels;
        register unsigned char *ip;
        register unsigned char *op;
        unsigned int r, g, b, a;
        int y; 

        for (y=0; y<height; y++) {
            if (orientation) {
                ip = (unsigned char *) (image + (height - y - 1) * width); 
            } else {
                ip = (unsigned char *) (image + y * width);
            }

            npixels = width;
            op = scan;
            while (--npixels >= 0) {
                switch (inorder) {
                case 0:
                    a = *ip++;
                    b = *ip++;
                    g = *ip++;
                    r = *ip++;
                        break;
                case 1:
                    r = *ip++;
                    g = *ip++;
                    b = *ip++;
                    a = *ip++;
                        break;
                case 2:
                    a = *ip++;
                    r = *ip++;
                    g = *ip++;
                    b = *ip++;
                        break;
                case 3:
                    b = *ip++;
                    g = *ip++;
                    r = *ip++;
                    a = *ip++;
                        break;
                }

                *op++ = r;
                *op++ = g;
                *op++ = b;
                if (sendalpha)
                        *op++ = a;

            }
            if (TIFFWriteScanline(tif, scan, y, 0) < 0)
                goto omigosh;
        }
    }

    (void) TIFFClose(tif);
    free(scan);

    return 1;

omigosh:
    free(scan);
    (void) TIFFClose(tif);
    return 0;
}