2 * Image Library -- Image compression/decompression interface
4 * (c) 2006 Pavel Charvat <pchar@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
13 #include "lib/mempool.h"
14 #include "images/images.h"
15 #include "images/error.h"
16 #include "images/io-main.h"
21 image_io_init(struct image_context *ctx, struct image_io *io)
23 DBG("image_io_init()");
24 bzero(io, sizeof(*io));
26 #ifdef CONFIG_IMAGES_LIBJPEG
27 if (!libjpeg_init(io))
30 #ifdef CONFIG_IMAGES_LIBPNG
34 #ifdef CONFIG_IMAGES_LIBUNGIF
35 if (!libungif_init(io))
38 #ifdef CONFIG_IMAGES_LIBMAGICK
39 if (!libmagick_init(io))
40 goto libmagick_failed;
42 io->internal_pool = mp_new(1024);
44 #ifdef CONFIG_IMAGES_LIBMAGICK
45 libmagick_cleanup(io);
48 #ifdef CONFIG_IMAGES_LIBUNGIF
52 #ifdef CONFIG_IMAGES_LIBPNG
56 #ifdef CONFIG_IMAGES_LIBJPEG
64 image_io_read_cancel(struct image_io *io)
69 io->read_cancel = NULL;
74 image_io_image_destroy(struct image_io *io)
76 if (io->image && (io->flags & IMAGE_IO_NEED_DESTROY))
78 image_destroy(io->image);
79 io->flags &= ~IMAGE_IO_NEED_DESTROY;
85 image_io_cleanup(struct image_io *io)
87 DBG("image_io_cleanup()");
88 image_io_read_cancel(io);
89 image_io_image_destroy(io);
90 #ifdef CONFIG_IMAGES_LIBMAGICK
91 libmagick_cleanup(io);
93 #ifdef CONFIG_IMAGES_LIBUNGIF
96 #ifdef CONFIG_IMAGES_LIBPNG
99 #ifdef CONFIG_IMAGES_LIBJPEG
102 mp_delete(io->internal_pool);
106 image_io_reset(struct image_io *io)
108 DBG("image_io_reset()");
109 image_io_read_cancel(io);
110 image_io_image_destroy(io);
111 struct mempool *pool = io->internal_pool;
112 struct image_context *ctx = io->context;
114 bzero(io, sizeof(*io));
115 io->internal_pool = pool;
120 image_io_read_header(struct image_io *io)
122 DBG("image_io_read_header()");
123 image_io_read_cancel(io);
124 image_io_image_destroy(io);
125 switch (io->format) {
126 case IMAGE_FORMAT_JPEG:
127 #if defined(CONFIG_IMAGES_LIBJPEG)
128 return libjpeg_read_header(io);
129 #elif defined(CONFIG_IMAGES_LIBMAGICK)
130 return libmagick_read_header(io);
134 case IMAGE_FORMAT_PNG:
135 #if defined(CONFIG_IMAGES_LIBPNG)
136 return libpng_read_header(io);
137 #elif defined(CONFIG_IMAGES_LIBMAGICK)
138 return libmagick_read_header(io);
142 case IMAGE_FORMAT_GIF:
143 #if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF)
144 return libungif_read_header(io);
145 #elif defined(CONFIG_IMAGES_LIBMAGICK)
146 return libmagick_read_header(io);
150 case IMAGE_FORMAT_UNDEFINED:
151 #if defined (CONFIG_IMAGES_LIBMAGICK)
152 return libmagick_read_header(io);
159 IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_FILE_FORMAT, "Image format not supported.");
164 image_io_read_data(struct image_io *io, int ref)
166 DBG("image_io_read_data()");
167 ASSERT(io->read_cancel);
168 io->read_cancel = NULL;
170 switch (io->format) {
171 case IMAGE_FORMAT_JPEG:
172 #if defined(CONFIG_IMAGES_LIBJPEG)
173 result = libjpeg_read_data(io);
174 #elif defined(CONFIG_IMAGES_LIBMAGICK)
175 result = libmagick_read_data(io);
181 case IMAGE_FORMAT_PNG:
182 #if defined(CONFIG_IMAGES_LIBPNG)
183 result = libpng_read_data(io);
184 #elif defined(CONFIG_IMAGES_LIBMAGICK)
185 result = libmagick_read_data(io);
191 case IMAGE_FORMAT_GIF:
192 #if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF)
193 result = libungif_read_data(io);
194 #elif defined(CONFIG_IMAGES_LIBMAGICK)
195 result = libmagick_read_data(io);
201 case IMAGE_FORMAT_UNDEFINED:
202 #if defined(CONFIG_IMAGES_LIBMAGICK)
203 result = libmagick_read_data(io);
215 io->flags |= IMAGE_IO_NEED_DESTROY;
217 io->flags &= ~IMAGE_IO_NEED_DESTROY;
225 image_io_read(struct image_io *io, int ref)
227 if (!image_io_read_header(io))
229 return image_io_read_data(io, ref);
233 image_io_write(struct image_io *io)
235 DBG("image_io_write()");
236 image_io_read_cancel(io);
237 switch (io->format) {
238 case IMAGE_FORMAT_JPEG:
239 #if defined(CONFIG_IMAGES_LIBJPEG)
240 return libjpeg_write(io);
241 #elif defined(CONFIG_IMAGES_LIBMAGICK)
242 return libmagick_write(io);
246 case IMAGE_FORMAT_PNG:
247 #if defined(CONFIG_IMAGES_LIBPNG)
248 return libpng_write(io);
249 #elif defined(CONFIG_IMAGES_LIBMAGICK)
250 return libmagick_write(io);
254 case IMAGE_FORMAT_GIF:
255 #if defined(CONFIG_IMAGES_LIBMAGICK)
256 return libmagick_write(io);
263 IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_FILE_FORMAT, "Output format not supported.");
268 image_format_to_extension(enum image_format format)
272 case IMAGE_FORMAT_JPEG:
274 case IMAGE_FORMAT_PNG:
276 case IMAGE_FORMAT_GIF:
284 image_extension_to_format(byte *extension)
286 if (!strcasecmp(extension, "jpg"))
287 return IMAGE_FORMAT_JPEG;
288 if (!strcasecmp(extension, "jpeg"))
289 return IMAGE_FORMAT_JPEG;
290 if (!strcasecmp(extension, "png"))
291 return IMAGE_FORMAT_PNG;
292 if (!strcasecmp(extension, "gif"))
293 return IMAGE_FORMAT_GIF;
294 return IMAGE_FORMAT_UNDEFINED;
298 image_file_name_to_format(byte *file_name)
300 byte *extension = strrchr(file_name, '.');
301 return extension ? image_extension_to_format(extension + 1) : IMAGE_FORMAT_UNDEFINED;
305 image_io_read_data_prepare(struct image_io_read_data_internals *rdi, struct image_io *io, uns cols, uns rows, uns flags)
307 DBG("image_io_read_data_prepare()");
308 if (rdi->need_transformations = io->cols != cols || io->rows != rows ||
309 ((io->flags ^ flags) & IMAGE_NEW_FLAGS))
310 return rdi->image = image_new(io->context, cols, rows, flags & IMAGE_IO_IMAGE_FLAGS, NULL);
312 return rdi->image = image_new(io->context, io->cols, io->rows, io->flags & IMAGE_IO_IMAGE_FLAGS, io->pool);
316 image_io_read_data_finish(struct image_io_read_data_internals *rdi, struct image_io *io)
318 DBG("image_io_read_data_finish()");
319 if (rdi->need_transformations)
321 /* Scale the image */
322 if (io->cols != rdi->image->cols || io->rows != rdi->image->rows)
324 DBG("Scaling image");
325 uns flags = rdi->image->flags;
326 if (!(rdi->need_transformations = ((io->flags ^ rdi->image->flags) & (IMAGE_NEW_FLAGS & ~IMAGE_PIXELS_ALIGNED))))
328 struct image *img = image_new(io->context, io->cols, io->rows, flags, rdi->need_transformations ? NULL : io->pool);
331 image_destroy(rdi->image);
334 if (unlikely(!image_scale(io->context, img, rdi->image)))
336 image_destroy(rdi->image);
340 image_destroy(rdi->image);
344 /* Merge with background */
345 if ((io->flags ^ rdi->image->flags) & IMAGE_ALPHA)
347 DBG("Applying background");
348 uns flags = rdi->image->flags & ~IMAGE_ALPHA;
349 if (!(rdi->need_transformations = (flags ^ io->flags) & (IMAGE_NEW_FLAGS & ~IMAGE_PIXELS_ALIGNED)))
351 struct image *img = image_new(io->context, io->cols, io->rows, flags, rdi->need_transformations ? NULL : io->pool);
354 image_destroy(rdi->image);
357 if (unlikely(!image_apply_background(io->context, img, rdi->image, &io->background_color)))
359 image_destroy(rdi->image);
363 image_destroy(rdi->image);
367 // FIXME: support for various color spaces
369 ASSERT(!rdi->need_transformations);
373 io->image = rdi->image;
378 image_io_read_data_break(struct image_io_read_data_internals *rdi, struct image_io *io UNUSED)
380 DBG("image_io_read_data_break()");
382 image_destroy(rdi->image);