]> mj.ucw.cz Git - libucw.git/blobdiff - images/io-main.c
more MJ's corrections... to be continue
[libucw.git] / images / io-main.c
index ac3c3c6272d8f18ffedb3e67691006240765a9ae..7b176b70a187e4944bfa8af6966e4a3a3f6b96a3 100644 (file)
 #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 <string.h>
 
-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 +73,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 +87,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 +109,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 +140,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 +148,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 +189,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 +198,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 +260,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 +300,84 @@ 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;
+       }
+
+      /* Merge with background */
+      if ((io->flags ^ rdi->image->flags) & IMAGE_ALPHA)
+        {
+         DBG("Applying background");
+         uns flags = rdi->image->flags & ~IMAGE_ALPHA;
+         if (!(rdi->need_transformations = (flags ^ io->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_apply_background(io->context, img, rdi->image, &io->background_color)))
+            {
+              image_destroy(rdi->image);
+             image_destroy(img);
+             return 0;
+           }
+         image_destroy(rdi->image);
+         rdi->image = img;
+       }
+
+      // FIXME: support for various color spaces
+
+      ASSERT(!rdi->need_transformations);
+    }
+
+  /* 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);
+}