Include screen.h in dialog.h for definition of WScreen
[wmaker-crm.git] / wrlib / load_ppm.c
blob3b2d5b1eefe2a53e16707562f0ebcf10048af985
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,
21 * MA 02110-1301, USA.
24 #include <config.h>
26 #include <X11/Xlib.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <limits.h>
32 #include "wraster.h"
33 #include "imgformat.h"
34 #include "wr_i18n.h"
38 * fileio.c - routines to read elements based on Netpbm
40 * Copyright (C) 1988 by Jef Poskanzer.
42 * Permission to use, copy, modify, and distribute this software and its
43 * documentation for any purpose and without fee is hereby granted, provided
44 * that the above copyright notice appear in all copies and that both that
45 * copyright notice and this permission notice appear in supporting
46 * documentation. This software is provided "as is" without express or
47 * implied warranty.
50 char pm_getc(FILE *const fileP, const char *filename)
52 int ich;
53 char ch;
55 ich = getc(fileP);
56 if (ich == EOF)
57 fprintf(stderr, _("wrlib: EOF / read error reading a byte from PPM file \"%s\"\n"), filename);
58 ch = (char)ich;
60 if (ch == '#') {
61 do {
62 ich = getc(fileP);
63 if (ich == EOF)
64 fprintf(stderr, _("wrlib: EOF / read error reading a byte from PPM file \"%s\"\n"), filename);
65 ch = (char)ich;
66 } while (ch != '\n' && ch != '\r');
68 return ch;
71 unsigned char pm_getrawbyte(FILE *const file, const char *filename)
73 int iby;
75 iby = getc(file);
76 if (iby == EOF)
77 fprintf(stderr, _("wrlib: EOF / read error reading a byte from PPM file \"%s\"\n"), filename);
78 return (unsigned char)iby;
81 int pm_getuint(FILE *const ifP, const char *filename)
83 char ch;
84 unsigned int i;
86 do {
87 ch = pm_getc(ifP, filename);
88 } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
90 if (ch < '0' || ch > '9') {
91 fprintf(stderr, _("wrlib: junk in PPM file \"%s\", expected an unsigned integer but got 0x%02X\n"), filename, (int)ch);
92 return -1;
95 i = 0;
96 do {
97 unsigned int const digitVal = ch - '0';
99 if (i > INT_MAX / 10) {
100 fprintf(stderr, _("wrlib: ASCII decimal integer in PPM file \"%s\" is too large to be processed\n"), filename);
101 return -1;
104 i *= 10;
106 if (i > INT_MAX - digitVal) {
107 fprintf(stderr, _("wrlib: ASCII decimal integer in PPM file \"%s\" is too large to be processed\n"), filename);
108 return -1;
111 i += digitVal;
113 ch = pm_getc(ifP, filename);
114 } while (ch >= '0' && ch <= '9');
116 return i;
118 /* end of fileio.c re-used code */
119 /******************************************************************************************/
121 /* PGM: support for portable graymap ascii and binary encoding */
122 static RImage *load_graymap(FILE *file, int w, int h, int max, int raw, const char *filename)
124 RImage *image;
125 unsigned char *ptr;
126 int x, y;
128 if (raw != '2' && raw != '5') {
129 RErrorCode = RERR_BADFORMAT;
130 return NULL;
133 image = RCreateImage(w, h, 0);
134 if (!image) {
135 RErrorCode = RERR_NOMEMORY;
136 return NULL;
139 if (max < 256) {
140 ptr = image->data;
141 if (raw == '2') {
142 int val;
144 for (y = 0; y < h; y++) {
145 for (x = 0; x < w; x++) {
146 val = pm_getuint(file, filename);
148 if (val > max || val < 0) {
149 RErrorCode = RERR_BADIMAGEFILE;
150 RReleaseImage(image);
151 return NULL;
154 val = val * 255 / max;
155 *(ptr++) = val;
156 *(ptr++) = val;
157 *(ptr++) = val;
160 } else {
161 if (raw == '5') {
162 char *buf;
164 buf = malloc(w + 1);
165 if (!buf) {
166 RErrorCode = RERR_NOMEMORY;
167 RReleaseImage(image);
168 return NULL;
170 for (y = 0; y < h; y++) {
171 if (!fread(buf, w, 1, file)) {
172 free(buf);
173 RErrorCode = RERR_BADIMAGEFILE;
174 RReleaseImage(image);
175 return NULL;
178 for (x = 0; x < w; x++) {
179 *(ptr++) = buf[x];
180 *(ptr++) = buf[x];
181 *(ptr++) = buf[x];
184 free(buf);
188 return image;
191 /* PPM: support for portable pixmap ascii and binary encoding */
192 static RImage *load_pixmap(FILE *file, int w, int h, int max, int raw, const char *filename)
194 RImage *image;
195 int i;
196 unsigned char *ptr;
198 if (raw != '3' && raw != '6') {
199 RErrorCode = RERR_BADFORMAT;
200 return NULL;
203 image = RCreateImage(w, h, 0);
204 if (!image) {
205 RErrorCode = RERR_NOMEMORY;
206 return NULL;
209 ptr = image->data;
210 if (max < 256) {
211 if (raw == '3') {
212 int x, y, val;
214 for (y = 0; y < h; y++) {
215 for (x = 0; x < w; x++) {
216 for (i = 0; i < 3; i++) {
217 val = pm_getuint(file, filename);
219 if (val > max || val < 0) {
220 RErrorCode = RERR_BADIMAGEFILE;
221 RReleaseImage(image);
222 return NULL;
225 val = val * 255 / max;
226 *(ptr++) = val;
230 } else if (raw == '6') {
231 char buf[3];
233 i = 0;
234 while (i < w * h) {
235 if (fread(buf, 1, 3, file) != 3) {
236 RErrorCode = RERR_BADIMAGEFILE;
237 RReleaseImage(image);
238 return NULL;
241 *(ptr++) = buf[0];
242 *(ptr++) = buf[1];
243 *(ptr++) = buf[2];
244 i++;
248 return image;
251 /* PBM: support for portable bitmap ascii and binary encoding */
252 static RImage *load_bitmap(FILE *file, int w, int h, int max, int raw, const char *filename)
254 RImage *image;
255 int val;
256 unsigned char *ptr;
258 if (raw != '1' && raw != '4') {
259 RErrorCode = RERR_BADFORMAT;
260 return NULL;
263 image = RCreateImage(w, h, 0);
264 if (!image) {
265 RErrorCode = RERR_NOMEMORY;
266 return NULL;
269 ptr = image->data;
270 if (raw == '1') {
271 int i = 0;
273 while (i < w * h) {
274 val = pm_getuint(file, filename);
276 if (val > max || val < 0) {
277 RErrorCode = RERR_BADIMAGEFILE;
278 RReleaseImage(image);
279 return NULL;
282 val = (val == 0) ? 255 : 0;
283 *(ptr++) = val;
284 *(ptr++) = val;
285 *(ptr++) = val;
286 i++;
288 } else {
289 if (raw == '4') {
290 unsigned char buf;
291 int bitshift;
292 int x, y;
294 for (y = 0; y < h; y++) {
295 bitshift = -1;
296 for (x = 0; x < w; x++) {
297 if (bitshift == -1) {
298 buf = pm_getrawbyte(file, filename);
299 bitshift = 7;
301 val = (buf >> bitshift) & 1;
302 val = (val == 0) ? 255 : 0;
303 --bitshift;
304 *(ptr++) = val;
305 *(ptr++) = val;
306 *(ptr++) = val;
311 return image;
314 RImage *RLoadPPM(const char *file_name)
316 FILE *file;
317 RImage *image = NULL;
318 char buffer[256];
319 int w, h, m;
320 int type;
322 file = fopen(file_name, "rb");
323 if (!file) {
324 RErrorCode = RERR_OPEN;
325 return NULL;
328 /* get signature */
329 if (!fgets(buffer, 255, file)) {
330 RErrorCode = RERR_BADIMAGEFILE;
331 fclose(file);
332 return NULL;
335 /* accept bitmaps, pixmaps or graymaps */
336 if (buffer[0] != 'P' || (buffer[1] < '1' || buffer[1] > '6')) {
337 RErrorCode = RERR_BADFORMAT;
338 fclose(file);
339 return NULL;
342 type = buffer[1];
344 /* skip comments */
345 while (1) {
346 if (!fgets(buffer, 255, file)) {
347 RErrorCode = RERR_BADIMAGEFILE;
348 fclose(file);
349 return NULL;
352 if (buffer[0] != '#')
353 break;
356 /* get size */
357 if (sscanf(buffer, "%i %i", &w, &h) != 2 || w < 1 || h < 1) {
358 /* Short file */
359 RErrorCode = RERR_BADIMAGEFILE;
360 fclose(file);
361 return NULL;
364 if (type != '1' && type != '4') {
365 if (!fgets(buffer, 255, file)) {
366 RErrorCode = RERR_BADIMAGEFILE;
367 fclose(file);
368 return NULL;
370 /* get max value */
371 if (sscanf(buffer, "%i", &m) != 1 || m < 1) {
372 /* Short file */
373 RErrorCode = RERR_BADIMAGEFILE;
374 fclose(file);
375 return NULL;
377 } else {
378 m = 1;
381 if (type == '1' || type == '4') {
382 /* Portable Bit Map: P1 is for 'plain' (ascii, rare), P4 for 'regular' (binary) */
383 image = load_bitmap(file, w, h, m, type, file_name);
384 } else if (type == '2' || type == '5') {
385 /* Portable Gray Map: P2 is for 'plain' (ascii, rare), P5 for 'regular' (binary) */
386 image = load_graymap(file, w, h, m, type, file_name);
387 } else if (type == '3' || type == '6') {
388 /* Portable Pix Map: P3 is for 'plain' (ascii, rare), P6 for 'regular' (binary) */
389 image = load_pixmap(file, w, h, m, type, file_name);
392 fclose(file);
393 return image;