Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!wuarchive!brutus.cs.uiuc.edu!apple!well!pokey From: pokey@well.UUCP (Jef Poskanzer) Newsgroups: alt.sources Subject: PBMPLUS, part 15 of 18 Message-ID: <13621@well.UUCP> Date: 14 Sep 89 11:26:04 GMT Reply-To: Jef Poskanzer Organization: Paratheo-Anametamystikhood Of Eris Esoteric, Ada Lovelace Cabal Lines: 1657 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # ppm/qrttoppm.c # ppm/qrttoppm.1 # ppm/ppmtops.c # ppm/ppmtops.1 # ppm/ppmtogif.c # ppm/ppmtogif.1 # ppm/ppmtoilbm.c # ppm/ppmtoilbm.1 # This archive created: Thu Sep 14 03:43:48 1989 # By: Jef Poskanzer (Paratheo-Anametamystikhood Of Eris Esoteric, Ada Lovelace Cabal) export PATH; PATH=/bin:$PATH if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/qrttoppm.c'" '(1788 characters)' if test -f 'ppm/qrttoppm.c' then echo shar: will not over-write existing file "'ppm/qrttoppm.c'" else sed 's/^X//' << \SHAR_EOF > 'ppm/qrttoppm.c' X/* qrttoppm.c - read a QRT ray-tracer output file and produce a portable pixmap X** X** Copyright (C) 1989 by Jef Poskanzer. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include X#include "ppm.h" X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X register pixel *pixelrow; X int rows, cols, row, col; X pixval maxval; X unsigned char *buf; X X pm_progname = argv[0]; X X if ( argc > 2 ) X pm_usage( "[qrtfile]" ); X X if ( argc == 2 ) X ifd = pm_openr( argv[1] ); X else X ifd = stdin; X X /* Read in the QRT file. First the header. */ X cols = getc( ifd ); X cols += getc( ifd ) << 8; X rows = getc( ifd ); X rows += getc( ifd ) << 8; X X if ( cols <= 0 || rows <= 0 ) X pm_error( "invalid size: %d %d", cols, rows, 0,0,0 ); X maxval = 255; X X ppm_writeppminit( stdout, cols, rows, maxval ); X pixelrow = ppm_allocrow( cols ); X buf = (unsigned char *) malloc( 3 * cols ); X if ( buf == (unsigned char *) 0 ) X pm_error( "out of memory", 0,0,0,0,0 ); X X for ( row = 0; row < rows; row++ ) X { X (void) getc( ifd ); /* discard */ X (void) getc( ifd ); /* linenum */ X if ( fread( buf, 3 * cols, 1, ifd ) != 1 ) X pm_error( "premature EOF", 0,0,0,0,0 ); X for ( col = 0; col < cols; col++ ) X PPM_ASSIGN( X pixelrow[col], buf[col], buf[cols + col], buf[2 * cols + col] ); X ppm_writeppmrow( stdout, pixelrow, cols, maxval ); X } X X pm_close( ifd ); X X exit( 0 ); X } SHAR_EOF if test 1788 -ne "`wc -c < 'ppm/qrttoppm.c'`" then echo shar: error transmitting "'ppm/qrttoppm.c'" '(should have been 1788 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/qrttoppm.1'" '(666 characters)' if test -f 'ppm/qrttoppm.1' then echo shar: will not over-write existing file "'ppm/qrttoppm.1'" else sed 's/^X//' << \SHAR_EOF > 'ppm/qrttoppm.1' X.TH qrttoppm 1 "25 August 1989" X.SH NAME Xqrttoppm - convert output from the QRT ray tracer into a portable pixmap X.SH SYNOPSIS Xqrttoppm [qrtfile] X.SH DESCRIPTION XReads a qrt file as input. XProduces a portable pixmap as output. X.SH "SEE ALSO" Xppm(5) X.SH AUTHOR XCopyright (C) 1989 by Jef Poskanzer. X XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, provided Xthat the above copyright notice appear in all copies and that both that Xcopyright notice and this permission notice appear in supporting Xdocumentation. This software is provided "as is" without express or Ximplied warranty. SHAR_EOF if test 666 -ne "`wc -c < 'ppm/qrttoppm.1'`" then echo shar: error transmitting "'ppm/qrttoppm.1'" '(should have been 666 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmtops.c'" '(4720 characters)' if test -f 'ppm/ppmtops.c' then echo shar: will not over-write existing file "'ppm/ppmtops.c'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtops.c' X/* ppmtops.c - read a portable pixmap and produce a PostScript file X** X** Copyright (C) 1989 by Jef Poskanzer. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include X#ifdef SYSV X#include X#define index strchr X#else SYSV X#include X#endif SYSV X#include "ppm.h" X X#define max(a,b) ((a) > (b) ? (a) : (b)) X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X register pixel *pixrow, *pP; X int argn, rows, cols, format, bps, padright, row, col; X pixval maxval; X float scale; X char name[100], *cp; X char *usage = "[-scale ] [ppmfile]"; X X pm_progname = argv[0]; X X argn = 1; X scale = 1.0; X X /* Check for flags. */ X while ( argn < argc && argv[argn][0] == '-' ) X { X if ( strncmp(argv[argn],"-scale",max(strlen(argv[argn]),2)) == 0 ) X { X argn++; X if ( argn == argc || sscanf( argv[argn], "%f", &scale ) != 1 ) X pm_usage( usage ); X } X else X pm_usage( usage ); X argn++; X } X X if ( argn < argc ) X { X ifd = pm_openr( argv[argn] ); X strcpy( name, argv[argn] ); X if ( strcmp( name, "-" ) == 0 ) X strcpy( name, "noname" ); X X if ( ( cp = index( name, '.' ) ) != 0 ) X *cp = '\0'; X argn++; X } X else X { X ifd = stdin; X strcpy( name, "noname" ); X } X X if ( argn != argc ) X pm_usage( usage ); X X ppm_readppminit( ifd, &cols, &rows, &maxval, &format ); X pixrow = ppm_allocrow( cols ); X X /* Figure out bps. */ X bps = maxvaltobps( maxval ); X X /* Compute padding to round cols * bps up to the nearest multiple of 8. */ X padright = ( ( cols * bps + 7 ) / 8 ) * 8 - cols * bps; X X putinit( name, cols, rows, bps, scale ); X for ( row = 0; row < rows; row++ ) X { X ppm_readppmrow( ifd, pixrow, cols, maxval, format ); X for ( col = 0, pP = pixrow; col < cols; col++, pP++ ) X putpix( *pP ); X for ( col = 0; col < padright; col++ ) X putpix( maxval ); X } X X pm_close( ifd ); X X putrest( ); X X exit( 0 ); X } X Xint Xmaxvaltobps( maxval ) Xpixval maxval; X { X switch ( maxval ) X { X case 1: X return 1; X X case 3: X return 2; X X case 15: X return 4; X X case 255: X return 8; X X#ifdef notdef X case 7: X return 3; X X case 31: X return 5; X X case 63: X return 6; X X case 127: X return 7; X#endif notdef X X default: X pm_error( "maxval of %d is not supported", maxval, 0,0,0,0 ); X /* NOTREACHED */ X } X } X X Xint bitspersample, item, bitsperitem, bitshift, itemsperline, items; X#define HSBUFSIZ 384 X Xputinit( name, cols, rows, bps, scale ) Xchar *name; Xint cols, rows, bps; Xfloat scale; X { X int scols, srows, llx, lly; X X scols = cols * 0.96 + 0.5; /* 0.96 is the multiple of */ X srows = rows * 0.96 + 0.5; /* 72/300 that is closest to 1 */ X llx = 300 - ( scols / 2 ); X lly = 400 - ( srows / 2 ); X X printf( "%%!PS-Adobe-2.0 EPSF-2.)\n" ); X printf( "%%%%Creator: ppmtops\n" ); X printf( "%%%%Title: %s.ps\n", name ); X printf( "%%%%Pages: 1\n" ); X printf( X "%%%%BoundingBox: %d %d %d %d\n", llx, lly, llx + scols, lly + srows ); X printf( "%%%%EndComments\n" ); X printf( "%%%%EndProlog\n" ); X printf( "%%%%Page 1 1\n" ); X printf( "/picstr %d string def\n", HSBUFSIZ ); X printf( "gsave\n" ); X printf( "%d %d translate\n", llx, lly ); X printf( "%g %g scale\n", scale, scale ); X printf( "%d %d scale\n", scols, srows ); X printf( "%d %d %d\n", cols, rows, bps ); X printf( "[ %d 0 0 -%d 0 %d ]\n", cols, rows, rows ); X printf( "{ currentfile picstr readhexstring pop }\n" ); X printf( "false 3\n" ); X printf( "colorimage\n" ); X X bitspersample = bps; X itemsperline = items = 0; X item = 0; X bitsperitem = 0; X bitshift = 8 - bitspersample; X } X Xputitem( ) X { X if ( itemsperline == 30 ) X { X putchar( '\n' ); X itemsperline = 0; X } X printf( "%02x", item ); X itemsperline++; X items++; X item = 0; X bitsperitem = 0; X bitshift = 8 - bitspersample; X } X Xputpix( p ) Xpixel p; X { X putgray( PPM_GETR( p ) ); X putgray( PPM_GETG( p ) ); X putgray( PPM_GETB( p ) ); X } X Xputgray( g ) Xpixval g; X { X if ( bitsperitem == 8 ) X putitem( ); X item += g << bitshift; X bitsperitem += bitspersample; X bitshift -= bitspersample; X } X Xputrest( ) X { X if ( bitsperitem > 0 ) X putitem( ); X while ( items % HSBUFSIZ != 0 ) X putitem( ); X printf( "\n" ); X printf( "grestore\n" ); X printf( "showpage\n" ); X printf( "%%%%Trailer\n" ); X } SHAR_EOF if test 4720 -ne "`wc -c < 'ppm/ppmtops.c'`" then echo shar: error transmitting "'ppm/ppmtops.c'" '(should have been 4720 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmtops.1'" '(1551 characters)' if test -f 'ppm/ppmtops.1' then echo shar: will not over-write existing file "'ppm/ppmtops.1'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtops.1' X.TH ppmtops 1 "01 September 1989" X.SH NAME Xppmtops - convert a portable pixmap into color Encapsulated PostScript X.SH SYNOPSIS Xppmtops [-scale ] [] X.SH DESCRIPTION XReads a portable pixmap as input. XProduces Encapsulated PostScript as output, using the colorimage Xoperator. XThis operator is only defined on color printers and very recent B&W printers. XMost of the time you will NOT want to use ppmtops; instead, do a Xppmtopgm | pgmtops. X.PP XThe -scale flag controls the scale of the result. The default scale is 1, Xwhich results in one ppm pixel producing a 3x3 square of PostScript Xpixels. On a 300 dpi printer such as the Apple LaserWriter, this makes Xthe output look about the same size as the input would if it was displayed Xon a typical 72 dpi screen. XTo get one ppm pixel per LaserWriter pixel, use "-s 0.333333". X.PP XAll flags can be abbreviated to their shortest unique prefix. X.PP XNote that there is no pstoppm Xtool - this transformation is one-way, because a pstoppm tool would Xbe a full-fledged PostScript interpreter, which is beyond the scope Xof this package. X.SH "SEE ALSO" Xppm(5), pgmtops(1), psidtopgm(1) X.SH AUTHOR XCopyright (C) 1989 by Jef Poskanzer. X XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, provided Xthat the above copyright notice appear in all copies and that both that Xcopyright notice and this permission notice appear in supporting Xdocumentation. This software is provided "as is" without express or Ximplied warranty. SHAR_EOF if test 1551 -ne "`wc -c < 'ppm/ppmtops.1'`" then echo shar: error transmitting "'ppm/ppmtops.1'" '(should have been 1551 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmtogif.c'" '(19592 characters)' if test -f 'ppm/ppmtogif.c' then echo shar: will not over-write existing file "'ppm/ppmtogif.c'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtogif.c' X/* ppmtogif.c - read a portable pixmap and produce a GIF file X** X** Based on GIFENCOD by David Rowley .A X** Lempel-Zim compression based on "compress". X** X** Copyright (C) 1989 by Jef Poskanzer. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include X#include "ppm.h" X#include "ppmcmap.h" X X#define MAXCOLORS 256 X Xpixel **pixels; Xcolorhash_table cht; X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X int argn, rows, cols, colors, i, BitsPerPixel; X pixval maxval; X colorhist_vector chv; X int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS]; X int GetPixel(); X char *usage = "[ppmfile]"; X X pm_progname = argv[0]; X X argn = 1; X X if ( argn < argc ) X { X ifd = pm_openr( argv[argn] ); X argn++; X } X else X ifd = stdin; X X if ( argn != argc ) X pm_usage( usage ); X X pixels = ppm_readppm( ifd, &cols, &rows, &maxval ); X X pm_close( ifd ); X X /* Figure out the colormap. */ X fprintf( stderr, "(Computing colormap..." ); X fflush( stderr ); X chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors ); X if ( chv == (colorhist_vector) 0 ) X pm_error( X "too many colors - try running the pixmap through 'ppmquant 256'", X 0,0,0,0,0 ); X fprintf( stderr, " Done. %d colors found.)\n", colors ); X X /* Now turn the ppm colormap into the appropriate GIF colormap. */ X if ( maxval > 255 ) X fprintf( X stderr, "(Maxval is not 255 -- automatically rescaling colors.)\n"); X for ( i = 0; i < colors; i++ ) X { X if ( maxval == 255 ) X { X Red[i] = PPM_GETR( chv[i].color ); X Green[i] = PPM_GETG( chv[i].color ); X Blue[i] = PPM_GETB( chv[i].color ); X } X else X { X Red[i] = (int) PPM_GETR( chv[i].color ) * 255 / maxval; X Green[i] = (int) PPM_GETG( chv[i].color ) * 255 / maxval; X Blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / maxval; X } X } X BitsPerPixel = colorstobpp( colors ); X X /* And make a hash table for fast lookup. */ X cht = ppm_colorhisttocolorhash( chv, colors ); X ppm_freecolorhist( chv ); X X /* All set, let's do it. */ X GIFEncode( X stdout, cols, rows, 0, 0, BitsPerPixel, Red, Green, Blue, GetPixel ); X X exit( 0 ); X } X Xint Xcolorstobpp( colors ) Xint colors; X { X int bpp; X X if ( colors <= 2 ) X bpp = 1; X else if ( colors <= 4 ) X bpp = 2; X else if ( colors <= 8 ) X bpp = 3; X else if ( colors <= 16 ) X bpp = 4; X else if ( colors <= 32 ) X bpp = 5; X else if ( colors <= 64 ) X bpp = 6; X else if ( colors <= 128 ) X bpp = 7; X else if ( colors <= 256 ) X bpp = 8; X else X pm_error( "can't happen", 0,0,0,0,0 ); X X return bpp; X } X XGetPixel( x, y ) Xint x, y; X { X int color; X X color = ppm_lookupcolor( cht, pixels[y][x] ); X return color; X } X X X/***************************************************************************** X * X * GIFENCODE.C - GIF Image compression interface X * X * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, X * BitsPerPixel, Red, Green, Blue, GetPixel ) X * X *****************************************************************************/ X X/* X * Pointer to function returning an int X */ Xtypedef int (* ifunptr)(); X X#define TRUE 1 X#define FALSE 0 X Xint Width, Height; Xint curx, cury; Xlong CountDown; Xint Pass = 0; Xint Interlace; X X/* X * Bump the 'curx' and 'cury' to point to the next pixel X */ XBumpPixel() X{ X /* X * Bump the current X position X */ X curx++; X X /* X * If we are at the end of a scan line, set curx back to the beginning X * If we are interlaced, bump the cury to the appropriate spot, X * otherwise, just increment it. X */ X if( curx == Width ) { X curx = 0; X X if( !Interlace ) X cury++; X else { X switch( Pass ) { X X case 0: X cury += 8; X if( cury >= Height ) { X Pass++; X cury = 4; X } X break; X X case 1: X cury += 8; X if( cury >= Height ) { X Pass++; X cury = 2; X } X break; X X case 2: X cury += 4; X if( cury >= Height ) { X Pass++; X cury = 1; X } X break; X X case 3: X cury += 2; X break; X } X } X } X} X X/* X * Return the next pixel from the image X */ XGIFNextPixel( getpixel ) Xifunptr getpixel; X{ X int r; X X if( CountDown == 0 ) X return EOF; X X CountDown--; X X r = ( * getpixel )( curx, cury ); X X BumpPixel(); X X return r; X} X X/* public */ X XGIFEncode( fp, GWidth, GHeight, GInterlace, Background, X BitsPerPixel, Red, Green, Blue, GetPixel ) X XFILE *fp; Xint GWidth, GHeight; Xint GInterlace; Xint Background; Xint BitsPerPixel; Xint Red[], Green[], Blue[]; Xifunptr GetPixel; X X{ X int B; X int RWidth, RHeight; X int LeftOfs, TopOfs; X int Resolution; X int ColorMapSize; X int InitCodeSize; X int i; X X Interlace = GInterlace; X X ColorMapSize = 1 << BitsPerPixel; X X RWidth = Width = GWidth; X RHeight = Height = GHeight; X LeftOfs = TopOfs = 0; X X Resolution = BitsPerPixel; X X /* X * Calculate number of bits we are expecting X */ X CountDown = (long)Width * (long)Height; X X /* X * Indicate which pass we are on (if interlace) X */ X Pass = 0; X X /* X * The initial code size X */ X if( BitsPerPixel <= 1 ) X InitCodeSize = 2; X else X InitCodeSize = BitsPerPixel; X X /* X * Set up the current x and y position X */ X curx = cury = 0; X X /* X * Write the Magic header X */ X fwrite( "GIF87a", 1, 6, fp ); X X /* X * Write out the screen width and height X */ X Putword( RWidth, fp ); X Putword( RHeight, fp ); X X /* X * Indicate that there is a global colour map X */ X B = 0x80; /* Yes, there is a color map */ X X /* X * OR in the resolution X */ X B |= (Resolution - 1) << 5; X X /* X * OR in the Bits per Pixel X */ X B |= (BitsPerPixel - 1); X X /* X * Write it out X */ X fputc( B, fp ); X X /* X * Write out the Background colour X */ X fputc( Background, fp ); X X /* X * Byte of 0's (future expansion) X */ X fputc( 0, fp ); X X /* X * Write out the Global Colour Map X */ X for( i=0; i X/* #include */ X X#define ARGVAL() (*++(*argv) || (--argc && *++argv)) X Xint n_bits; /* number of bits/code */ Xint maxbits = BITS; /* user settable max # bits/code */ Xcode_int maxcode; /* maximum code, given n_bits */ Xcode_int maxmaxcode = (code_int)1 << BITS; /* should NEVER generate this Xcode */ X#ifdef COMPATIBLE /* But wrong! */ X# define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1) X#else X# define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) X#endif /* COMPATIBLE */ X Xcount_int htab [HSIZE]; Xunsigned short codetab [HSIZE]; X#define HashTabOf(i) htab[i] X#define CodeTabOf(i) codetab[i] X Xcode_int hsize = HSIZE; /* for dynamic table sizing */ Xcount_int fsize; X X/* X * To save much memory, we overlay the table used by compress() with those X * used by decompress(). The tab_prefix table is the same size and type X * as the codetab. The tab_suffix table needs 2**BITS characters. We X * get this from the beginning of htab. The output stack uses the rest X * of htab, and contains characters. There is plenty of room for any X * possible stack (stack used to be 8000 characters). X */ X X#define tab_prefixof(i) CodeTabOf(i) X#define tab_suffixof(i) ((char_type *)(htab))[i] X#define de_stack ((char_type *)&tab_suffixof((code_int)1< 0 ) X goto probe; Xnomatch: X output ( (code_int) ent ); X out_count++; X ent = c; X#ifdef SIGNED_COMPARE_SLOW X if ( (unsigned) free_ent < (unsigned) maxmaxcode) { X#else X if ( free_ent < maxmaxcode ) { X#endif X CodeTabOf (i) = free_ent++; /* code -> hashtable */ X HashTabOf (i) = fcode; X } else X cl_block(); X } X /* X * Put out the final code. X */ X output( (code_int)ent ); X out_count++; X output( (code_int) EOFCode ); X X return; X} X X/***************************************************************** X * TAG( output ) X * X * Output the given code. X * Inputs: X * code: A n_bits-bit integer. If == -1, then EOF. This assumes X * that n_bits =< (long)wordsize - 1. X * Outputs: X * Outputs code to the file. X * Assumptions: X * Chars are 8 bits long. X * Algorithm: X * Maintain a BITS character long buffer (so that 8 codes will X * fit in it exactly). Use the VAX insv instruction to insert each X * code in turn. When the buffer fills up empty it and start over. X */ X Xunsigned long cur_accum = 0; Xint cur_bits = 0; X Xunsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, X 0x001F, 0x003F, 0x007F, 0x00FF, X 0x01FF, 0x03FF, 0x07FF, 0x0FFF, X 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; X Xoutput( code ) Xcode_int code; X{ X cur_accum &= masks[ cur_bits ]; X X if( cur_bits > 0 ) X cur_accum |= ((long)code << cur_bits); X else X cur_accum = code; X X cur_bits += n_bits; X X while( cur_bits >= 8 ) { X char_out( (unsigned int)(cur_accum & 0xff) ); X cur_accum >>= 8; X cur_bits -= 8; X } X X /* X * If the next entry is going to be too big for the code size, X * then increase it, if possible. X */ X if ( free_ent > maxcode || clear_flg ) { X X if( clear_flg ) { X X maxcode = MAXCODE (n_bits = g_init_bits); X clear_flg = 0; X X } else { X X n_bits++; X if ( n_bits == maxbits ) X maxcode = maxmaxcode; X else X maxcode = MAXCODE(n_bits); X } X } X X if( code == EOFCode ) { X /* X * At EOF, write the rest of the buffer. X */ X while( cur_bits > 0 ) { X char_out( (unsigned int)(cur_accum & 0xff) ); X cur_accum >>= 8; X cur_bits -= 8; X } X X flush_char(); X X fflush( g_outfile ); X X if( ferror( g_outfile ) ) X writeerr(); X } X} X X/* X * Clear out the hash table X */ Xcl_block () /* table clear for block compress */ X{ X X cl_hash ( (count_int) hsize ); X free_ent = ClearCode + 2; X clear_flg = 1; X X output( (code_int)ClearCode ); X} X Xcl_hash(hsize) /* reset code table */ Xregister count_int hsize; X{ X X register count_int *htab_p = htab+hsize; X X register long i; X register long m1 = -1; X X i = hsize - 16; X do { /* might use Sys V memset(3) here */ X *(htab_p-16) = m1; X *(htab_p-15) = m1; X *(htab_p-14) = m1; X *(htab_p-13) = m1; X *(htab_p-12) = m1; X *(htab_p-11) = m1; X *(htab_p-10) = m1; X *(htab_p-9) = m1; X *(htab_p-8) = m1; X *(htab_p-7) = m1; X *(htab_p-6) = m1; X *(htab_p-5) = m1; X *(htab_p-4) = m1; X *(htab_p-3) = m1; X *(htab_p-2) = m1; X *(htab_p-1) = m1; X htab_p -= 16; X } while ((i -= 16) >= 0); X X for ( i += 16; i > 0; i-- ) X *--htab_p = m1; X} X Xwriteerr() X{ X printf( "error writing output file\n" ); X exit(1); X} X X/****************************************************************************** X * X * GIF Specific routines X * X ******************************************************************************/ X X/* X * Number of characters so far in this 'packet' X */ Xint a_count; X X/* X * Set up the 'byte output' routine X */ Xchar_init() X{ X a_count = 0; X} X X/* X * Define the storage for the packet accumulator X */ Xchar accum[ 256 ]; X X/* X * Add a character to the end of the current packet, and if it is 254 X * characters, flush the packet to disk. X */ Xchar_out( c ) Xint c; X{ X accum[ a_count++ ] = c; X if( a_count >= 254 ) X flush_char(); X} X X/* X * Flush the packet to disk, and reset the accumulator X */ Xflush_char() X{ X if( a_count > 0 ) { X fputc( a_count, g_outfile ); X fwrite( accum, 1, a_count, g_outfile ); X a_count = 0; X } X} X X/* The End */ SHAR_EOF if test 19592 -ne "`wc -c < 'ppm/ppmtogif.c'`" then echo shar: error transmitting "'ppm/ppmtogif.c'" '(should have been 19592 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmtogif.1'" '(774 characters)' if test -f 'ppm/ppmtogif.1' then echo shar: will not over-write existing file "'ppm/ppmtogif.1'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtogif.1' X.TH ppmtogif 1 "01 September 1989" X.SH NAME Xppmtogif - convert a portable pixmap into a GIF file X.SH SYNOPSIS Xppmtogif [] X.SH DESCRIPTION XReads a portable pixmap as input. XProduces a GIF file as output. X.SH "SEE ALSO" Xgiftoppm(1), ppm(5) X.SH AUTHOR XBased on GIFENCOD by David Rowley . XLempel-Zim compression based on "compress". X XCopyright (C) 1989 by Jef Poskanzer. X XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, provided Xthat the above copyright notice appear in all copies and that both that Xcopyright notice and this permission notice appear in supporting Xdocumentation. This software is provided "as is" without express or Ximplied warranty. SHAR_EOF if test 774 -ne "`wc -c < 'ppm/ppmtogif.1'`" then echo shar: error transmitting "'ppm/ppmtogif.1'" '(should have been 774 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmtoilbm.c'" '(7039 characters)' if test -f 'ppm/ppmtoilbm.c' then echo shar: will not over-write existing file "'ppm/ppmtoilbm.c'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtoilbm.c' X/* ppmtoilbm.c - read a portable pixmap and produce an Amiga IFF ILBM file X** X** Copyright (C) 1989 by Jef Poskanzer. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include X#include "ppm.h" X#include "ppmcmap.h" X#include "ilbm.h" X X#define MAXCOLORS 32 X X#define odd(n) ((n) & 1) X#define abs(x) ((x) >= 0 ? (x) : -(x)) X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X int argn, rows, cols, colors, i, ham, nPlanes, formsize, cmapsize; X pixel **pixels, *pP; X int row, col, plane; X pixval maxval; X colorhash_table cht; X colorhist_vector chv; X unsigned char *raw_rowbuf, *coded_rowbuf; X X pm_progname = argv[0]; X X argn = 1; X X if ( argn < argc ) X { X ifd = pm_openr( argv[argn] ); X argn++; X } X else X ifd = stdin; X X if ( argn != argc ) X pm_usage( "[ppmfile]" ); X X pixels = ppm_readppm( ifd, &cols, &rows, &maxval ); X X pm_close( ifd ); X X /* Figure out the colormap. */ X fprintf( stderr, "(Computing colormap..." ); X fflush( stderr ); X chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors ); X if ( chv == (colorhist_vector) 0 ) X { X fprintf( X stderr, " Too many colors - proceeding to write a HAM file.\n" ); X fprintf( X stderr, X "If you want a non-HAM file, try running the pixmap through 'ppmquant 32'.)\n" ); X ham = 1; X colors = 16; X nPlanes = 6; X } X else X { X fprintf( stderr, " Done. %d colors found.)\n", colors ); X ham = 0; X nPlanes = colorstobpp( colors ); X /* Make a hash table for fast color lookup. */ X cht = ppm_colorhisttocolorhash( chv, colors ); X } X X /* Start off the ILBM with a FORM ILBM. */ X cmapsize = colors * 3; X if ( odd( colors ) ) X cmapsize++; /* pad CMAP to word */ X formsize = X 4 + /* ILBM */ X 4 + 4 + 20 + /* BMHD size header*/ X 4 + 4 + cmapsize + /* CMAP size colors */ X 4 + 4 + 4 + /* CAMG size val */ X 4 + 4 + rows * nPlanes * RowBytes(cols); /* BODY size data */ X put_chunk_head( "FORM", formsize ); X put_fourchars( "ILBM" ); X X /* Write out the BMHD. */ X put_chunk_head( "BMHD", 20 ); X put_big_short( cols ); X put_big_short( rows ); X put_big_short( 0 ); /* x */ X put_big_short( 0 ); /* y */ X put_byte( nPlanes ); X put_byte( mskNone ); X put_byte( cmpNone ); X put_byte( 0 ); /* pad1 */ X put_big_short( 0 ); /* transparentColor */ X put_byte( 10 ); /* xAsp */ X put_byte( 10 ); /* yAsp */ X put_big_short( cols ); /* pageWidth */ X put_big_short( rows ); /* pageHeight */ X X /* Write out the CMAP. */ X if ( maxval > 255 ) X fprintf( X stderr, "(Maxval is not 255 -- automatically rescaling colors.)\n"); X put_chunk_head( "CMAP", cmapsize ); X for ( i = 0; i < colors; i++ ) X { X if ( ham ) X { /* Grayscale colormap for HAM. */ X put_byte( i << 4 ); X put_byte( i << 4 ); X put_byte( i << 4 ); X } X else if ( maxval == 255 ) X { X put_byte( PPM_GETR( chv[i].color ) ); X put_byte( PPM_GETG( chv[i].color ) ); X put_byte( PPM_GETB( chv[i].color ) ); X } X else X { X put_byte( (char) ( (int) PPM_GETR(chv[i].color) * 255 / maxval ) ); X put_byte( (char) ( (int) PPM_GETG(chv[i].color) * 255 / maxval ) ); X put_byte( (char) ( (int) PPM_GETB(chv[i].color) * 255 / maxval ) ); X } X } X if ( odd( colors ) ) X put_byte( 0 ); /* Pad to word. */ X X /* Write out the CAMG. */ X put_chunk_head( "CAMG", 4 ); X if ( ham ) X put_big_long( vmHAM ); X else X put_big_long( 0 ); X X /* And finally, encode and write out the BODY. */ X raw_rowbuf = (unsigned char *) malloc( cols ); X coded_rowbuf = (unsigned char *) malloc( RowBytes(cols) ); X if ( raw_rowbuf == 0 || coded_rowbuf == 0 ) X pm_error( "out of memory", 0,0,0,0,0 ); X put_chunk_head( "BODY", rows * nPlanes * RowBytes(cols) ); X for ( row = 0; row < rows; row++ ) X { X /* Go from pixels to raw bytes. */ X if ( ham ) X { /* HAM mode. */ X register int noprev, pr, pg, pb, r, g, b, l; X X noprev = 1; X for ( col = 0, pP = pixels[row]; col < cols; col++, pP++ ) X { X r = PPM_GETR( *pP ); X g = PPM_GETG( *pP ); X b = PPM_GETB( *pP ); X l = PPM_LUMIN( *pP ); X if ( maxval != 15 ) X { X r = r * 15 / maxval; X g = g * 15 / maxval; X b = b * 15 / maxval; X l = l * 15 / maxval; X } X if ( noprev ) X { /* No previous pixels, gotta use the gray option. */ X raw_rowbuf[col] = l; X pr = pg = pb = l; X noprev = 0; X } X else X { X register int dred, dgreen, dblue, dgray; X X /* Compute distances for the four options. */ X dred = abs( g - pg ) + abs( b - pb ); X dgreen = abs( r - pr ) + abs( b - pb ); X dblue = abs( r - pr ) + abs( g - pg ); X dgray = abs( r - l ) + abs( g - l ) + abs( b - l ); X X if ( dgray < dred && dgray < dgreen && dgray < dblue ) X { X raw_rowbuf[col] = l; X pr = pg = pb = l; X } X else if ( dblue < dred && dblue < dgreen ) X { X raw_rowbuf[col] = ( 1 << 4 ) + b; X pb = b; X } X else if ( dred < dgreen ) X { X raw_rowbuf[col] = ( 2 << 4 ) + r; X pr = r; X } X else X { X raw_rowbuf[col] = ( 3 << 4 ) + g; X pg = g; X } X } X } X } X else X /* Non-HAM. */ X for ( col = 0, pP = pixels[row]; col < cols; col++, pP++ ) X raw_rowbuf[col] = ppm_lookupcolor( cht, *pP ); X X /* Encode and write raw bytes in plane-interleaved form. */ X for ( plane = 0; plane < nPlanes; plane++ ) X { X int mask; X unsigned char *cp; X X mask = 1 << plane; X cp = coded_rowbuf; X *cp = 0; X for ( col = 0; col < cols; col++ ) X { X int b; X X b = ( raw_rowbuf[col] & mask ) ? 1 : 0; X *cp |= b << ( 7 - col % 8 ); X if ( col % 8 == 7 ) X { X cp++; X *cp = 0; X } X } X fwrite( coded_rowbuf, RowBytes(cols), 1, stdout ); X } X } X X exit( 0 ); X } X Xint Xcolorstobpp( colors ) Xint colors; X { X int bpp; X X if ( colors <= 2 ) X bpp = 1; X else if ( colors <= 4 ) X bpp = 2; X else if ( colors <= 8 ) X bpp = 3; X else if ( colors <= 16 ) X bpp = 4; X else if ( colors <= 32 ) X bpp = 5; X else if ( colors <= 64 ) X bpp = 6; X else if ( colors <= 128 ) X bpp = 7; X else if ( colors <= 256 ) X bpp = 8; X else X pm_error( "can't happen", 0,0,0,0,0 ); X X return bpp; X } X Xput_chunk_head( str, size ) Xchar *str; Xlong size; X { X put_fourchars( str ); X put_big_long( size ); X } X Xput_fourchars( str ) Xchar *str; X { X fputs( str, stdout ); X } X Xput_big_short( s ) Xshort s; X { X put_byte( s >> 8 ); X put_byte( s & 0xff ); X } X Xput_big_long( l ) Xlong l; X { X put_byte( l >> 24 ); X put_byte( ( l >> 16 ) & 0xff ); X put_byte( ( l >> 8 ) & 0xff ); X put_byte( l & 0xff ); X } X Xput_byte( b ) Xunsigned char b; X { X putchar( b ); X } SHAR_EOF if test 7039 -ne "`wc -c < 'ppm/ppmtoilbm.c'`" then echo shar: error transmitting "'ppm/ppmtoilbm.c'" '(should have been 7039 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmtoilbm.1'" '(781 characters)' if test -f 'ppm/ppmtoilbm.1' then echo shar: will not over-write existing file "'ppm/ppmtoilbm.1'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtoilbm.1' X.TH ppmtoilbm 1 "07 September 1989" X.SH NAME Xppmtoilbm - convert a portable pixmap into an Amiga IFF ILBM file X.SH SYNOPSIS Xppmtoilbm [] X.SH DESCRIPTION XReads a portable pixmap as input. XProduces an Amiga IFF ILBM file as output. X.PP XIf the pixmap won't fit into the Amiga's maximum of 5 planes, a HAM Xfile is written. X.SH "SEE ALSO" Xilbmtoppm(1), ppm(5) X.SH AUTHOR XCopyright (C) 1989 by Jef Poskanzer. X XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, provided Xthat the above copyright notice appear in all copies and that both that Xcopyright notice and this permission notice appear in supporting Xdocumentation. This software is provided "as is" without express or Ximplied warranty. SHAR_EOF if test 781 -ne "`wc -c < 'ppm/ppmtoilbm.1'`" then echo shar: error transmitting "'ppm/ppmtoilbm.1'" '(should have been 781 characters)' fi fi # end of overwriting check # End of shell archive exit 0