1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2000-2009 by Denton Woods
5 // Last modified: 03/07/2009
6 //
7 // Filename: src-IL/src/il_pnm.c
8 //
9 // Description: Reads/writes to/from pbm/pgm/ppm formats (enough slashes? =)
10 //
11 //-----------------------------------------------------------------------------
12 
13 
14 
15 #include "il_internal.h"
16 #ifndef IL_NO_PNM
17 #include "il_pnm.h"
18 #include <limits.h>  // for maximum values
19 #include <ctype.h>
20 #include "il_manip.h"
21 #include "il_bits.h"
22 
23 // According to the ppm specs, it's 70, but PSP
24 //  likes to output longer lines.
25 #define MAX_BUFFER 180
26 static ILbyte LineBuffer[MAX_BUFFER];
27 static ILbyte SmallBuff[MAX_BUFFER];
28 
29 // Can't read direct bits from a lump yet
30 ILboolean IsLump = IL_FALSE;
31 
32 
33 //! Checks if the file specified in FileName is a valid .pnm file.
ilIsValidPnm(ILconst_string FileName)34 ILboolean ilIsValidPnm(ILconst_string FileName)
35 {
36 	ILHANDLE	PnmFile;
37 	ILboolean	bPnm = IL_FALSE;
38 
39 	if (   !iCheckExtension(FileName, IL_TEXT("pbm"))
40 		&& !iCheckExtension(FileName, IL_TEXT("pgm"))
41 		&& !iCheckExtension(FileName, IL_TEXT("ppm"))
42 		&& !iCheckExtension(FileName, IL_TEXT("pnm"))) {
43 		ilSetError(IL_INVALID_EXTENSION);
44 		return bPnm;
45 	}
46 
47 	PnmFile = iopenr(FileName);
48 	if (PnmFile == NULL) {
49 		ilSetError(IL_COULD_NOT_OPEN_FILE);
50 		return bPnm;
51 	}
52 
53 	bPnm = ilIsValidPnmF(PnmFile);
54 	icloser(PnmFile);
55 
56 	return bPnm;
57 }
58 
59 
60 //! Checks if the ILHANDLE contains a valid .pnm file at the current position.
ilIsValidPnmF(ILHANDLE File)61 ILboolean ilIsValidPnmF(ILHANDLE File)
62 {
63 	ILuint		FirstPos;
64 	ILboolean	bRet;
65 
66 	iSetInputFile(File);
67 	FirstPos = itell();
68 	bRet = iIsValidPnm();
69 	iseek(FirstPos, IL_SEEK_SET);
70 
71 	return bRet;
72 }
73 
74 
75 //! Checks if Lump is a valid .pnm lump.
ilIsValidPnmL(const void * Lump,ILuint Size)76 ILboolean ilIsValidPnmL(const void *Lump, ILuint Size)
77 {
78 	iSetInputLump(Lump, Size);
79 	return iIsValidPnm();
80 }
81 
82 
83 // Internal function to get the header and check it.
iIsValidPnm()84 ILboolean iIsValidPnm()
85 {
86 	char	Head[2];
87 	ILint	Read;
88 
89 	Read = iread(Head, 1, 2);
90 	iseek(-Read, IL_SEEK_CUR);  // Go ahead and restore to previous state
91 	if (Read != 2)
92 		return IL_FALSE;
93 
94 	return iCheckPnm(Head);
95 }
96 
97 
98 // Internal function used to check if the HEADER is a valid .pnm header.
iCheckPnm(char Header[2])99 ILboolean iCheckPnm(char Header[2])
100 {
101 	if (Header[0] != 'P')
102 		return IL_FALSE;
103 	switch (Header[1])
104 	{
105 		case '1':
106 		case '2':
107 		case '3':
108 		case '4':
109 		case '5':
110 		case '6':
111 			return IL_TRUE;
112 	}
113 
114 	return IL_FALSE;
115 }
116 
117 
118 // Reads a file
ilLoadPnm(ILconst_string FileName)119 ILboolean ilLoadPnm(ILconst_string FileName)
120 {
121 	ILHANDLE	PnmFile;
122 	ILboolean	bPnm = IL_FALSE;
123 
124 	PnmFile = iopenr(FileName);
125 	if (PnmFile == NULL) {
126 		ilSetError(IL_COULD_NOT_OPEN_FILE);
127 		return bPnm;
128 	}
129 
130 	bPnm = ilLoadPnmF(PnmFile);
131 	icloser(PnmFile);
132 
133 	return bPnm;
134 }
135 
136 
137 // Reads an already-opened file
ilLoadPnmF(ILHANDLE File)138 ILboolean ilLoadPnmF(ILHANDLE File)
139 {
140 	ILuint		FirstPos;
141 	ILboolean	bRet;
142 
143 	iSetInputFile(File);
144 	FirstPos = itell();
145 	bRet = iLoadPnmInternal();
146 	iseek(FirstPos, IL_SEEK_SET);
147 
148 	return bRet;
149 }
150 
151 
152 // Reads from a memory "lump"
ilLoadPnmL(const void * Lump,ILuint Size)153 ILboolean ilLoadPnmL(const void *Lump, ILuint Size)
154 {
155 	iSetInputLump(Lump, Size);
156 	return iLoadPnmInternal();
157 }
158 
159 
160 // Load either a pgm or a ppm
iLoadPnmInternal()161 ILboolean iLoadPnmInternal()
162 {
163 	ILimage		*PmImage = NULL;
164 	PPMINFO		Info;
165 //	ILuint		LineInc = 0, SmallInc = 0;
166 
167 	Info.Type = 0;
168 
169 	if (iCurImage == NULL) {
170 		ilSetError(IL_ILLEGAL_OPERATION);
171 		return IL_FALSE;
172 	}
173 
174 	// Find out what type of pgm/ppm this is
175 	if (iGetWord(IL_FALSE) == IL_FALSE)
176 		return IL_FALSE;
177 
178 	if (SmallBuff[0] != 'P') {
179 		ilSetError(IL_INVALID_FILE_HEADER);
180 		return IL_FALSE;
181 	}
182 
183 	switch( SmallBuff[1] ) {
184 		case '1':
185 			Info.Type = IL_PBM_ASCII;
186 			break;
187 		case '2':
188 			Info.Type = IL_PGM_ASCII;
189 			break;
190 		case '3':
191 			Info.Type = IL_PPM_ASCII;
192 			break;
193 		case '4':
194 			Info.Type = IL_PBM_BINARY;
195 			if (IsLump) {
196 				ilSetError(IL_FORMAT_NOT_SUPPORTED);
197 				return IL_FALSE;
198 			}
199 			break;
200 		case '5':
201 			Info.Type = IL_PGM_BINARY;
202 			break;
203 		case '6':
204 			Info.Type = IL_PPM_BINARY;
205 			break;
206 		default:
207 			ilSetError(IL_INVALID_FILE_HEADER);
208 			return IL_FALSE;
209 	}
210 
211 	// Retrieve the width and height
212 	if (iGetWord(IL_FALSE) == IL_FALSE)
213 		return IL_FALSE;
214 	Info.Width = atoi((const char*)SmallBuff);
215 	if (Info.Width == 0) {
216 		ilSetError(IL_INVALID_FILE_HEADER);
217 		return IL_FALSE;
218 	}
219 
220 	if (iGetWord(IL_FALSE) == IL_FALSE)
221 		return IL_FALSE;
222 	Info.Height = atoi((const char*)SmallBuff);
223 	if (Info.Height == 0) {
224 		ilSetError(IL_INVALID_FILE_HEADER);
225 		return IL_FALSE;
226 	}
227 
228 	// Retrieve the maximum colour component value
229 	if (Info.Type != IL_PBM_ASCII && Info.Type != IL_PBM_BINARY) {
230 		if (iGetWord(IL_TRUE) == IL_FALSE)
231 			return IL_FALSE;
232 		if ((Info.MaxColour = atoi((const char*)SmallBuff)) == 0) {
233 			ilSetError(IL_INVALID_FILE_HEADER);
234 			return IL_FALSE;
235 		}
236 	} else {
237 		Info.MaxColour = 1;
238 	}
239 
240 	if (Info.Type == IL_PBM_ASCII || Info.Type == IL_PBM_BINARY ||
241 		Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY) {
242 		if (Info.Type == IL_PGM_ASCII) {
243 			Info.Bpp = Info.MaxColour < 256 ? 1 : 2;
244 		} else {
245 			Info.Bpp = 1;
246 		}
247 	} else {
248 		Info.Bpp = 3;
249 	}
250 
251 	switch (Info.Type) {
252 		case IL_PBM_ASCII:
253 		case IL_PGM_ASCII:
254 		case IL_PPM_ASCII:
255 			PmImage = ilReadAsciiPpm(&Info);
256 			break;
257 		case IL_PBM_BINARY:
258 			PmImage = ilReadBitPbm(&Info);
259 			break;
260 		case IL_PGM_BINARY:
261 		case IL_PPM_BINARY:
262 			PmImage = ilReadBinaryPpm(&Info);
263 			break;
264 		default:
265 			return IL_FALSE;
266 	}
267 
268 	if (PmImage == NULL) {
269 	    iCurImage->Format = ilGetFormatBpp(iCurImage->Bpp);
270 	    ilSetError(IL_FILE_READ_ERROR);
271 	    return IL_FALSE;
272 	}
273 
274 	// Is this conversion needed?  Just 0's and 1's shows up as all black
275 	if (Info.Type == IL_PBM_ASCII) {
276 		PbmMaximize(PmImage);
277 	}
278 
279 	if (Info.MaxColour > 255)
280 		PmImage->Type = IL_UNSIGNED_SHORT;
281 	PmImage->Origin = IL_ORIGIN_UPPER_LEFT;
282 	if (Info.Type == IL_PBM_ASCII || Info.Type == IL_PBM_BINARY ||
283 		Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY)
284 		PmImage->Format = IL_LUMINANCE;
285 	else
286 		PmImage->Format = IL_RGB;
287 	PmImage->Origin = IL_ORIGIN_UPPER_LEFT;
288 
289 	if (PmImage == NULL)
290 		return IL_FALSE;
291 	return ilFixImage();
292 }
293 
294 
295 
ilReadAsciiPpm(PPMINFO * Info)296 ILimage *ilReadAsciiPpm(PPMINFO *Info)
297 {
298 	ILint	LineInc = 0, SmallInc = 0, DataInc = 0, Size;
299 //	ILint	BytesRead = 0;
300 
301 	if (Info->MaxColour > 255)
302 		Info->Bpp *= 2;
303 
304 	Size = Info->Width * Info->Height * Info->Bpp;
305 
306 	if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) {
307 		return IL_FALSE;
308 	}
309 	iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
310 	if (Info->MaxColour > 255)
311 		iCurImage->Type = IL_UNSIGNED_SHORT;
312 
313 	while (DataInc < Size) {  // && !feof(File)) {
314 		LineInc = 0;
315 
316 		if (iFgets((char *)LineBuffer, MAX_BUFFER) == NULL) {
317 			//ilSetError(IL_ILLEGAL_FILE_VALUE);
318 			//return NULL;
319 			//return iCurImage;
320 			break;
321 		}
322 		if (LineBuffer[0] == '#') {  // Comment
323 			continue;
324 		}
325 
326 		while ((LineBuffer[LineInc] != NUL) && (LineBuffer[LineInc] != '\n')) {
327 
328 			SmallInc = 0;
329 			while (!isalnum(LineBuffer[LineInc])) {  // Skip any whitespace
330 				LineInc++;
331 			}
332 			while (isalnum(LineBuffer[LineInc])) {
333 				SmallBuff[SmallInc] = LineBuffer[LineInc];
334 				SmallInc++;
335 				LineInc++;
336 			}
337 			SmallBuff[SmallInc] = NUL;
338 			iCurImage->Data[DataInc] = atoi((const char*)SmallBuff);  // Convert from string to colour
339 
340 			// PSP likes to put whitespace at the end of lines...figures. =/
341 			while (!isalnum(LineBuffer[LineInc]) && LineBuffer[LineInc] != NUL) {  // Skip any whitespace
342 				LineInc++;
343 			}
344 
345 			// We should set some kind of state flag that enables this
346 			//Image->Data[DataInc] *= (ILubyte)(255 / Info->MaxColour);  // Scales to 0-255
347 			if (Info->MaxColour > 255)
348 				DataInc++;
349 			DataInc++;
350 		}
351 	}
352 
353 	// If we read less than what we should have...
354 	if (DataInc < Size) {
355 		//ilCloseImage(iCurImage);
356 		//ilSetCurImage(NULL);
357 		ilSetError(IL_ILLEGAL_FILE_VALUE);
358 		return NULL;
359 	}
360 
361 	return iCurImage;
362 }
363 
364 
ilReadBinaryPpm(PPMINFO * Info)365 ILimage *ilReadBinaryPpm(PPMINFO *Info)
366 {
367 	ILuint	Size;
368 
369 	Size = Info->Width * Info->Height * Info->Bpp;
370 
371 	if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) {
372 		return IL_FALSE;
373 	}
374 	iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
375 
376 	/* 4/3/2007 Dario Meloni
377 	 Here it seems we have eaten too much bytes and it is needed to fix
378 	 the starting point
379 	 works well on various images
380 
381 	No more need of this workaround. fixed iGetWord
382 	iseek(0,IL_SEEK_END);
383 	ILuint size = itell();
384 	iseek(size-Size,IL_SEEK_SET);
385 	*/
386 	if (iread(iCurImage->Data, 1, Size ) != Size) {
387 		ilCloseImage(iCurImage);
388 		return NULL;
389 	}
390 	return iCurImage;
391 }
392 
393 
ilReadBitPbm(PPMINFO * Info)394 ILimage *ilReadBitPbm(PPMINFO *Info)
395 {
396 	ILuint	m, j, x, CurrByte;
397 
398 	if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) {
399 		return IL_FALSE;
400 	}
401 	iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
402 
403 	x = 0;
404 	for (j = 0; j < iCurImage->SizeOfData;) {
405 		CurrByte = igetc();
406 		for (m = 128; m > 0 && x < Info->Width; m >>= 1, ++x, ++j) {
407 			iCurImage->Data[j] = (CurrByte & m)?255:0;
408 		}
409 		if (x == Info->Width)
410 			x = 0;
411 	}
412 
413 	return iCurImage;
414 }
415 
416 
iGetWord(ILboolean final)417 ILboolean iGetWord(ILboolean final)
418 {
419 	ILint WordPos = 0;
420 	ILint Current = 0;
421 	ILboolean Started = IL_FALSE;
422 	ILboolean Looping = IL_TRUE;
423 
424 	if (ieof())
425 		return IL_FALSE;
426 
427 	while (Looping) {
428 		while ((Current = igetc()) != IL_EOF && Current != '\n' && Current != '#' && Current != ' ') {
429 			if (WordPos >= MAX_BUFFER)  // We have hit the maximum line length.
430 				return IL_FALSE;
431 
432 			if (!isalnum(Current)) {
433 				if (Started) {
434 					Looping = IL_FALSE;
435 					break;
436 				}
437 				continue;
438 			}
439 
440 			if (Looping)
441 				SmallBuff[WordPos++] = Current;
442 		}
443 		if (Current == IL_EOF)
444 			return IL_FALSE;
445 		SmallBuff[WordPos] = 0; // 08-17-2008 - was NULL, changed to avoid warning
446 		if (final == IL_TRUE)
447 	        break;
448 
449 		if (!Looping)
450 			break;
451 
452 		if (Current == '#') {  // '#' is a comment...read until end of line
453 			while ((Current = igetc()) != IL_EOF && Current != '\n');
454 		}
455 
456 		// Get rid of any erroneous spaces
457 		while ((Current = igetc()) != IL_EOF) {
458 			if (Current != ' ')
459 				break;
460 		}
461 		iseek(-1, IL_SEEK_CUR);
462 
463 		if (WordPos > 0)
464 			break;
465 	}
466 
467 	if (Current == -1 || WordPos == 0) {
468 		ilSetError(IL_INVALID_FILE_HEADER);
469 		return IL_FALSE;
470 	}
471 
472 	return IL_TRUE;
473 }
474 
475 
476 ILstring FName = NULL;
477 
478 //! Writes a Pnm file
ilSavePnm(const ILstring FileName)479 ILboolean ilSavePnm(const ILstring FileName)
480 {
481 	ILHANDLE	PnmFile;
482 	ILuint		PnmSize;
483 
484 	if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
485 		if (iFileExists(FileName)) {
486 			ilSetError(IL_FILE_ALREADY_EXISTS);
487 			return IL_FALSE;
488 		}
489 	}
490 
491 	PnmFile = iopenw(FileName);
492 	if (PnmFile == NULL) {
493 		ilSetError(IL_COULD_NOT_OPEN_FILE);
494 		return IL_FALSE;
495 	}
496 
497 	PnmSize = ilSavePnmF(PnmFile);
498 	iclosew(PnmFile);
499 
500 	if (PnmSize == 0)
501 		return IL_FALSE;
502 	return IL_TRUE;
503 }
504 
505 
506 //! Writes a Pnm to an already-opened file
ilSavePnmF(ILHANDLE File)507 ILuint ilSavePnmF(ILHANDLE File)
508 {
509 	ILuint Pos;
510 	iSetOutputFile(File);
511 	Pos = itellw();
512 	if (iSavePnmInternal() == IL_FALSE)
513 		return 0;  // Error occurred
514 	return itellw() - Pos;  // Return the number of bytes written.
515 }
516 
517 
518 //! Writes a Pnm to a memory "lump"
ilSavePnmL(void * Lump,ILuint Size)519 ILuint ilSavePnmL(void *Lump, ILuint Size)
520 {
521 	ILuint Pos;
522 	FName = NULL;
523 	iSetOutputLump(Lump, Size);
524 	Pos = itellw();
525 	if (iSavePnmInternal() == IL_FALSE)
526 		return 0;  // Error occurred
527 	return itellw() - Pos;  // Return the number of bytes written.
528 }
529 
530 
531 // Internal function used to save the Pnm.
iSavePnmInternal()532 ILboolean iSavePnmInternal()
533 {
534 	ILuint		Bpp, MaxVal = UCHAR_MAX, i = 0, j, k;
535 	ILenum		Type = 0;
536 	ILuint		LinePos = 0;  // Cannot exceed 70 for pnm's!
537 	ILboolean	Binary;
538 	ILimage		*TempImage;
539 	ILubyte		*TempData;
540 
541 	if (iCurImage == NULL) {
542 		ilSetError(IL_ILLEGAL_OPERATION);
543 		return IL_FALSE;
544 	}
545 
546 	if (iCheckExtension(FName, IL_TEXT("pbm")))
547 		Type = IL_PBM_ASCII;
548 	else if (iCheckExtension(FName, IL_TEXT("pgm")))
549 		Type = IL_PGM_ASCII;
550 	else if (iCheckExtension(FName, IL_TEXT("ppm")))
551 		Type = IL_PPM_ASCII;
552 	else
553 		Type = IL_PPM_ASCII;
554 
555 	/*if (!Type) {
556 		ilSetError(IL_INVALID_EXTENSION);
557 		return IL_FALSE;
558 	}*/
559 
560 	if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) {
561 		Type += 3;
562 		Binary = IL_TRUE;
563 	}
564 	else {
565 		Binary = IL_FALSE;
566 	}
567 
568 	if (iCurImage->Type == IL_UNSIGNED_BYTE) {
569 		MaxVal = UCHAR_MAX;
570 	}
571 	else if (iCurImage->Type == IL_UNSIGNED_SHORT) {
572 		MaxVal = USHRT_MAX;
573 	}
574 	else {
575 		ilSetError(IL_FORMAT_NOT_SUPPORTED);
576 		return IL_FALSE;
577 	}
578 	if (MaxVal > UCHAR_MAX && Type >= IL_PBM_BINARY) {  // binary cannot be higher than 255
579 		ilSetError(IL_FORMAT_NOT_SUPPORTED);
580 		return IL_FALSE;
581 	}
582 
583 	switch (Type)
584 	{
585 		case IL_PBM_ASCII:
586 			Bpp = 1;
587 			ilprintf("P1\n");
588 			TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE);
589 			break;
590 		//case IL_PBM_BINARY:  // Don't want to mess with saving bits just yet...
591 			//Bpp = 1;
592 			//ilprintf("P4\n");
593 			//break;
594 		case IL_PBM_BINARY:
595 			ilSetError(IL_FORMAT_NOT_SUPPORTED);
596 			return IL_FALSE;
597 		case IL_PGM_ASCII:
598 			Bpp = 1;
599 			ilprintf("P2\n");
600 			TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE);
601 			break;
602 		case IL_PGM_BINARY:
603 			Bpp = 1;
604 			ilprintf("P5\n");
605 			TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE);
606 			break;
607 		case IL_PPM_ASCII:
608 			Bpp = 3;
609 			ilprintf("P3\n");
610 			TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
611 			break;
612 		case IL_PPM_BINARY:
613 			Bpp = 3;
614 			ilprintf("P6\n");
615 			TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
616 			break;
617 		default:
618 			ilSetError(IL_INTERNAL_ERROR);
619 			return IL_FALSE;
620 	}
621 
622 	if (TempImage == NULL)
623 		return IL_FALSE;
624 
625 	if (Bpp != TempImage->Bpp) {
626 		ilSetError(IL_INVALID_CONVERSION);
627 		return IL_FALSE;
628 	}
629 
630 	if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) {
631 		TempData = iGetFlipped(TempImage);
632 		if (TempData == NULL) {
633 			ilCloseImage(TempImage);
634 			return IL_FALSE;
635 		}
636 	}
637 	else {
638 		TempData = TempImage->Data;
639 	}
640 
641 	ilprintf("%d %d\n", TempImage->Width, TempImage->Height);
642 	if (Type != IL_PBM_BINARY && Type != IL_PBM_ASCII)  // not needed for .pbm's (only 0 and 1)
643 		ilprintf("%d\n", MaxVal);
644 
645 	while (i < TempImage->SizeOfPlane) {
646 		for (j = 0; j < Bpp; j++) {
647 			if (Binary) {
648 				if (Type == IL_PBM_BINARY) {
649 					iputc((ILubyte)(TempData[i] > 127 ? 1 : 0));
650 				}
651 				else {
652 					iputc(TempData[i]);
653 				}
654 			}
655 			else {
656 				if (TempImage->Type == IL_UNSIGNED_BYTE)
657 					k = TempData[i];
658 				else  // IL_UNSIGNED_SHORT
659 					k = *((ILushort*)TempData + i);
660 				if (Type == IL_PBM_ASCII) {
661 					LinePos += ilprintf("%d ", TempData[i] > 127 ? 1 : 0);
662 				}
663 				else {
664 					LinePos += ilprintf("%d ", TempData[i]);
665 				}
666 			}
667 
668 			if (TempImage->Type == IL_UNSIGNED_SHORT)
669 				i++;
670 			i++;
671 		}
672 
673 		if (LinePos > 65) {  // Just a good number =]
674 			ilprintf("\n");
675 			LinePos = 0;
676 		}
677 	}
678 
679 	if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT)
680 		ifree(TempData);
681 	ilCloseImage(TempImage);
682 
683 	return IL_TRUE;
684 }
685 
686 
687 // Converts a .pbm to something viewable.
PbmMaximize(ILimage * Image)688 void PbmMaximize(ILimage *Image)
689 {
690 	ILuint i = 0;
691 	for (i = 0; i < Image->SizeOfPlane; i++)
692 		if (Image->Data[i] == 1)
693 			Image->Data[i] = 0xFF;
694 	return;
695 }
696 
697 
698 #endif//IL_NO_PNM
699