Fix ImageMagick support, disable GraphicsMagick support
[colorize.git] / src / img.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include "img.h"
5
6 int save_depth = 16;
7
8 #ifdef WITH_MAGICK
9 #include <magick/api.h>
10
11 /* load given image to memory. return short RGB values */
12 unsigned short *load_img(int *width, int *height, const char *filename, int index)
13 {
14         Image *image = NULL;
15         ImageInfo *imageinfo = NULL;
16         ExceptionInfo exception;
17         unsigned short *img = NULL;
18
19         MagickCoreGenesis(NULL, MagickFalse);
20 //      InitializeMagick(NULL);
21         imageinfo = CloneImageInfo(0);
22         GetExceptionInfo(&exception);
23
24         sprintf(imageinfo->filename, filename, index);
25
26         image = ReadImage(imageinfo, &exception);
27         if (!image) {
28 //              printf("failed to read image '%s' via *magick\n", filename);
29                 goto exit;
30         }
31
32         *width = image->columns;
33         *height = image->rows;
34
35         img = (unsigned short *)malloc((*width) * (*height) * 3 * 2);
36         if (!img) {
37                 printf("%s:failed to allocate image data\n", __func__);
38                 goto exit;
39         }
40
41         ExportImagePixels(image, 0, 0, *width, *height, "RGB", ShortPixel, img, NULL);
42 //      DispatchImage(image, 0, 0, *width, *height, "RGB", ShortPixel, img, NULL);
43
44 exit:
45         if (image)
46                 DestroyImage(image);
47
48         if (imageinfo)
49                 DestroyImageInfo(imageinfo);
50
51         MagickCoreTerminus();
52 //      DestroyMagick();
53
54         return img;
55 }
56
57 /* save given image */
58 int save_img(unsigned short *img, int width, int height, int alpha, const char *filename, int index)
59 {
60         int rc = -1;
61         Image *image = NULL;
62         ImageInfo *imageinfo = NULL;
63         ExceptionInfo exception;
64
65         MagickCoreGenesis(NULL, MagickFalse);
66 //      InitializeMagick(NULL);
67         imageinfo = CloneImageInfo(0);
68         GetExceptionInfo(&exception);
69
70         imageinfo->quality = 100;
71
72         image=ConstituteImage(width, height, (alpha)?"RGBA":"RGB", ShortPixel, img, &exception);
73         if (!image) {
74                 printf("%s:failed to prepare to write image\n", __func__);
75                 goto exit;
76         }
77
78         /* store as 16 bit, if lib and format supports it */
79         image->depth = save_depth;
80
81         sprintf(image->filename, filename, index); /* ACHTUNG: nicht imageinfo!!! */
82         if (!WriteImage(imageinfo, image)) {
83                 printf("%s:failed to write image\n", __func__);
84                 goto exit;
85         }
86
87         rc = 0;
88
89 exit:
90         if (image)
91                 DestroyImage(image);
92
93         if (imageinfo)
94                 DestroyImageInfo(imageinfo);
95
96         MagickCoreTerminus();
97 //      DestroyMagick();
98
99         return rc;
100 }
101 #else
102
103 /* load given image to memory. return short RGB values */
104 unsigned short *load_img(int *width, int *height, const char *filename, int index)
105 {
106         FILE *fp = NULL;
107         unsigned short *img = NULL;
108         char line[256];
109         int words, i;
110
111         sprintf(line, filename, index);
112 //      printf("reading image: %s\n", line);
113         fp = fopen(line, "r");
114         if (!fp) {
115 //              printf("failed to read ppm image '%s'\n", filename);
116                 goto exit;
117         }
118 again1:
119         if (!fgets(line, sizeof(line), fp)) {
120                 printf("%s:failed to read image depth\n", __func__);
121                 goto exit;
122         }
123         line[sizeof(line)-1] = '\0';
124         if (line[0]) line[strlen(line)-1] = '\0';
125         if (line[0] == '#')
126                 goto again1;
127         if (!!strcmp(line, "P6")) {
128                 printf("%s:expecting image depth 'P6'\n", __func__);
129                 goto exit;
130         }
131 again2:
132         if (!fgets(line, sizeof(line), fp)) {
133                 printf("%s:failed to read image size\n", __func__);
134                 goto exit;
135         }
136         line[sizeof(line)-1] = '\0';
137         if (line[0]) line[strlen(line)-1] = '\0';
138         if (line[0] == '#')
139                 goto again2;
140         sscanf(line, "%d %d", width, height);
141 //      printf("Image size: w=%d h=%d\n", *width, *height);
142 again3:
143         if (!fgets(line, sizeof(line), fp)) {
144                 printf("%s:failed to read line '255' or '65535'\n", __func__);
145                 goto exit;
146         }
147         line[sizeof(line)-1] = '\0';
148         if (line[0]) line[strlen(line)-1] = '\0';
149         if (line[0] == '#')
150                 goto again3;
151         if (!strcmp(line, "255")) {
152                 words = 1;
153         } else
154         if (!strcmp(line, "65535")) {
155                 words = 2;
156         } else {
157                 printf("%s:expecting line '255' or '65535'\n", __func__);
158                 goto exit;
159         }
160
161         img = (unsigned short *)malloc((*width) * (*height) * 3 * 2);
162         if (!img) {
163                 printf("%s:failed to allocate image data\n", __func__);
164                 goto exit;
165         }
166         if (fread(img, (*width) * (*height) * 3 * words, 1, fp) != 1) {
167                 printf("%s:failed to read image data\n", __func__);
168                 goto exit;
169         }
170
171         /* char to short (255 -> 65535) */
172         if (words == 1) {
173                 unsigned char *from = (unsigned char *)img, c;
174                 for (i = (*width) * (*height) * 3 - 1; i >= 0; i--) {
175                         c = from[i];
176                         img[i] = (c << 8) | c;
177                 }
178         } else {
179                 /* correct byte order */
180                 unsigned short v;
181                 unsigned char *from = (unsigned char *)img;
182                 for (i = 0; i < (*width) * (*height) * 3; i++) {
183                         v = ((*from++) << 8);
184                         v |= (*from++);
185                         img[i] = v;
186                 }
187         }
188
189 exit:
190         if (fp)
191                 fclose(fp);
192
193         return img;
194 }
195
196 /* save given image */
197 int save_img(unsigned short *img, int width, int height, int alpha, const char *filename, int index)
198 {
199         FILE *fp = NULL;
200         int rc = -1;
201         char line[256];
202         int i;
203         unsigned short v;
204         unsigned char *to;
205
206         if (alpha) {
207                 printf("%s:cannot save alpha component with PPM support only\n", __func__);
208                 alpha = 0;
209                 goto exit;
210         }
211
212         sprintf(line, filename, index);
213 //      printf("writing image: %s\n", line);
214         fp = fopen(line, "w");
215         if (!fp) {
216                 printf("%s:failed to write image\n", __func__);
217                 goto exit;
218         }
219         fprintf(fp, "P6\n%d %d\n65535\n", width, height);
220
221         /* correct byte order, write and restore byte order */
222         to = (unsigned char *)img;
223         for (i = 0; i < width * height * 3; i++) {
224                 v = img[i];
225                 if (i/100*i == i) { printf("%04x ", v); }
226                 (*to++) = v >> 8;
227                 (*to++) = v;
228         }
229         rc = fwrite(img, width * height * 3 * 2, 1, fp);
230         to = (unsigned char *)img;
231         for (i = 0; i < width * height * 3; i++) {
232                 v = (*to++) << 8;
233                 v |= (*to++);
234                 img[i] = v;
235         }
236         if (rc != 1) {
237                 printf("%s:failed to write image data\n", __func__);
238                 goto exit;
239         }
240
241         rc = 0;
242
243 exit:
244         if (fp)
245                 fclose(fp);
246
247         return rc;
248 }
249 #endif
250
251 int save_img_array(double *array, int width, int height, int alpha, const char *filename, int index)
252 {
253         int rc = -1;
254         unsigned short *img = NULL;
255         int components;
256
257 #ifndef WITH_MAGICK
258         if (alpha) {
259                 printf("%s:warning, cannot save alpha component with PPM support only\n", __func__);
260                 alpha = 0;
261         }
262 #endif
263         components = (alpha) ? 4 : 3;
264
265         img = (unsigned short *)malloc(width * height * components * 2);
266         if (!img) {
267                 printf("%s:failed to allocate image data\n", __func__);
268                 goto exit;
269         }
270
271         array2img_short(array, width, height, img, width, height, alpha);
272
273         save_img(img, width, height, alpha, filename, index);
274
275         rc = 0;
276
277 exit:
278         if (img)
279                 free(img);
280
281         return rc;
282 }
283
284 /* convert an image to a three dimensional array of double
285  * the size is: width, height, 3
286  */
287 void img2array_short(unsigned short *img, int iw, int ih, double *array, int aw, int ah)
288 {
289         int x, y;
290         int channel;
291         double r, g, b;
292
293         channel = aw * ah;
294
295         for (y = 0; y < ih; y++) {
296                 for (x = 0; x < iw; x++) {
297                         r = img[(x+iw*y)*3] / 65535.0F;
298                         g = img[(x+iw*y)*3+1] / 65535.0F;
299                         b = img[(x+iw*y)*3+2] / 65535.0F;
300                         array[x+aw*y] = r;
301                         array[x+aw*y+channel] = g;
302                         array[x+aw*y+channel+channel] = b;
303                 }
304         }
305 }
306
307 /* convert a three dimensional array of double to an image
308  * the size is: width, height, 3
309  */
310 void array2img_short(double *array, int aw, int ah, unsigned short *img, int iw, int ih, int alpha)
311 {
312         int x, y, c;
313         int channel, components;
314         double r, g, b, a;
315
316         channel = aw * ah;
317         components = (alpha) ? 4 : 3;
318
319         for (y = 0; y < ih; y++) {
320                 for (x = 0; x < iw; x++) {
321                         r = array[x+aw*y];
322                         c = (r * 65535.0F + 0.5F);
323                         if (c < 0)
324                                 c = 0;
325                         else if (c > 65535)
326                                 c = 65535;
327                         img[(x+iw*y)*components] = c;
328                         g = array[x+aw*y+channel];
329                         c = (g * 65535.0F + 0.5F);
330                         if (c < 0)
331                                 c = 0;
332                         else if (c > 65535)
333                                 c = 65535;
334                         img[(x+iw*y)*components+1] = c;
335                         b = array[x+aw*y+channel+channel];
336                         c = (b * 65535.0F + 0.5F);
337                         if (c < 0)
338                                 c = 0;
339                         else if (c > 65535)
340                                 c = 65535;
341                         img[(x+iw*y)*components+2] = c;
342                         if (alpha) {
343                                 a = array[x+aw*y+channel+channel+channel];
344                                 c = (a * 65535.0F + 0.5F);
345                                 if (c < 0)
346                                         c = 0;
347                                 else if (c > 65535)
348                                         c = 65535;
349                                 img[(x+iw*y)*components+3] = c;
350                         }
351                 }
352         }
353 }
354
355 /*
356  * scale down image in img_buffer by calculating average
357  */
358 void scale_img(unsigned short *img, int width, int height, int scale)
359 {
360         int w, h, i, j, x, y;
361         int r, g, b;
362
363         if (scale == 1)
364                 return;
365
366         w = width / scale;
367         h = height / scale;
368
369         for (i = 0; i < h; i++) {
370                 for (j = 0; j < w; j++) {
371                         r = g = b = 0;
372                         for (y = 0; y < scale; y++) {
373                                 for (x = 0; x < scale; x++) {
374                                         r += img[((i*scale+y) * width + j*scale+x) * 3 + 0];
375                                         g += img[((i*scale+y) * width + j*scale+x) * 3 + 1];
376                                         b += img[((i*scale+y) * width + j*scale+x) * 3 + 2];
377                                 }
378                         }
379                         img[(i * w + j)*3 + 0] = r / scale / scale;
380                         img[(i * w + j)*3 + 1] = g / scale / scale;
381                         img[(i * w + j)*3 + 2] = b / scale / scale;
382                 }
383         }
384 }
385
386