1 /* ppm.c - load PPM image from file
3 * Raster graphics library
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 2014 Window Maker Team
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
33 #include "imgformat.h"
36 * fileio.c - routines to read elements based on Netpbm
38 * Copyright (C) 1988 by Jef Poskanzer.
40 * Permission to use, copy, modify, and distribute this software and its
41 * documentation for any purpose and without fee is hereby granted, provided
42 * that the above copyright notice appear in all copies and that both that
43 * copyright notice and this permission notice appear in supporting
44 * documentation. This software is provided "as is" without express or
48 char pm_getc(FILE * const fileP
)
55 fprintf(stderr
, "EOF / read error reading a byte\n");
62 fprintf(stderr
, "EOF / read error reading a byte\n");
64 } while (ch
!= '\n' && ch
!= '\r');
69 unsigned char pm_getrawbyte(FILE * const file
)
75 fprintf(stderr
, "EOF / read error reading a one-byte sample\n");
76 return (unsigned char)iby
;
79 int pm_getuint(FILE * const ifP
)
86 } while (ch
== ' ' || ch
== '\t' || ch
== '\n' || ch
== '\r');
88 if (ch
< '0' || ch
> '9')
89 fprintf(stderr
, "junk in file where an unsigned integer should be\n");
93 unsigned int const digitVal
= ch
- '0';
95 if (i
> INT_MAX
/ 10) {
96 fprintf(stderr
, "ASCII decimal integer in file is too large to be processed\n");
102 if (i
> INT_MAX
- digitVal
) {
103 fprintf(stderr
, "ASCII decimal integer in file is too large to be processed\n");
110 } while (ch
>= '0' && ch
<= '9');
114 /* end of fileio.c re-used code */
115 /******************************************************************************************/
117 /* PGM: support for portable graymap ascii and binary encoding */
118 static RImage
*load_graymap(FILE * file
, int w
, int h
, int max
, int raw
)
124 if (raw
!= '2' && raw
!= '5') {
125 RErrorCode
= RERR_BADFORMAT
;
129 image
= RCreateImage(w
, h
, 0);
131 RErrorCode
= RERR_NOMEMORY
;
140 for (y
= 0; y
< h
; y
++) {
141 for (x
= 0; x
< w
; x
++) {
142 val
= pm_getuint(file
);
144 if (val
> max
|| val
< 0) {
145 RErrorCode
= RERR_BADIMAGEFILE
;
146 RReleaseImage(image
);
150 val
= val
* 255 / max
;
162 RErrorCode
= RERR_NOMEMORY
;
163 RReleaseImage(image
);
166 for (y
= 0; y
< h
; y
++) {
167 if (!fread(buf
, w
, 1, file
)) {
169 RErrorCode
= RERR_BADIMAGEFILE
;
170 RReleaseImage(image
);
174 for (x
= 0; x
< w
; x
++) {
187 /* PPM: support for portable pixmap ascii and binary encoding */
188 static RImage
*load_pixmap(FILE * file
, int w
, int h
, int max
, int raw
)
194 if (raw
!= '3' && raw
!= '6') {
195 RErrorCode
= RERR_BADFORMAT
;
199 image
= RCreateImage(w
, h
, 0);
201 RErrorCode
= RERR_NOMEMORY
;
210 for (y
= 0; y
< h
; y
++) {
211 for (x
= 0; x
< w
; x
++) {
212 for (i
= 0; i
< 3; i
++) {
213 val
= pm_getuint(file
);
215 if (val
> max
|| val
< 0) {
216 RErrorCode
= RERR_BADIMAGEFILE
;
217 RReleaseImage(image
);
221 val
= val
* 255 / max
;
226 } else if (raw
== '6') {
231 if (fread(buf
, 1, 3, file
) != 3) {
232 RErrorCode
= RERR_BADIMAGEFILE
;
233 RReleaseImage(image
);
247 /* PBM: support for portable bitmap ascii and binary encoding */
248 static RImage
*load_bitmap(FILE * file
, int w
, int h
, int max
, int raw
)
254 if (raw
!= '1' && raw
!= '4') {
255 RErrorCode
= RERR_BADFORMAT
;
259 image
= RCreateImage(w
, h
, 0);
261 RErrorCode
= RERR_NOMEMORY
;
270 val
= pm_getuint(file
);
272 if (val
> max
|| val
< 0) {
273 RErrorCode
= RERR_BADIMAGEFILE
;
274 RReleaseImage(image
);
278 val
= (val
== 0) ? 255 : 0;
290 for (y
= 0; y
< h
; y
++) {
292 for (x
= 0; x
< w
; x
++) {
293 if (bitshift
== -1) {
294 buf
= pm_getrawbyte(file
);
297 val
= (buf
>> bitshift
) & 1;
298 val
= (val
== 0) ? 255 : 0;
310 RImage
*RLoadPPM(const char *file_name
)
313 RImage
*image
= NULL
;
318 file
= fopen(file_name
, "rb");
320 RErrorCode
= RERR_OPEN
;
325 if (!fgets(buffer
, 255, file
)) {
326 RErrorCode
= RERR_BADIMAGEFILE
;
331 /* accept bitmaps, pixmaps or graymaps */
332 if (buffer
[0] != 'P' || (buffer
[1] < '1' || buffer
[1] > '6')) {
333 RErrorCode
= RERR_BADFORMAT
;
342 if (!fgets(buffer
, 255, file
)) {
343 RErrorCode
= RERR_BADIMAGEFILE
;
348 if (buffer
[0] != '#')
353 if (sscanf(buffer
, "%i %i", &w
, &h
) != 2 || w
< 1 || h
< 1) {
355 RErrorCode
= RERR_BADIMAGEFILE
;
360 if (type
!= '1' && type
!= '4') {
361 if (!fgets(buffer
, 255, file
)) {
362 RErrorCode
= RERR_BADIMAGEFILE
;
367 if (sscanf(buffer
, "%i", &m
) != 1 || m
< 1) {
369 RErrorCode
= RERR_BADIMAGEFILE
;
377 if (type
== '1' || type
== '4') {
378 /* Portable Bit Map: P1 is for 'plain' (ascii, rare), P4 for 'regular' (binary) */
379 image
= load_bitmap(file
, w
, h
, m
, type
);
380 } else if (type
== '2' || type
== '5') {
381 /* Portable Gray Map: P2 is for 'plain' (ascii, rare), P5 for 'regular' (binary) */
382 image
= load_graymap(file
, w
, h
, m
, type
);
383 } else if (type
== '3' || type
== '6') {
384 /* Portable Pix Map: P3 is for 'plain' (ascii, rare), P6 for 'regular' (binary) */
385 image
= load_pixmap(file
, w
, h
, m
, type
);