Version 0.3
[colorize.git] / src / ppm.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include "ppm.h"
5
6 #ifdef WITH_MAGICK
7 #include <magick/api.h>
8
9 int save_depth = 16;
10
11 /* load given image to memory. return memory pointer, witdth and height
12  * if offset is given, no memory is allocated */
13 int load_img(int offset, unsigned short **buffer, int *width, int *height,
14         const char *filename, int index)
15 {
16         int rc = -1;
17         Image *image = NULL;
18         ImageInfo *imageinfo = NULL;
19         ExceptionInfo exception;
20
21 //      MagickCoreGenesis(NULL,MagickFalse);
22         InitializeMagick(NULL);
23         imageinfo = CloneImageInfo(0);
24         GetExceptionInfo(&exception);
25
26         sprintf(imageinfo->filename, filename, index);
27
28         image = ReadImage(imageinfo, &exception);
29         if (!image) {
30 //              printf("failed to read image '%s' via *magick\n", filename);
31                 goto exit;
32         }
33         *width = image->columns;
34         *height = image->rows;
35
36         if (offset < 0) {
37                 *buffer = (unsigned short *)malloc((*width) * (*height) * 3 * sizeof(unsigned short));
38                 if (!*buffer) {
39                         printf("failed to allocate image data\n");
40                         goto exit;
41                 }
42                 offset = 0;
43         }
44 //      ExportImagePixels(image, 0, 0, *width, *height, "RGB", CharPixel, *buffer, NULL);
45         DispatchImage(image, 0, 0, *width, *height, "RGB", ShortPixel, *buffer, NULL);
46
47         rc = 0;
48
49 exit:
50         if (image)
51                 DestroyImage(image);
52
53         if (imageinfo)
54                 DestroyImageInfo(imageinfo);
55
56 //      MagickCoreTerminus();
57         DestroyMagick();
58
59         return rc;
60 }
61
62 /* save given image */
63 int save_img(unsigned short *buffer, int width, int height, const char *filename,
64         int index)
65 {
66         int rc = -1;
67         Image *image = NULL;
68         ImageInfo *imageinfo = NULL;
69         ExceptionInfo exception;
70
71 //      MagickCoreGenesis(NULL,MagickFalse);
72         InitializeMagick(NULL);
73         imageinfo = CloneImageInfo(0);
74         GetExceptionInfo(&exception);
75
76         imageinfo->quality = 100;
77
78         image=ConstituteImage(width, height, "RGB", ShortPixel, buffer, &exception);
79         if (!image) {
80                 printf("failed to prepare to write image\n");
81                 goto exit;
82         }
83
84         /* store as 16 bit, if lib and format supports it */
85         image->depth = save_depth;
86
87         sprintf(image->filename, filename, index); /* ACHTUNG: nicht imageinfo!!! */
88         if (!WriteImage(imageinfo, image)) {
89                 printf("failed to write image\n");
90                 goto exit;
91         }
92
93         rc = 0;
94
95 exit:
96         if (image)
97                 DestroyImage(image);
98
99         if (imageinfo)
100                 DestroyImageInfo(imageinfo);
101
102 //      MagickCoreTerminus();
103         DestroyMagick();
104
105         return rc;
106 }
107 #else
108
109 /* load given PPM image to memory. return memory pointer, witdth and height
110  * if offset is given, no memory is allocated */
111 int load_img(int offset, unsigned short **buffer, int *width, int *height,
112         const char *filename, int index)
113 {
114         FILE *fp;
115         char line[256];
116         int words, i;
117
118         sprintf(line, filename, index);
119 //      printf("reading image: %s\n", line);
120         fp = fopen(line, "r");
121         if (!fp) {
122 //              printf("failed to read ppm image '%s'\n", filename);
123                 return -1;
124         }
125 again1:
126         if (!fgets(line, sizeof(line), fp)) {
127                 printf("failed to read image depth\n");
128                 fclose(fp);
129                 return -1;
130         }
131         line[sizeof(line)-1] = '\0';
132         if (line[0]) line[strlen(line)-1] = '\0';
133         if (line[0] == '#')
134                 goto again1;
135         if (!!strcmp(line, "P6")) {
136                 printf("expecting image depth 'P6'\n");
137                 fclose(fp);
138                 return -1;
139         }
140 again2:
141         if (!fgets(line, sizeof(line), fp)) {
142                 printf("failed to read image size\n");
143                 fclose(fp);
144                 return -1;
145         }
146         line[sizeof(line)-1] = '\0';
147         if (line[0]) line[strlen(line)-1] = '\0';
148         if (line[0] == '#')
149                 goto again2;
150         sscanf(line, "%d %d", width, height);
151 //      printf("Image size: w=%d h=%d\n", *width, *height);
152 again3:
153         if (!fgets(line, sizeof(line), fp)) {
154                 printf("failed to read line '255' or '65535'\n");
155                 fclose(fp);
156                 return -1;
157         }
158         line[sizeof(line)-1] = '\0';
159         if (line[0]) line[strlen(line)-1] = '\0';
160         if (line[0] == '#')
161                 goto again3;
162         if (!strcmp(line, "255")) {
163                 words = 1;
164         } else
165         if (!strcmp(line, "65535")) {
166                 words = 2;
167         } else {
168                 printf("expecting line '255' or '65535'\n");
169                 fclose(fp);
170                 return -1;
171         }
172         if (offset < 0) {
173                 *buffer = (unsigned short *)malloc((*width) * (*height) * 3 * words * sizeof(unsigned short));
174                 if (!*buffer) {
175                         printf("failed to allocate image data\n");
176                         fclose(fp);
177                         return -1;
178                 }
179                 offset = 0;
180         }
181         if (fread((*buffer) + offset, (*width) * (*height) * 3 * words, 1, fp) != 1) {
182                 printf("failed to read image data\n");
183                 free(*buffer);
184                 fclose(fp);
185                 return -1;
186         }
187
188         /* convert 8 to 16 bits */
189         if (words == 8) {
190                 for (i = (*width) * (*height) * 3 - 1; i >= 0; i--) {
191                         (*buffer)[offset + i] = ((unsigned char *)((*buffer) - offset + (i >> 1)))[0] << 8;
192                         (*buffer)[offset + i] = ((unsigned char *)((*buffer) - offset + (i >> 1)))[1] << 8;
193                 }
194         } else {
195                 for (i = 0; i < (*width) * (*height) * 3; i++) {
196                         /* correct bit order */
197                         (*buffer)[offset + i] = ((unsigned char *)((*buffer) - offset + i))[0] << 8;
198                         (*buffer)[offset + i] |= ((unsigned char *)((*buffer) - offset + i))[1];
199                 }
200         }
201
202         fclose(fp);
203
204         return 0;
205 }
206
207 /* save given image */
208 int save_img(unsigned short *buffer, int width, int height, const char *filename,
209         int index)
210 {
211         FILE *fp;
212         int rc;
213         char line[256];
214
215         sprintf(line, filename, index);
216 //      printf("writing image: %s\n", line);
217         fp = fopen(line, "w");
218         if (!fp) {
219                 printf("failed to write image\n");
220                 return -1;
221         }
222         fprintf(fp, "P6\n%d %d\n65535\n", width, height);
223         for (i = 0; i < (*width) * (*height) * 3; i++) {
224                 /* correct bit order */
225                 rc = fputc(((unsigned char *)((*buffer) - offset + i))[0] >> 8, fp);
226                 rc = fputc(((unsigned char *)((*buffer) - offset + i))[1], fp);
227         }
228
229         fclose(fp);
230
231         return rc;
232 }
233 #endif
234
235 /* convert an image to a three dimensional array of double
236  * the size is: width, height, 3
237  */
238 void img2array(unsigned short *img, int iw, int ih, double *array, int aw,
239         int ah)
240 {
241         int x, y;
242         int plane = aw * ah;
243         double r, g, b;
244
245         for (y = 0; y < ih; y++) {
246                 for (x = 0; x < iw; x++) {
247                         r = img[(x+iw*y)*3] / 65535.0F;
248                         g = img[(x+iw*y)*3+1] / 65535.0F;
249                         b = img[(x+iw*y)*3+2] / 65535.0F;
250                         array[x+aw*y] = r;
251                         array[x+aw*y+plane] = g;
252                         array[x+aw*y+plane+plane] = b;
253                 }
254         }
255 }
256
257 /* convert a three dimensional array of double to an image
258  * the size is: width, height, 3
259  */
260 void array2img(double *array, int aw, int ah, unsigned short *img, int iw,
261         int ih)
262 {
263         int x, y, c;
264         int plane = aw * ah;
265         double r, g, b;
266
267         for (y = 0; y < ih; y++) {
268                 for (x = 0; x < iw; x++) {
269                         r = array[x+aw*y];
270                         g = array[x+aw*y+plane];
271                         b = array[x+aw*y+plane+plane];
272                         c = (r * 65535.0F + 0.5F);
273                         if (c < 0)
274                                 c = 0;
275                         else if (c > 65535)
276                                 c = 65535;
277                         img[(x+iw*y)*3] = c;
278                         c = (g * 65535.0F + 0.5F);
279                         if (c < 0)
280                                 c = 0;
281                         else if (c > 65535)
282                                 c = 65535;
283                         img[(x+iw*y)*3+1] = c;
284                         c = (b * 65535.0F + 0.5F);
285                         if (c < 0)
286                                 c = 0;
287                         else if (c > 65535)
288                                 c = 65535;
289                         img[(x+iw*y)*3+2] = c;
290                 }
291         }
292 }
293
294