home *** CD-ROM | disk | FTP | other *** search
- /* pbm utility library
- **
- ** Copyright (C) 1988 by Jef Poskanzer.
- **
- ** 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.
- */
-
- /* modified by Günther Röhrich */
- /* WARNING: This file is not for use with normal pbm programs */
-
- /* support functions for the ppm stuff */
-
- #include <stdarg.h>
- #include "ppm.h"
- #include "ppm2AGA.h"
- #include "libpbm.h"
- #include "libppm.h"
- #include "libpgm.h"
-
- extern jmp_buf ErrorEnv;
- static bit pbm_getbit(FILE *);
- extern pixel **pixels;
- extern int cols;
- extern int rows;
- extern int rowcnt;
- extern pixel *pixrow;
- extern pixval maxval;
- extern int ppmformat;
- extern int ColorRegMax;
-
- extern long *thisrerr;
- extern long *nextrerr;
- extern long *thisgerr;
- extern long *nextgerr;
- extern long *thisberr;
- extern long *nextberr;
- extern int Convert4096;
- extern int Convert262144;
- extern int fs_direction;
- #define FS_SCALE 1024
-
- void FSrow(pixel *pixelrow, int cols);
-
- /* this is called when an error in ppm2ilbm() is found */
- void pm_error(char *format, ...)
- {
- va_list args;
- va_start(args, format);
- vprintf(format, args); /* modify this if we don't output to stdout any more */
- va_end(args);
- longjmp(ErrorEnv, 10);
- }
-
- /* this is defined in ppm2AGA.c
- void pm_message(char *format, ...)
- {
- va_list args;
- va_start(args, format);
- vprintf(format, args);
- va_end(args);
- }
- */
-
- void ppm_readppminitrest(FILE *file, int *colsP, int *rowsP, pixval *maxvalP)
- {
- int maxval;
-
- /* Read size. */
- *colsP = pbm_getint( file );
- *rowsP = pbm_getint( file );
-
- /* Read maxval. */
- maxval = pbm_getint( file );
- if ( maxval > PPM_MAXMAXVAL )
- pm_error(
- "maxval is too large - try reconfiguring with PGM_BIGGRAYS\n\
- or without PPM_PACKCOLORS\n" );
- *maxvalP = maxval;
- }
-
- pixval ppm_pbmmaxval = 1;
-
- void ppm_readppminit(FILE *file, int *colsP, int *rowsP,
- pixval *maxvalP, int *formatP)
- {
- /* Check magic number. */
- *formatP = pbm_readmagicnumber( file );
- switch ( PPM_FORMAT_TYPE(*formatP) )
- {
- case PPM_TYPE:
- ppm_readppminitrest( file, colsP, rowsP, maxvalP );
- break;
-
- case PGM_TYPE:
- pgm_readpgminitrest( file, colsP, rowsP, maxvalP );
- break;
-
- case PBM_TYPE:
- pbm_readpbminitrest( file, colsP, rowsP );
- *maxvalP = ppm_pbmmaxval;
- break;
-
- default:
- pm_error( "bad magic number - not a ppm, pgm, or pbm file\n" );
- }
- }
-
-
- char pbm_getc(FILE *file)
- {
- register int ich;
- register char ch;
-
- ich = getc( file );
- if ( ich == EOF )
- pm_error( "EOF / read error\n" );
- ch = (char) ich;
-
- if ( ch == '#' )
- {
- do
- {
- ich = getc( file );
- if ( ich == EOF )
- pm_error( "EOF / read error\n" );
- ch = (char) ich;
- }
- while ( ch != '\n' && ch != '\r' );
- }
-
- return ch;
- }
-
- unsigned char pbm_getrawbyte(FILE *file)
- {
- register int iby;
-
- iby = getc( file );
- if ( iby == EOF )
- pm_error( "EOF / read error\n" );
- return (unsigned char) iby;
- }
-
- int pbm_getint(FILE *file)
- {
- register char ch;
- register int i;
-
- do
- {
- ch = pbm_getc( file );
- }
- while ( ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' );
-
- if ( ch < '0' || ch > '9' )
- pm_error( "junk in file where an integer should be\n" );
-
- i = 0;
- do
- {
- i = i * 10 + ch - '0';
- ch = pbm_getc( file );
- }
- while ( ch >= '0' && ch <= '9' );
-
- return i;
- }
-
- int pbm_readmagicnumber(FILE *file)
- {
- int ich1, ich2;
-
- ich1 = getc( file );
- if ( ich1 == EOF )
- pm_error( "EOF / read error reading magic number\n" );
- ich2 = getc( file );
- if ( ich2 == EOF )
- pm_error( "EOF / read error reading magic number\n" );
- return ich1 * 256 + ich2;
- }
-
-
- void pbm_readpbminitrest(FILE *file, int *colsP, int *rowsP )
- {
- /* Read size. */
- *colsP = pbm_getint( file );
- *rowsP = pbm_getint( file );
- }
-
- void pgm_readpgminitrest(FILE *file, int *colsP, int *rowsP, gray *maxvalP)
- {
- int maxval;
-
- /* Read size. */
- *colsP = pbm_getint( file );
- *rowsP = pbm_getint( file );
-
- /* Read maxval. */
- maxval = pbm_getint( file );
- if ( maxval > PGM_MAXMAXVAL )
- pm_error( "maxval is too large - try reconfiguring with PGM_BIGGRAYS\n" );
- *maxvalP = maxval;
- }
-
- /* Variable-sized arrays. */
-
- char*
- pm_allocrow( cols, size )
- int cols;
- int size;
- {
- register char* itrow;
-
- itrow = (char*) malloc( cols * size );
- if ( itrow == (char*) 0 )
- pm_error( "out of memory allocating a row\n" );
- return itrow;
- }
-
- void
- pm_freerow( itrow )
- char* itrow;
- {
- free( itrow );
- }
-
- char**
- pm_allocarray( cols, rows, size )
- int cols, rows;
- int size;
- {
- char** its;
- int i;
- its = (char**) malloc( (rows + 1) * sizeof(char*) );
- if ( its == (char**) 0 )
- pm_error( "out of memory allocating an array\n" );
-
- /* initialize the array, modified by Günther Röhrich */
- /* this is needed for using pm_freearray() even if the array */
- /* is not completely allocated */
-
- memset((void *)its, 0, (rows + 1) * sizeof(char*));
-
- its[rows] = its[0] = (char*) malloc( rows * cols * size );
- if ( its[0] != (char*) 0 )
- for ( i = 1; i < rows; ++i )
- its[i] = &(its[0][i * cols * size]);
- else
- for( i = 0; i < rows; ++i )
- {
- /* modified by Günther Röhrich */
- if(!(its[i] = (char*) malloc( cols * size )))
- {
- pm_freearray(its, rows);
- its = NULL;
- break;
- }
- }
- return its;
- }
-
- void
- pm_freearray( its, rows )
- char** its;
- int rows;
- {
- int i;
- if( its[rows] != (char*) 0 )
- free( its[rows] );
- else
- for( i = 0; i < rows; ++i )
- pm_freerow( its[i] );
- free( its );
- }
-
- void ppm_readppmrow(FILE* file, pixel* pixelrow, int cols, pixval maxval, int format)
- {
- register int col;
- register pixel* pP;
- register pixval r, g, b;
- gray* grayrow;
- register gray* gP;
- bit* bitrow;
- register bit* bP;
-
- switch ( format )
- {
- case PPM_FORMAT:
-
- for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
- {
- r = pbm_getint( file );
- #ifdef DEBUG
- if ( r > maxval )
- pm_error( "r value out of bounds (%u > %u)\n", r, maxval );
- #endif /*DEBUG*/
- g = pbm_getint( file );
- #ifdef DEBUG
- if ( g > maxval )
- pm_error( "g value out of bounds (%u > %u)\n", g, maxval );
- #endif /*DEBUG*/
- b = pbm_getint( file );
- #ifdef DEBUG
- if ( b > maxval )
- pm_error( "b value out of bounds (%u > %u)\n", b, maxval );
- #endif /*DEBUG*/
- PPM_ASSIGN( *pP, r, g, b );
- }
- if(Convert4096 || Convert262144) FSrow(pixelrow, cols);
- break;
-
- case RPPM_FORMAT:
- for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
- {
- r = pbm_getrawbyte( file );
- #ifdef DEBUG
- if ( r > maxval )
- pm_error( "r value out of bounds (%u > %u)\n", r, maxval );
- #endif /*DEBUG*/
- g = pbm_getrawbyte( file );
- #ifdef DEBUG
- if ( g > maxval )
- pm_error( "g value out of bounds (%u > %u)\n", g, maxval );
- #endif /*DEBUG*/
- b = pbm_getrawbyte( file );
- #ifdef DEBUG
- if ( b > maxval )
- pm_error( "b value out of bounds (%u > %u)\n", b, maxval );
- #endif /*DEBUG*/
- PPM_ASSIGN( *pP, r, g, b );
- }
- if(Convert4096 || Convert262144) FSrow(pixelrow, cols);
- break;
-
- case PGM_FORMAT:
- case RPGM_FORMAT:
- grayrow = pgm_allocrow( cols );
- pgm_readpgmrow( file, grayrow, cols, maxval, format );
- for ( col = 0, gP = grayrow, pP = pixelrow; col < cols; ++col, ++gP, ++pP )
- {
- r = *gP;
- PPM_ASSIGN( *pP, r, r, r );
- }
- pgm_freerow( grayrow );
- break;
-
- case PBM_FORMAT:
- case RPBM_FORMAT:
- bitrow = pbm_allocrow( cols );
- pbm_readpbmrow( file, bitrow, cols, format );
- for ( col = 0, bP = bitrow, pP = pixelrow; col < cols; ++col, ++bP, ++pP )
- {
- r = ( *bP == PBM_WHITE ) ? maxval : 0;
- PPM_ASSIGN( *pP, r, r, r );
- }
- pbm_freerow( bitrow );
- break;
-
- default:
- pm_error( "can't happen\n" );
- }
- }
-
-
- /* converts one row from 16M colors to 4096/262144 colors using FS dithering */
-
- void FSrow(pixel *pixelrow, int cols)
- {
-
- /* if floyd is nonzero we will use Floyd-Steinberg dithering */
- register int col, limitcol;
- register long sg, sr, sb, err;
- long *temperr;
- register pixel *pP;
-
- for ( col = 0; col < cols + 2; ++col )
- nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
-
- if ( fs_direction )
- {
- col = 0;
- limitcol = cols;
- /* pP = pixels[row]; */
- pP = pixelrow;
- }
- else
- {
- col = cols - 1;
- limitcol = -1;
- /* pP = &(pixels[row][col]); */
- pP = &pixelrow[col];
- }
-
- do
- {
- /* Use Floyd-Steinberg errors to adjust actual color. */
- sr = PPM_GETR(*pP) + thisrerr[col + 1] / FS_SCALE;
- sg = PPM_GETG(*pP) + thisgerr[col + 1] / FS_SCALE;
- sb = PPM_GETB(*pP) + thisberr[col + 1] / FS_SCALE;
- if ( sr < 0 ) sr = 0;
- else if ( sr > maxval ) sr = maxval;
- if ( sg < 0 ) sg = 0;
- else if ( sg > maxval ) sg = maxval;
- if ( sb < 0 ) sb = 0;
- else if ( sb > maxval ) sb = maxval;
- /* PPM_ASSIGN( *pP, sr, sg, sb ); */
- if(Convert4096)
- PPM_ASSIGN(*pP, sr&0xF0, sg&0xF0, sb&0xF0);
- else
- PPM_ASSIGN(*pP, sr&0xFC, sg&0xFC, sb&0xFC);
-
- /* Propagate Floyd-Steinberg error terms. */
- if ( fs_direction )
- {
- err = ( sr - (long) PPM_GETR(*pP) ) * FS_SCALE;
- thisrerr[col + 2] += ( err * 7 ) / 16;
- nextrerr[col ] += ( err * 3 ) / 16;
- nextrerr[col + 1] += ( err * 5 ) / 16;
- nextrerr[col + 2] += ( err ) / 16;
- err = ( sg - (long) PPM_GETG(*pP) ) * FS_SCALE;
- thisgerr[col + 2] += ( err * 7 ) / 16;
- nextgerr[col ] += ( err * 3 ) / 16;
- nextgerr[col + 1] += ( err * 5 ) / 16;
- nextgerr[col + 2] += ( err ) / 16;
- err = ( sb - (long) PPM_GETB(*pP) ) * FS_SCALE;
- thisberr[col + 2] += ( err * 7 ) / 16;
- nextberr[col ] += ( err * 3 ) / 16;
- nextberr[col + 1] += ( err * 5 ) / 16;
- nextberr[col + 2] += ( err ) / 16;
- }
- else
- {
- err = ( sr - (long) PPM_GETR(*pP) ) * FS_SCALE;
- thisrerr[col ] += ( err * 7 ) / 16;
- nextrerr[col + 2] += ( err * 3 ) / 16;
- nextrerr[col + 1] += ( err * 5 ) / 16;
- nextrerr[col ] += ( err ) / 16;
- err = ( sg - (long) PPM_GETG(*pP) ) * FS_SCALE;
- thisgerr[col ] += ( err * 7 ) / 16;
- nextgerr[col + 2] += ( err * 3 ) / 16;
- nextgerr[col + 1] += ( err * 5 ) / 16;
- nextgerr[col ] += ( err ) / 16;
- err = ( sb - (long) PPM_GETB(*pP) ) * FS_SCALE;
- thisberr[col ] += ( err * 7 ) / 16;
- nextberr[col + 2] += ( err * 3 ) / 16;
- nextberr[col + 1] += ( err * 5 ) / 16;
- nextberr[col ] += ( err ) / 16;
- }
-
- if ( fs_direction )
- {
- ++col;
- ++pP;
- }
- else
- {
- --col;
- --pP;
- }
- } while ( col != limitcol );
-
- temperr = thisrerr;
- thisrerr = nextrerr;
- nextrerr = temperr;
- temperr = thisgerr;
- thisgerr = nextgerr;
- nextgerr = temperr;
- temperr = thisberr;
- thisberr = nextberr;
- nextberr = temperr;
- fs_direction = ! fs_direction;
- }
-
-
-
-
- void pgm_readpgmrow(FILE* file, gray* grayrow, int cols, gray maxval, int format)
- {
- register int col;
- register gray* gP;
- bit* bitrow;
- register bit* bP;
-
- switch ( format )
- {
- case PGM_FORMAT:
- for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
- {
- *gP = pbm_getint( file );
- #ifdef DEBUG
- if ( *gP > maxval )
- pm_error( "value out of bounds (%u > %u)\n", *gP, maxval );
- #endif /*DEBUG*/
- }
- break;
-
- case RPGM_FORMAT:
- for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
- {
- *gP = pbm_getrawbyte( file );
- #ifdef DEBUG
- if ( *gP > maxval )
- pm_error( "value out of bounds (%u > %u)\n", *gP, maxval );
- #endif /*DEBUG*/
- }
- break;
-
- case PBM_FORMAT:
- case RPBM_FORMAT:
- bitrow = pbm_allocrow( cols );
- pbm_readpbmrow( file, bitrow, cols, format );
- for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
- *gP = ( *bP == PBM_WHITE ) ? maxval : 0;
- pbm_freerow( bitrow );
- break;
-
- default:
- pm_error( "can't happen\n" );
- }
- }
-
- void pbm_readpbmrow(FILE *file, bit *bitrow, int cols, int format )
- {
- register int col, bitshift;
- register unsigned char item;
- register bit* bP;
-
- switch ( format )
- {
- case PBM_FORMAT:
- for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
- *bP = pbm_getbit( file );
- break;
-
- case RPBM_FORMAT:
- bitshift = -1;
- for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
- {
- if ( bitshift == -1 )
- {
- item = pbm_getrawbyte( file );
- bitshift = 7;
- }
- *bP = ( item >> bitshift ) & 1;
- --bitshift;
- }
- break;
-
- default:
- pm_error( "can't happen\n" );
- }
- }
-
- static bit pbm_getbit(FILE *file )
- {
- register char ch;
-
- do
- {
- ch = pbm_getc( file );
- }
- while ( ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' );
-
- if ( ch != '0' && ch != '1' )
- pm_error( "junk in file where bits should be\n" );
-
- return ( ch == '1' ) ? 1 : 0;
- }
-
-
- pixel *next_pixrow(FILE *fp, int row, int ColorShift)
- {
- int i;
- pixel *pP;
-
- if( pixels )
- pixrow = pixels[row];
- else {
- if( row != rowcnt )
- pm_error("big mistake\n");
- rowcnt++;
- ppm_readppmrow(fp, pixrow, cols, maxval, ppmformat);
- if(maxval == 255)
- {
- for(i=0,pP=pixrow; i<cols; i++,pP++)
- {
- pP->r = pP->r >> ColorShift;
- pP->g = pP->g >> ColorShift;
- pP->b = pP->b >> ColorShift;
- }
- }
- else
- {
- for(i=0,pP=pixrow; i<cols; i++,pP++) PPM_DEPTH(*pP, *pP, maxval, ColorRegMax);
- }
- }
- return pixrow;
- }
-