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