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_destroy)
41 image_destroy(io->image);
42 io->image_destroy = 0;
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;
64 bzero(io, sizeof(*io));
65 io->internal_pool = pool;
69 image_io_read_header(struct image_io *io)
71 DBG("image_io_read_header()");
72 image_io_read_cancel(io);
73 image_io_image_destroy(io);
75 case IMAGE_FORMAT_JPEG:
76 #if defined(CONFIG_IMAGES_LIBJPEG)
77 return libjpeg_read_header(io);
78 #elif defined(CONFIG_IMAGES_LIBMAGICK)
79 return libmagick_read_header(io);
83 case IMAGE_FORMAT_PNG:
84 #if defined(CONFIG_IMAGES_LIBPNG)
85 return libpng_read_header(io);
86 #elif defined(CONFIG_IMAGES_LIBMAGICK)
87 return libmagick_read_header(io);
91 case IMAGE_FORMAT_GIF:
92 #if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF)
93 return libungif_read_header(io);
94 #elif defined(CONFIG_IMAGES_LIBMAGICK)
95 return libmagick_read_header(io);
99 case IMAGE_FORMAT_UNDEFINED:
100 // FIXME: auto-detect
106 image_thread_err(io->thread, IMAGE_ERR_INVALID_FILE_FORMAT, "Image format not supported.");
111 image_io_read_data(struct image_io *io, int ref)
113 DBG("image_io_read_data()");
114 ASSERT(io->read_cancel);
115 io->read_cancel = NULL;
117 switch (io->format) {
118 case IMAGE_FORMAT_JPEG:
119 #if defined(CONFIG_IMAGES_LIBJPEG)
120 result = libjpeg_read_data(io);
121 #elif defined(CONFIG_IMAGES_LIBMAGICK)
122 result = libmagick_read_data(io);
128 case IMAGE_FORMAT_PNG:
129 #if defined(CONFIG_IMAGES_LIBPNG)
130 result = libpng_read_data(io);
131 #elif defined(CONFIG_IMAGES_LIBMAGICK)
132 result = libmagick_read_data(io);
138 case IMAGE_FORMAT_GIF:
139 #if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF)
140 result = libungif_read_data(io);
141 #elif defined(CONFIG_IMAGES_LIBMAGICK)
142 result = libmagick_read_data(io);
154 io->image_destroy = 0;
162 image_io_read(struct image_io *io, int ref)
164 if (!image_io_read_header(io))
166 return image_io_read_data(io, ref);
170 image_io_write(struct image_io *io)
172 DBG("image_io_write()");
173 image_io_read_cancel(io);
174 switch (io->format) {
175 case IMAGE_FORMAT_JPEG:
176 #if defined(CONFIG_IMAGES_LIBJPEG)
177 return libjpeg_write(io);
178 #elif defined(CONFIG_IMAGES_LIBMAGICK)
179 return libmagick_write(io);
183 case IMAGE_FORMAT_PNG:
184 #if defined(CONFIG_IMAGES_LIBPNG)
185 return libpng_write(io);
186 #elif defined(CONFIG_IMAGES_LIBMAGICK)
187 return libmagick_write(io);
191 case IMAGE_FORMAT_GIF:
192 #if defined(CONFIG_IMAGES_LIBMAGICK)
193 return libmagick_write(io);
200 image_thread_err(io->thread, IMAGE_ERR_INVALID_FILE_FORMAT, "Image format not supported.");
205 image_format_to_extension(enum image_format format)
209 case IMAGE_FORMAT_JPEG:
211 case IMAGE_FORMAT_PNG:
213 case IMAGE_FORMAT_GIF:
221 image_extension_to_format(byte *extension)
223 if (!strcasecmp(extension, "jpg"))
224 return IMAGE_FORMAT_JPEG;
225 if (!strcasecmp(extension, "jpeg"))
226 return IMAGE_FORMAT_JPEG;
227 if (!strcasecmp(extension, "png"))
228 return IMAGE_FORMAT_PNG;
229 if (!strcasecmp(extension, "gif"))
230 return IMAGE_FORMAT_GIF;
231 return IMAGE_FORMAT_UNDEFINED;
235 image_file_name_to_format(byte *file_name)
237 byte *extension = strrchr(file_name, '.');
238 return extension ? image_extension_to_format(extension + 1) : IMAGE_FORMAT_UNDEFINED;
242 image_io_read_data_prepare(struct image_io_read_data_internals *rdi, struct image_io *io, uns cols, uns rows, uns flags)
244 DBG("image_io_read_data_prepare()");
245 if (rdi->need_transformations = io->cols != cols || io->rows != rows || io->flags != flags)
247 rdi->need_destroy = 1;
248 return rdi->image = image_new(io->thread, cols, rows, flags & IMAGE_IO_IMAGE_FLAGS, NULL);
252 rdi->need_destroy = !io->pool;
253 return rdi->image = image_new(io->thread, io->cols, io->rows, io->flags & IMAGE_IO_IMAGE_FLAGS, io->pool);
258 image_io_read_data_finish(struct image_io_read_data_internals *rdi, struct image_io *io)
260 DBG("image_io_read_data_finish()");
261 if (rdi->need_transformations)
263 /* Scale the image */
264 if (io->cols != rdi->image->cols || io->rows != rdi->image->rows)
266 DBG("Scaling image");
267 rdi->need_transformations = io->flags != rdi->image->flags;
268 rdi->need_destroy = rdi->need_transformations || !io->pool;
269 struct image *img = image_new(io->thread, io->cols, io->rows, rdi->image->flags, rdi->need_transformations ? NULL : io->pool);
272 image_destroy(rdi->image);
275 if (unlikely(!image_scale(io->thread, img, rdi->image)))
277 image_destroy(rdi->image);
278 if (rdi->need_destroy)
285 /* Merge with background */
286 if ((io->flags ^ rdi->image->flags) & IMAGE_ALPHA)
288 DBG("Aplying background");
289 rdi->need_transformations = 0;
290 rdi->need_destroy = rdi->need_transformations || !io->pool;
291 struct image *img = image_new(io->thread, io->cols, io->rows, io->flags, rdi->need_transformations ? NULL : io->pool);
294 image_destroy(rdi->image);
297 if (unlikely(!image_apply_background(io->thread, img, rdi->image, &io->background_color)))
299 image_destroy(rdi->image);
300 if (rdi->need_destroy)
307 ASSERT(!rdi->need_transformations);
311 io->image = rdi->image;
312 io->image_destroy = rdi->need_destroy;
317 image_io_read_data_break(struct image_io_read_data_internals *rdi, struct image_io *io UNUSED)
319 DBG("image_io_read_data_break()");
320 if (rdi->need_destroy)
321 image_destroy(rdi->image);