]> mj.ucw.cz Git - libucw.git/blob - images/io-main.c
UCW: Added bget_utf16_{le,be} routines.
[libucw.git] / images / io-main.c
1 /*
2  *      Image Library -- Image compression/decompression interface
3  *
4  *      (c) 2006 Pavel Charvat <pchar@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #undef LOCAL_DEBUG
11
12 #include "lib/lib.h"
13 #include "lib/mempool.h"
14 #include "images/images.h"
15 #include "images/error.h"
16 #include "images/io-main.h"
17 #include "images/color.h"
18
19 #include <string.h>
20
21 int
22 image_io_init(struct image_context *ctx, struct image_io *io)
23 {
24   DBG("image_io_init()");
25   bzero(io, sizeof(*io));
26   io->context = ctx;
27 #ifdef CONFIG_IMAGES_LIBJPEG
28   if (!libjpeg_init(io))
29     goto libjpeg_failed;
30 #endif
31 #ifdef CONFIG_IMAGES_LIBPNG
32   if (!libpng_init(io))
33     goto libpng_failed;
34 #endif
35 #ifdef CONFIG_IMAGES_LIBUNGIF
36   if (!libungif_init(io))
37     goto libungif_failed;
38 #endif
39 #ifdef CONFIG_IMAGES_LIBMAGICK
40   if (!libmagick_init(io))
41     goto libmagick_failed;
42 #endif
43   io->internal_pool = mp_new(1024);
44   return 1;
45 #ifdef CONFIG_IMAGES_LIBMAGICK
46   libmagick_cleanup(io);
47 libmagick_failed:
48 #endif
49 #ifdef CONFIG_IMAGES_LIBUNGIF
50   libungif_cleanup(io);
51 libungif_failed:
52 #endif
53 #ifdef CONFIG_IMAGES_LIBPNG
54   libpng_cleanup(io);
55 libpng_failed:
56 #endif
57 #ifdef CONFIG_IMAGES_LIBJPEG
58   libjpeg_cleanup(io);
59 libjpeg_failed:
60 #endif
61   return 0;
62 }
63
64 static inline void
65 image_io_read_cancel(struct image_io *io)
66 {
67   if (io->read_cancel)
68     {
69       io->read_cancel(io);
70       io->read_cancel = NULL;
71     }
72 }
73
74 static inline void
75 image_io_image_destroy(struct image_io *io)
76 {
77   if (io->image && (io->flags & IMAGE_IO_NEED_DESTROY))
78     {
79       image_destroy(io->image);
80       io->flags &= ~IMAGE_IO_NEED_DESTROY;
81       io->image = NULL;
82     }
83 }
84
85 void
86 image_io_cleanup(struct image_io *io)
87 {
88   DBG("image_io_cleanup()");
89   image_io_read_cancel(io);
90   image_io_image_destroy(io);
91 #ifdef CONFIG_IMAGES_LIBMAGICK
92   libmagick_cleanup(io);
93 #endif
94 #ifdef CONFIG_IMAGES_LIBUNGIF
95   libungif_cleanup(io);
96 #endif
97 #ifdef CONFIG_IMAGES_LIBPNG
98   libpng_cleanup(io);
99 #endif
100 #ifdef CONFIG_IMAGES_LIBJPEG
101   libjpeg_cleanup(io);
102 #endif
103   mp_delete(io->internal_pool);
104 }
105
106 void
107 image_io_reset(struct image_io *io)
108 {
109   DBG("image_io_reset()");
110   image_io_read_cancel(io);
111   image_io_image_destroy(io);
112   struct mempool *pool = io->internal_pool;
113   struct image_context *ctx = io->context;
114   mp_flush(pool);
115   bzero(io, sizeof(*io));
116   io->internal_pool = pool;
117   io->context = ctx;
118 }
119
120 int
121 image_io_read_header(struct image_io *io)
122 {
123   DBG("image_io_read_header()");
124   image_io_read_cancel(io);
125   image_io_image_destroy(io);
126   switch (io->format) {
127     case IMAGE_FORMAT_JPEG:
128 #if defined(CONFIG_IMAGES_LIBJPEG)
129       return libjpeg_read_header(io);
130 #elif defined(CONFIG_IMAGES_LIBMAGICK)
131       return libmagick_read_header(io);
132 #endif
133       break;
134
135     case IMAGE_FORMAT_PNG:
136 #if defined(CONFIG_IMAGES_LIBPNG)
137       return libpng_read_header(io);
138 #elif defined(CONFIG_IMAGES_LIBMAGICK)
139       return libmagick_read_header(io);
140 #endif
141       break;
142
143     case IMAGE_FORMAT_GIF:
144 #if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF)
145       return libungif_read_header(io);
146 #elif defined(CONFIG_IMAGES_LIBMAGICK)
147       return libmagick_read_header(io);
148 #endif
149       break;
150
151     case IMAGE_FORMAT_UNDEFINED:
152 #if defined (CONFIG_IMAGES_LIBMAGICK)
153       return libmagick_read_header(io);
154 #endif
155       break;
156
157     default:
158       ASSERT(0);
159   }
160   IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_FILE_FORMAT, "Image format not supported.");
161   return 0;
162 }
163
164 struct image *
165 image_io_read_data(struct image_io *io, int ref)
166 {
167   DBG("image_io_read_data()");
168   ASSERT(io->read_cancel);
169   io->read_cancel = NULL;
170   int result;
171   switch (io->format) {
172     case IMAGE_FORMAT_JPEG:
173 #if defined(CONFIG_IMAGES_LIBJPEG)
174       result = libjpeg_read_data(io);
175 #elif defined(CONFIG_IMAGES_LIBMAGICK)
176       result = libmagick_read_data(io);
177 #else
178       ASSERT(0);
179 #endif
180       break;
181
182     case IMAGE_FORMAT_PNG:
183 #if defined(CONFIG_IMAGES_LIBPNG)
184       result = libpng_read_data(io);
185 #elif defined(CONFIG_IMAGES_LIBMAGICK)
186       result = libmagick_read_data(io);
187 #else
188       ASSERT(0);
189 #endif
190       break;
191
192     case IMAGE_FORMAT_GIF:
193 #if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF)
194       result = libungif_read_data(io);
195 #elif defined(CONFIG_IMAGES_LIBMAGICK)
196       result = libmagick_read_data(io);
197 #else
198       ASSERT(0);
199 #endif
200       break;
201
202     case IMAGE_FORMAT_UNDEFINED:
203 #if defined(CONFIG_IMAGES_LIBMAGICK)
204       result = libmagick_read_data(io);
205 #else
206       ASSERT(0);
207 #endif
208       break;
209
210     default:
211       ASSERT(0);
212   }
213   if (result)
214     {
215       if (!ref)
216         io->flags |= IMAGE_IO_NEED_DESTROY;
217       else
218         io->flags &= ~IMAGE_IO_NEED_DESTROY;
219       return io->image;
220     }
221   else
222     return NULL;
223 }
224
225 struct image *
226 image_io_read(struct image_io *io, int ref)
227 {
228   if (!image_io_read_header(io))
229     return NULL;
230   return image_io_read_data(io, ref);
231 }
232
233 int
234 image_io_write(struct image_io *io)
235 {
236   DBG("image_io_write()");
237   image_io_read_cancel(io);
238   switch (io->format) {
239     case IMAGE_FORMAT_JPEG:
240 #if defined(CONFIG_IMAGES_LIBJPEG)
241       return libjpeg_write(io);
242 #elif defined(CONFIG_IMAGES_LIBMAGICK)
243       return libmagick_write(io);
244 #endif
245       break;
246
247     case IMAGE_FORMAT_PNG:
248 #if defined(CONFIG_IMAGES_LIBPNG)
249       return libpng_write(io);
250 #elif defined(CONFIG_IMAGES_LIBMAGICK)
251       return libmagick_write(io);
252 #endif
253       break;
254
255     case IMAGE_FORMAT_GIF:
256 #if defined(CONFIG_IMAGES_LIBMAGICK)
257       return libmagick_write(io);
258 #endif
259       break;
260
261     default:
262       break;
263   }
264   IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_FILE_FORMAT, "Output format not supported.");
265   return 0;
266 }
267
268 byte *
269 image_format_to_extension(enum image_format format)
270 {
271   switch (format)
272     {
273       case IMAGE_FORMAT_JPEG:
274         return "jpg";
275       case IMAGE_FORMAT_PNG:
276         return "png";
277       case IMAGE_FORMAT_GIF:
278         return "gif";
279       default:
280         return NULL;
281     }
282 }
283
284 enum image_format
285 image_extension_to_format(byte *extension)
286 {
287   if (!strcasecmp(extension, "jpg"))
288     return IMAGE_FORMAT_JPEG;
289   if (!strcasecmp(extension, "jpeg"))
290     return IMAGE_FORMAT_JPEG;
291   if (!strcasecmp(extension, "png"))
292     return IMAGE_FORMAT_PNG;
293   if (!strcasecmp(extension, "gif"))
294     return IMAGE_FORMAT_GIF;
295   return IMAGE_FORMAT_UNDEFINED;
296 }
297
298 enum image_format
299 image_file_name_to_format(byte *file_name)
300 {
301   byte *extension = strrchr(file_name, '.');
302   return extension ? image_extension_to_format(extension + 1) : IMAGE_FORMAT_UNDEFINED;
303 }
304
305 struct image *
306 image_io_read_data_prepare(struct image_io_read_data_internals *rdi, struct image_io *io, uns cols, uns rows, uns flags)
307 {
308   DBG("image_io_read_data_prepare()");
309   if (rdi->need_transformations = io->cols != cols || io->rows != rows ||
310       ((io->flags ^ flags) & IMAGE_NEW_FLAGS))
311     return rdi->image = image_new(io->context, cols, rows, flags & IMAGE_IO_IMAGE_FLAGS, NULL);
312   else
313     return rdi->image = image_new(io->context, io->cols, io->rows, io->flags & IMAGE_IO_IMAGE_FLAGS, io->pool);
314 }
315
316 int
317 image_io_read_data_finish(struct image_io_read_data_internals *rdi, struct image_io *io)
318 {
319   DBG("image_io_read_data_finish()");
320   if (rdi->need_transformations)
321     {
322       /* Scale the image */
323       if (io->cols != rdi->image->cols || io->rows != rdi->image->rows)
324         {
325           DBG("Scaling image");
326           uns flags = rdi->image->flags;
327           if (!(rdi->need_transformations = ((io->flags ^ rdi->image->flags) & (IMAGE_NEW_FLAGS & ~IMAGE_PIXELS_ALIGNED))))
328             flags = io->flags;
329           struct image *img = image_new(io->context, io->cols, io->rows, flags, rdi->need_transformations ? NULL : io->pool);
330           if (unlikely(!img))
331             {
332               image_destroy(rdi->image);
333               return 0;
334             }
335           if (unlikely(!image_scale(io->context, img, rdi->image)))
336             {
337               image_destroy(rdi->image);
338               image_destroy(img);
339               return 0;
340             }
341           image_destroy(rdi->image);
342           rdi->image = img;
343         }
344
345       /* Convert pixel format */
346       if (io->flags != rdi->image->flags)
347         {
348           struct image *img = image_new(io->context, io->cols, io->rows, io->flags, io->pool);
349           if (unlikely(!img))
350             {
351               image_destroy(rdi->image);
352               return 0;
353             }
354           struct image_conv_options opt = image_conv_defaults;
355           opt.background = io->background_color;
356           if (unlikely(!image_conv(io->context, img, rdi->image, &opt)))
357             {
358               image_destroy(rdi->image);
359               image_destroy(img);
360               return 0;
361             }
362           image_destroy(rdi->image);
363           rdi->image = img;
364         }
365     }
366
367   /* Success */
368   io->image = rdi->image;
369   return 1;
370 }
371
372 void
373 image_io_read_data_break(struct image_io_read_data_internals *rdi, struct image_io *io UNUSED)
374 {
375   DBG("image_io_read_data_break()");
376   if (rdi->image)
377     image_destroy(rdi->image);
378 }