/*
 * 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.
 */
/*
 * ppmtorle - A program which will convert pbmplus/ppm images
 *            to Utah's "rle" image format.
 *
 * Author:      Wesley C. Barris
 *              AHPCRC
 *              Minnesota Supercomputer Center, Inc.
 * Date:        Fri July 20 1990
 * Copyright (c) Wesley C. Barris
 */
#ifndef lint
static char rcsid[] = "$Header: /l/spencer/src/urt/cnv/RCS/ppmtorle.c,v 3.0.1.4 1992/03/04 19:29:43 spencer Exp $";
#endif
#if 0
ppmtorle()			/* Tag. */
#endif
/*-----------------------------------------------------
 * System includes.
 */
#define NO_DECLARE_MALLOC	/* ppm.h does it */
#include "rle.h"
#include <stdio.h>
#include <ppm.h>

#define VPRINTF if (verbose || header) fprintf

typedef unsigned char U_CHAR;
/*
 * Global variables.
 */
FILE	*fp;
rle_hdr hdr;
int	format;
int	width, height;
int	verbose = 0, header = 0, do_alpha = 0;
gray	maxval;
/*-----------------------------------------------------------------------------
 *                                        Read the ppm image file header.
 */
void read_ppm_header()
{
   ppm_readppminit(fp, &width, &height, &maxval, &format);
   VPRINTF(stderr, "Image type: 24 bit true color\n");
   VPRINTF(stderr, "Full image: %dx%d\n", width, height);
   VPRINTF(stderr, "Maxval:     %d\n", maxval);
   if (do_alpha)
      VPRINTF(stderr, "Computing alpha channel...\n");
}
/*-----------------------------------------------------------------------------
 *                                             Write the rle image file header.
 */
void write_rle_header()
{
   hdr.xmin    = 0;
   hdr.xmax    = width-1;
   hdr.ymin    = 0;
   hdr.ymax    = height-1;
   hdr.ncolors = 3;
   hdr.background = 0;
   if (do_alpha) {
      hdr.alpha = 1;
      RLE_SET_BIT(hdr, RLE_ALPHA);
      }
   RLE_SET_BIT(hdr, RLE_RED);
   RLE_SET_BIT(hdr, RLE_GREEN);
   RLE_SET_BIT(hdr, RLE_BLUE);
   rle_put_setup(&hdr);
}
/*-----------------------------------------------------------------------------
 *                                      Write the rle data portion of the file.
 */
void write_rle_data()
{
   register int		x;
   register int		scan;
   register pixel	*pixelrow, *pP;
   rle_pixel		***scanlines, **scanline;
   /*
    * Allocate some memory.
    */
   pixelrow = ppm_allocrow(width);
   scanlines = (rle_pixel ***)malloc( height * sizeof(rle_pixel **) );
   RLE_CHECK_ALLOC( hdr.cmd, scanlines, "scanline pointers" );

   for ( scan = 0; scan < height; scan++ )
      RLE_CHECK_ALLOC( hdr.cmd, (rle_row_alloc(&hdr, &scanlines[scan]) >= 0),
		       "pixel memory" );

   /*
    * Loop through the ppm files image window, read data and flip vertically.
    */
   for (scan = 0; scan < height; scan++) {
      scanline = scanlines[height - scan - 1];
      ppm_readppmrow(fp, pixelrow, width, maxval, format);
      for (x = 0, pP = pixelrow; x < width; x++, pP++) {
	 scanline[RLE_RED][x]   = PPM_GETR(*pP);
	 scanline[RLE_GREEN][x] = PPM_GETG(*pP);
	 scanline[RLE_BLUE][x]  = PPM_GETB(*pP);
	 if (do_alpha) {
	    scanline[RLE_ALPHA][x] = (scanline[RLE_RED][x] ||
				      scanline[RLE_GREEN][x] ||
				      scanline[RLE_BLUE][x] ? 255 : 0);
	 }
      }
   }
   /*
    * Write out data in URT order (bottom to top).
    */
   for ( scan = 0; scan < height; scan++ )
   {
      rle_putrow(scanlines[scan], width, &hdr);
      rle_row_free( &hdr, scanlines[scan] );
   }
   free( scanlines );

   VPRINTF(stderr, "Done -- write eof to RLE data.\n");
   rle_puteof(&hdr);
}
/*-----------------------------------------------------------------------------
 *                      Convert an PPM image file into an rle image file.
 */
int
main(argc, argv)
int argc;
char **argv;
{
   char		*periodP, *ppmname = NULL, *outname = NULL;
   static char	filename[BUFSIZ];
   int		oflag, c;
/*
 * Get those options.
 */
   if (!scanargs(argc,argv,
       "% v%- h%- a%- o%-outfile!s infile.ppm%s\n(\
\tConvert PPM file to URT RLE format.\n\
\t-a\tFake an alpha channel.  Alpha=0 when input=0, 255 otherwise.\n\
\t-h\tPrint header of PGM file.\n\
\t-v\tVerbose mode.\n\
\tInput file name (if given) is forced to end in .ppm.)",
       &verbose,
       &header,
       &do_alpha,
       &oflag, &outname,
       &ppmname))
      exit(-1);

   hdr = *rle_hdr_init( (rle_hdr *)NULL );
   rle_names( &hdr, cmd_name( argv ), outname, 0 );
/*
 * Open the file.
 */
   if (ppmname == NULL) {
      strcpy(filename, "stdin");
      fp = stdin;
      }
   else {
      periodP = strrchr(ppmname, '.');
      strcpy(filename, ppmname);
      if (periodP) {
         if (strcmp(periodP, ".ppm")) /* does not end in ppm */
            strcat(filename, ".ppm");
         }
      else				/* no ext -- add one */
         strcat(filename, ".ppm");
      if (!(fp = fopen(filename, "r"))) {
         fprintf(stderr, "%s: Cannot open %s for reading.\n",
		 hdr.cmd, filename);
         exit(-1);
         }
      }

   hdr.rle_file = rle_open_f( hdr.cmd, outname, "w" );
   while ( (c = getc( fp )) != EOF )
   {
      ungetc( c, fp );
      /*
       * Read the PPM file header.
       */
      read_ppm_header();
      if (header)
	 break;

      /*
       * Write the rle file header.
       */
      rle_addhist(argv, (rle_hdr *)NULL, &hdr);
      write_rle_header();
      /*
       * Write the rle file data.
       */
      write_rle_data();
   }

   fclose(fp);
   return 0;
}
