Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

libpnmrw.c

Go to the documentation of this file.
00001 /* libpnmrw.c - PBM/PGM/PPM read/write library
00002  **
00003  ** Copyright (C) 1988, 1989, 1991, 1992 by Jef Poskanzer.
00004  **
00005  ** Permission to use, copy, modify, and distribute this software and its
00006  ** documentation for any purpose and without fee is hereby granted, provided
00007  ** that the above copyright notice appear in all copies and that both that
00008  ** copyright notice and this permission notice appear in supporting
00009  ** documentation.  This software is provided "as is" without express or
00010  ** implied warranty.
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 /* CONFIGURE: If your system is >= 4.2BSD, set the BSD option; if you're a
00021  ** System V site, set the SYSV option; and if you're IBM-compatible, set
00022 ** MSDOS.  If your compiler is ANSI C, you're probably better off setting
00023 ** SYSV - all it affects is string handling.
00024 */
00025 #define BSD
00026 /* #define SYSV */
00027 /* #define MSDOS */
00028 #endif
00029 
00030 #include <stdio.h>
00031 #include "libpnmrw.h"
00032 
00033 /* if don't have string.h, try strings.h */
00034 #include <string.h>
00035 #define rindex(s,c) strrchr(s,c)
00036 
00037 
00038 /* Definitions. */
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 /* Variables. */
00055 
00056 static char* progname;
00057 
00058 
00059 /* Variable-sized arrays. */
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 /* File open/close that handles "-" as stdin and checks errors. */
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   /* Read size. */
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   /* Read size. */
00496   *colsP = pbm_getint( file );
00497   *rowsP = pbm_getint( file );
00498   if ( *colsP == -1 || *rowsP == -1 )
00499     return -1;
00500 
00501   /* Read maxval. */
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 /*__STDC__*/
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 /*__STDC__*/
00526 {
00527   register int col, val;
00528   register gray* gP;
00529   /*
00530     bit* bitrow;
00531     register bit* bP;
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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   /* Read size. */
00668   *colsP = pbm_getint( file );
00669   *rowsP = pbm_getint( file );
00670   if ( *colsP == -1 || *rowsP == -1 )
00671     return -1;
00672 
00673   /* Read maxval. */
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 /*__STDC__*/
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 /*__STDC__*/
00697 {
00698   register int col;
00699   register pixel* pP;
00700   register int r, g, b;
00701   gray* grayrow;
00702   register gray* gP;
00703   /*
00704     bit* bitrow;
00705     register bit* bP;
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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   /* Save program name. */
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   /* Check magic number. */
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /* Colormap stuff. */
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   /* Search colorhist for the color. */
01146   for ( i = 0; i < *colorsP; ++i )
01147     if ( PPM_EQUAL( chv[i].color, *colorP ) )
01148       {
01149         /* Found it - move to new slot. */
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       /* Didn't find it, but there's room to add it; so do so. */
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   /* Go through the entire image, building a hash table of colors. */
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   /* Now collate the hash table into a simple colorhist array. */
01277   chv = (colorhist_vector) malloc( maxcolors * sizeof(struct colorhist_item) );
01278   /* (Leave room for expansion by caller.) */
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   /* Loop through the hash table. */
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         /* Add the new entry. */
01292         chv[j] = chl->ch;
01293         ++j;
01294       }
01295 
01296   /* All done. */
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 /* added from libpnm3.c: */
01386 
01387 /* libpnm3.c - pnm utility library part 3
01388  **
01389  ** Copyright (C) 1989, 1991 by Jef Poskanzer.
01390  **
01391  ** Permission to use, copy, modify, and distribute this software and its
01392  ** documentation for any purpose and without fee is hereby granted, provided
01393  ** that the above copyright notice appear in all copies and that both that
01394  ** copyright notice and this permission notice appear in supporting
01395  ** documentation.  This software is provided "as is" without express or
01396  ** implied warranty.
01397  */
01398 
01399 #if __STDC__
01400 xel
01401   pnm_backgroundxel( xel** xels, int cols, int rows, xelval maxval, int format )
01402 #else /*__STDC__*/
01403 xel
01404   pnm_backgroundxel( xels, cols, rows, maxval, format )
01405 xel** xels;
01406 int cols, rows, format;
01407 xelval maxval;
01408 #endif /*__STDC__*/
01409 {
01410   xel bgxel, ul, ur, ll, lr;
01411 
01412   /* Guess a good background value. */
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   /* First check for three corners equal. */
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   /* Nope, check for two corners equal. */
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       /* Nope, we have to average the four corners.  This breaks the
01438        ** rules of pnm, but oh well.  Let's try to do it portably. */
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 /*__STDC__*/
01475 xel
01476   pnm_backgroundxelrow( xelrow, cols, maxval, format )
01477 xel* xelrow;
01478 int cols, format;
01479 xelval maxval;
01480 #endif /*__STDC__*/
01481 {
01482   xel bgxel, l, r;
01483 
01484   /* Guess a good background value. */
01485   l = xelrow[0];
01486   r = xelrow[cols-1];
01487 
01488   /* First check for both corners equal. */
01489   if ( PNM_EQUAL( l, r ) )
01490     bgxel = l;
01491   else
01492     {
01493       /* Nope, we have to average the two corners.  This breaks the
01494        ** rules of pnm, but oh well.  Let's try to do it portably. */
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             /* One black, one white.  Gotta count. */
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 /*__STDC__*/
01540 xel
01541   pnm_whitexel( maxval, format )
01542 xelval maxval;
01543 int format;
01544 #endif /*__STDC__*/
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 /*__STDC__*/
01573 xel
01574   pnm_blackxel( maxval, format )
01575 xelval maxval;
01576 int format;
01577 #endif /*__STDC__*/
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 /*__STDC__*/
01606 void
01607   pnm_invertxel( xP, maxval, format )
01608 xel* xP;
01609 xelval maxval;
01610 int format;
01611 #endif /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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 /*__STDC__*/
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   /* Are we promoting to the same type? */
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       /* Increase maxval. */
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   /* We must be promoting to a higher type. */
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             {                   /* Increase maxval. */
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 
 

Powered by Plone

This site conforms to the following standards: