home *** CD-ROM | disk | FTP | other *** search
- /* pnmtorle.c - convert portable anymap to Utah Raster Toolkit image
- **
- ** Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- **
- ** 09/Dec/94: first version
- */
- #include "pnm.h"
- #include "rle.h"
-
- /* prototypes */
- static void write_rle_header ARGS((FILE *ofp, int cols, int rows, int channels, int pixelbits));
- static void pnm_to_1_channel ARGS((FILE *ofp, xel **image, int cols, int rows));
- static void pnm_to_3_channels ARGS((FILE *ofp, xel **image, int cols, int rows));
- static void write_channel ARGS((FILE *ofp, int channel, unsigned char *rawrow, int cols));
- static void write_bytedata ARGS((FILE *ofp, unsigned char *rawrow, int nbytes));
- static void write_rundata ARGS((FILE *ofp, unsigned char *rawrow, int nbytes));
- static void put_byte ARGS((FILE *fp, int byte));
- static void put_short ARGS((FILE *fp, int word));
- #define plural(x) ((x) == 1 ? "" : "s")
-
-
- int
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int argn, cols, rows, format, channels, pixelbits;
- xel **image;
- xelval maxval;
- FILE *ifp;
- char *usage = "[-8bit] [pnmfile]";
- short scale, force8;
-
- pnm_init(&argc, argv);
- force8 = 0;
-
- argn = 1;
- /* empty loop for easy option adding */
- while( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) {
- if( pm_keymatch(argv[argn], "-8bit", 2) )
- force8 = 1;
- else
- pm_usage(usage);
- ++argn;
- }
- if( argn < argc ) {
- ifp = pm_openr( argv[argn] );
- argn++;
- }
- else
- ifp = stdin;
- if( argn != argc )
- pm_usage(usage);
-
- pnm_pbmmaxval = 1; /* PBM -> 1 bit per pixel */
- image = pnm_readpnm(ifp, &cols, &rows, &maxval, &format);
-
- if( maxval > 255 ) {
- pm_message("maxval too large - scaling pixel values");
- scale = 1;
- }
- else
- if( force8 && maxval < 255 ) {
- pm_message("scaling pixels to 8 bit");
- scale = 1;
- }
- else
- scale = 0;
-
- if( scale ) {
- int newformat = format;
- if( PNM_FORMAT_TYPE(format) == PBM_TYPE ) {
- pm_message("promoting PBM to PGM");
- newformat = PGM_TYPE;
- }
- pnm_promoteformat(image, cols, rows, maxval, format, 255, newformat);
- maxval = 255;
- format = newformat;
- }
-
- pixelbits = pm_maxvaltobits(maxval);
- if( PNM_FORMAT_TYPE(format) == PPM_TYPE )
- channels = 3;
- else
- channels = 1;
-
- pm_message("writing RLE image: %d channel%s, %d bit%s/pixel (per channel)",
- channels, plural(channels), pixelbits, plural(pixelbits));
-
- write_rle_header(stdout, cols, rows, channels, pixelbits);
- if( channels == 1 )
- pnm_to_1_channel(stdout, image, cols, rows);
- else
- pnm_to_3_channels(stdout, image, cols, rows);
- put_byte(stdout, OP_EOF);
- put_byte(stdout, 0); /* dummy datum, in case someone reads opcode+datum as a word */
- exit(0);
- }
-
-
- static void
- write_rle_header(ofp, cols, rows, channels, pixelbits)
- FILE *ofp;
- int cols, rows, channels, pixelbits;
- {
- put_short(ofp, RLE_MAGIC);
- put_short(ofp, 0); /* xpos */
- put_short(ofp, 0); /* ypos */
- put_short(ofp, cols); /* xsize */
- put_short(ofp, rows); /* ysize */
- put_byte(ofp, H_NO_BACKGROUND); /* flags */
- put_byte(ofp, channels); /* ncolors */
- put_byte(ofp, pixelbits); /* pixelbits */
- put_byte(ofp, 0); /* ncmap */
- put_byte(ofp, 0); /* cmaplen */
-
- put_byte(ofp, 0); /* fill byte for H_NO_BACKGROUND */
- }
-
-
- static void
- pnm_to_1_channel(ofp, image, cols, rows)
- FILE *ofp;
- xel **image;
- int cols, rows;
- {
- int row, col;
- unsigned char *rawrow = (unsigned char *)pm_allocrow(cols, sizeof(unsigned char));
-
- for( row = rows-1; row >= 0; row-- ) {
- for( col = 0; col < cols; col++ )
- rawrow[col] = PNM_GET1(image[row][col]);
- write_channel(ofp, 0, rawrow, cols);
- put_byte(ofp, OP_SKIPLINES); put_byte(ofp, 1);
- }
- }
-
-
- static void
- pnm_to_3_channels(ofp, image, cols, rows)
- FILE *ofp;
- xel **image;
- int cols, rows;
- {
- int row, col;
- unsigned char *redrow, *greenrow, *bluerow;
-
- redrow = (unsigned char *)pm_allocrow(cols, sizeof(unsigned char));
- greenrow = (unsigned char *)pm_allocrow(cols, sizeof(unsigned char));
- bluerow = (unsigned char *)pm_allocrow(cols, sizeof(unsigned char));
-
- for( row = rows-1; row >= 0; row-- ) {
- for( col = 0; col < cols; col++ ) {
- redrow[col] = PPM_GETR(image[row][col]);
- greenrow[col] = PPM_GETG(image[row][col]);
- bluerow[col] = PPM_GETB(image[row][col]);
- }
- write_channel(ofp, CHANNEL_RED, redrow, cols);
- write_channel(ofp, CHANNEL_GREEN, greenrow, cols);
- write_channel(ofp, CHANNEL_BLUE, bluerow, cols);
- put_byte(ofp, OP_SKIPLINES); put_byte(ofp, 1);
- }
- }
-
-
- static void
- write_channel(ofp, channel, src, cols)
- FILE *ofp;
- int channel;
- unsigned char *src;
- int cols;
- {
- unsigned char *end, *lit, *rep;
- #define MINLEN 5
-
- put_byte(ofp, OP_SETCOLOR); put_byte(ofp, channel);
- #if 0
- write_bytedata(ofp, src, cols);
- #else
-
- end = src + cols;
- lit = src;
- while( src < end ) {
- /* find longest literal run */
- do
- if( ++src == end )
- goto Done;
- while( *src != *(src-1) );
-
- /* find longest replicate run */
- rep = src-1;
- do
- if( ++src == end )
- break;
- while( *src == *(src-1) );
-
- /* if the replicate run is at least MINLEN bytes, save the literal
- run and the replicate run, else merge the replicate run into the
- literal run */
- if( src-rep >= MINLEN ) {
- if( rep > lit )
- write_bytedata(ofp, lit, rep-lit);
- write_rundata(ofp, rep, src-rep);
- lit = src;
- }
- }
-
- Done:
- if( src > lit )
- write_bytedata(ofp, lit, src-lit);
- #endif
- }
-
-
- static void
- write_bytedata(ofp, rawrow, nbytes)
- FILE *ofp;
- unsigned char *rawrow;
- int nbytes;
- {
- if( nbytes <= 256 ) {
- put_byte(ofp, OP_BYTEDATA); put_byte(ofp, nbytes-1);
- }
- else {
- put_byte(ofp, OP_BYTEDATA|OP_LONG_DATUM); put_byte(ofp, 0);
- put_short(ofp, nbytes-1);
- }
- if( fwrite(rawrow, 1, nbytes, ofp) != nbytes )
- pm_error("write error");
- if( odd(nbytes) )
- put_byte(ofp, 0);
- }
-
-
- static void
- write_rundata(ofp, rawrow, nbytes)
- FILE *ofp;
- unsigned char *rawrow;
- int nbytes;
- {
- if( nbytes <= 256 ) {
- put_byte(ofp, OP_RUNDATA); put_byte(ofp, nbytes-1);
- }
- else {
- put_byte(ofp, OP_RUNDATA|OP_LONG_DATUM); put_byte(ofp, 0);
- put_short(ofp, nbytes-1);
- }
- put_short(ofp, *rawrow);
- }
-
-
- static void
- put_byte(fp, byte)
- FILE *fp;
- int byte;
- {
- if( fputc((unsigned char)byte, fp) == EOF )
- pm_error("write error");
- }
-
-
- static void
- put_short(fp, word)
- FILE *fp;
- int word;
- {
- if( pm_writelittleshort(fp, (unsigned short)word) == -1 )
- pm_error("write error");
- }
-
-