]> mj.ucw.cz Git - libucw.git/blobdiff - images/image.c
Fastbuf: fbmulti: *'s and whitespace
[libucw.git] / images / image.c
index deb8f9f81141f81b4d53425ad2e6074c5a9b8b7c..d0d16d8feab2b109ee70e02a854b5825557d3b2b 100644 (file)
@@ -9,72 +9,42 @@
 
 #undef LOCAL_DEBUG
 
-#include "lib/lib.h"
-#include "lib/mempool.h"
-#include "images/images.h"
-#include <string.h>
-
-#define MAX_IMAGE_BYTES (1 << 30)
-
-void
-image_thread_init(struct image_thread *it)
-{
-  DBG("image_thread_init()");
-  bzero(it, sizeof(*it));
-  it->pool = mp_new(1024);
-}
-
-void
-image_thread_cleanup(struct image_thread *it)
-{
-  DBG("image_thread_cleanup()");
-  mp_delete(it->pool);
-}
+#include <ucw/lib.h>
+#include <ucw/mempool.h>
+#include <images/images.h>
+#include <images/error.h>
+#include <images/color.h>
 
-void
-image_thread_err_format(struct image_thread *it, uns code, char *msg, ...)
-{
-  va_list args;
-  va_start(args, msg);
-  it->err_code = code;
-  it->err_msg = mp_vprintf(it->pool, msg, args);
-  va_end(args);
-}
+#include <string.h>
 
 static inline uns
 flags_to_pixel_size(uns flags)
 {
-  uns pixel_size;
-  switch (flags & IMAGE_COLOR_SPACE)
-    {
-      case COLOR_SPACE_GRAYSCALE:
-       pixel_size = 1;
-       break;
-      case COLOR_SPACE_RGB:
-       pixel_size = 3;
-       break;
-      default:
-       ASSERT(0);
-    }
+  uns pixel_size = color_space_channels[flags & IMAGE_COLOR_SPACE];
   if (flags & IMAGE_ALPHA)
     pixel_size++;
   return pixel_size;
 }
 
 struct image *
-image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool *pool)
+image_new(struct image_context *ctx, uns cols, uns rows, uns flags, struct mempool *pool)
 {
   DBG("image_new(cols=%u rows=%u flags=0x%x pool=%p)", cols, rows, flags, pool);
   flags &= IMAGE_NEW_FLAGS;
   if (unlikely(!image_dimensions_valid(cols, rows)))
     {
-      image_thread_err_format(it, IMAGE_ERR_INVALID_DIMENSIONS, "Invalid image dimensions (%ux%u)", cols, rows);
+      IMAGE_ERROR(ctx, IMAGE_ERROR_INVALID_DIMENSIONS, "Invalid image dimensions (%ux%u)", cols, rows);
       return NULL;
     }
   struct image *img;
-  uns pixel_size, row_size, align;
-  pixel_size = flags_to_pixel_size(flags);
-  switch (pixel_size)
+  uns channels, pixel_size, row_pixels_size, row_size, align;
+  pixel_size = channels = flags_to_pixel_size(flags);
+  if (!channels || channels > 4)
+    {
+      IMAGE_ERROR(ctx, IMAGE_ERROR_INVALID_PIXEL_FORMAT, "Invalid number of color channels (%u)", channels);
+      return NULL;
+    }
+  switch (channels)
     {
       case 1:
       case 2:
@@ -94,13 +64,13 @@ image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool
     align = pixel_size;
   else
     align = 1;
-  row_size = cols * pixel_size;
-  row_size = ALIGN(row_size, align);
+  row_pixels_size = cols * pixel_size;
+  row_size = ALIGN_TO(row_pixels_size, align);
   u64 image_size_64 = (u64)row_size * rows;
   u64 bytes_64 = image_size_64 + (sizeof(struct image) + IMAGE_SSE_ALIGN_SIZE - 1 + sizeof(uns));
-  if (unlikely(bytes_64 > MAX_IMAGE_BYTES))
+  if (unlikely(bytes_64 > image_max_bytes))
     {
-      image_thread_err(it, IMAGE_ERR_INVALID_DIMENSIONS, "Image does not fit in memory");
+      IMAGE_ERROR(ctx, IMAGE_ERROR_INVALID_DIMENSIONS, "Image does not fit in memory");
       return NULL;
     }
   if (pool)
@@ -114,10 +84,12 @@ image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool
   byte *p = (byte *)img + sizeof(struct image);
   img->pixels = ALIGN_PTR(p, IMAGE_SSE_ALIGN_SIZE);
   img->flags = flags;
+  img->channels = channels;
   img->pixel_size = pixel_size;
   img->cols = cols;
   img->rows = rows;
   img->row_size = row_size;
+  img->row_pixels_size = row_pixels_size;
   img->image_size = image_size_64;
   DBG("img=%p flags=0x%x pixel_size=%u row_size=%u image_size=%u pixels=%p",
     img, img->flags, img->pixel_size, img->row_size, img->image_size, img->pixels);
@@ -125,34 +97,35 @@ image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool
 }
 
 struct image *
-image_clone(struct image_thread *it, struct image *src, uns flags, struct mempool *pool)
+image_clone(struct image_context *ctx, struct image *src, uns flags, struct mempool *pool)
 {
   DBG("image_clone(src=%p flags=0x%x pool=%p)", src, src->flags, pool);
   struct image *img;
   flags &= IMAGE_NEW_FLAGS & ~IMAGE_CHANNELS_FORMAT;
   flags |= src->flags & IMAGE_CHANNELS_FORMAT;
-  if (!(img = image_new(it, src->cols, src->rows, flags, pool)))
+  if (!(img = image_new(ctx, src->cols, src->rows, flags, pool)))
     return NULL;
+  ASSERT(src->channels == img->channels);
   if (img->image_size)
     {
       if (src->pixel_size != img->pixel_size) /* conversion between aligned and unaligned RGB */
         {
+         ASSERT(src->channels == 3);
 #        define IMAGE_WALK_PREFIX(x) walk_##x
 #         define IMAGE_WALK_INLINE
 #        define IMAGE_WALK_IMAGE img
 #        define IMAGE_WALK_SEC_IMAGE src
 #         define IMAGE_WALK_DOUBLE
 #         define IMAGE_WALK_DO_STEP do{ walk_pos[0] = walk_sec_pos[0]; walk_pos[1] = walk_sec_pos[1]; walk_pos[2] = walk_sec_pos[2]; }while(0)
-#         include "images/image-walk.h"
+#         include <images/image-walk.h>
        }
       else if (src->row_size != img->row_size || ((img->flags | src->flags) & IMAGE_GAPS_PROTECTED))
         {
           byte *s = src->pixels;
           byte *d = img->pixels;
-          uns bytes = src->cols * img->pixel_size;
          for (uns row = src->rows; row--; )
             {
-             memcpy(d, s, bytes);
+             memcpy(d, s, src->row_pixels_size);
              d += img->row_size;
              s += src->row_size;
            }
@@ -172,7 +145,7 @@ image_destroy(struct image *img)
 }
 
 void
-image_clear(struct image_thread *it UNUSED, struct image *img)
+image_clear(struct image_context *ctx UNUSED, struct image *img)
 {
   DBG("image_clear(img=%p)", img);
   if (img->image_size)
@@ -188,34 +161,36 @@ image_clear(struct image_thread *it UNUSED, struct image *img)
 }
 
 struct image *
-image_init_matrix(struct image_thread *it, struct image *img, byte *pixels, uns cols, uns rows, uns row_size, uns flags)
+image_init_matrix(struct image_context *ctx, struct image *img, byte *pixels, uns cols, uns rows, uns row_size, uns flags)
 {
   DBG("image_init_matrix(img=%p pixels=%p cols=%u rows=%u row_size=%u flags=0x%x)", img, pixels, cols, rows, row_size, flags);
   if (unlikely(!image_dimensions_valid(cols, rows)))
     {
-      image_thread_err_format(it, IMAGE_ERR_INVALID_DIMENSIONS, "Invalid image dimensions (%ux%u)", cols, rows);
+      IMAGE_ERROR(ctx, IMAGE_ERROR_INVALID_DIMENSIONS, "Invalid image dimensions (%ux%u)", cols, rows);
       return NULL;
     }
   img->pixels = pixels;
   img->cols = cols;
   img->rows = rows;
-  img->pixel_size = flags_to_pixel_size(flags);
+  img->pixel_size = img->channels = flags_to_pixel_size(flags);
   img->row_size = row_size;
+  img->row_pixels_size = cols * img->pixel_size;
   img->image_size = rows * row_size;
   img->flags = flags & (IMAGE_NEW_FLAGS | IMAGE_GAPS_PROTECTED);
   return img;
 }
 
 struct image *
-image_init_subimage(struct image_thread *it UNUSED, struct image *img, struct image *src, uns left, uns top, uns cols, uns rows)
+image_init_subimage(struct image_context *ctx UNUSED, struct image *img, struct image *src, uns left, uns top, uns cols, uns rows)
 {
   DBG("image_init_subimage(img=%p src=%p left=%u top=%u cols=%u rows=%u)", img, src, left, top, cols, rows);
   ASSERT(left + cols <= src->cols && top + rows <= src->rows);
   img->pixels = src->pixels + left * src->pixel_size + top * src->row_size;
   img->cols = cols;
   img->rows = rows;
-  img->pixel_size = src->pixel_size;
+  img->pixel_size = img->channels = src->pixel_size;
   img->row_size = src->row_size;
+  img->row_pixels_size = cols * src->pixel_size;
   img->image_size = src->row_size * rows;
   img->flags = src->flags & IMAGE_NEW_FLAGS;
   img->flags |= IMAGE_GAPS_PROTECTED;
@@ -223,45 +198,30 @@ image_init_subimage(struct image_thread *it UNUSED, struct image *img, struct im
 }
 
 byte *
-color_space_to_name(enum color_space cs)
-{
-  return image_channels_format_to_name(cs);
-}
-
-byte *
-image_channels_format_to_name(uns format)
+image_channels_format_to_name(uns format, byte *buf)
 {
-  switch (format)
-    {
-      case COLOR_SPACE_GRAYSCALE:
-       return "Gray";
-      case COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA:
-       return "GrayAlpha";
-      case COLOR_SPACE_RGB:
-       return "RGB";
-      case COLOR_SPACE_RGB | IMAGE_ALPHA:
-       return "RGBAlpha";
-      default:
-       return NULL;
-    }
+  byte *cs_name = color_space_id_to_name(format & IMAGE_COLOR_SPACE);
+  uns l = strlen(cs_name);
+  memcpy(buf, cs_name, l + 1);
+  if (format & IMAGE_ALPHA)
+    strcpy(buf + l, "+Alpha");
+  return buf;
 }
 
 uns
 image_name_to_channels_format(byte *name)
 {
-  if (!strcasecmp(name, "gray"))
-    return COLOR_SPACE_GRAYSCALE;
-  if (!strcasecmp(name, "grayscale"))
-    return COLOR_SPACE_GRAYSCALE;
-  if (!strcasecmp(name, "grayalpha"))
-    return COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA;
-  if (!strcasecmp(name, "grayscalealpha"))
-    return COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA;
-  if (!strcasecmp(name, "rgb"))
-    return COLOR_SPACE_RGB;
-  if (!strcasecmp(name, "rgbalpha"))
-    return COLOR_SPACE_RGB + IMAGE_ALPHA;
-  if (!strcasecmp(name, "rgba"))
-    return COLOR_SPACE_RGB + IMAGE_ALPHA;
+  uns i;
+  if (i = color_space_name_to_id(name))
+    return i;
+  uns l = strlen(name);
+  if (l > 6 && !strcasecmp(name + l - 5, "+alpha"))
+    {
+      byte buf[l + 1];
+      memcpy(buf, name, l - 6);
+      buf[l - 6] = 0;
+      if (i = color_space_name_to_id(name))
+       return i;
+    }
   return 0;
 }