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 "images/images.h"
14 #include "images/io-main.h"
18 image_io_init(struct image_thread *it, struct image_io *io)
20 DBG("image_io_init()");
21 bzero(io, sizeof(*io));
23 io->internal_pool = mp_new(1024);
27 image_io_read_cancel(struct image_io *io)
32 io->read_cancel = NULL;
37 image_io_image_destroy(struct image_io *io)
39 if (io->image && (io->flags & IMAGE_IO_NEED_DESTROY))
41 image_destroy(io->image);
42 io->flags &= ~IMAGE_IO_NEED_DESTROY;
48 image_io_cleanup(struct image_io *io)
50 DBG("image_io_cleanup()");
51 image_io_read_cancel(io);
52 image_io_image_destroy(io);
53 mp_delete(io->internal_pool);
57 image_io_reset(struct image_io *io)
59 DBG("image_io_reset()");
60 image_io_read_cancel(io);
61 image_io_image_destroy(io);
62 struct mempool *pool = io->internal_pool;
63 struct image_thread *thread = io->thread;
65 bzero(io, sizeof(*io));
66 io->internal_pool = pool;
71 image_io_read_header(struct image_io *io)
73 DBG("image_io_read_header()");
74 image_io_read_cancel(io);
75 image_io_image_destroy(io);
77 case IMAGE_FORMAT_JPEG:
78 #if defined(CONFIG_IMAGES_LIBJPEG)
79 return libjpeg_read_header(io);
80 #elif defined(CONFIG_IMAGES_LIBMAGICK)
81 return libmagick_read_header(io);
85 case IMAGE_FORMAT_PNG:
86 #if defined(CONFIG_IMAGES_LIBPNG)
87 return libpng_read_header(io);
88 #elif defined(CONFIG_IMAGES_LIBMAGICK)
89 return libmagick_read_header(io);
93 case IMAGE_FORMAT_GIF:
94 #if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF)
95 return libungif_read_header(io);
96 #elif defined(CONFIG_IMAGES_LIBMAGICK)
97 return libmagick_read_header(io);
101 case IMAGE_FORMAT_UNDEFINED:
102 // FIXME: auto-detect
108 image_thread_err(io->thread, IMAGE_ERR_INVALID_FILE_FORMAT, "Image format not supported.");
113 image_io_read_data(struct image_io *io, int ref)
115 DBG("image_io_read_data()");
116 ASSERT(io->read_cancel);
117 io->read_cancel = NULL;
119 switch (io->format) {
120 case IMAGE_FORMAT_JPEG:
121 #if defined(CONFIG_IMAGES_LIBJPEG)
122 result = libjpeg_read_data(io);
123 #elif defined(CONFIG_IMAGES_LIBMAGICK)
124 result = libmagick_read_data(io);
130 case IMAGE_FORMAT_PNG:
131 #if defined(CONFIG_IMAGES_LIBPNG)
132 result = libpng_read_data(io);
133 #elif defined(CONFIG_IMAGES_LIBMAGICK)
134 result = libmagick_read_data(io);
140 case IMAGE_FORMAT_GIF:
141 #if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF)
142 result = libungif_read_data(io);
143 #elif defined(CONFIG_IMAGES_LIBMAGICK)
144 result = libmagick_read_data(io);
156 io->flags |= IMAGE_IO_NEED_DESTROY;
158 io->flags &= ~IMAGE_IO_NEED_DESTROY;
166 image_io_read(struct image_io *io, int ref)
168 if (!image_io_read_header(io))
170 return image_io_read_data(io, ref);
174 image_io_write(struct image_io *io)
176 DBG("image_io_write()");
177 image_io_read_cancel(io);
178 switch (io->format) {
179 case IMAGE_FORMAT_JPEG:
180 #if defined(CONFIG_IMAGES_LIBJPEG)
181 return libjpeg_write(io);
182 #elif defined(CONFIG_IMAGES_LIBMAGICK)
183 return libmagick_write(io);
187 case IMAGE_FORMAT_PNG:
188 #if defined(CONFIG_IMAGES_LIBPNG)
189 return libpng_write(io);
190 #elif defined(CONFIG_IMAGES_LIBMAGICK)
191 return libmagick_write(io);
195 case IMAGE_FORMAT_GIF:
196 #if defined(CONFIG_IMAGES_LIBMAGICK)
197 return libmagick_write(io);
204 image_thread_err(io->thread, IMAGE_ERR_INVALID_FILE_FORMAT, "Image format not supported.");
209 image_format_to_extension(enum image_format format)
213 case IMAGE_FORMAT_JPEG:
215 case IMAGE_FORMAT_PNG:
217 case IMAGE_FORMAT_GIF:
225 image_extension_to_format(byte *extension)
227 if (!strcasecmp(extension, "jpg"))
228 return IMAGE_FORMAT_JPEG;
229 if (!strcasecmp(extension, "jpeg"))
230 return IMAGE_FORMAT_JPEG;
231 if (!strcasecmp(extension, "png"))
232 return IMAGE_FORMAT_PNG;
233 if (!strcasecmp(extension, "gif"))
234 return IMAGE_FORMAT_GIF;
235 return IMAGE_FORMAT_UNDEFINED;
239 image_file_name_to_format(byte *file_name)
241 byte *extension = strrchr(file_name, '.');
242 return extension ? image_extension_to_format(extension + 1) : IMAGE_FORMAT_UNDEFINED;
246 image_io_read_data_prepare(struct image_io_read_data_internals *rdi, struct image_io *io, uns cols, uns rows, uns flags)
248 DBG("image_io_read_data_prepare()");
249 if (rdi->need_transformations = io->cols != cols || io->rows != rows ||
250 ((io->flags ^ flags) & IMAGE_NEW_FLAGS))
251 return rdi->image = image_new(io->thread, cols, rows, flags & IMAGE_IO_IMAGE_FLAGS, NULL);
253 return rdi->image = image_new(io->thread, io->cols, io->rows, io->flags & IMAGE_IO_IMAGE_FLAGS, io->pool);
257 image_io_read_data_finish(struct image_io_read_data_internals *rdi, struct image_io *io)
259 DBG("image_io_read_data_finish()");
260 if (rdi->need_transformations)
262 /* Scale the image */
263 if (io->cols != rdi->image->cols || io->rows != rdi->image->rows)
265 DBG("Scaling image");
266 rdi->need_transformations = ((io->flags ^ rdi->image->flags) & IMAGE_NEW_FLAGS);
267 struct image *img = image_new(io->thread, io->cols, io->rows, rdi->image->flags, rdi->need_transformations ? NULL : io->pool);
270 image_destroy(rdi->image);
273 if (unlikely(!image_scale(io->thread, img, rdi->image)))
275 image_destroy(rdi->image);
282 /* Merge with background */
283 if ((io->flags ^ rdi->image->flags) & IMAGE_ALPHA)
285 DBG("Aplying background");
286 uns flags = rdi->image->flags & ~IMAGE_ALPHA;
287 if (!(rdi->need_transformations = (flags & io->flags) & (IMAGE_NEW_FLAGS & ~IMAGE_PIXELS_ALIGNED)))
289 struct image *img = image_new(io->thread, io->cols, io->rows, flags, rdi->need_transformations ? NULL : io->pool);
292 image_destroy(rdi->image);
295 if (unlikely(!image_apply_background(io->thread, img, rdi->image, &io->background_color)))
297 image_destroy(rdi->image);
304 ASSERT(!rdi->need_transformations);
308 io->image = rdi->image;
313 image_io_read_data_break(struct image_io_read_data_internals *rdi, struct image_io *io UNUSED)
315 DBG("image_io_read_data_break()");
317 image_destroy(rdi->image);