1 /*
2  * This software is copyrighted as noted below.  It may be freely copied,
3  * modified, and redistributed, provided that the copyright notice is
4  * preserved on all copies.
5  *
6  * There is no warranty or other guarantee of fitness for this software,
7  * it is provided solely "as is".  Bug reports or fixes may be sent
8  * to the author, who may or may not act on them as he desires.
9  *
10  * You may not include this software in a program or other software product
11  * without supplying the source, or without informing the end-user that the
12  * source is available for no extra charge.
13  *
14  * If you modify this software, you should include a notice giving the
15  * name of the person performing the modification, the date of modification,
16  * and the reason for such modification.
17  */
18 /*
19  * pbm.c - interface with PBP/PGM/PPM file formats.
20  *
21  * Author:      Raul Rivero
22  *              Mathematics Dept.
23  *              University of Oviedo
24  * Date:        Mon Feb 3 1992
25  * Copyright (c) 1992, Raul Rivero
26  *
27  */
28 
29 #include <lug.h>
30 #include <lugfnts.h>
31 
32 extern int LUGverbose;
33 
read_pbm_file(name,bitmap)34 read_pbm_file( name, bitmap )
35 char *name;
36 bitmap_hdr *bitmap;
37 {
38   FILE *handle;
39 
40   /* Open the file descriptor */
41   if ( name != NULL )
42     handle = Fopen( name, "rb" );
43   else handle = stdin;
44 
45   /* Read the bitmap */
46   read_pbm( handle, bitmap );
47   rm_compress();
48 
49   /* Close the file */
50   Fclose( handle );
51 }
52 
read_pbm(handle,image)53 read_pbm(handle, image)
54 FILE *handle;
55 bitmap_hdr *image;
56 {
57   int type;
58   int totalsize;
59 
60   /* Is really a PBM file */
61   if ( fgetc(handle) != 'P' )
62     error( 5 );
63 
64   /* Get its type */
65   switch( type = fgetc(handle) - '0' ) {
66     case 1:
67     case 4:
68                 image->depth = 1;
69                 image->cmap = (byte *) Malloc( 6 );
70                 image->cmap[3] = image->cmap[4] = image->cmap[5] = 255;
71                 break;
72     case 2:
73     case 5:
74                 image->depth = 8;
75                 image->cmap = create_bw_pallete();
76                 break;
77     case 3:
78     case 6:
79                 image->depth = 24;
80                 break;
81     default:
82                 fprintf( stderr, "Unknow PBM file type (%d)\n", type );
83                 error( 99 );
84   }
85 
86   /* Get the sizes and depth */
87   image->colors = ( 1 << image->depth );
88   image->magic = LUGUSED;
89   skip_pbm( handle );
90   fscanf( handle, "%d", &(image->xsize) );
91   fscanf( handle, "%d", &(image->ysize) );
92   totalsize = image->xsize * image->ysize;
93 
94   /* Ok, we have it all.  Allocate memory */
95   image->r = (byte *) Malloc( totalsize );
96   if ( image->depth > 8 ) {
97     image->g = (byte *) Malloc( totalsize );
98     image->b = (byte *) Malloc( totalsize );
99   }
100 
101   if ( type < 4 ) {
102     /* An ASCII file */
103     fprintf( stderr, "The PBM/PGM/PPM ascii file format type is not supported.\n" );
104     error( 99 );
105   }else {
106     register int i, j;
107     byte *line, *ptr;
108     byte *rb, *gb, *bb;
109 
110     switch ( type ) {
111       case 4:
112                 line = image->r;
113                 ptr  = line + totalsize;
114 
115                 skip_pbm( handle );
116                 /* One byte has 8 pixels, so ... */
117                 while ( line < ptr ) {
118                   i = fgetc( handle );
119                   for ( j = 7; j >= 0; j-- )
120                     *line++ =  i & ( 1 << j );
121                 }
122                 break;
123       case 5:
124                 /* Skip the max. value */
125                 fscanf( handle, "%d", &type );
126                 skip_pbm( handle );
127 
128                 /* Read the raw data info */
129                 Fread( image->r, totalsize, 1, handle );
130                 break;
131       case 6:
132                 /* Skip the max. value */
133                 fscanf( handle, "%d", &type );
134                 skip_pbm( handle );
135 
136                 /* Set pointers */
137                 line = (byte *) Malloc( 3 * image->xsize );
138                 rb = image->r;
139                 gb = image->g;
140                 bb = image->b;
141                 /* Read each line and split RGB */
142                 for ( i = 0; i < image->ysize; i++ ) {
143                   Fread( line, 3, image->xsize, handle );
144                   j = image->xsize, ptr = line;
145                   while ( j-- ) {
146                     *rb++ = *ptr++;
147                     *gb++ = *ptr++;
148                     *bb++ = *ptr++;
149                   }
150                 }
151 
152                 /* Free memory */
153                 free( line );
154                 break;
155     }
156   }
157   return 0;
158 }
159 
write_pbm_file(name,image)160 write_pbm_file( name, image )
161 char *name;
162 bitmap_hdr *image;
163 {
164   FILE *handle;
165 
166   /* Open the file descriptor */
167   if ( name != NULL )
168     handle = Fopen( name, "wb" );
169   else handle = stdout;
170 
171   /* Write the bitmap */
172   write_pbm( handle, image );
173 
174   /* Close the file */
175   Fclose( handle );
176 }
177 
write_pbm(handle,image)178 write_pbm(handle, image)
179 FILE *handle;
180 bitmap_hdr *image;
181 {
182   int totalsize = image->xsize * image->ysize;
183   bitmap_hdr aux_bitmap;
184   byte *r, *g, *b, *end;
185   register int i, j;
186 
187   if ( image->magic != LUGUSED )
188     error( 19 );
189 
190   switch( image->depth ) {
191     case 1:     /** B&W images **/
192                 /*
193                  * Write the file header: P4 ( b&w / binary format )
194                  * and the image sizes.
195                  */
196                 fprintf( handle, "P4\n" );
197                 fprintf( handle, "# PBM image generated by The LUG Library\n");
198                 fprintf( handle, "%d %d\n", image->xsize, image->ysize );
199 
200                 /* Set pointers */
201                 r = image->r;
202                 end = r + image->xsize * image->ysize;
203 
204                 /*
205                  * Now pack all the image. We can build a
206                  * single byte from 8 pixels.
207                  */
208                 while ( r < end ) {
209                   for ( i = 7, j = 0; i >= 0 && r < end; i-- )
210                     if ( *r++ )
211                       j |= ( 1 << i );
212                   fputc( j, handle );
213                 }
214                 break;
215     case 32:    /** Futures releases **/
216     case 24:    /** True color images **/
217                 /*
218                  * Write the file header: P6 ( true color / binary format ),
219                  * the image sizes and the max. value.
220                  */
221                 fprintf( handle, "P6\n" );
222                 fprintf( handle, "# PBM image generated by The LUG Library\n");
223                 fprintf( handle, "%d %d 255\n", image->xsize, image->ysize );
224 
225                 /* Set pointers */
226                 r = image->r;
227                 g = image->g;
228                 b = image->b;
229                 while ( totalsize-- ) {
230                   fputc( *r++, handle );
231                   fputc( *g++, handle );
232                   fputc( *b++, handle );
233                 }
234                 break;
235     default:    /** Mapped images ( ... ok, only gray mapped ) **/
236                 /*
237                  * Write the file header: P5 ( gray map / binary format ),
238                  * the image sizes and the max. value.
239                  */
240                 fprintf( handle, "P5\n" );
241                 fprintf( handle, "# PGM image generated by The LUG Library\n");
242                 fprintf( handle, "%d %d 255\n", image->xsize, image->ysize );
243 
244                 /*
245                  * Now we need a raster level information, so convert
246                  * our image ... and write it !.
247                  */
248                 to_raw_bw( image, &aux_bitmap );
249                 Fwrite( aux_bitmap.r, totalsize, 1, handle );
250 
251                 /* Free memory */
252                 freebitmap( &aux_bitmap );
253 
254                 break;
255   }
256   return 0;
257 }
258 
259 /*
260  * PBM files suport coments, so if a line begin with
261  * a '#' char then ...
262  */
skip_pbm(handle)263 skip_pbm( handle )
264 FILE *handle;
265 {
266   int c;
267 
268   while ( !feof( handle ) ) {
269     /* Skip until next line */
270     while( fgetc( handle ) != '\n' );
271     /*
272      * If the first char is a '#' then we have
273      * a comment ( so we re-begin ), else return.
274      */
275     if ( (c = fgetc( handle )) != '#' ) {
276       ungetc( c, handle );
277       return;
278     }
279   }
280 
281   /*
282    * Hmmm ???, if all the pbm image was comments I suppose
283    * an error, and you ?.
284    */
285   error( 6 );
286 }
287