ftp.nice.ch/pub/next/unix/graphics/urt.3.0.s.tar.gz#/urt.3.0.s/cnv/rastorle.c

This is rastorle.c in view mode; [Download] [Up]

/*
 * 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.
 */
/*
 * rastorle  --
 *   convert Sun Rasterfile to Utah RLE format 
 *   reads Sun rasterfile or stdin and writes stdout.
 *
 * Author:         Berry Kercheval (berry@mordor.s1.gov)
 *                 Lawrence Livermore National Laboratory
 *                 Livermore, CA.
 * Date:           9 March 1987
 * History:  
 *   27 March 1987:  bbk: make it understand depth one (B&W) rasterfiles.
 *   6 September 1990: Clark: make it understand RT_BYTE_ENCODED rasterfiles,
 *			      add flag so alpha channel is done only if desired,
 *                            and output a colormap for images of depth 8.
 *
 * Usage is:
 *   rastorle [-a] [-o outfile.rle] [ infile.ras ]
 * 		(optionally) | rleflip -v > out.rle
 *
 * -a		Fake an alpha channel.
 *
 *   (The flip is necessary because Sun numbers the rows differently.)
 *
 * This will be difficult to compile on a non-sun, as it uses the pixrect
 * library include files.
 */

#include <stdio.h>
#include <pixrect/pixrect_hs.h>
#include <sysexits.h>
#include "rle.h"

#define MAXLINE        1280	/* max width of a line    */
#define MAXVAL          255	/* max value for pixel */
#define CMAPSIZE	256	/* Max size of color map  */
#define ESCAPE		128	/* Escape value for RT_BYTE_ENCODED rasterfiles */
/* #define DEBUG                /* debug output turned on */

int getbit();

static rle_map out_map[3*(1<<8)];

unsigned char *outrows[4];	/* array of rows for RLE output */
unsigned char redline[MAXLINE], /* rle red row values */
              grnline[MAXLINE],
	      bluline[MAXLINE], 
	      alfline[MAXLINE];	/* alpha channel values */

unsigned char red[CMAPSIZE],	/* red colormap entries */
            green[CMAPSIZE],	/* Green ditto */
	    blue[CMAPSIZE];	/* see a pattern? */

void
main(argc, argv)
int argc;
char *argv[];
{
    char	     *outfname = NULL;
    char	     *infname = NULL;
    int		      flag = 0, aflag = 0, oflag = 0;
    FILE             *rasfile;	/* where input comes from */
    FILE             *outfile;	/* where output goes to */
    int               i;	/* useful index */
    int               p;	/* pixel value read from a file -- 
				 * used to index rasterfile color map. */
    int               count;    /* Holds current byte count for rasterfiles
				 * of type RT_BYTE_ENCODED */
    int               h;	/* index for looping along a row */
    struct rasterfile rashdr;	/* standard header of a Sun rasterfile*/
    
    if ( scanargs( argc, argv, "% a%- o%-outfile!s infile%s",
		   &aflag, &oflag, &outfname, &infname ) == 0 )
	exit( EX_USAGE );

    rasfile = rle_open_f( "rastorle", infname, "r" );
    outfile = rle_open_f( "rastorle", outfname, "w" );

    rle_addhist( argv, (rle_hdr *)NULL, &rle_dflt_hdr );

    /* first read the rasterfile header */
    if(fread(&rashdr, sizeof(rashdr), 1, rasfile) != 1)
    {
	fprintf(stderr, "Can't read rasterfile header.\n");
	exit(EX_DATAERR);
    }
    /* it has to start with the magic number... */
    if (rashdr.ras_magic != RAS_MAGIC)
    {
	fprintf(stderr, "Error: \"%s\" is not a rasterfile.\n", 
		rasfile==stdin?"stdin":argv[1]);
	exit(EX_DATAERR);
    }
#ifdef DEBUG
    fprintf (stderr, "rasterfile width     =  %d\n", rashdr.ras_width);
    fprintf (stderr, "rasterfile height    =  %d\n", rashdr.ras_height);
    fprintf (stderr, "rasterfile depth     =  %d\n", rashdr.ras_depth);
    fprintf (stderr, "rasterfile length    =  %d\n", rashdr.ras_length);
    fprintf (stderr, "rasterfile type      =  %d\n", rashdr.ras_type);
    fprintf (stderr, "rasterfile maplength =  %d\n", rashdr.ras_maplength);
#endif

    /* read in color map */
    switch(rashdr.ras_maptype)
    {
      case RMT_NONE:
#ifdef DEBUG
	fprintf (stderr, "No color map\n");
#endif
	for (i = 0; i < 256; i++)
	  red[i] = green[i] = blue[i] = i ;
	break;
      case RMT_RAW:
#ifdef DEBUG
	fprintf (stderr, "Raw color map\n");
#endif
	for (i = 0; i < 256; i++)
	  red[i] = green[i] = blue[i] = i ;
	for (i = 0; i < rashdr.ras_maplength; i++)
	  getc(rasfile);
	break;
      case RMT_EQUAL_RGB:
#ifdef DEBUG
	fprintf (stderr, "RGB color map\n");
#endif
	/* read red */
	for (i = 0; i < rashdr.ras_maplength/3; i++)
	  red[i] = getc(rasfile);
	/* read green */
	for (i = 0; i < rashdr.ras_maplength/3; i++)
	  green[i] = getc(rasfile);
	/* read blue */
	for (i = 0; i < rashdr.ras_maplength/3; i++)
	  blue[i] = getc(rasfile);
	break;
      default:
	fprintf (stderr, "Unknown color map type (%d)\n", rashdr.ras_maptype);
	exit (EX_DATAERR);
    }
    /* we need to work on this... */
    switch(rashdr.ras_depth)
    {
      default:
	fprintf(stderr,
	  "Sorry, I can't deal with a rasterfile depth %d\n",rashdr.ras_depth);
	break;

      case 1:			/* black & white */
	/* next few lines stolen from painttorle.c */
	RLE_SET_BIT(rle_dflt_hdr, RLE_RED);
	RLE_SET_BIT(rle_dflt_hdr, RLE_GREEN);
	RLE_SET_BIT(rle_dflt_hdr, RLE_BLUE);
	if ( aflag )
            RLE_SET_BIT(rle_dflt_hdr, RLE_ALPHA );
	else
            RLE_CLR_BIT(rle_dflt_hdr, RLE_ALPHA );
	rle_dflt_hdr.rle_file = outfile;
	rle_dflt_hdr.xmin = 0 ;
	rle_dflt_hdr.xmax = rashdr.ras_width-1;
	rle_dflt_hdr.ymin = 0 ;
	rle_dflt_hdr.ymax = rashdr.ras_height-1;
	rle_dflt_hdr.ncmap = 0 ;
	if ( aflag )
            rle_dflt_hdr.alpha = 1;
        else 
            rle_dflt_hdr.alpha = 0;
	outrows[0] = alfline;
	/* all three can have the same value since it's B&W */
	outrows[1] = redline;
	outrows[2] = redline;
	outrows[3] = redline;
	
	rle_put_setup( &rle_dflt_hdr );
	for (i=0; i<rashdr.ras_height; i++) 
	{
	    for(h = 0; h < rashdr.ras_width; h++)
	    {
		p = getbit(rasfile, 0);
		redline[h] = p?0:MAXVAL;
		if ( aflag )
		    alfline[h] = p?0:MAXVAL;
	    }
	    /* write a line to the rle file */
	    rle_putrow(&outrows[1], rashdr.ras_width, &rle_dflt_hdr);
	    getbit(NULL, 1);
	}
	break; /* end case 1: */

      case 8:
      case 24:
      case 32:
	/* next few lines stolen from painttorle.c */
	RLE_SET_BIT(rle_dflt_hdr, RLE_RED);
	RLE_SET_BIT(rle_dflt_hdr, RLE_GREEN);
	RLE_SET_BIT(rle_dflt_hdr, RLE_BLUE);
	if ( aflag || rashdr.ras_depth == 32 )
            RLE_SET_BIT(rle_dflt_hdr, RLE_ALPHA );
        else 
            RLE_CLR_BIT(rle_dflt_hdr, RLE_ALPHA );
	rle_dflt_hdr.rle_file = outfile;
	rle_dflt_hdr.xmin = 0 ;
	rle_dflt_hdr.xmax = rashdr.ras_width-1;
	rle_dflt_hdr.ymin = 0 ;
	rle_dflt_hdr.ymax = rashdr.ras_height-1;
	if ( aflag || rashdr.ras_depth == 32 )
            rle_dflt_hdr.alpha = 1;
        else 
            rle_dflt_hdr.alpha = 0;
	if (rashdr.ras_depth == 8)
	{
	    rle_dflt_hdr.ncolors =  1;
	    rle_dflt_hdr.ncmap = 3;
	    rle_dflt_hdr.cmaplen = 8;
	    rle_dflt_hdr.cmap = out_map;
	    for (i=0;i<(1<<8);i++)
	    {
        	out_map[i+(0<<8)] = red[i] << 8;
        	out_map[i+(1<<8)] = green[i] << 8;
        	out_map[i+(2<<8)] = blue[i] << 8;
	    }
        }
 	
	outrows[0] = alfline;
	outrows[1] = redline;
	outrows[2] = grnline;
	outrows[3] = bluline;
	
	rle_put_setup( &rle_dflt_hdr );
	/* now just loop through the rows */
	
	if (rashdr.ras_type == RT_BYTE_ENCODED)
	    count = 9999;
	for (i=0; i<rashdr.ras_height; i++)
	{
	    /* read a line from the rasterfile */
	    switch(rashdr.ras_depth)
	    {
	      case 8:
		for (h=0; h < rashdr.ras_width; h++)
		{
		    if (rashdr.ras_type != RT_BYTE_ENCODED)
			p = getc(rasfile);
		    else
		    {
			if (count == 9999)
			{
			    p = getc(rasfile);
			    if (p == ESCAPE)
			    {
				count = getc(rasfile);
				if (count == 0)
				    count = 9999;
				else
				    p = getc(rasfile);
			    }
			} 
			else
			{
			    if (--count == 0)
				count = 9999;
			}
		    }
		    redline[h] = p;
		    grnline[h] = p;
		    bluline[h] = p;
		    /* fake up an alpha channel */
		    if ( aflag || rashdr.ras_depth == 32 )
		    {
            		if (redline[h] || grnline[h] || bluline[h])
		  	    alfline[h] = 255;
			else
			    alfline[h] = 0;
		    }
		}
		/* Since records are an even number of bytes */
		if (rashdr.ras_width & 1) p = getc(rasfile);
		break ;

	      case 24:
		for (h=0; h < rashdr.ras_width; h++)
		{
		    register int r,g,b ;
		    r = getc(rasfile);
		    g = getc(rasfile);
		    b = getc(rasfile);
		    redline[h] = red[r];
		    grnline[h] = green[g];
		    bluline[h] = blue[b];
		    /* fake up an alpha channel */
		    if ( aflag )
		    {
            		if (redline[h] || grnline[h] || bluline[h])
		  	    alfline[h] = 255;
			else
			    alfline[h] = 0;
		    }
		}
		break ;

	      case 32:
		for (h=0; h < rashdr.ras_width; h++)
		{
		    register int r,g,b,a ;
		    a = getc(rasfile);
		    r = getc(rasfile);
		    g = getc(rasfile);
		    b = getc(rasfile);
		    redline[h] = red[r];
		    grnline[h] = green[g];
		    bluline[h] = blue[b];
		    alfline[h] = a;
		}
		break ;
	    }
	    /* write a line to the rle file */
	    rle_putrow(&outrows[1], rashdr.ras_width, &rle_dflt_hdr);
	}
	break; /* end case 8: */
    } /* end switch */
}

/*
 * get a bit from the file fp.  Read a byte and return its bits
 * one at a time.  (actually returns zero or non-zero).
 */
int
getbit(fp, force)
FILE *fp;
int force;			/* true if we should read a byte anyway */
{
    static int c;		/* the char we are picking apart */
    static unsigned int mask
      = 0x0;			/* mask to get the next bit -- init to huge
				 * so that we get a byte the first time */
    int val;			/* value to be returned */
    if (force)			/* read a new byte next time */
    {
	mask = 0x0;
	return 0;
    }
    if(mask == 0)		/* time to get the next byte */
    {
	c = getc(fp);
	mask = 0x80;		/* reset the mask */
    }
    val = c & mask;		/* true if this bit on */
    mask >>= 1;			/* shift mask over one bit */
    return val;			/* the bit we saved goes back to caller */
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.