1 # include "bitmapConfig.h"
2
3 # include <stdlib.h>
4 # include <stdio.h>
5 # include <ctype.h>
6 # include <string.h>
7
8 # include "bmintern.h"
9 # include <appDebugon.h>
10 # include <sioFileio.h>
11
12 /************************************************************************/
13 /* */
14 /* Read a PBM/PGM/PPM file. */
15 /* */
16 /************************************************************************/
17
bmPbmGetNumber(int * pNum,SimpleInputStream * sis)18 static int bmPbmGetNumber( int * pNum,
19 SimpleInputStream * sis )
20 {
21 int num= 0;
22 int c= sioInGetByte( sis );
23
24 for (;;)
25 {
26 if ( isspace( c ) )
27 { c= sioInGetByte( sis ); continue; }
28
29 if ( isdigit( c ) )
30 { break; }
31
32 if ( c == '#' )
33 {
34 for (;;)
35 {
36 c= sioInGetByte( sis );
37 if ( c == EOF )
38 { CDEB(c); return -1; }
39 if ( c == '\n' )
40 { c= sioInGetByte( sis ); break; }
41 }
42
43 continue;
44 }
45
46 CDEB(c); return -1;
47 }
48
49 while( isdigit( c ) )
50 { num= 10* num+ c- '0'; c= sioInGetByte( sis ); }
51
52 sioInUngetLastRead( sis ); *pNum= num; return 0;
53 }
54
bmReadPbmFile(const MemoryBuffer * filename,unsigned char ** pBuf,BitmapDescription * bd,int * pPrivateFormat)55 int bmReadPbmFile( const MemoryBuffer * filename,
56 unsigned char ** pBuf,
57 BitmapDescription * bd,
58 int * pPrivateFormat )
59 {
60 SimpleInputStream * sis;
61 int privateFormat;
62 int c;
63 int row;
64 int col;
65
66 int wide;
67 int high;
68 int mval= 1;
69 int shift;
70
71 unsigned char * buffer;
72 unsigned char * to;
73
74 sis= sioInFileioOpen( filename );
75 if ( ! sis )
76 { XDEB(sis); return -1; }
77
78 c= sioInGetByte( sis );
79 if ( c != 'P' )
80 { CDEB(c); sioInClose( sis ); return -1; }
81
82 c= sioInGetByte( sis );
83 switch( c )
84 {
85 case '1': case '2': case '3': case '4': case '5': case '6':
86 privateFormat= c- '0'; break;
87 default:
88 CDEB(c); sioInClose( sis ); return -1;
89 }
90
91 if ( bmPbmGetNumber( &wide, sis ) )
92 { LDEB(1); sioInClose( sis ); return -1; }
93 if ( bmPbmGetNumber( &high, sis ) )
94 { LDEB(1); sioInClose( sis ); return -1; }
95
96 bd->bdXResolution= bd->bdYResolution= 1;
97 bd->bdUnit= BMunPIXEL;
98
99 bd->bdHasAlpha= 0;
100
101 bd->bdPixelsWide= wide;
102 bd->bdPixelsHigh= high;
103
104 switch( privateFormat )
105 {
106 case 1: case 4:
107 bd->bdColorEncoding= BMcoBLACKWHITE;
108 bd->bdSamplesPerPixel= 1;
109 bd->bdBitsPerSample= 1;
110 break;
111
112 case 2: case 5:
113 if ( bmPbmGetNumber( &mval, sis ) )
114 { LDEB(1); sioInClose( sis ); return -1; }
115
116 bd->bdColorEncoding= BMcoWHITEBLACK;
117 bd->bdSamplesPerPixel= 1;
118 bd->bdBitsPerSample= 8;
119 break;
120
121 case 3: case 6:
122 if ( bmPbmGetNumber( &mval, sis ) )
123 { LDEB(1); sioInClose( sis ); return -1; }
124
125 bd->bdColorEncoding= BMcoRGB;
126 bd->bdBitsPerSample= 8;
127 break;
128
129 default:
130 CDEB(c); sioInClose( sis ); return -1;
131 }
132
133 bmCalculateSizes( bd );
134
135 buffer= (unsigned char *)malloc( bd->bdBufferLength );
136 if ( ! buffer )
137 { XDEB(buffer); sioInClose( sis ); return -1; }
138
139 switch( privateFormat )
140 {
141 case 1:
142 memset( buffer, 0, bd->bdBufferLength );
143 for ( row= 0; row < high; row++ )
144 {
145 to= buffer+ row* bd->bdBytesPerRow; shift= 7;
146 for ( col= 0; col < wide; col++ )
147 {
148 if ( bmPbmGetNumber( &c, sis ) )
149 {
150 LLDEB(row,col);
151 free( buffer ); sioInClose( sis ); return -1;
152 }
153 *to |= ( c != 0 ) << shift;
154 if ( shift == 0 )
155 { shift= 7; to++; }
156 else{ shift--; }
157 }
158 }
159 break;
160
161 case 4:
162 c= sioInGetByte( sis );
163 for ( row= 0; row < high; row++ )
164 {
165 to= buffer+ row* bd->bdBytesPerRow;
166 if ( sioInReadBytes( sis, to, bd->bdBytesPerRow ) !=
167 bd->bdBytesPerRow )
168 {
169 LDEB(bd->bdBufferLength);
170 free( buffer ); sioInClose( sis ); return -1;
171 }
172 }
173 break;
174
175 case 5:
176 switch( bd->bdBitsPerPixel )
177 {
178 case 8:
179 c= sioInGetByte( sis );
180 if ( sioInReadBytes( sis, buffer, bd->bdBufferLength ) !=
181 bd->bdBufferLength )
182 {
183 LDEB(bd->bdBufferLength);
184 free( buffer ); sioInClose( sis ); return -1;
185 }
186 break;
187 case 1: case 2: case 4:
188 default:
189 LLDEB(privateFormat,bd->bdBitsPerPixel);
190 free( buffer ); sioInClose( sis ); return -1;
191 }
192 break;
193
194 case 2:
195 switch( bd->bdBitsPerPixel )
196 {
197 case 8:
198 to= buffer;
199 for ( col= 0; col < bd->bdBufferLength; col++ )
200 {
201 if ( bmPbmGetNumber( &c, sis ) )
202 {
203 LDEB(col);
204 free( buffer ); sioInClose( sis );
205 return -1;
206 }
207 if ( c > 255 )
208 { CDEB(c); c= 255; }
209 *(to++)= ( 255* c )/ mval;
210 }
211 break;
212 case 1: case 2: case 4:
213 default:
214 LLDEB(privateFormat,bd->bdBitsPerPixel);
215 free( buffer ); sioInClose( sis ); return -1;
216 }
217 break;
218
219 case 3:
220 switch( bd->bdBitsPerSample )
221 {
222 case 8:
223 to= buffer;
224 for ( col= 0; col < bd->bdBufferLength; col++ )
225 {
226 if ( bmPbmGetNumber( &c, sis ) )
227 {
228 LDEB(col);
229 free( buffer ); sioInClose( sis );
230 return -1;
231 }
232 if ( c > 255 )
233 { CDEB(c); c= 255; }
234 *(to++)= ( 255* c )/ mval;
235 }
236 break;
237 case 1: case 2: case 4:
238 default:
239 LLDEB(privateFormat,bd->bdBitsPerSample);
240 free( buffer ); sioInClose( sis ); return -1;
241 }
242 break;
243
244 case 6:
245 switch( bd->bdBitsPerSample )
246 {
247 case 8:
248 c= sioInGetByte( sis );
249 if ( sioInReadBytes( sis, buffer, bd->bdBufferLength ) !=
250 bd->bdBufferLength )
251 {
252 LDEB(bd->bdBufferLength);
253 free( buffer ); sioInClose( sis ); return -1;
254 }
255 break;
256 case 1: case 2: case 4:
257 default:
258 LLDEB(privateFormat,bd->bdBitsPerSample);
259 free( buffer ); sioInClose( sis ); return -1;
260 }
261 break;
262
263 default:
264 free( buffer );
265 LDEB(privateFormat); sioInClose( sis ); return -1;
266 }
267
268 sioInClose( sis );
269
270 *pBuf= buffer;
271 *pPrivateFormat= privateFormat;
272
273 return 0;
274 }
275
276 /************************************************************************/
277 /* */
278 /* Write a PGM file. */
279 /* */
280 /************************************************************************/
281
bmCanWritePbmFile(const BitmapDescription * bd,int privateFormat)282 int bmCanWritePbmFile( const BitmapDescription * bd,
283 int privateFormat )
284 {
285 if ( bd->bdHasAlpha )
286 { return -1; }
287
288 if ( privateFormat == 1 &&
289 bd->bdColorEncoding == BMcoWHITEBLACK &&
290 bd->bdBitsPerPixel == 1 )
291 { return 0; }
292 if ( privateFormat == 1 &&
293 bd->bdColorEncoding == BMcoBLACKWHITE &&
294 bd->bdBitsPerPixel == 1 )
295 { return 0; }
296
297 if ( privateFormat == 2 &&
298 bd->bdColorEncoding == BMcoWHITEBLACK &&
299 bd->bdBitsPerPixel == 1 )
300 { return 0; }
301 if ( privateFormat == 2 &&
302 bd->bdColorEncoding == BMcoBLACKWHITE &&
303 bd->bdBitsPerPixel == 1 )
304 { return 0; }
305
306 if ( privateFormat == 4 &&
307 bd->bdColorEncoding == BMcoBLACKWHITE &&
308 bd->bdBitsPerPixel == 1 )
309 { return 0; }
310
311 if ( privateFormat == 5 &&
312 bd->bdColorEncoding == BMcoWHITEBLACK &&
313 bd->bdBitsPerPixel == 8 )
314 { return 0; }
315
316 return -1;
317 }
318
319 /************************************************************************/
320 /* */
321 /* Write some kinds of pbm files. Code is written to visually inspect */
322 /* the files do debug images. Simplicity is preferred over efficiency. */
323 /* */
324 /************************************************************************/
325
bmWriteBitmapBitsAscii(SimpleOutputStream * sos,const unsigned char * buffer,const BitmapDescription * bd,const char * b1,const char * b0)326 static void bmWriteBitmapBitsAscii(
327 SimpleOutputStream * sos,
328 const unsigned char * buffer,
329 const BitmapDescription * bd,
330 const char * b1,
331 const char * b0 )
332 {
333 int row;
334
335 for ( row= 0; row < bd->bdPixelsHigh; row++ )
336 {
337 int col;
338 const unsigned char * r= buffer+ row* bd->bdBytesPerRow;
339
340 for ( col= 0; col < bd->bdPixelsWide; col++ )
341 {
342 if ( r[col/8] & ( 0x80 >> ( col % 8 ) ) )
343 { sioOutPutString( b1, sos ); }
344 else{ sioOutPutString( b0, sos ); }
345 }
346
347 sioOutPrintf( sos, "\n" );
348 }
349
350 return;
351 }
352
bmStartPbm(SimpleOutputStream * sos,int privateFormat,const BitmapDescription * bd)353 static void bmStartPbm( SimpleOutputStream * sos,
354 int privateFormat,
355 const BitmapDescription * bd )
356 {
357 sioOutPrintf( sos, "P%d\n", privateFormat );
358
359 sioOutPrintf( sos, "%d %d\n\n", bd->bdPixelsWide, bd->bdPixelsHigh );
360 return;
361 }
362
bmStartPnm(SimpleOutputStream * sos,int privateFormat,const BitmapDescription * bd)363 static void bmStartPnm( SimpleOutputStream * sos,
364 int privateFormat,
365 const BitmapDescription * bd )
366 {
367 int mval= ( 1 << bd->bdBitsPerSample )- 1;
368
369
370 sioOutPrintf( sos, "P%d\n", privateFormat );
371
372 sioOutPrintf( sos, "%d %d %d\n\n",
373 bd->bdPixelsWide, bd->bdPixelsHigh, mval );
374 return;
375 }
376
bmPbmRuler(SimpleOutputStream * sos,const BitmapDescription * bd)377 static void bmPbmRuler( SimpleOutputStream * sos,
378 const BitmapDescription * bd )
379 {
380 int col;
381
382 sioOutPrintf( sos, "#0" );
383
384 for ( col= 1; col < bd->bdPixelsWide; col++ )
385 { sioOutPrintf( sos, " %d", col % 10 ); }
386
387 sioOutPrintf( sos, "\n" );
388 }
389
bmWritePbmFile(const MemoryBuffer * filename,const unsigned char * buffer,const BitmapDescription * bd,int privateFormat)390 int bmWritePbmFile( const MemoryBuffer * filename,
391 const unsigned char * buffer,
392 const BitmapDescription * bd,
393 int privateFormat )
394 {
395 SimpleOutputStream * sos= (SimpleOutputStream *)0;
396 int rval= 0;
397
398 if ( bd->bdHasAlpha )
399 { LDEB(bd->bdHasAlpha); rval= -1; goto ready; }
400
401 sos= sioOutFileioOpen( filename );
402 if ( ! sos )
403 { XDEB(sos); rval= -1; goto ready; }
404
405 switch( privateFormat )
406 {
407 case 1:
408 switch( bd->bdColorEncoding )
409 {
410 case BMcoWHITEBLACK:
411 switch( bd->bdBitsPerPixel )
412 {
413 case 1:
414 bmStartPbm( sos, privateFormat, bd );
415
416 if ( bd->bdPixelsWide <= 40 )
417 { bmPbmRuler( sos, bd ); }
418
419 bmWriteBitmapBitsAscii( sos, buffer, bd,
420 " 0", " 1" );
421 break;
422
423 default:
424 LDEB(bd->bdBitsPerPixel); rval= -1; goto ready;
425 }
426 break;
427
428 case BMcoBLACKWHITE:
429 switch( bd->bdBitsPerPixel )
430 {
431 case 1:
432 bmStartPbm( sos, privateFormat, bd );
433
434 if ( bd->bdPixelsWide <= 40 )
435 { bmPbmRuler( sos, bd ); }
436
437 bmWriteBitmapBitsAscii( sos, buffer, bd,
438 " 1", " 0" );
439 break;
440
441 default:
442 LDEB(bd->bdBitsPerPixel); rval= -1; goto ready;
443 }
444 break;
445
446 default:
447 LDEB(bd->bdColorEncoding); rval= -1; goto ready;
448 }
449 break;
450
451 case 2:
452 switch( bd->bdColorEncoding )
453 {
454 case BMcoWHITEBLACK:
455 switch( bd->bdBitsPerPixel )
456 {
457 case 1:
458 bmStartPnm( sos, privateFormat, bd );
459
460 if ( bd->bdPixelsWide <= 40 )
461 { bmPbmRuler( sos, bd ); }
462
463 bmWriteBitmapBitsAscii( sos, buffer, bd,
464 " 1", " 0" );
465 break;
466
467 default:
468 LDEB(bd->bdBitsPerPixel); rval= -1; goto ready;
469 }
470 break;
471
472 case BMcoBLACKWHITE:
473 switch( bd->bdBitsPerPixel )
474 {
475 case 1:
476 bmStartPnm( sos, privateFormat, bd );
477
478 if ( bd->bdPixelsWide <= 40 )
479 { bmPbmRuler( sos, bd ); }
480
481 bmWriteBitmapBitsAscii( sos, buffer, bd,
482 " 0", " 1" );
483 break;
484
485 default:
486 LDEB(bd->bdBitsPerPixel); rval= -1; goto ready;
487 }
488 break;
489
490 default:
491 LDEB(bd->bdColorEncoding); rval= -1; goto ready;
492 }
493 break;
494
495 case 4:
496 switch( bd->bdColorEncoding )
497 {
498 case BMcoBLACKWHITE:
499 switch( bd->bdBitsPerPixel )
500 {
501 case 1:
502 bmStartPbm( sos, privateFormat, bd );
503 sioOutWriteBytes( sos, buffer, bd->bdBufferLength );
504 break;
505
506 default:
507 LDEB(bd->bdBitsPerPixel); rval= -1; goto ready;
508 }
509 break;
510
511 case BMcoWHITEBLACK:
512 default:
513 LDEB(bd->bdColorEncoding); rval= -1; goto ready;
514 }
515 break;
516
517 case 5:
518 switch( bd->bdColorEncoding )
519 {
520 case BMcoWHITEBLACK:
521 switch( bd->bdBitsPerPixel )
522 {
523 case 8:
524 bmStartPnm( sos, privateFormat, bd );
525
526 sioOutWriteBytes( sos, buffer, bd->bdBufferLength );
527 break;
528
529 default:
530 LDEB(bd->bdBitsPerPixel); rval= -1; goto ready;
531 }
532 break;
533
534 case BMcoBLACKWHITE:
535 default:
536 LDEB(bd->bdColorEncoding); rval= -1; goto ready;
537 }
538 break;
539
540
541 default:
542 LDEB(privateFormat); rval= -1; goto ready;
543 }
544
545 ready:
546
547 if ( sos )
548 { sioOutClose( sos ); }
549
550 return rval;
551 }
552