X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=images%2Fio-main.c;h=f69b8b6c4a4bf926706f365c36cbbd5f2d6f3dc1;hb=3d7098f19d62bb9000048d1f36a2091e0fc263b0;hp=ac3c3c6272d8f18ffedb3e67691006240765a9ae;hpb=7ae5e8180b1211be9a9ba3328115990982204a6a;p=libucw.git diff --git a/images/io-main.c b/images/io-main.c index ac3c3c62..f69b8b6c 100644 --- a/images/io-main.c +++ b/images/io-main.c @@ -10,17 +10,55 @@ #undef LOCAL_DEBUG #include "lib/lib.h" +#include "lib/mempool.h" #include "images/images.h" +#include "images/error.h" #include "images/io-main.h" +#include "images/color.h" + #include -void -image_io_init(struct image_thread *it, struct image_io *io) +int +image_io_init(struct image_context *ctx, struct image_io *io) { DBG("image_io_init()"); bzero(io, sizeof(*io)); - io->thread = it; + io->context = ctx; +#ifdef CONFIG_IMAGES_LIBJPEG + if (!libjpeg_init(io)) + goto libjpeg_failed; +#endif +#ifdef CONFIG_IMAGES_LIBPNG + if (!libpng_init(io)) + goto libpng_failed; +#endif +#ifdef CONFIG_IMAGES_LIBUNGIF + if (!libungif_init(io)) + goto libungif_failed; +#endif +#ifdef CONFIG_IMAGES_LIBMAGICK + if (!libmagick_init(io)) + goto libmagick_failed; +#endif io->internal_pool = mp_new(1024); + return 1; +#ifdef CONFIG_IMAGES_LIBMAGICK + libmagick_cleanup(io); +libmagick_failed: +#endif +#ifdef CONFIG_IMAGES_LIBUNGIF + libungif_cleanup(io); +libungif_failed: +#endif +#ifdef CONFIG_IMAGES_LIBPNG + libpng_cleanup(io); +libpng_failed: +#endif +#ifdef CONFIG_IMAGES_LIBJPEG + libjpeg_cleanup(io); +libjpeg_failed: +#endif + return 0; } static inline void @@ -36,10 +74,10 @@ image_io_read_cancel(struct image_io *io) static inline void image_io_image_destroy(struct image_io *io) { - if (io->image_destroy) + if (io->image && (io->flags & IMAGE_IO_NEED_DESTROY)) { image_destroy(io->image); - io->image_destroy = 0; + io->flags &= ~IMAGE_IO_NEED_DESTROY; io->image = NULL; } } @@ -50,6 +88,18 @@ image_io_cleanup(struct image_io *io) DBG("image_io_cleanup()"); image_io_read_cancel(io); image_io_image_destroy(io); +#ifdef CONFIG_IMAGES_LIBMAGICK + libmagick_cleanup(io); +#endif +#ifdef CONFIG_IMAGES_LIBUNGIF + libungif_cleanup(io); +#endif +#ifdef CONFIG_IMAGES_LIBPNG + libpng_cleanup(io); +#endif +#ifdef CONFIG_IMAGES_LIBJPEG + libjpeg_cleanup(io); +#endif mp_delete(io->internal_pool); } @@ -60,9 +110,11 @@ image_io_reset(struct image_io *io) image_io_read_cancel(io); image_io_image_destroy(io); struct mempool *pool = io->internal_pool; + struct image_context *ctx = io->context; mp_flush(pool); bzero(io, sizeof(*io)); io->internal_pool = pool; + io->context = ctx; } int @@ -89,7 +141,7 @@ image_io_read_header(struct image_io *io) break; case IMAGE_FORMAT_GIF: -#if defined(CONFIG_IMAGES_LIBUNGIF) +#if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF) return libungif_read_header(io); #elif defined(CONFIG_IMAGES_LIBMAGICK) return libmagick_read_header(io); @@ -97,13 +149,15 @@ image_io_read_header(struct image_io *io) break; case IMAGE_FORMAT_UNDEFINED: - // FIXME: auto-detect +#if defined (CONFIG_IMAGES_LIBMAGICK) + return libmagick_read_header(io); +#endif break; default: ASSERT(0); } - image_thread_err(io->thread, IMAGE_ERR_INVALID_FILE_FORMAT, "Image format not supported."); + IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_FILE_FORMAT, "Image format not supported."); return 0; } @@ -136,7 +190,7 @@ image_io_read_data(struct image_io *io, int ref) break; case IMAGE_FORMAT_GIF: -#if defined(CONFIG_IMAGES_LIBUNGIF) +#if defined(CONFIG_IMAGES_LIBUNGIF) || defined(CONFIG_IMAGES_LIBGIF) result = libungif_read_data(io); #elif defined(CONFIG_IMAGES_LIBMAGICK) result = libmagick_read_data(io); @@ -145,13 +199,23 @@ image_io_read_data(struct image_io *io, int ref) #endif break; + case IMAGE_FORMAT_UNDEFINED: +#if defined(CONFIG_IMAGES_LIBMAGICK) + result = libmagick_read_data(io); +#else + ASSERT(0); +#endif + break; + default: ASSERT(0); } if (result) { - if (ref) - io->image_destroy = 0; + if (!ref) + io->flags |= IMAGE_IO_NEED_DESTROY; + else + io->flags &= ~IMAGE_IO_NEED_DESTROY; return io->image; } else @@ -197,7 +261,7 @@ image_io_write(struct image_io *io) default: break; } - image_thread_err(io->thread, IMAGE_ERR_INVALID_FILE_FORMAT, "Image format not supported."); + IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_FILE_FORMAT, "Output format not supported."); return 0; } @@ -237,3 +301,78 @@ image_file_name_to_format(byte *file_name) byte *extension = strrchr(file_name, '.'); return extension ? image_extension_to_format(extension + 1) : IMAGE_FORMAT_UNDEFINED; } + +struct image * +image_io_read_data_prepare(struct image_io_read_data_internals *rdi, struct image_io *io, uns cols, uns rows, uns flags) +{ + DBG("image_io_read_data_prepare()"); + if (rdi->need_transformations = io->cols != cols || io->rows != rows || + ((io->flags ^ flags) & IMAGE_NEW_FLAGS)) + return rdi->image = image_new(io->context, cols, rows, flags & IMAGE_IO_IMAGE_FLAGS, NULL); + else + return rdi->image = image_new(io->context, io->cols, io->rows, io->flags & IMAGE_IO_IMAGE_FLAGS, io->pool); +} + +int +image_io_read_data_finish(struct image_io_read_data_internals *rdi, struct image_io *io) +{ + DBG("image_io_read_data_finish()"); + if (rdi->need_transformations) + { + /* Scale the image */ + if (io->cols != rdi->image->cols || io->rows != rdi->image->rows) + { + DBG("Scaling image"); + uns flags = rdi->image->flags; + if (!(rdi->need_transformations = ((io->flags ^ rdi->image->flags) & (IMAGE_NEW_FLAGS & ~IMAGE_PIXELS_ALIGNED)))) + flags = io->flags; + struct image *img = image_new(io->context, io->cols, io->rows, flags, rdi->need_transformations ? NULL : io->pool); + if (unlikely(!img)) + { + image_destroy(rdi->image); + return 0; + } + if (unlikely(!image_scale(io->context, img, rdi->image))) + { + image_destroy(rdi->image); + image_destroy(img); + return 0; + } + image_destroy(rdi->image); + rdi->image = img; + } + + /* Convert pixel format */ + if (io->flags != rdi->image->flags) + { + struct image *img = image_new(io->context, io->cols, io->rows, io->flags, io->pool); + if (unlikely(!img)) + { + image_destroy(rdi->image); + return 0; + } + struct image_conv_options opt = image_conv_defaults; + opt.background = io->background_color; + if (unlikely(!image_conv(io->context, img, rdi->image, &opt))) + { + image_destroy(rdi->image); + image_destroy(img); + return 0; + } + image_destroy(rdi->image); + rdi->image = img; + } + } + + /* Success */ + io->image = rdi->image; + return 1; +} + +void +image_io_read_data_break(struct image_io_read_data_internals *rdi, struct image_io *io UNUSED) +{ + DBG("image_io_read_data_break()"); + if (rdi->image) + image_destroy(rdi->image); +}