This is ppmtopcx.c in view mode; [Download] [Up]
/* ppmtopcx.c - read a portable pixmap and produce a PCX file ** ** Copyright (C) 1990 by Michael Davidson. ** ** 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. */ #include <stdio.h> #include "ppm.h" #include "ppmcmap.h" #define MAXCOLORS 256 #define MAXPLANES 4 /* * Pointer to function returning an int */ typedef void (* vfunptr) ARGS(( int, int, unsigned char*, int, int )); static void PCXEncode ARGS(( FILE* fp, int GWidth, int GHeight, int Colors, int Red[], int Green[], int Blue[], vfunptr GetPlanes )); static void PutPlane ARGS(( FILE* fp, unsigned char* buf, int Size )); static void ReadPlanes ARGS(( int y, int width, unsigned char* buf, int planes, int bits )); static void Putword ARGS(( int w, FILE* fp )); static void Putbyte ARGS(( int b, FILE* fp )); static pixel** pixels; static colorhash_table cht; int main( argc, argv ) int argc; char* argv[]; { FILE* ifp; int argn, rows, cols, colors, i; pixval maxval; pixel black_pixel; colorhist_vector chv; int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS]; char* usage = "[ppmfile]"; ppm_init( &argc, argv ); argn = 1; if ( argn < argc ) { ifp = pm_openr( argv[argn] ); ++argn; } else ifp = stdin; if ( argn != argc ) pm_usage( usage ); pixels = ppm_readppm( ifp, &cols, &rows, &maxval ); pm_close( ifp ); /* Figure out the colormap. */ pm_message( "computing colormap..." ); chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors ); if ( chv == (colorhist_vector) 0 ) pm_error( "too many colors - try doing a 'ppmquant %d'", MAXCOLORS ); pm_message( "%d colors found", colors ); /* Force black to slot 0 if possible. */ PPM_ASSIGN(black_pixel, 0, 0, 0 ); ppm_addtocolorhist(chv, &colors, MAXCOLORS, &black_pixel, 0, 0 ); /* Now turn the ppm colormap into the appropriate PCX colormap. */ if ( maxval > 255 ) pm_message( "maxval is not 255 - automatically rescaling colors" ); for ( i = 0; i < colors; ++i ) { if ( maxval == 255 ) { Red[i] = PPM_GETR( chv[i].color ); Green[i] = PPM_GETG( chv[i].color ); Blue[i] = PPM_GETB( chv[i].color ); } else { Red[i] = (int) PPM_GETR( chv[i].color ) * 255 / maxval; Green[i] = (int) PPM_GETG( chv[i].color ) * 255 / maxval; Blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / maxval; } } /* And make a hash table for fast lookup. */ cht = ppm_colorhisttocolorhash( chv, colors ); ppm_freecolorhist( chv ); /* All set, let's do it. */ PCXEncode( stdout, cols, rows, colors, Red, Green, Blue, ReadPlanes ); exit( 0 ); } /***************************************************************************** * * PCXENCODE.C - PCX Image compression interface * * PCXEncode( FName, GHeight, GWidth, Colors, Red, Green, Blue, GetPlanes ) * *****************************************************************************/ #define TRUE 1 #define FALSE 0 /* public */ static void PCXEncode(fp, GWidth, GHeight, Colors, Red, Green, Blue, GetPlanes ) FILE* fp; int GWidth, GHeight; int Colors; int Red[], Green[], Blue[]; vfunptr GetPlanes; { int BytesPerLine; int Planes; int BitsPerPixel; unsigned char *buf; int i; int n; int y; /* * select number of planes and number of bits * per pixel according to number of colors */ /* * 16 colors or less are handled as 1 bit per pixel * with 1, 2, 3 or 4 color planes. * more than 16 colors are handled as 8 bits per pixel * with 1 plane */ if (Colors > 16) { BitsPerPixel = 8; Planes = 1; } else { BitsPerPixel = 1; if (Colors > 8) Planes = 4; else if (Colors > 4) Planes = 3; else if (Colors > 2) Planes = 2; else Planes = 1; } /* * Write the PCX header */ Putbyte( 0x0a, fp); /* .PCX magic number */ Putbyte( 0x05, fp); /* PC Paintbrush version */ Putbyte( 0x01, fp); /* .PCX run length encoding */ Putbyte( BitsPerPixel, fp); /* bits per pixel */ Putword( 0, fp ); /* x1 - image left */ Putword( 0, fp ); /* y1 - image top */ Putword( GWidth-1, fp ); /* x2 - image right */ Putword( GHeight-1, fp ); /* y2 - image bottom */ Putword( GWidth, fp ); /* horizontal resolution */ Putword( GHeight, fp ); /* vertical resolution */ /* * Write out the Color Map for images with 16 colors or less */ n = (Colors <= 16) ? Colors : 16; for (i = 0; i < n; ++i) { Putbyte( Red[i], fp ); Putbyte( Green[i], fp ); Putbyte( Blue[i], fp ); } for (; i < 16; ++i) { Putbyte( 255, fp ); Putbyte( 255, fp ); Putbyte( 255, fp ); } Putbyte( 0, fp); /* reserved byte */ Putbyte( Planes, fp); /* number of color planes */ BytesPerLine = ((GWidth * BitsPerPixel) + 7) / 8; Putword( BytesPerLine, fp ); /* number of bytes per scanline */ Putword( 1, fp); /* pallette info */ for (i = 0; i < 58; ++i) /* fill to end of header */ Putbyte( 0, fp ); buf = (unsigned char *)malloc( MAXPLANES * BytesPerLine ); for (y = 0; y < GHeight; ++y) { (*GetPlanes)(y, GWidth, buf, Planes, BitsPerPixel); for (i = 0; i < Planes; ++i) PutPlane(fp, buf + (i * BytesPerLine), BytesPerLine); } /* * color map for > 16 colors is at end of file */ if (Colors > 16) { Putbyte( 0x0c, fp); /* magic for 256 colors */ for (i = 0; i < Colors; ++i) { Putbyte( Red[i], fp ); Putbyte( Green[i], fp ); Putbyte( Blue[i], fp ); } for (; i < MAXCOLORS; ++i) { Putbyte( 255, fp ); Putbyte( 255, fp ); Putbyte( 255, fp ); } } fclose( fp ); } static void PutPlane(fp, buf, Size) FILE *fp; unsigned char *buf; int Size; { unsigned char *end; int c; int previous; int count; end = buf + Size; previous = *buf++; count = 1; while (buf < end) { c = *buf++; if (c == previous && count < 63) { ++count; continue; } if (count > 1 || (previous & 0xc0) == 0xc0) { count |= 0xc0; Putbyte ( count , fp ); } Putbyte(previous, fp); previous = c; count = 1; } if (count > 1 || (previous & 0xc0) == 0xc0) { count |= 0xc0; Putbyte ( count , fp ); } Putbyte(previous, fp); } static unsigned long PixMap[8][16] = { 0x00000000L, 0x00000080L, 0x00008000L, 0x00008080L, 0x00800000L, 0x00800080L, 0x00808000L, 0x00808080L, 0x80000000L, 0x80000080L, 0x80008000L, 0x80008080L, 0x80800000L, 0x80800080L, 0x80808000L, 0x80808080L, }; static void ReadPlanes(y, width, buf, planes, bits) int y; int width; unsigned char *buf; int planes; int bits; { static int first_time = 1; unsigned char *plane0, *plane1, *plane2, *plane3; int i, j, x; /* * 256 color, 1 plane, 8 bits per pixel */ if (planes == 1 && bits == 8) { for (x = 0; x < width; ++x) buf[x] = ppm_lookupcolor( cht, &pixels[y][x] ); return; } /* * must be 16 colors or less, 4 planes or less, 1 bit per pixel */ if (first_time) { for (i = 1; i < 8; ++i) for (j = 0; j < 16; ++j) PixMap[i][j] = PixMap[0][j] >> i; first_time = 0; } i = (width + 7) / 8; plane0 = buf; plane1 = plane0 + i; plane2 = plane1 + i; plane3 = plane2 + i; i = 0; x = 0; while ( x < width ) { register unsigned long t; t = PixMap[0][ppm_lookupcolor( cht, &pixels[y][x++] )]; t |= PixMap[1][ppm_lookupcolor( cht, &pixels[y][x++] )]; t |= PixMap[2][ppm_lookupcolor( cht, &pixels[y][x++] )]; t |= PixMap[3][ppm_lookupcolor( cht, &pixels[y][x++] )]; t |= PixMap[4][ppm_lookupcolor( cht, &pixels[y][x++] )]; t |= PixMap[5][ppm_lookupcolor( cht, &pixels[y][x++] )]; t |= PixMap[6][ppm_lookupcolor( cht, &pixels[y][x++] )]; t |= PixMap[7][ppm_lookupcolor( cht, &pixels[y][x++] )]; plane0[i] = t; plane1[i] = t >> 8; plane2[i] = t >> 16; plane3[i++] = t >> 24; } } /* * Write out a word to the PCX file */ static void Putword( w, fp ) int w; FILE *fp; { fputc( w & 0xff, fp ); fputc( (w / 256) & 0xff, fp ); } /* * Write out a byte to the PCX file */ static void Putbyte( b, fp ) int b; FILE *fp; { fputc( b & 0xff, fp ); } /* The End */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.