00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #define pm_error(x) exit(1)
00014
00015
00016 #if defined(SVR2) || defined(SVR3) || defined(SVR4)
00017 #define SYSV
00018 #endif
00019 #if ! ( defined(BSD) || defined(SYSV) || defined(MSDOS) )
00020
00021
00022
00023
00024
00025 #define BSD
00026
00027
00028 #endif
00029
00030 #include <stdio.h>
00031 #include "libpnmrw.h"
00032
00033
00034 #include <string.h>
00035 #define rindex(s,c) strrchr(s,c)
00036
00037
00038
00039
00040 #define pbm_allocarray( cols, rows ) ((bit**) pm_allocarray( cols, rows, sizeof(bit) ))
00041 #define pbm_allocrow( cols ) ((bit*) pm_allocrow( cols, sizeof(bit) ))
00042 #define pbm_freearray( bits, rows ) pm_freearray( (char**) bits, rows )
00043 #define pbm_freerow( bitrow ) pm_freerow( (char*) bitrow )
00044 #define pgm_allocarray( cols, rows ) ((gray**) pm_allocarray( cols, rows, sizeof(gray) ))
00045 #define pgm_allocrow( cols ) ((gray*) pm_allocrow( cols, sizeof(gray) ))
00046 #define pgm_freearray( grays, rows ) pm_freearray( (char**) grays, rows )
00047 #define pgm_freerow( grayrow ) pm_freerow( (char*) grayrow )
00048 #define ppm_allocarray( cols, rows ) ((pixel**) pm_allocarray( cols, rows, sizeof(pixel) ))
00049 #define ppm_allocrow( cols ) ((pixel*) pm_allocrow( cols, sizeof(pixel) ))
00050 #define ppm_freearray( pixels, rows ) pm_freearray( (char**) pixels, rows )
00051 #define ppm_freerow( pixelrow ) pm_freerow( (char*) pixelrow )
00052
00053
00054
00055
00056 static char* progname;
00057
00058
00059
00060
00061 char*
00062 pm_allocrow( cols, size )
00063 int cols;
00064 int size;
00065 {
00066 register char* itrow;
00067
00068 itrow = (char*) malloc( cols * size );
00069 if ( itrow == (char*) 0 )
00070 {
00071 (void) fprintf(
00072 stderr, "%s: out of memory allocating a row\n", progname );
00073 return (char*) 0;
00074 }
00075 return itrow;
00076 }
00077
00078 void
00079 pm_freerow( itrow )
00080 char* itrow;
00081 {
00082 free( itrow );
00083 }
00084
00085 char**
00086 pm_allocarray( cols, rows, size )
00087 int cols, rows;
00088 int size;
00089 {
00090 char** its;
00091 int i;
00092
00093 its = (char**) malloc( rows * sizeof(char*) );
00094 if ( its == (char**) 0 )
00095 {
00096 (void) fprintf(
00097 stderr, "%s: out of memory allocating an array\n", progname );
00098 return (char**) 0;
00099 }
00100 its[0] = (char*) malloc( rows * cols * size );
00101 if ( its[0] == (char*) 0 )
00102 {
00103 (void) fprintf(
00104 stderr, "%s: out of memory allocating an array\n", progname );
00105 free( (char*) its );
00106 return (char**) 0;
00107 }
00108 for ( i = 1; i < rows; ++i )
00109 its[i] = &(its[0][i * cols * size]);
00110 return its;
00111 }
00112
00113 void
00114 pm_freearray( its, rows )
00115 char** its;
00116 int rows;
00117 {
00118 free( its[0] );
00119 free( its );
00120 }
00121
00122
00123
00124
00125 static void
00126 pm_perror( reason )
00127 char* reason;
00128 {
00129 #if 0
00130 extern char* sys_errlist[];
00131 extern int errno;
00132 char* e;
00133
00134 e = sys_errlist[errno];
00135
00136 if ( reason != 0 && reason[0] != '\0' )
00137 (void) fprintf( stderr, "%s: %s - %s\n", progname, reason, e );
00138 else
00139 (void) fprintf( stderr, "%s: %s\n", progname, e );
00140 #else
00141 (void) fprintf(stderr,"%s: %s\n" , progname ,
00142 (reason != 0 && reason[0] != '\0') ? reason
00143 : "Unnamed Error" ) ;
00144 #endif
00145 }
00146
00147 FILE*
00148 pm_openr( name )
00149 char* name;
00150 {
00151 FILE* f;
00152
00153 if ( strcmp( name, "-" ) == 0 )
00154 f = stdin;
00155 else
00156 {
00157 f = fopen( name, "rb" );
00158 if ( f == NULL )
00159 {
00160 pm_perror( name );
00161 return (FILE*) 0;
00162 }
00163 }
00164 return f;
00165 }
00166
00167 FILE*
00168 pm_openw( name )
00169 char* name;
00170 {
00171 FILE* f;
00172
00173 f = fopen( name, "wb" );
00174 if ( f == NULL ) {
00175 pm_perror( name );
00176 return (FILE*) 0;
00177 }
00178 return f;
00179 }
00180
00181 int
00182 pm_closer( f )
00183 FILE* f;
00184 {
00185 if ( ferror( f ) )
00186 {
00187 (void) fprintf(
00188 stderr, "%s: a file read error occurred at some point\n",
00189 progname );
00190 return -1;
00191 }
00192 if ( f != stdin )
00193 if ( fclose( f ) != 0 )
00194 {
00195 pm_perror( "fclose" );
00196 return -1;
00197 }
00198 return 0;
00199 }
00200
00201 int
00202 pm_closew( f )
00203 FILE* f;
00204 {
00205 fflush( f );
00206 if ( ferror( f ) )
00207 {
00208 (void) fprintf(
00209 stderr, "%s: a file write error occurred at some point\n",
00210 progname );
00211 return -1;
00212 }
00213 if ( f != stdout )
00214 if ( fclose( f ) != 0 )
00215 {
00216 pm_perror( "fclose" );
00217 return -1;
00218 }
00219 return 0;
00220 }
00221
00222 static int
00223 pbm_getc( file )
00224 FILE* file;
00225 {
00226 register int ich;
00227
00228 ich = getc( file );
00229 if ( ich == EOF )
00230 {
00231 (void) fprintf( stderr, "%s: EOF / read error\n", progname );
00232 return EOF;
00233 }
00234
00235 if ( ich == '#' )
00236 {
00237 do
00238 {
00239 ich = getc( file );
00240 if ( ich == EOF )
00241 {
00242 (void) fprintf( stderr, "%s: EOF / read error\n", progname );
00243 return EOF;
00244 }
00245 }
00246 while ( ich != '\n' && ich != '\r' );
00247 }
00248
00249 return ich;
00250 }
00251
00252 static bit
00253 pbm_getbit( file )
00254 FILE* file;
00255 {
00256 register int ich;
00257
00258 do
00259 {
00260 ich = pbm_getc( file );
00261 if ( ich == EOF )
00262 return -1;
00263 }
00264 while ( ich == ' ' || ich == '\t' || ich == '\n' || ich == '\r' );
00265
00266 if ( ich != '0' && ich != '1' )
00267 {
00268 (void) fprintf(
00269 stderr, "%s: junk in file where bits should be\n", progname );
00270 return -1;
00271 }
00272
00273 return ( ich == '1' ) ? 1 : 0;
00274 }
00275
00276 static int
00277 pbm_readmagicnumber( file )
00278 FILE* file;
00279 {
00280 int ich1, ich2;
00281
00282 ich1 = getc( file );
00283 if ( ich1 == EOF )
00284 {
00285 (void) fprintf(
00286 stderr, "%s: EOF / read error reading magic number\n", progname );
00287 return -1;
00288 }
00289 ich2 = getc( file );
00290 if ( ich2 == EOF )
00291 {
00292 (void) fprintf(
00293 stderr, "%s: EOF / read error reading magic number\n", progname );
00294 return -1;
00295 }
00296 return ich1 * 256 + ich2;
00297 }
00298
00299 static int
00300 pbm_getint( file )
00301 FILE* file;
00302 {
00303 register int ich;
00304 register int i;
00305
00306 do
00307 {
00308 ich = pbm_getc( file );
00309 if ( ich == EOF )
00310 return -1;
00311 }
00312 while ( ich == ' ' || ich == '\t' || ich == '\n' || ich == '\r' );
00313
00314 if ( ich < '0' || ich > '9' )
00315 {
00316 (void) fprintf(
00317 stderr, "%s: junk in file where an integer should be\n", progname );
00318 return -1;
00319 }
00320
00321 i = 0;
00322 do
00323 {
00324 i = i * 10 + ich - '0';
00325 ich = pbm_getc( file );
00326 if ( ich == EOF )
00327 return -1;
00328 }
00329 while ( ich >= '0' && ich <= '9' );
00330
00331 return i;
00332 }
00333
00334 static int
00335 pbm_readpbminitrest( file, colsP, rowsP )
00336 FILE* file;
00337 int* colsP;
00338 int* rowsP;
00339 {
00340
00341 *colsP = pbm_getint( file );
00342 *rowsP = pbm_getint( file );
00343 if ( *colsP == -1 || *rowsP == -1 )
00344 return -1;
00345 return 0;
00346 }
00347
00348 static int
00349 pbm_getrawbyte( file )
00350 FILE* file;
00351 {
00352 register int iby;
00353
00354 iby = getc( file );
00355 if ( iby == EOF )
00356 {
00357 (void) fprintf( stderr, "%s: EOF / read error\n", progname );
00358 return -1;
00359 }
00360 return iby;
00361 }
00362
00363 static int
00364 pbm_readpbmrow( file, bitrow, cols, format )
00365 FILE* file;
00366 bit* bitrow;
00367 int cols, format;
00368 {
00369 register int col, bitshift, b;
00370 register int item;
00371 register bit* bP;
00372
00373 switch ( format )
00374 {
00375 case PBM_FORMAT:
00376 for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
00377 {
00378 b = pbm_getbit( file );
00379 if ( b == -1 )
00380 return -1;
00381 *bP = b;
00382 }
00383 break;
00384
00385 case RPBM_FORMAT:
00386 bitshift = -1;
00387 for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
00388 {
00389 if ( bitshift == -1 )
00390 {
00391 item = pbm_getrawbyte( file );
00392 if ( item == -1 )
00393 return -1;
00394 bitshift = 7;
00395 }
00396 *bP = ( item >> bitshift ) & 1;
00397 --bitshift;
00398 }
00399 break;
00400
00401 default:
00402 (void) fprintf( stderr, "%s: can't happen\n", progname );
00403 return -1;
00404 }
00405 return 0;
00406 }
00407
00408 static void
00409 pbm_writepbminit( file, cols, rows, forceplain )
00410 FILE* file;
00411 int cols, rows;
00412 int forceplain;
00413 {
00414 if ( ! forceplain )
00415 (void) fprintf(
00416 file, "%c%c\n%d %d\n", PBM_MAGIC1, RPBM_MAGIC2, cols, rows );
00417 else
00418 (void) fprintf(
00419 file, "%c%c\n%d %d\n", PBM_MAGIC1, PBM_MAGIC2, cols, rows );
00420 }
00421
00422 static void
00423 pbm_writepbmrowraw( file, bitrow, cols )
00424 FILE* file;
00425 bit* bitrow;
00426 int cols;
00427 {
00428 register int col, bitshift;
00429 register unsigned char item;
00430 register bit* bP;
00431
00432 bitshift = 7;
00433 item = 0;
00434 for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
00435 {
00436 if ( *bP )
00437 item += 1 << bitshift;
00438 --bitshift;
00439 if ( bitshift == -1 )
00440 {
00441 (void) putc( item, file );
00442 bitshift = 7;
00443 item = 0;
00444 }
00445 }
00446 if ( bitshift != 7 )
00447 (void) putc( item, file );
00448 }
00449
00450 static void
00451 pbm_writepbmrowplain( file, bitrow, cols )
00452 FILE* file;
00453 bit* bitrow;
00454 int cols;
00455 {
00456 register int col, charcount;
00457 register bit* bP;
00458
00459 charcount = 0;
00460 for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
00461 {
00462 if ( charcount >= 70 )
00463 {
00464 (void) putc( '\n', file );
00465 charcount = 0;
00466 }
00467 putc( *bP ? '1' : '0', file );
00468 ++charcount;
00469 }
00470 (void) putc( '\n', file );
00471 }
00472
00473 static void
00474 pbm_writepbmrow( file, bitrow, cols, forceplain )
00475 FILE* file;
00476 bit* bitrow;
00477 int cols;
00478 int forceplain;
00479 {
00480 if ( ! forceplain )
00481 pbm_writepbmrowraw( file, bitrow, cols );
00482 else
00483 pbm_writepbmrowplain( file, bitrow, cols );
00484 }
00485
00486 static int
00487 pgm_readpgminitrest( file, colsP, rowsP, maxvalP )
00488 FILE* file;
00489 int* colsP;
00490 int* rowsP;
00491 gray* maxvalP;
00492 {
00493 int maxval;
00494
00495
00496 *colsP = pbm_getint( file );
00497 *rowsP = pbm_getint( file );
00498 if ( *colsP == -1 || *rowsP == -1 )
00499 return -1;
00500
00501
00502 maxval = pbm_getint( file );
00503 if ( maxval == -1 )
00504 return -1;
00505 if ( maxval > PGM_MAXMAXVAL )
00506 {
00507 (void) fprintf( stderr, "%s: maxval is too large\n", progname );
00508 return -1;
00509 }
00510 *maxvalP = maxval;
00511 return 0;
00512 }
00513
00514 #if __STDC__
00515 static int
00516 pgm_readpgmrow( FILE* file, gray* grayrow, int cols, gray maxval, int format )
00517 #else
00518 static int
00519 pgm_readpgmrow( file, grayrow, cols, maxval, format )
00520 FILE* file;
00521 gray* grayrow;
00522 int cols;
00523 gray maxval;
00524 int format;
00525 #endif
00526 {
00527 register int col, val;
00528 register gray* gP;
00529
00530
00531
00532
00533
00534 switch ( format )
00535 {
00536 case PGM_FORMAT:
00537 for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
00538 {
00539 val = pbm_getint( file );
00540 if ( val == -1 )
00541 return -1;
00542 *gP = val;
00543 }
00544 break;
00545
00546 case RPGM_FORMAT:
00547 if ( fread( grayrow, 1, cols, file ) != cols )
00548 {
00549 (void) fprintf( stderr, "%s: EOF / read error\n", progname );
00550 return -1;
00551 }
00552 break;
00553
00554 default:
00555 (void) fprintf( stderr, "%s: can't happen\n", progname );
00556 return -1;
00557 }
00558 return 0;
00559 }
00560
00561 #if __STDC__
00562 static void
00563 pgm_writepgminit( FILE* file, int cols, int rows, gray maxval, int forceplain )
00564 #else
00565 static void
00566 pgm_writepgminit( file, cols, rows, maxval, forceplain )
00567 FILE* file;
00568 int cols, rows;
00569 gray maxval;
00570 int forceplain;
00571 #endif
00572 {
00573 if ( maxval <= 255 && ! forceplain )
00574 fprintf(
00575 file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, RPGM_MAGIC2,
00576 cols, rows, maxval );
00577 else
00578 fprintf(
00579 file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, PGM_MAGIC2,
00580 cols, rows, maxval );
00581 }
00582
00583 static void
00584 putus( n, file )
00585 unsigned short n;
00586 FILE* file;
00587 {
00588 if ( n >= 10 )
00589 putus( n / 10, file );
00590 putc( n % 10 + '0', file );
00591 }
00592
00593 static int
00594 pgm_writepgmrowraw( file, grayrow, cols, maxval )
00595 FILE* file;
00596 gray* grayrow;
00597 int cols;
00598 gray maxval;
00599 {
00600 if ( fwrite( grayrow, 1, cols, file ) != cols )
00601 {
00602 (void) fprintf( stderr, "%s: write error\n", progname );
00603 return -1;
00604 }
00605 return 0;
00606 }
00607
00608 static int
00609 pgm_writepgmrowplain( file, grayrow, cols, maxval )
00610 FILE* file;
00611 gray* grayrow;
00612 int cols;
00613 gray maxval;
00614 {
00615 register int col, charcount;
00616 register gray* gP;
00617
00618 charcount = 0;
00619 for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
00620 {
00621 if ( charcount >= 65 )
00622 {
00623 (void) putc( '\n', file );
00624 charcount = 0;
00625 }
00626 else if ( charcount > 0 )
00627 {
00628 (void) putc( ' ', file );
00629 ++charcount;
00630 }
00631 putus( (unsigned short) *gP, file );
00632 charcount += 3;
00633 }
00634 if ( charcount > 0 )
00635 (void) putc( '\n', file );
00636 return 0;
00637 }
00638
00639 #if __STDC__
00640 static int
00641 pgm_writepgmrow( FILE* file, gray* grayrow, int cols, gray maxval, int forceplain )
00642 #else
00643 static int
00644 pgm_writepgmrow( file, grayrow, cols, maxval, forceplain )
00645 FILE* file;
00646 gray* grayrow;
00647 int cols;
00648 gray maxval;
00649 int forceplain;
00650 #endif
00651 {
00652 if ( maxval <= 255 && ! forceplain )
00653 return pgm_writepgmrowraw( file, grayrow, cols, maxval );
00654 else
00655 return pgm_writepgmrowplain( file, grayrow, cols, maxval );
00656 }
00657
00658 static int
00659 ppm_readppminitrest( file, colsP, rowsP, maxvalP )
00660 FILE* file;
00661 int* colsP;
00662 int* rowsP;
00663 pixval* maxvalP;
00664 {
00665 int maxval;
00666
00667
00668 *colsP = pbm_getint( file );
00669 *rowsP = pbm_getint( file );
00670 if ( *colsP == -1 || *rowsP == -1 )
00671 return -1;
00672
00673
00674 maxval = pbm_getint( file );
00675 if ( maxval == -1 )
00676 return -1;
00677 if ( maxval > PPM_MAXMAXVAL )
00678 {
00679 (void) fprintf( stderr, "%s: maxval is too large\n", progname );
00680 return -1;
00681 }
00682 *maxvalP = maxval;
00683 return 0;
00684 }
00685
00686 #if __STDC__
00687 static int
00688 ppm_readppmrow( FILE* file, pixel* pixelrow, int cols, pixval maxval, int format )
00689 #else
00690 static int
00691 ppm_readppmrow( file, pixelrow, cols, maxval, format )
00692 FILE* file;
00693 pixel* pixelrow;
00694 int cols, format;
00695 pixval maxval;
00696 #endif
00697 {
00698 register int col;
00699 register pixel* pP;
00700 register int r, g, b;
00701 gray* grayrow;
00702 register gray* gP;
00703
00704
00705
00706
00707
00708 switch ( format )
00709 {
00710 case PPM_FORMAT:
00711 for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
00712 {
00713 r = pbm_getint( file );
00714 g = pbm_getint( file );
00715 b = pbm_getint( file );
00716 if ( r == -1 || g == -1 || b == -1 )
00717 return -1;
00718 PPM_ASSIGN( *pP, r, g, b );
00719 }
00720 break;
00721
00722 case RPPM_FORMAT:
00723 grayrow = pgm_allocrow( 3 * cols );
00724 if ( grayrow == (gray*) 0 )
00725 return -1;
00726 if ( fread( grayrow, 1, 3 * cols, file ) != 3 * cols )
00727 {
00728 (void) fprintf( stderr, "%s: EOF / read error\n", progname );
00729 return -1;
00730 }
00731 for ( col = 0, gP = grayrow, pP = pixelrow; col < cols; ++col, ++pP )
00732 {
00733 r = *gP++;
00734 g = *gP++;
00735 b = *gP++;
00736 PPM_ASSIGN( *pP, r, g, b );
00737 }
00738 pgm_freerow( grayrow );
00739 break;
00740
00741 default:
00742 (void) fprintf( stderr, "%s: can't happen\n", progname );
00743 return -1;
00744 }
00745 return 0;
00746 }
00747
00748 #if __STDC__
00749 static void
00750 ppm_writeppminit( FILE* file, int cols, int rows, pixval maxval, int forceplain )
00751 #else
00752 static void
00753 ppm_writeppminit( file, cols, rows, maxval, forceplain )
00754 FILE* file;
00755 int cols, rows;
00756 pixval maxval;
00757 int forceplain;
00758 #endif
00759 {
00760 if ( maxval <= 255 && ! forceplain )
00761 fprintf(
00762 file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, RPPM_MAGIC2,
00763 cols, rows, maxval );
00764 else
00765 fprintf(
00766 file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, PPM_MAGIC2,
00767 cols, rows, maxval );
00768 }
00769
00770 static int
00771 ppm_writeppmrowraw( file, pixelrow, cols, maxval )
00772 FILE* file;
00773 pixel* pixelrow;
00774 int cols;
00775 pixval maxval;
00776 {
00777 register int col;
00778 register pixel* pP;
00779 gray* grayrow;
00780 register gray* gP;
00781
00782 grayrow = pgm_allocrow( 3 * cols );
00783 if ( grayrow == (gray*) 0 )
00784 return -1;
00785 for ( col = 0, pP = pixelrow, gP = grayrow; col < cols; ++col, ++pP )
00786 {
00787 *gP++ = PPM_GETR( *pP );
00788 *gP++ = PPM_GETG( *pP );
00789 *gP++ = PPM_GETB( *pP );
00790 }
00791 if ( fwrite( grayrow, 1, 3 * cols, file ) != 3 * cols )
00792 {
00793 (void) fprintf( stderr, "%s: write error\n", progname );
00794 return -1;
00795 }
00796 pgm_freerow( grayrow );
00797 return 0;
00798 }
00799
00800 static int
00801 ppm_writeppmrowplain( file, pixelrow, cols, maxval )
00802 FILE* file;
00803 pixel* pixelrow;
00804 int cols;
00805 pixval maxval;
00806 {
00807 register int col, charcount;
00808 register pixel* pP;
00809 register pixval val;
00810
00811 charcount = 0;
00812 for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
00813 {
00814 if ( charcount >= 65 )
00815 {
00816 (void) putc( '\n', file );
00817 charcount = 0;
00818 }
00819 else if ( charcount > 0 )
00820 {
00821 (void) putc( ' ', file );
00822 (void) putc( ' ', file );
00823 charcount += 2;
00824 }
00825 val = PPM_GETR( *pP );
00826 putus( val, file );
00827 (void) putc( ' ', file );
00828 val = PPM_GETG( *pP );
00829 putus( val, file );
00830 (void) putc( ' ', file );
00831 val = PPM_GETB( *pP );
00832 putus( val, file );
00833 charcount += 11;
00834 }
00835 if ( charcount > 0 )
00836 (void) putc( '\n', file );
00837 return 0;
00838 }
00839
00840 #if __STDC__
00841 static int
00842 ppm_writeppmrow( FILE* file, pixel* pixelrow, int cols, pixval maxval, int forceplain )
00843 #else
00844 static int
00845 ppm_writeppmrow( file, pixelrow, cols, maxval, forceplain )
00846 FILE* file;
00847 pixel* pixelrow;
00848 int cols;
00849 pixval maxval;
00850 int forceplain;
00851 #endif
00852 {
00853 if ( maxval <= 255 && ! forceplain )
00854 return ppm_writeppmrowraw( file, pixelrow, cols, maxval );
00855 else
00856 return ppm_writeppmrowplain( file, pixelrow, cols, maxval );
00857 }
00858
00859 void
00860 pnm_init2( pn )
00861 char* pn;
00862 {
00863
00864 progname = pn;
00865 }
00866
00867 xelval pnm_pbmmaxval = 1;
00868
00869 int
00870 pnm_readpnminit( file, colsP, rowsP, maxvalP, formatP )
00871 FILE* file;
00872 int* colsP;
00873 int* rowsP;
00874 int* formatP;
00875 xelval* maxvalP;
00876 {
00877 gray gmaxval;
00878
00879
00880 *formatP = pbm_readmagicnumber( file );
00881 if ( *formatP == -1 )
00882 return -1;
00883 switch ( PNM_FORMAT_TYPE(*formatP) )
00884 {
00885 case PPM_TYPE:
00886 if ( ppm_readppminitrest( file, colsP, rowsP, (pixval*) maxvalP ) < 0 )
00887 return -1;
00888 break;
00889
00890 case PGM_TYPE:
00891 if ( pgm_readpgminitrest( file, colsP, rowsP, &gmaxval ) < 0 )
00892 return -1;
00893 *maxvalP = (xelval) gmaxval;
00894 break;
00895
00896 case PBM_TYPE:
00897 if ( pbm_readpbminitrest( file, colsP, rowsP ) < 0 )
00898 return -1;
00899 *maxvalP = pnm_pbmmaxval;
00900 break;
00901
00902 default:
00903 (void) fprintf(
00904 stderr, "%s: bad magic number - not a ppm, pgm, or pbm file\n",
00905 progname );
00906 return -1;
00907 }
00908 return 0;
00909 }
00910
00911 #if __STDC__
00912 int
00913 pnm_readpnmrow( FILE* file, xel* xelrow, int cols, xelval maxval, int format )
00914 #else
00915 int
00916 pnm_readpnmrow( file, xelrow, cols, maxval, format )
00917 FILE* file;
00918 xel* xelrow;
00919 xelval maxval;
00920 int cols, format;
00921 #endif
00922 {
00923 register int col;
00924 register xel* xP;
00925 gray* grayrow;
00926 register gray* gP;
00927 bit* bitrow;
00928 register bit* bP;
00929
00930 switch ( PNM_FORMAT_TYPE(format) )
00931 {
00932 case PPM_TYPE:
00933 if ( ppm_readppmrow( file, (pixel*) xelrow, cols, (pixval) maxval, format ) < 0 )
00934 return -1;
00935 break;
00936
00937 case PGM_TYPE:
00938 grayrow = pgm_allocrow( cols );
00939 if ( grayrow == (gray*) 0 )
00940 return -1;
00941 if ( pgm_readpgmrow( file, grayrow, cols, (gray) maxval, format ) < 0 )
00942 return -1;
00943 for ( col = 0, xP = xelrow, gP = grayrow; col < cols; ++col, ++xP, ++gP )
00944 PNM_ASSIGN1( *xP, *gP );
00945 pgm_freerow( grayrow );
00946 break;
00947
00948 case PBM_TYPE:
00949 bitrow = pbm_allocrow( cols );
00950 if ( bitrow == (bit*) 0 )
00951 return -1;
00952 if ( pbm_readpbmrow( file, bitrow, cols, format ) < 0 )
00953 {
00954 pbm_freerow( bitrow );
00955 return -1;
00956 }
00957 for ( col = 0, xP = xelrow, bP = bitrow; col < cols; ++col, ++xP, ++bP )
00958 PNM_ASSIGN1( *xP, *bP == PBM_BLACK ? 0: pnm_pbmmaxval );
00959 pbm_freerow( bitrow );
00960 break;
00961
00962 default:
00963 (void) fprintf( stderr, "%s: can't happen\n", progname );
00964 return -1;
00965 }
00966 return 0;
00967 }
00968
00969 xel**
00970 pnm_readpnm( file, colsP, rowsP, maxvalP, formatP )
00971 FILE* file;
00972 int* colsP;
00973 int* rowsP;
00974 int* formatP;
00975 xelval* maxvalP;
00976 {
00977 xel** xels;
00978 int row;
00979
00980 if ( pnm_readpnminit( file, colsP, rowsP, maxvalP, formatP ) < 0 )
00981 return (xel**) 0;
00982
00983 xels = pnm_allocarray( *colsP, *rowsP );
00984 if ( xels == (xel**) 0 )
00985 return (xel**) 0;
00986
00987 for ( row = 0; row < *rowsP; ++row )
00988 if ( pnm_readpnmrow( file, xels[row], *colsP, *maxvalP, *formatP ) < 0 )
00989 {
00990 pnm_freearray( xels, *rowsP );
00991 return (xel**) 0;
00992 }
00993
00994 return xels;
00995 }
00996
00997 #if __STDC__
00998 int
00999 pnm_writepnminit( FILE* file, int cols, int rows, xelval maxval, int format, int forceplain )
01000 #else
01001 int
01002 pnm_writepnminit( file, cols, rows, maxval, format, forceplain )
01003 FILE* file;
01004 int cols, rows, format;
01005 xelval maxval;
01006 int forceplain;
01007 #endif
01008 {
01009 switch ( PNM_FORMAT_TYPE(format) )
01010 {
01011 case PPM_TYPE:
01012 ppm_writeppminit( file, cols, rows, (pixval) maxval, forceplain );
01013 break;
01014
01015 case PGM_TYPE:
01016 pgm_writepgminit( file, cols, rows, (gray) maxval, forceplain );
01017 break;
01018
01019 case PBM_TYPE:
01020 pbm_writepbminit( file, cols, rows, forceplain );
01021 break;
01022
01023 default:
01024 (void) fprintf( stderr, "%s: can't happen\n", progname );
01025 return -1;
01026 }
01027 return 0;
01028 }
01029
01030 #if __STDC__
01031 int
01032 pnm_writepnmrow( FILE* file, xel* xelrow, int cols, xelval maxval, int format, int forceplain )
01033 #else
01034 int
01035 pnm_writepnmrow( file, xelrow, cols, maxval, format, forceplain )
01036 FILE* file;
01037 xel* xelrow;
01038 int cols, format;
01039 xelval maxval;
01040 int forceplain;
01041 #endif
01042 {
01043 register int col;
01044 register xel* xP;
01045 gray* grayrow;
01046 register gray* gP;
01047 bit* bitrow;
01048 register bit* bP;
01049
01050 switch ( PNM_FORMAT_TYPE(format) )
01051 {
01052 case PPM_TYPE:
01053 if ( ppm_writeppmrow( file, (pixel*) xelrow, cols, (pixval) maxval, forceplain ) < 0 )
01054 return -1;
01055 break;
01056
01057 case PGM_TYPE:
01058 grayrow = pgm_allocrow( cols );
01059 if ( grayrow == (gray*) 0 )
01060 return -1;
01061 for ( col = 0, gP = grayrow, xP = xelrow; col < cols; ++col, ++gP, ++xP )
01062 *gP = PNM_GET1( *xP );
01063 if ( pgm_writepgmrow( file, grayrow, cols, (gray) maxval, forceplain ) < 0 )
01064 {
01065 pgm_freerow( grayrow );
01066 return -1;
01067 }
01068 pgm_freerow( grayrow );
01069 break;
01070
01071 case PBM_TYPE:
01072 bitrow = pbm_allocrow( cols );
01073 if ( bitrow == (bit*) 0 )
01074 return -1;
01075 for ( col = 0, bP = bitrow, xP = xelrow; col < cols; ++col, ++bP, ++xP )
01076 *bP = PNM_GET1( *xP ) == 0 ? PBM_BLACK : PBM_WHITE;
01077 pbm_writepbmrow( file, bitrow, cols, forceplain );
01078 pbm_freerow( bitrow );
01079 break;
01080
01081 default:
01082 (void) fprintf( stderr, "%s: can't happen\n", progname );
01083 return -1;
01084 }
01085 return 0;
01086 }
01087
01088 #if __STDC__
01089 int
01090 pnm_writepnm( FILE* file, xel** xels, int cols, int rows, xelval maxval, int format, int forceplain )
01091 #else
01092 int
01093 pnm_writepnm( file, xels, cols, rows, maxval, format, forceplain )
01094 FILE* file;
01095 xel** xels;
01096 xelval maxval;
01097 int cols, rows, format;
01098 int forceplain;
01099 #endif
01100 {
01101 int row;
01102
01103 if ( pnm_writepnminit( file, cols, rows, maxval, format, forceplain ) < 0 )
01104 return -1;
01105
01106 for ( row = 0; row < rows; ++row )
01107 if ( pnm_writepnmrow( file, xels[row], cols, maxval, format, forceplain ) < 0 )
01108 return -1;
01109 return 0;
01110 }
01111
01112
01113
01114
01115 #define HASH_SIZE 20023
01116
01117 #define ppm_hashpixel(p) ( ( ( (long) PPM_GETR(p) * 33023 + (long) PPM_GETG(p) * 30013 + (long) PPM_GETB(p) * 27011 ) & 0x7fffffff ) % HASH_SIZE )
01118
01119 colorhist_vector
01120 ppm_computecolorhist( pixels, cols, rows, maxcolors, colorsP )
01121 pixel** pixels;
01122 int cols, rows, maxcolors;
01123 int* colorsP;
01124 {
01125 colorhash_table cht;
01126 colorhist_vector chv;
01127
01128 cht = ppm_computecolorhash( pixels, cols, rows, maxcolors, colorsP );
01129 if ( cht == (colorhash_table) 0 )
01130 return (colorhist_vector) 0;
01131 chv = ppm_colorhashtocolorhist( cht, maxcolors );
01132 ppm_freecolorhash( cht );
01133 return chv;
01134 }
01135
01136 void
01137 ppm_addtocolorhist( chv, colorsP, maxcolors, colorP, value, position )
01138 colorhist_vector chv;
01139 pixel* colorP;
01140 int* colorsP;
01141 int maxcolors, value, position;
01142 {
01143 int i, j;
01144
01145
01146 for ( i = 0; i < *colorsP; ++i )
01147 if ( PPM_EQUAL( chv[i].color, *colorP ) )
01148 {
01149
01150 if ( position > i )
01151 {
01152 for ( j = i; j < position; ++j )
01153 chv[j] = chv[j + 1];
01154 }
01155 else if ( position < i )
01156 {
01157 for ( j = i; j > position; --j )
01158 chv[j] = chv[j - 1];
01159 }
01160 chv[position].color = *colorP;
01161 chv[position].value = value;
01162 return;
01163 }
01164 if ( *colorsP < maxcolors )
01165 {
01166
01167 for ( i = *colorsP; i > position; --i )
01168 chv[i] = chv[i - 1];
01169 chv[position].color = *colorP;
01170 chv[position].value = value;
01171 ++(*colorsP);
01172 }
01173 }
01174
01175 colorhash_table
01176 ppm_computecolorhash( pixels, cols, rows, maxcolors, colorsP )
01177 pixel** pixels;
01178 int cols, rows, maxcolors;
01179 int* colorsP;
01180 {
01181 colorhash_table cht;
01182 register pixel* pP;
01183 colorhist_list chl;
01184 int col, row, hash;
01185
01186 cht = ppm_alloccolorhash( );
01187 if ( cht == (colorhash_table) 0 )
01188 return (colorhash_table) 0;
01189 *colorsP = 0;
01190
01191
01192 for ( row = 0; row < rows; ++row )
01193 for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
01194 {
01195 hash = ppm_hashpixel( *pP );
01196 for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
01197 if ( PPM_EQUAL( chl->ch.color, *pP ) )
01198 break;
01199 if ( chl != (colorhist_list) 0 )
01200 ++(chl->ch.value);
01201 else
01202 {
01203 if ( ++(*colorsP) > maxcolors )
01204 {
01205 ppm_freecolorhash( cht );
01206 return (colorhash_table) 0;
01207 }
01208 chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
01209 if ( chl == 0 )
01210 {
01211 (void) fprintf(
01212 stderr, "%s: out of memory computing hash table\n",
01213 progname );
01214 ppm_freecolorhash( cht );
01215 return (colorhash_table) 0;
01216 }
01217 chl->ch.color = *pP;
01218 chl->ch.value = 1;
01219 chl->next = cht[hash];
01220 cht[hash] = chl;
01221 }
01222 }
01223
01224 return cht;
01225 }
01226
01227 colorhash_table
01228 ppm_alloccolorhash( )
01229 {
01230 colorhash_table cht;
01231 int i;
01232
01233 cht = (colorhash_table) malloc( HASH_SIZE * sizeof(colorhist_list) );
01234 if ( cht == 0 )
01235 {
01236 (void) fprintf(
01237 stderr, "%s: out of memory allocating hash table\n", progname );
01238 return (colorhash_table) 0;
01239 }
01240
01241 for ( i = 0; i < HASH_SIZE; ++i )
01242 cht[i] = (colorhist_list) 0;
01243
01244 return cht;
01245 }
01246
01247 int
01248 ppm_addtocolorhash( cht, colorP, value )
01249 colorhash_table cht;
01250 pixel* colorP;
01251 int value;
01252 {
01253 register int hash;
01254 register colorhist_list chl;
01255
01256 chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
01257 if ( chl == 0 )
01258 return -1;
01259 hash = ppm_hashpixel( *colorP );
01260 chl->ch.color = *colorP;
01261 chl->ch.value = value;
01262 chl->next = cht[hash];
01263 cht[hash] = chl;
01264 return 0;
01265 }
01266
01267 colorhist_vector
01268 ppm_colorhashtocolorhist( cht, maxcolors )
01269 colorhash_table cht;
01270 int maxcolors;
01271 {
01272 colorhist_vector chv;
01273 colorhist_list chl;
01274 int i, j;
01275
01276
01277 chv = (colorhist_vector) malloc( maxcolors * sizeof(struct colorhist_item) );
01278
01279 if ( chv == (colorhist_vector) 0 )
01280 {
01281 (void) fprintf(
01282 stderr, "%s: out of memory generating histogram\n", progname );
01283 return (colorhist_vector) 0;
01284 }
01285
01286
01287 j = 0;
01288 for ( i = 0; i < HASH_SIZE; ++i )
01289 for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chl->next )
01290 {
01291
01292 chv[j] = chl->ch;
01293 ++j;
01294 }
01295
01296
01297 return chv;
01298 }
01299
01300 colorhash_table
01301 ppm_colorhisttocolorhash( chv, colors )
01302 colorhist_vector chv;
01303 int colors;
01304 {
01305 colorhash_table cht;
01306 int i, hash;
01307 pixel color;
01308 colorhist_list chl;
01309
01310 cht = ppm_alloccolorhash( );
01311 if ( cht == (colorhash_table) 0 )
01312 return (colorhash_table) 0;
01313
01314 for ( i = 0; i < colors; ++i )
01315 {
01316 color = chv[i].color;
01317 hash = ppm_hashpixel( color );
01318 for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
01319 if ( PPM_EQUAL( chl->ch.color, color ) )
01320 {
01321 (void) fprintf(
01322 stderr, "%s: same color found twice - %d %d %d\n", progname,
01323 PPM_GETR(color), PPM_GETG(color), PPM_GETB(color) );
01324 ppm_freecolorhash( cht );
01325 return (colorhash_table) 0;
01326 }
01327 chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
01328 if ( chl == (colorhist_list) 0 )
01329 {
01330 (void) fprintf( stderr, "%s: out of memory\n", progname );
01331 ppm_freecolorhash( cht );
01332 return (colorhash_table) 0;
01333 }
01334 chl->ch.color = color;
01335 chl->ch.value = i;
01336 chl->next = cht[hash];
01337 cht[hash] = chl;
01338 }
01339
01340 return cht;
01341 }
01342
01343 int
01344 ppm_lookupcolor( cht, colorP )
01345 colorhash_table cht;
01346 pixel* colorP;
01347 {
01348 int hash;
01349 colorhist_list chl;
01350
01351 hash = ppm_hashpixel( *colorP );
01352 for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
01353 if ( PPM_EQUAL( chl->ch.color, *colorP ) )
01354 return chl->ch.value;
01355
01356 return -1;
01357 }
01358
01359 void
01360 ppm_freecolorhist( chv )
01361 colorhist_vector chv;
01362 {
01363 free( (char*) chv );
01364 }
01365
01366 void
01367 ppm_freecolorhash( cht )
01368 colorhash_table cht;
01369 {
01370 int i;
01371 colorhist_list chl, chlnext;
01372
01373 for ( i = 0; i < HASH_SIZE; ++i )
01374 for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chlnext )
01375 {
01376 chlnext = chl->next;
01377 free( (char*) chl );
01378 }
01379 free( (char*) cht );
01380 }
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399 #if __STDC__
01400 xel
01401 pnm_backgroundxel( xel** xels, int cols, int rows, xelval maxval, int format )
01402 #else
01403 xel
01404 pnm_backgroundxel( xels, cols, rows, maxval, format )
01405 xel** xels;
01406 int cols, rows, format;
01407 xelval maxval;
01408 #endif
01409 {
01410 xel bgxel, ul, ur, ll, lr;
01411
01412
01413 ul = xels[0][0];
01414 ur = xels[0][cols-1];
01415 ll = xels[rows-1][0];
01416 lr = xels[rows-1][cols-1];
01417
01418
01419 if ( PNM_EQUAL( ul, ur ) && PNM_EQUAL( ur, ll ) )
01420 bgxel = ul;
01421 else if ( PNM_EQUAL( ul, ur ) && PNM_EQUAL( ur, lr ) )
01422 bgxel = ul;
01423 else if ( PNM_EQUAL( ul, ll ) && PNM_EQUAL( ll, lr ) )
01424 bgxel = ul;
01425 else if ( PNM_EQUAL( ur, ll ) && PNM_EQUAL( ll, lr ) )
01426 bgxel = ur;
01427
01428 else if ( PNM_EQUAL( ul, ur ) || PNM_EQUAL( ul, ll ) ||
01429 PNM_EQUAL( ul, lr ) )
01430 bgxel = ul;
01431 else if ( PNM_EQUAL( ur, ll ) || PNM_EQUAL( ur, lr ) )
01432 bgxel = ur;
01433 else if ( PNM_EQUAL( ll, lr ) )
01434 bgxel = ll;
01435 else
01436 {
01437
01438
01439 switch ( PNM_FORMAT_TYPE(format) )
01440 {
01441 case PPM_TYPE:
01442 PPM_ASSIGN( bgxel,
01443 PPM_GETR(ul) + PPM_GETR(ur) + PPM_GETR(ll) + PPM_GETR(lr) / 4,
01444 PPM_GETG(ul) + PPM_GETG(ur) + PPM_GETG(ll) + PPM_GETG(lr) / 4,
01445 PPM_GETB(ul) + PPM_GETB(ur) + PPM_GETB(ll) + PPM_GETB(lr) / 4 );
01446 break;
01447
01448 case PGM_TYPE:
01449 {
01450 gray gul, gur, gll, glr;
01451 gul = (gray) PNM_GET1( ul );
01452 gur = (gray) PNM_GET1( ur );
01453 gll = (gray) PNM_GET1( ll );
01454 glr = (gray) PNM_GET1( lr );
01455 PNM_ASSIGN1( bgxel, ( ( gul + gur + gll + glr ) / 4 ) );
01456 break;
01457 }
01458
01459 case PBM_TYPE:
01460 pm_error(
01461 "pnm_backgroundxel: four bits no two of which equal each other??" );
01462
01463 default:
01464 pm_error( "can't happen" );
01465 }
01466 }
01467
01468 return bgxel;
01469 }
01470
01471 #if __STDC__
01472 xel
01473 pnm_backgroundxelrow( xel* xelrow, int cols, xelval maxval, int format )
01474 #else
01475 xel
01476 pnm_backgroundxelrow( xelrow, cols, maxval, format )
01477 xel* xelrow;
01478 int cols, format;
01479 xelval maxval;
01480 #endif
01481 {
01482 xel bgxel, l, r;
01483
01484
01485 l = xelrow[0];
01486 r = xelrow[cols-1];
01487
01488
01489 if ( PNM_EQUAL( l, r ) )
01490 bgxel = l;
01491 else
01492 {
01493
01494
01495 switch ( PNM_FORMAT_TYPE(format) )
01496 {
01497 case PPM_TYPE:
01498 PPM_ASSIGN( bgxel, PPM_GETR(l) + PPM_GETR(r) / 2,
01499 PPM_GETG(l) + PPM_GETG(r) / 2, PPM_GETB(l) + PPM_GETB(r) / 2 );
01500 break;
01501
01502 case PGM_TYPE:
01503 {
01504 gray gl, gr;
01505 gl = (gray) PNM_GET1( l );
01506 gr = (gray) PNM_GET1( r );
01507 PNM_ASSIGN1( bgxel, ( ( gl + gr ) / 2 ) );
01508 break;
01509 }
01510
01511 case PBM_TYPE:
01512 {
01513 int col, blacks;
01514
01515
01516 for ( col = 0, blacks = 0; col < cols; ++col )
01517 {
01518 if ( PNM_GET1( xelrow[col] ) == 0 )
01519 ++blacks;
01520 }
01521 if ( blacks >= cols / 2 )
01522 PNM_ASSIGN1( bgxel, 0 );
01523 else
01524 PNM_ASSIGN1( bgxel, pnm_pbmmaxval );
01525 break;
01526 }
01527
01528 default:
01529 pm_error( "can't happen" );
01530 }
01531 }
01532
01533 return bgxel;
01534 }
01535
01536 #if __STDC__
01537 xel
01538 pnm_whitexel( xelval maxval, int format )
01539 #else
01540 xel
01541 pnm_whitexel( maxval, format )
01542 xelval maxval;
01543 int format;
01544 #endif
01545 {
01546 xel x;
01547
01548 switch ( PNM_FORMAT_TYPE(format) )
01549 {
01550 case PPM_TYPE:
01551 PPM_ASSIGN( x, maxval, maxval, maxval );
01552 break;
01553
01554 case PGM_TYPE:
01555 PNM_ASSIGN1( x, maxval );
01556 break;
01557
01558 case PBM_TYPE:
01559 PNM_ASSIGN1( x, pnm_pbmmaxval );
01560 break;
01561
01562 default:
01563 pm_error( "can't happen" );
01564 }
01565
01566 return x;
01567 }
01568
01569 #if __STDC__
01570 xel
01571 pnm_blackxel( xelval maxval, int format )
01572 #else
01573 xel
01574 pnm_blackxel( maxval, format )
01575 xelval maxval;
01576 int format;
01577 #endif
01578 {
01579 xel x;
01580
01581 switch ( PNM_FORMAT_TYPE(format) )
01582 {
01583 case PPM_TYPE:
01584 PPM_ASSIGN( x, 0, 0, 0 );
01585 break;
01586
01587 case PGM_TYPE:
01588 PNM_ASSIGN1( x, (xelval) 0 );
01589 break;
01590
01591 case PBM_TYPE:
01592 PNM_ASSIGN1( x, (xelval) 0 );
01593 break;
01594
01595 default:
01596 pm_error( "can't happen" );
01597 }
01598
01599 return x;
01600 }
01601
01602 #if __STDC__
01603 void
01604 pnm_invertxel( xel* xP, xelval maxval, int format )
01605 #else
01606 void
01607 pnm_invertxel( xP, maxval, format )
01608 xel* xP;
01609 xelval maxval;
01610 int format;
01611 #endif
01612 {
01613 switch ( PNM_FORMAT_TYPE(format) )
01614 {
01615 case PPM_TYPE:
01616 PPM_ASSIGN(
01617 *xP, maxval - PPM_GETR( *xP ),
01618 maxval - PPM_GETG( *xP ), maxval - PPM_GETB( *xP ) );
01619 break;
01620
01621 case PGM_TYPE:
01622 PNM_ASSIGN1( *xP, (gray) maxval - (gray) PNM_GET1( *xP ) );
01623 break;
01624
01625 case PBM_TYPE:
01626 PNM_ASSIGN1( *xP, ( PNM_GET1( *xP ) == 0 ) ? pnm_pbmmaxval : 0 );
01627 break;
01628
01629 default:
01630 pm_error( "can't happen" );
01631 }
01632 }
01633
01634 #if __STDC__
01635 void
01636 pnm_promoteformat( xel** xels, int cols, int rows, xelval maxval, int format, xelval newmaxval, int newformat )
01637 #else
01638 void
01639 pnm_promoteformat( xels, cols, rows, maxval, format, newmaxval, newformat )
01640 xel** xels;
01641 xelval maxval, newmaxval;
01642 int cols, rows, format, newformat;
01643 #endif
01644 {
01645 int row;
01646
01647 for ( row = 0; row < rows; ++row )
01648 pnm_promoteformatrow(
01649 xels[row], cols, maxval, format, newmaxval, newformat );
01650 }
01651
01652 #if __STDC__
01653 void
01654 pnm_promoteformatrow( xel* xelrow, int cols, xelval maxval, int format, xelval newmaxval, int newformat )
01655 #else
01656 void
01657 pnm_promoteformatrow( xelrow, cols, maxval, format, newmaxval, newformat )
01658 xel* xelrow;
01659 xelval maxval, newmaxval;
01660 int cols, format, newformat;
01661 #endif
01662 {
01663 register int col;
01664 register xel* xP;
01665
01666 if ( ( PNM_FORMAT_TYPE(format) == PPM_TYPE &&
01667 ( PNM_FORMAT_TYPE(newformat) == PGM_TYPE ||
01668 PNM_FORMAT_TYPE(newformat) == PBM_TYPE ) ) ||
01669 ( PNM_FORMAT_TYPE(format) == PGM_TYPE &&
01670 PNM_FORMAT_TYPE(newformat) == PBM_TYPE ) )
01671 pm_error( "pnm_promoteformatrow: can't promote downwards!" );
01672
01673
01674 if ( PNM_FORMAT_TYPE(format) == PNM_FORMAT_TYPE(newformat) )
01675 {
01676 if ( PNM_FORMAT_TYPE(format) == PBM_TYPE )
01677 return;
01678 if ( newmaxval < maxval )
01679 pm_error(
01680 "pnm_promoteformatrow: can't decrease maxval - try using pnmdepth" );
01681 if ( newmaxval == maxval )
01682 return;
01683
01684 switch ( PNM_FORMAT_TYPE(format) )
01685 {
01686 case PGM_TYPE:
01687 for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
01688 PNM_ASSIGN1(
01689 *xP, (int) PNM_GET1(*xP) * newmaxval / maxval );
01690 break;
01691
01692 case PPM_TYPE:
01693 for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
01694 PPM_DEPTH( *xP, *xP, maxval, newmaxval );
01695 break;
01696
01697 default:
01698 pm_error( "shouldn't happen" );
01699 }
01700 return;
01701 }
01702
01703
01704 switch ( PNM_FORMAT_TYPE(format) )
01705 {
01706 case PBM_TYPE:
01707 switch ( PNM_FORMAT_TYPE(newformat) )
01708 {
01709 case PGM_TYPE:
01710 for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
01711 if ( PNM_GET1(*xP) == 0 )
01712 PNM_ASSIGN1( *xP, 0 );
01713 else
01714 PNM_ASSIGN1( *xP, newmaxval );
01715 break;
01716
01717 case PPM_TYPE:
01718 for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
01719 if ( PNM_GET1(*xP) == 0 )
01720 PPM_ASSIGN( *xP, 0, 0, 0 );
01721 else
01722 PPM_ASSIGN( *xP, newmaxval, newmaxval, newmaxval );
01723 break;
01724
01725 default:
01726 pm_error( "can't happen" );
01727 }
01728 break;
01729
01730 case PGM_TYPE:
01731 switch ( PNM_FORMAT_TYPE(newformat) )
01732 {
01733 case PPM_TYPE:
01734 if ( newmaxval < maxval )
01735 pm_error(
01736 "pnm_promoteformatrow: can't decrease maxval - try using pnmdepth" );
01737 if ( newmaxval == maxval )
01738 {
01739 for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
01740 PPM_ASSIGN(
01741 *xP, PNM_GET1(*xP), PNM_GET1(*xP), PNM_GET1(*xP) );
01742 }
01743 else
01744 {
01745 for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
01746 PPM_ASSIGN(
01747 *xP, (int) PNM_GET1(*xP) * newmaxval / maxval,
01748 (int) PNM_GET1(*xP) * newmaxval / maxval,
01749 (int) PNM_GET1(*xP) * newmaxval / maxval );
01750 }
01751 break;
01752
01753 default:
01754 pm_error( "can't happen" );
01755 }
01756 break;
01757
01758 default:
01759 pm_error( "can't happen" );
01760 }
01761 }
01762
01763