1 /*
2  * gen_image.c - Part of psiconv, a PSION 5 file formats converter
3  * Copyright (c) 1999-2014  Frodo Looijaard <frodo@frodo.looijaard.name>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 #include "config.h"
21 #include "psiconv/data.h"
22 #include "gen.h"
23 #include "psiconv.h"
24 #include <string.h>
25 #include <stdlib.h>
26 
27 #ifdef IMAGEMAGICK
28 #include "magick-aux.h"
29 #endif
30 
31 #ifdef DMALLOC
32 #include "dmalloc.h"
33 #endif
34 
35 #ifdef IMAGEMAGICK
36 static Image *get_paint_data_section(psiconv_paint_data_section sec);
37 static void image_to_list(psiconv_list list,Image *image,const char *dest);
38 static void gen_image_list(const psiconv_config config,psiconv_list list,
39                            const psiconv_list sections, const char *dest);
40 static void gen_clipart(const psiconv_config config,psiconv_list list,
41                               const psiconv_clipart_f f, const char *dest);
42 static void gen_mbm(const psiconv_config config,psiconv_list list,
43                           const psiconv_mbm_f f, const char *dest);
44 static void gen_sketch(const psiconv_config config,psiconv_list list,
45                              const psiconv_sketch_f f, const char *dest);
46 static int gen_image(psiconv_config config, psiconv_list list,
47                      const psiconv_file file, const char *dest,
48 		     const encoding encoding_type);
49 
50 /* This is ridiculously simple using ImageMagick. Without it, it would
51    be quite somewhat harder - it will be left for later on.
52    Note that we ignore any errors. Dangerous... */
53 
get_paint_data_section(psiconv_paint_data_section sec)54 Image *get_paint_data_section(psiconv_paint_data_section sec)
55 {
56   Image *image;
57   float *pixel, *p, *red, *green, *blue;
58   int x,y;
59   ExceptionInfo exc;
60 
61   GetExceptionInfo(&exc);
62   red = sec->red;
63   green = sec->green;
64   blue = sec->blue;
65   p = pixel = malloc(sec->xsize * sec->ysize * 3 * sizeof(float));
66   for (y = 0; y < sec->ysize; y++) {
67     for (x = 0; x < sec->xsize; x++) {
68       *p++ = *red++;
69       *p++ = *green++;
70       *p++ = *blue++;
71     }
72   }
73 
74   image = ConstituteImage(sec->xsize,sec->ysize,"RGB",FloatPixel,pixel,&exc);
75   if (! image || (exc.severity != UndefinedException)) {
76     MagickError(exc.severity,exc.reason,exc.description);
77     exit(1);
78   }
79   free(pixel);
80 
81   DestroyExceptionInfo(&exc);
82 
83   return image;
84 }
85 
86 
image_to_list(psiconv_list list,Image * image,const char * dest)87 void image_to_list(psiconv_list list,Image *image,const char *dest)
88 {
89   ImageInfo *image_info;
90   ExceptionInfo exc;
91   size_t length;
92   unsigned char *data;
93   int i;
94 
95   strcpy(image->magick,dest);
96   image_info = CloneImageInfo(NULL);
97   GetExceptionInfo(&exc);
98   data = ImageToBlob(image_info,image,&length,&exc);
99   if (!data || (exc.severity != UndefinedException)) {
100     MagickError(exc.severity,exc.reason,exc.description);
101     exit(1);
102   }
103   for (i = 0; i < length; i++) {
104     if (psiconv_list_add(list,data+i)) {
105       fprintf(stderr,"Out of memory error");
106       exit(1);
107     }
108   }
109   DestroyExceptionInfo(&exc);
110   DestroyImageInfo(image_info);
111 }
112 
gen_image_list(const psiconv_config config,psiconv_list list,const psiconv_list sections,const char * dest)113 void gen_image_list(const psiconv_config config,psiconv_list list,
114                            const psiconv_list sections, const char *dest)
115 {
116   psiconv_paint_data_section section;
117   const MagickInfo *mi;
118   ImageInfo *image_info;
119   Image *image = NULL;
120   Image *last_image = NULL;
121   Image *this_image, *images;
122   ExceptionInfo exc;
123   int i;
124 
125   GetExceptionInfo(&exc);
126   mi = GetMagickInfo(dest,&exc);
127   if (!mi || (exc.severity != UndefinedException)) {
128     MagickError(exc.severity,exc.reason,exc.description);
129     exit(1);
130   }
131 
132   if ((psiconv_list_length(sections) < 1) ||
133       ((psiconv_list_length(sections)) > 1 && ! (mi->adjoin))) {
134     fprintf(stderr,"This image type supports only one image\n");
135     exit(1);
136   }
137 
138   for (i = 0; i < psiconv_list_length(sections); i++) {
139     if (!(section = psiconv_list_get(sections,i))) {
140       fprintf(stderr,"Internal data structures corrupted\n");
141       exit(1);
142     }
143     this_image = get_paint_data_section(section);
144     if (! image) {
145       image = this_image;
146     } else {
147       last_image->next=this_image;
148       this_image->previous=last_image;
149     }
150     last_image = this_image;
151   }
152 
153   image_info = CloneImageInfo(NULL);
154   if (image->next) {
155     images = CoalesceImages(image,&exc);
156     if (!images || (exc.severity != UndefinedException)) {
157       MagickError(exc.severity,exc.reason,exc.description);
158       exit(1);
159     }
160   } else
161     images = image;
162 
163   image_to_list(list,image,dest);
164 
165   DestroyExceptionInfo(&exc);
166   DestroyImageInfo(image_info);
167   if (image != images)
168     DestroyImages(image);
169   DestroyImages(images);
170 }
171 
gen_clipart(const psiconv_config config,psiconv_list list,const psiconv_clipart_f f,const char * dest)172 void gen_clipart(const psiconv_config config,psiconv_list list,
173                               const psiconv_clipart_f f, const char *dest)
174 {
175   int i;
176   psiconv_list sections;
177   psiconv_clipart_section section;
178 
179   if (!(sections = psiconv_list_new(sizeof(*section->picture)))) {
180     fprintf(stderr,"Out of memory error\n");
181     exit(1);
182   }
183   for (i = 0; i < psiconv_list_length(f->sections); i ++) {
184     if (!(section = psiconv_list_get(f->sections,i))) {
185       fprintf(stderr,"Internal data structures corrupted\n");
186       exit(1);
187     }
188     if ((psiconv_list_add(sections,section->picture))) {
189       fprintf(stderr,"Out of memory error\n");
190       exit(1);
191     }
192   }
193   gen_image_list(config,list,sections,dest);
194   psiconv_list_free(sections);
195 }
196 
gen_mbm(const psiconv_config config,psiconv_list list,const psiconv_mbm_f f,const char * dest)197 void gen_mbm(const psiconv_config config,psiconv_list list,
198                           const psiconv_mbm_f f, const char *dest)
199 {
200   gen_image_list(config,list,f->sections,dest);
201 }
202 
203 
gen_sketch(const psiconv_config config,psiconv_list list,const psiconv_sketch_f f,const char * dest)204 void gen_sketch(const psiconv_config config,psiconv_list list,
205                              const psiconv_sketch_f f, const char *dest)
206 {
207   Image *image;
208 
209   image = get_paint_data_section(f->sketch_sec->picture);
210   image_to_list(list,image,dest);
211   DestroyImage(image);
212 }
213 
214 
gen_image(psiconv_config config,psiconv_list list,const psiconv_file file,const char * dest,const encoding encoding_type)215 int gen_image(psiconv_config config, psiconv_list list,
216                      const psiconv_file file, const char *dest,
217 		     const encoding encoding_type)
218 {
219   if (file->type == psiconv_mbm_file)
220     gen_mbm(config,list,(psiconv_mbm_f) file->file,dest);
221   else if (file->type == psiconv_clipart_file)
222     gen_clipart(config,list,
223 	              (psiconv_clipart_f) file->file,dest);
224   else
225   if (file->type == psiconv_sketch_file) {
226     gen_sketch(config, list,(psiconv_sketch_f) file->file,dest);
227   } else
228     return -1;
229   return 0;
230 }
231 
232 #endif
233 
init_image(void)234 void init_image(void)
235 {
236   struct fileformat_s ff;
237 #if IMAGEMAGICK
238   const MagickInfo **mi;
239   int i;
240 #if IMAGEMAGICK_API == 100
241   InitializeMagick(NULL);
242 #endif
243   ff.output = gen_image;
244   mi = GetMagickFileList();
245   i = 0;
246   while (mi[i]) {
247     if (mi[i]->encoder) {
248       ff.name = strdup(mi[i]->name);
249       ff.description = strdup(mi[i]->description);
250       ff.supported_format = FORMAT_CLIPART_SINGLE | FORMAT_MBM_SINGLE |
251 	                    FORMAT_SKETCH;
252       if (mi[i]->adjoin)
253 	ff.supported_format |= FORMAT_MBM_MULTIPLE | FORMAT_CLIPART_MULTIPLE;
254       psiconv_list_add(fileformat_list,&ff);
255     }
256     i++;
257   }
258 #endif
259 }
260 
261