tools/rlestereo.c

Summary

Maintainability
Test Coverage
/*
 * This software is copyrighted as noted below.  It may be freely copied,
 * modified, and redistributed, provided that the copyright notice is
 * preserved on all copies.
 *
 * There is no warranty or other guarantee of fitness for this software,
 * it is provided solely "as is".  Bug reports or fixes may be sent
 * to the author, who may or may not act on them as he desires.
 *
 * You may not include this software in a program or other software product
 * without supplying the source, or without informing the end-user that the
 * source is available for no extra charge.
 *
 * If you modify this software, you should include a notice giving the
 * name of the person performing the modification, the date of modification,
 * and the reason for such modification.
 */
/*
 * rlestereo.c - Merge two RLE images to form a single red-green or red-blue
 *          image suitable for viewing with them goofy glasses. 
 *
 * Author:      Craig E. Kolb
 *         Department of Mathematics
 *        Yale Unversity
 * Date:        Mon Jul 30 1990
 * Copyright (C) 1990, Craig E. Kolb
 */
#ifndef lint
char rcsid[] = "$Header: /l/spencer/src/urt/tools/RCS/rlestereo.c,v 3.0.1.3 1992/04/30 14:14:07 spencer Exp $";
#endif
/*
rlestereo()            Tag the file.
*/

#include <stdio.h>
#include "rle.h"

#define LEFTSCALE    0.7        /* Default left scale factor. */
#define RIGHTSCALE    1.0        /* Default right scale factor. */

/*
 * Macro to convert input values to greyscale, taking colormap into
 * account.
 */
#define REDC        0.30
#define GREENC        0.59
#define BLUEC        0.11
#define GREYCONV(r,g,b,m) (REDC*m[0][r]+GREENC*m[1][g]+BLUEC*m[2][b])

float    LeftScale = LEFTSCALE;        /* Scale factor for left channel. */
float    RightScale = RIGHTSCALE;    /* Scale factor for right channel. */
int    GreenFlag = 0;            /* True if second channel is green. */
int    Xres, Yres;            /* Image resolution. */
int    lcolors, rcolors;        /* # channels in left/right images. */
int    RightIndex;            /* Index of second channel (1 or 2). */
int    lchan1, lchan2;            /* Channel indices for left image. */
int    rchan1, rchan2;            /* Channel indices for right image. */
rle_pixel **lmap, **rmap;        /* Colormap for left/right images. */

#ifdef USE_PROTOTYPES
void convert_line(rle_pixel **, rle_pixel **, rle_pixel **);
int get_rle_setup(rle_hdr *, int *, int *);
#else
void convert_line();
int get_rle_setup();
#endif
/*
 * Read two named RLE files and produces a single image suitable for viewing
 * with red-blue or red-green glasses.  The 'left' image is converted to
 * greyscale and written on the red channel.  The 'right' image is converted
 * to greyscale and written on the blue or green channel.  The intensity of the
 * two channels may be scaled in order to compensate for the relative
 * intensities of the two base colors as viewed through the glasses.
 *
 * Options:
 * 
 *    -g        Produce red-green image rather than red-blue.
 *    -l scale    Scale factor for left-eye image (default 0.7).
 *    -r scale    Scale factor for right-eye image (default 1.0).
 */

void
main(argc, argv)
int argc;
char **argv;
{
    int y, i, Xtmp, Ytmp, scaleflag = 0;
    char *leftname = NULL, *rightname = NULL;
    char *outname = NULL;
    FILE *outfile = stdout;
    int oflag;
    rle_pixel **lline, **rline, **outline;
    rle_hdr     left_hdr, right_hdr, out_hdr;
    int rle_cnt = 0, rle_err;
    char *err_name = NULL;

     left_hdr = *rle_hdr_init( NULL );
    right_hdr = *rle_hdr_init( NULL ); 
    out_hdr = *rle_hdr_init( NULL );

    if (scanargs(argc, argv,
        "% g%- l%-leftscale!f r%-rightscale!f o%-outfile!s \n\
    leftimage!s rightimage!s",
        &GreenFlag, &scaleflag, &LeftScale, &scaleflag, &RightScale,
        &oflag, &outname,
        &leftname, &rightname) == 0) {
        exit(-1);
    }

    /*
     * Open left and right images.
     */
    (void)rle_hdr_init( &left_hdr );
    (void)rle_hdr_init( &right_hdr );
    left_hdr.rle_file = rle_open_f(cmd_name(argv), leftname, "r");
    right_hdr.rle_file = rle_open_f(cmd_name(argv), rightname, "r");
    rle_names( &left_hdr, cmd_name(argv), leftname, 0 );
    rle_names( &right_hdr, cmd_name(argv), rightname, 0 );
    rle_names( &out_hdr, left_hdr.cmd, outname, 0 );

    for ( rle_cnt = 0;; rle_cnt++ )
    {
        /*
         * Read headers of both images.
         */
        if ( (rle_err = 
          get_rle_setup(&left_hdr, &Xres, &Yres)) != RLE_SUCCESS )
        {
        err_name = leftname;
        break;
        }
        if ( (rle_err =
          get_rle_setup(&right_hdr, &Xtmp, &Ytmp)) != RLE_SUCCESS )
        {
        err_name = rightname;
        break;
        }

        /* Open the output file when first header is successfully read. */
        if ( rle_cnt == 0 )
        outfile = rle_open_f( cmd_name( argv ), outname, "w" );

        if (Xres != Xtmp || Yres != Ytmp) {
        fprintf(stderr,"Images are of different sizes.\n");
        exit(-1);
        }

        (void)rle_hdr_cp( &left_hdr, &out_hdr );
        out_hdr.ncolors = 3;
        out_hdr.ncmap = 0;
        out_hdr.rle_file = outfile;
        rle_addhist(argv, &left_hdr, &out_hdr);
        rle_put_setup(&out_hdr);

        /*
         * Ignore alpha and any channels > #2.
         */
        RLE_CLR_BIT(left_hdr, RLE_ALPHA);
        RLE_CLR_BIT(right_hdr, RLE_ALPHA);
        for (i = 3; i < left_hdr.ncolors; i++)
        RLE_CLR_BIT(left_hdr, i);
        for (i = 3; i < right_hdr.ncolors; i++)
        RLE_CLR_BIT(right_hdr, i);

        lcolors = left_hdr.ncolors > 3 ? 3 : left_hdr.ncolors;
        rcolors = right_hdr.ncolors > 3 ? 3 : right_hdr.ncolors;

        if (lcolors == 1)
        lchan1 = lchan2 = 0;
        else if (lcolors == 2) {
        lchan1 = 1;
        lchan2 = 0;
        } else {
        lchan1 = 1;
        lchan2 = 2;
        }

        if (rcolors == 1)
        rchan1 = rchan2 = 0;
        else if (rcolors == 2) {
        rchan1 = 1;
        rchan2 = 0;
        } else {
        rchan1 = 1;
        rchan2 = 2;
        }

        if ( rle_row_alloc(&left_hdr, &lline) < 0 ||
         rle_row_alloc(&right_hdr, &rline) < 0 ||
         rle_row_alloc(&out_hdr, &outline) < 0 )
        RLE_CHECK_ALLOC( left_hdr.cmd, 0, "images" );
        /*
         * Zero unused channel of output scanline.
         */
        if (GreenFlag) {
        RightIndex = 1;
        bzero(outline[2], Xres * sizeof(rle_pixel));
        } else {
        RightIndex = 2;
        bzero(outline[1], Xres * sizeof(rle_pixel));
        }

        /*
         * In case there's a colormap, DTRT.  We use a gamma of 1.
         * here because we want the output image to have the same
         * gamma as the left image.
         */
        lmap = buildmap(&left_hdr, 3, 1., 1.0);
        rmap = buildmap(&right_hdr, 3, 1., 1.0);
        /*
         * For each output scanline...
         */
        for (y = 0; y < Yres; y++) {
        /*
         * Read left and right scanline, converting each
         * to greyscale data.
         */
        rle_getrow(&left_hdr, lline);
        rle_getrow(&right_hdr, rline);
        convert_line(outline, lline, rline);
        rle_putrow(outline, Xres, &out_hdr);
        }
        while ( rle_getskip(&left_hdr) != 32768 )
        ;
        while ( rle_getskip(&right_hdr) != 32768 )
        ;

        rle_row_free(&left_hdr, lline);
        rle_row_free(&right_hdr, rline);
        rle_row_free(&out_hdr, outline);

        rle_puteof( &out_hdr );
    }
    fclose(left_hdr.rle_file);
    fclose(right_hdr.rle_file);

    /* Check for an error.  EOF or EMPTY is ok if at least one image
     * has been read.  Otherwise, print an error message.
     */
    if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
        rle_get_error( rle_err, cmd_name( argv ), err_name );
    exit(0);
}

int
get_rle_setup(the_hdr, xres, yres)
int *xres, *yres;
rle_hdr *the_hdr;
{
        int err;

    err = rle_get_setup(the_hdr);
    *xres = the_hdr->xmax - the_hdr->xmin + 1;
    *yres = the_hdr->ymax - the_hdr->ymin + 1;
    the_hdr->xmax -= the_hdr->xmin;
    the_hdr->xmin = 0;
    return err;
}

void
convert_line(out, left, right)
rle_pixel **out, **left, **right;
{
    register int i;
    
    /*
     * Convert input scanlines to 'stereo' output scanline.
     */
    for (i = 0; i < Xres; i++) {
        out[0][i] = LeftScale * GREYCONV(left[0][i], left[lchan1][i],
                left[lchan2][i], lmap);
        out[RightIndex][i] = RightScale * GREYCONV(right[0][i],
                right[rchan1][i], right[rchan2][i], rmap);
    }
}