]> mj.ucw.cz Git - libucw.git/blobdiff - images/image.c
fixes in libimages Makefile
[libucw.git] / images / image.c
index 4fb349dee5696df4598b88863e19be8b0993fa19..914d0f17c4f52112f3fabe20e637b3a2ff52d0d3 100644 (file)
@@ -14,7 +14,7 @@
 #include "images/images.h"
 #include <string.h>
 
-#define MAX_IMAGE_SIZE (1 << 30)
+#define MAX_IMAGE_BYTES (1 << 30)
 
 void
 image_thread_init(struct image_thread *it)
@@ -41,17 +41,10 @@ image_thread_err_format(struct image_thread *it, uns code, char *msg, ...)
   va_end(args);
 }
 
-struct image *
-image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool *pool)
+static inline uns
+flags_to_pixel_size(uns flags)
 {
-  DBG("image_new(cols=%u rows=%u flags=0x%x pool=%p)", cols, rows, flags, pool);
-  if (cols >= 0x10000 || rows >= 0x10000)
-    {
-      image_thread_err(it, IMAGE_ERR_INVALID_DIMENSIONS, "Image dimension(s) too large");
-      return NULL;
-    }
-  struct image *img;
-  uns pixel_size, row_size, image_size, align;
+  uns pixel_size;
   switch (flags & IMAGE_COLOR_SPACE)
     {
       case COLOR_SPACE_GRAYSCALE:
@@ -65,6 +58,22 @@ image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool
     }
   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)
+{
+  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);
+      return NULL;
+    }
+  struct image *img;
+  uns pixel_size, row_size, align;
+  pixel_size = flags_to_pixel_size(flags);
   switch (pixel_size)
     {
       case 1:
@@ -80,35 +89,36 @@ image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool
        ASSERT(0);
     }
   if (flags & IMAGE_SSE_ALIGNED)
-    align = MAX(16, sizeof(uns));
+    align = IMAGE_SSE_ALIGN_SIZE;
   else if (flags & IMAGE_PIXELS_ALIGNED)
     align = pixel_size;
   else
     align = 1;
   row_size = cols * pixel_size;
   row_size = ALIGN(row_size, align);
-  u64 image_size_64 = row_size * rows;
-  if (image_size_64 > MAX_IMAGE_SIZE)
+  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))
     {
       image_thread_err(it, IMAGE_ERR_INVALID_DIMENSIONS, "Image does not fit in memory");
       return NULL;
     }
-  if (!(image_size = image_size_64))
+  if (pool)
+    img = mp_alloc(pool, bytes_64);
+  else
     {
-      image_thread_err(it, IMAGE_ERR_INVALID_DIMENSIONS, "Zero dimension(s)");
-      return NULL;
+      img = xmalloc(bytes_64);
+      flags |= IMAGE_NEED_DESTROY;
     }
-  uns size = sizeof(struct image) + image_size + MAX(16, sizeof(uns)) - 1 + sizeof(uns);
-  img = pool ? mp_alloc(pool, size) : xmalloc(size);
   bzero(img, sizeof(struct image));
   byte *p = (byte *)img + sizeof(struct image);
-  img->pixels = ALIGN_PTR(p, MAX(16, sizeof(uns)));
+  img->pixels = ALIGN_PTR(p, IMAGE_SSE_ALIGN_SIZE);
   img->flags = flags;
   img->pixel_size = pixel_size;
   img->cols = cols;
   img->rows = rows;
   img->row_size = row_size;
-  img->image_size = image_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);
   return img;
@@ -119,18 +129,20 @@ image_clone(struct image_thread *it, struct image *src, uns flags, struct mempoo
 {
   DBG("image_clone(src=%p flags=0x%x pool=%p)", src, src->flags, pool);
   struct image *img;
-  flags &= ~IMAGE_CHANNELS_FORMAT;
+  flags &= IMAGE_NEW_FLAGS & ~IMAGE_CHANNELS_FORMAT;
   flags |= src->flags & IMAGE_CHANNELS_FORMAT;
   if (!(img = image_new(it, src->cols, src->rows, flags, pool)))
     return NULL;
   if (img->image_size)
     {
-      if (src->pixel_size != img->pixel_size)
+      if (src->pixel_size != img->pixel_size) /* conversion between aligned and unaligned RGB */
         {
-         struct image *sec_img = src;
+#        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{ *(u32 *)pos = *(u32 *)sec_pos; }while(0)
+#         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"
        }
       else if (src->row_size != img->row_size)
@@ -152,10 +164,11 @@ image_clone(struct image_thread *it, struct image *src, uns flags, struct mempoo
 }
 
 void
-image_destroy(struct image_thread *it UNUSED, struct image *img)
+image_destroy(struct image *img)
 {
   DBG("image_destroy(img=%p)", img);
-  xfree((byte *)img);
+  if (img->flags & IMAGE_NEED_DESTROY)
+    xfree(img);
 }
 
 void
@@ -166,6 +179,41 @@ image_clear(struct image_thread *it UNUSED, struct image *img)
     bzero(img->pixels, img->image_size);
 }
 
+struct image *
+image_init_matrix(struct image_thread *it, 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);
+      return NULL;
+    }
+  img->pixels = pixels;
+  img->cols = cols;
+  img->rows = rows;
+  img->pixel_size = flags_to_pixel_size(flags);
+  img->row_size = row_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)
+{
+  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->row_size = src->row_size;
+  img->image_size = src->row_size * rows;
+  img->flags = src->flags & IMAGE_NEW_FLAGS;
+  img->flags |= IMAGE_GAPS_PROTECTED;
+  return img;
+}
+
 byte *
 color_space_to_name(enum color_space cs)
 {