Make mv's use signed chars explicitly.
[xiph/unicode.git] / w3d / pnm.c
blob655591f6e78d824e9dc3c62e113e725bbe668360
1 /**
2 * Thanks to Simon who contributed the code to make these functions
3 * CR/LF safe !
4 */
6 #include <string.h>
7 #include <ctype.h>
9 #include "w3dtypes.h"
10 #include "mem.h"
14 static
15 int eat_ws_comments(FILE *fp)
17 int c;
19 while ((c = fgetc(fp)) != EOF) {
20 if (c == '#') { /* eat the comment */
21 do {
22 c = fgetc(fp);
23 if (c == EOF) /* but bail if we hit EOF */
24 return -1;
25 } while (c != '\n');
28 if (!isspace(c)) { /* we are done */
29 return ungetc(c,fp);
33 return -1; /* fell out of the loop */
37 /* this is a kludge, but raw pnm's are not well defined... */
38 static
39 int eat_ws_to_eol (FILE *fp)
41 int c;
43 do {
44 c = fgetc(fp);
46 if (c == '\n' || c == '\r') /* some dos/win pnms generated with */
47 return c; /* just '\r' after maxval */
48 } while (isspace(c));
50 return ungetc(c,fp);
54 static
55 int read_pnm_header_internal (FILE *fp, int *w, int *h)
57 int type, maxval;
59 if (fgetc(fp) != 'P')
60 return -1;
62 type = fgetc(fp) - '0';
64 if (type < 0 || type > 6)
65 return -1; /* invalid type */
67 eat_ws_comments(fp);
68 fscanf(fp, "%d", w);
70 eat_ws_comments(fp);
71 fscanf(fp, "%d", h);
73 eat_ws_comments(fp);
74 fscanf(fp, "%d", &maxval);
75 eat_ws_to_eol(fp);
77 return type;
81 int read_pnm_header (char *fname, int *w, int *h)
83 int type;
84 FILE *fp = fopen(fname, "rb");
86 if (!fp)
87 return -1;
89 type = read_pnm_header_internal (fp, w, h);
91 fclose (fp);
93 return (type == 3 || type == 6) ? 3 : 1;
97 int read_pnm (char *fname, uint8_t *buf)
99 FILE *fp = fopen(fname, "rb");
100 int type;
101 int w, h;
103 if (!fp)
104 return -1;
106 type = read_pnm_header_internal (fp, &w, &h);
108 switch (type) {
109 case 5:
110 if (fread (buf, 1, w*h, fp) != w*h)
111 return -1;
112 break;
113 case 6:
114 if (fread (buf, 3, w*h, fp) != w*h)
115 return -1;
116 break;
117 default:
118 fprintf (stderr, "%s: unimplemented image format !!!\n", __FUNCTION__);
121 fclose (fp);
123 return 0;
127 void write_pnm (char *fname, uint8_t *rgb, int w, int h)
129 FILE *outfile;
131 outfile = fopen (fname, "wb");
133 if (!outfile) {
134 fprintf (stderr, "error opening '%s' for writing !!!\n", fname);
135 exit (-1);
139 if (strstr(fname, ".ppm") == fname + strlen(fname)-4) {
140 fprintf (outfile, "P6\n%d %d\n%d\n", w, h, 255);
141 fwrite (rgb, 3, w*h, outfile);
142 } else if (strstr(fname, ".pgm") == fname + strlen(fname)-4) {
143 fprintf (outfile, "P5\n%d %d\n%d\n", w, h, 255);
144 fwrite (rgb, 1, w*h, outfile);
145 } else {
146 fprintf (stderr,
147 "%s: can't write anything else than .ppm's and .pgm's !\n",
148 __FUNCTION__);
149 exit (-1);
152 fclose (outfile);
156 static inline
157 uint8_t CLAMP(int16_t x)
159 return ((x > 255) ? 255 : (x < 0) ? 0 : x);
163 void write_pgm16 (char *fname, int16_t *rgb, int w, int h, int16_t offset)
165 int i;
166 FILE *outfile;
168 outfile = fopen (fname, "wb");
170 if (!outfile) {
171 printf ("error opening '%s' for writing !!!\n", fname);
172 exit (-1);
175 fprintf (outfile, "P5\n%d %d\n%d\n", w, h, 255);
176 for (i=0; i<w*h; i++) {
177 uint8_t c = CLAMP(rgb[i] + offset);
178 fwrite (&c, 1, 1, outfile);
180 fclose (outfile);