]> mj.ucw.cz Git - libucw.git/commitdiff
backup of some experimental code in duplicates search
authorPavel Charvat <pavel.charvat@netcentrum.cz>
Sun, 14 May 2006 20:25:57 +0000 (22:25 +0200)
committerPavel Charvat <pavel.charvat@netcentrum.cz>
Sun, 14 May 2006 20:25:57 +0000 (22:25 +0200)
images/Makefile
images/color.c
images/color.h
images/dup-cmp.c
images/dup-cmp.h
images/hilbert-test.c
images/image-idx.c
images/image-obj.h
images/image-sig.c
images/image-sig.h
images/images.h

index ccc343a323d481a64d240ae79e2cdc00211751ec..868dfbae1a51eafbbecc8962c89b95685f93ec6e 100644 (file)
@@ -12,7 +12,7 @@ $(o)/images/image-idx: LIBS+=-lGraphicsMagick -ljpeg -lpng
 $(o)/images/image-test: $(o)/images/image-test.o $(o)/images/kd-tree.o $(LIBSH)
 
 $(o)/images/color-t: LIBS+=-lm
-$(o)/images/hilbert-test: LIBS+= $(LIBSH)
+$(o)/images/hilbert-test: LIBS+=-lm $(LIBSH)
 
 TESTS+=$(addprefix $(o)/images/,color.test hilbert-test.test)
 
index 036535c7483e9db024274c3454a20882a4d7ce56..e6846605681d45a4c955f30192113370445a542c 100644 (file)
@@ -331,7 +331,7 @@ main(void)
 #ifdef LOCAL_DEBUG
 #define CNT 1000000
 #define TESTS 10
-  byte *a = xmalloc(3 * CNT), *b = xmalloc_zero(3 * CNT);
+  byte *a = xmalloc(3 * CNT), *b = xmalloc(3 * CNT);
   for (uns i = 0; i < 3 * CNT; i++)
     a[i] = random_max(256);
   init_timer();
index 59acd32d1026de6616de1bf4f8bac8fc4c9b57c3..ec3cd4afd99e928f88baef9f8bafa3a0712d3d5c 100644 (file)
@@ -16,7 +16,7 @@
  *     - maybe try to generate a long switch in color_conv_pixel()
  *       with optimized entries instead of access to interpolation table
  *     - most of multiplications in srgb_to_luv_pixels can be replaced
- *       with tables lookup... tests shows almost the speed for random
+ *       with tables lookup... tests shows almost the same speed for random
  *       input and cca 40% gain when input colors fit in CPU chache
  */
 
@@ -59,6 +59,7 @@ extern u32 srgb_to_luv_tab3[20 << SRGB_TO_LUV_TAB3_SIZE];
 void srgb_to_luv_init(void);
 void srgb_to_luv_pixels(byte *dest, byte *src, uns count);
 
+/* L covers the interval [0..255]; u and v are centered to 128 and scaled by 1/4 in respect of L */
 static inline void
 srgb_to_luv_pixel(byte *dest, byte *src)
 {
index 6a249ec3301db9d4d2b703f181275fbcd480fb5e..fbb2de8b801346c5c181f625e740e121f20c1bb6 100644 (file)
@@ -14,6 +14,8 @@
  *      - maybe better/slower last step
  *      - different thresholds for various transformations
  *      - do not test all transformations for symetric pictures
+ *      - allocated memory could be easily decreased to about 1/3 
+ *        for aspect ratio threshold near one
  *      - ... secret ideas :-)
  */
 
@@ -43,8 +45,17 @@ pixels_average(byte *dest, byte *src1, byte *src2)
   dest[2] = ((uns)src1[2] + (uns)src2[2]) >> 1;
 }
 
+uns
+image_dup_estimate_size(uns width, uns height)
+{
+  uns cols, rows;
+  for (cols = 0; (uns)(2 << cols) < width; cols++);
+  for (rows = 0; (uns)(2 << rows) < height; rows++);
+  return sizeof(struct image_dup) + (12 << (cols + rows));
+}
+
 void
-image_dup_init(struct image_dup *dup, struct image *image, struct mempool *pool)
+image_dup_init(struct image_dup *dup, struct image_data *image, struct mempool *pool)
 {
   ASSERT(image->width && image->height);
   
index d730f0e6d066f551cd01445fd0f42b3def763d6a..f3a1ee686853fea37ca30fda1e783b4b963e0f24 100644 (file)
@@ -1,10 +1,10 @@
 #ifndef _IMAGES_DUP_CMP_H
 #define _IMAGES_DUP_CMP_H
 
-struct image;
+struct image_data;
 
 struct image_dup {
-  struct image *image;
+  struct image_data *image;
   byte *buf;
   uns buf_size;
   uns flags;
@@ -20,7 +20,8 @@ struct image_dup {
 #define IMAGE_DUP_TRANS_ID     0x01
 #define IMAGE_DUP_TRANS_ALL    0xff
 
-void image_dup_init(struct image_dup *dup, struct image *image, struct mempool *pool);
+void image_dup_init(struct image_dup *dup, struct image_data *image, struct mempool *pool);
 int image_dup_compare(struct image_dup *dup1, struct image_dup *dup2, uns trans);
+uns image_dup_estimate_size(uns width, uns height);
 
 #endif
index 235c3ae4ebf1fe8814bbd8470a6c00b5ed594cf4..b07efa8c08e016d978f7b50bbe7ea9d419b0bfa1 100644 (file)
@@ -3,14 +3,80 @@
 #define LOCAL_DEBUG
 
 #include "lib/lib.h"
+#include "lib/mempool.h"
+#include "lib/math.h"
 
 #include <stdlib.h>
+#include <stdio.h>
+
+static struct mempool *pool;
+
+static uns dim;
+static uns order;
+
+static inline void
+rand_vec(uns *vec)
+{
+  for (uns i = 0; i < dim; i++)
+    vec[i] = (uns)rand() >> (32 - order);
+}
+
+static byte *
+print_vec(uns *vec)
+{
+  byte *s = mp_alloc(pool, dim * 16), *res = s;
+  *s++ = '(';
+  for (uns i = 0; i < dim; i++)
+    {
+      if (i)
+       *s++ = ' ';
+      s += sprintf(s, "%x", vec[i]);
+    }
+  *s++ = ')';
+  *s = 0;
+  return res;
+}
+
+static inline int
+cmp_vec(uns *vec1, uns *vec2)
+{
+  for (uns i = dim; i--; )
+    if (vec1[i] < vec2[i])
+      return -1;
+    else if (vec1[i] > vec2[i])
+      return 1;
+  return 0;
+}
+
+#if 0
+static long double
+param_dist(uns *vec1, uns *vec2)
+{
+  long double d1 = 0, d2 = 0;
+  for (uns i = 0; i < dim; i++)
+    {
+      d1 = (d1 + vec1[i]) / ((u64)1 << order);
+      d2 = (d2 + vec2[i]) / ((u64)1 << order);
+    }
+  return fabsl(d1 - d2);
+}
+
+static long double
+vec_dist(uns *vec1, uns *vec2)
+{
+  long double d = 0;
+  for (uns i = 0; i < dim; i++)
+    {
+      long double x = fabsl(vec1[i] - vec2[i]) / ((u64)1 << order);
+      d += x * x;
+    }
+  return sqrtl(d);
+}
+#endif
 
-static uns test1_dim;
-static uns test1_order;
 #define HILBERT_PREFIX(x) test1_##x
-#define HILBERT_DIM test1_dim
-#define HILBERT_ORDER test1_order
+#define HILBERT_DIM dim
+#define HILBERT_ORDER order
 #define HILBERT_WANT_DECODE
 #define HILBERT_WANT_ENCODE
 #include "images/hilbert.h"
@@ -19,17 +85,16 @@ static void
 test1(void)
 {
   uns a[32], b[32], c[32];
-  for (test1_dim = 2; test1_dim <= 8; test1_dim++)
-    for (test1_order = 8; test1_order <= 32; test1_order++)
+  for (dim = 2; dim <= 8; dim++)
+    for (order = 8; order <= 32; order++)
       for (uns i = 0; i < 1000; i++)
         {
-          for (uns j = 0; j < test1_dim; j++)
-           a[j] = (uns)rand() >> (32 - test1_order);
+         rand_vec(a);
           test1_encode(b, a);
           test1_decode(c, b);
-          for (uns j = 0; j < test1_dim; j++)
-           if (a[j] != c[j])
-             die("Error... dim=%d order=%d testnum=%d index=%d val1=0x%08x val2=0x%08x", test1_dim, test1_order, i, j, a[j], c[j]);
+         if (cmp_vec(a, c))
+           die("Error... dim=%d order=%d testnum=%d ... %s -> %s -> %s", 
+               dim, order, i, print_vec(a), print_vec(b), print_vec(c));
         }
 }
 
@@ -53,6 +118,7 @@ test_origin(void)
 int
 main(int argc UNUSED, char **argv UNUSED)
 {
+  pool = mp_new(1 << 16);
   test1();
   //test_origin();
   return 0;
index 8ef17b6bd942f68a638bbba654703e971a32f687..c53eb8b88ecd7b8434c13fd79bce3c9968df2f0a 100644 (file)
@@ -1,3 +1,5 @@
+// FIXME: this file is full of experiments... will be completely different in final version
+
 #undef LOCAL_DEBUG
 
 #include "sherlock/sherlock.h"
@@ -71,10 +73,10 @@ generate_signatures(uns limit)
           die("Failed to read card");
         if (attr = obj_find_attr(obj, 'N'))
           {
-#ifdef LOCAL_DEBUG         
+#ifdef LOCAL_DEBUG
            byte *url = obj_find_aval(obj_find_attr(obj, 'U' + OBJ_ATTR_SON)->son, 'U');
            DBG("Reading oid=%d url=%s", oid, url);
-#endif     
+#endif
            struct image_obj imo;
            imo_init(&imo, pool, obj);
            if (imo_decompress_thumbnail(&imo))
@@ -111,6 +113,162 @@ generate_signatures(uns limit)
   bclose(fb_signatures);
 }
 
+/*********************************************************************************/
+
+struct vectors_node {
+  oid_t oid;
+  u32 temp;
+  struct image_vector vec;
+};
+
+static uns vectors_count;
+static struct vectors_node *vectors;
+
+static void
+vectors_read(void)
+{
+  log(L_DEBUG, "Reading signature vectors");
+  struct fastbuf *fb = index_bopen("image-sig", O_RDONLY);
+  vectors_count = bgetl(fb);
+  if (vectors_count)
+    {
+      vectors = xmalloc(vectors_count * sizeof(struct vectors_node));
+      for (uns i = 0; i < vectors_count; i++)
+        {
+         bread(fb, &vectors[i].oid, sizeof(oid_t));
+         bread(fb, &vectors[i].vec, sizeof(struct image_vector));
+         bskip(fb, bgetc(fb) * sizeof(struct image_region));
+       }
+    }
+  bclose(fb);
+}
+
+static void
+vectors_cleanup(void)
+{
+  log(L_DEBUG, "Freeing signature vectors");
+  if (vectors_count)
+    xfree(vectors);
+}
+
+/*********************************************************************************/
+
+static u64 random_clusters_max_size = 500000;
+static uns random_clusters_max_count = 1000;
+
+#define RANDOM_CLUSTERS_SIZE   0x7fffffff
+#define RANDOM_CLUSTERS_LAST   0x80000000
+
+static struct random_clusters_node {
+  struct vectors_node *node;
+  s32 dot_prod;
+} *random_clusters_temp;
+static uns random_clusters_count;
+
+#define ASORT_PREFIX(x) random_clusters_##x
+#define ASORT_KEY_TYPE s32
+#define ASORT_ELT(i) start[i].dot_prod
+#define ASORT_SWAP(i,j) do { struct random_clusters_node _s = start[i]; start[i] = start[j]; start[j] = _s; } while(0)
+#define ASORT_EXTRA_ARGS , struct random_clusters_node *start
+#include "lib/arraysort.h"
+
+static void
+random_clusters_init(void)
+{
+  if (!vectors_count)
+    return;
+  log(L_INFO, "Initializing random clusters generator");
+  random_clusters_temp = xmalloc(vectors_count * sizeof(struct random_clusters_node));
+  for (uns i = 0; i < vectors_count; i++)
+    random_clusters_temp[i].node = vectors + i;
+}
+
+static void
+random_clusters_build(void)
+{
+  random_clusters_count = 0;
+  if (!vectors_count)
+    return;
+
+  log(L_INFO, "Generating random clusters for duplicates comparision");
+
+  for (uns i = 0; i < vectors_count; i++)
+    vectors[i].temp &= RANDOM_CLUSTERS_SIZE;
+
+  /* Initialize recursion */
+  struct stk {
+    uns count;
+    struct random_clusters_node *start;
+  } stk_top[64], *stk = stk_top + 1;
+  stk->start = random_clusters_temp;
+  stk->count = vectors_count;
+
+  /* Main loop */
+  while (stk != stk_top)
+    {
+      /* Split conditions */
+      uns split;
+      if (stk->count < 2)
+       split = 0;
+      else if (stk->count > random_clusters_max_count)
+       split = 1;
+      else
+        {
+          s64 size = random_clusters_max_size;
+          for (uns i = 0; i < stk->count && size >= 0; i++)
+           size -= stk->start[i].node->temp;
+         split = size < 0;
+       }
+
+      /* BSP leaf node */
+      if (!split)
+        {
+         stk->start[stk->count - 1].node->temp |= RANDOM_CLUSTERS_LAST;
+         random_clusters_count++;
+         stk--;
+       }
+
+      /* BSP internal node */
+      else
+        {
+         /* Generate random normal vector of the splitting plane */
+         int normal[IMAGE_VEC_K];
+         for (uns i = 0; i < IMAGE_VEC_K; i++)
+           normal[i] = random_max(0x20001) - 0x10000;
+
+         /* Compute dot produts */
+         for (uns i = 0; i < stk->count; i++)
+           {
+             stk->start[i].dot_prod = 0;
+             for (uns j = 0; j < IMAGE_VEC_K; j++)
+               stk->start[i].dot_prod += normal[j] * stk->start[i].node->vec.f[j];
+           }
+
+         /* Sort... could be faster, because we only need the median */
+         random_clusters_sort(stk->count, stk->start);
+
+         /* Split in the middle */
+         stk[1].count = stk[0].count >> 1;
+         stk[0].count -= stk[1].count;
+         stk[1].start = stk[0].start;
+         stk[0].start += stk[1].count;
+         stk++;
+       }
+    }
+  log(L_INFO, "Generated %u clusters", random_clusters_count);
+}
+
+static void
+random_clusters_cleanup(void)
+{
+  if (vectors_count)
+    xfree(random_clusters_temp);
+}
+
+/*********************************************************************************/
+
+// FIXME: use vectors_read()... duplicate code
+
 struct signature_record {
   oid_t oid;
   struct image_vector vec;
@@ -293,12 +451,29 @@ build_kd_tree(void)
 
 /*********************************************************************************/
 
+struct pass1_hilbert {
+  u32 index;
+  struct image_vector vec;
+};
+
+struct pass1_node {
+  cnode lru_node;
+  cnode buf_node;
+  uns buf_size;
+  byte *buf;
+  oid_t oid;
+  byte *url;
+  struct image_data image;
+  struct image_dup dup;
+};
+
 static uns pass1_buf_size = 400 << 20;
 static uns pass1_max_count = 100000;
 static uns pass1_search_dist = 40;
 static uns pass1_search_count = 500;
 
 static struct mempool *pass1_pool;
+static struct pass1_hilbert *pass1_hilbert_list;
 static byte *pass1_buf_start;
 static byte *pass1_buf_pos;
 static uns pass1_buf_free;
@@ -310,17 +485,64 @@ static u64 pass1_reads;
 static u64 pass1_pairs;
 static u64 pass1_dups;
 static u64 pass1_shrinks;
+static u64 pass1_alloc_sum;
+
+#define HILBERT_PREFIX(x) pass1_hilbert_##x
+#define HILBERT_TYPE byte
+#define HILBERT_ORDER 8
+#define HILBERT_DIM IMAGE_VEC_K
+#define HILBERT_WANT_ENCODE
+#include "images/hilbert.h"
+
+#define ASORT_PREFIX(x) pass1_hilbert_sort_##x
+#define ASORT_KEY_TYPE struct image_vector *
+#define ASORT_ELT(i) (&pass1_hilbert_list[i].vec)
+#define ASORT_LT(x,y) (memcmp(x, y, sizeof(*x)) < 0)
+#define ASORT_SWAP(i,j) do { struct pass1_hilbert _s;          \
+               _s = pass1_hilbert_list[i];                     \
+               pass1_hilbert_list[i] = pass1_hilbert_list[j];  \
+               pass1_hilbert_list[j] = _s; } while(0)
+#include "lib/arraysort.h"
 
-struct pass1_node {
-  cnode lru_node;
-  cnode buf_node;
-  uns buf_size;
-  byte *buf;
-  oid_t oid;
-  byte *url;
-  struct image image;
-  struct image_dup dup;
-};
+static void
+pass1_hilbert_sort(void)
+{
+  DBG("Computing positions on the Hilbert curve");
+  pass1_hilbert_list = xmalloc(tree.count * sizeof(struct pass1_hilbert));
+  for (uns i = 0; i < tree.count; i++)
+    {
+      struct pass1_hilbert *h = pass1_hilbert_list + i;
+      h->index = i;
+      byte vec[IMAGE_VEC_K];
+      pass1_hilbert_encode(vec, precords[i]->vec.f);
+      for (uns j = 0; j < IMAGE_VEC_K; j++)
+       h->vec.f[j] = vec[IMAGE_VEC_K - 1 - j];
+    }
+  DBG("Sorting signatures in order of incresing parameters on the Hilbert curve");
+  pass1_hilbert_sort_sort(tree.count);
+#if 0
+  for (uns i = 0; i < tree.count; i++)
+    {
+      if (i)
+        {
+         byte *v1 = precords[pass1_hilbert_list[i - 1].index]->vec.f;
+         byte *v2 = precords[pass1_hilbert_list[i].index]->vec.f;
+#define SQR(x) ((x)*(x))
+          uns dist = 0;
+         for (uns j = 0; j < 6; j++)
+           dist += SQR(v1[j] - v2[j]);
+         DBG("dist %d", dist);
+       }
+      DBG("index %d", pass1_hilbert_list[i].index);
+    }
+#endif
+}
+
+static void
+pass1_hilbert_cleanup(void)
+{
+  xfree(pass1_hilbert_list);
+}
 
 #define HASH_PREFIX(x) pass1_hash_##x
 #define HASH_NODE struct pass1_node
@@ -410,7 +632,7 @@ pass1_buf_alloc(uns size)
     {
       /* free some lru nodes */
       //DBG("freeing lru nodes");
-      while (size > pass1_buf_size - pass1_buf_used || pass1_buf_used * 2 > pass1_buf_size)
+      while (size > pass1_buf_size - pass1_buf_used || pass1_buf_used > pass1_buf_size / 2)
         {
          if (unlikely(clist_empty(&pass1_lru_list))) // FIXME
            die("Buffer too small");
@@ -425,6 +647,7 @@ pass1_buf_alloc(uns size)
   pass1_buf_pos += size;
   pass1_buf_free -= size;
   pass1_buf_used += size;
+  pass1_alloc_sum += size;
   return result;
 }
 
@@ -502,6 +725,14 @@ pass1_node_unlock(struct pass1_node *node)
   clist_add_tail(&pass1_lru_list, &node->lru_node);
 }
 
+static void
+pass1_show_stats(void)
+{
+  log(L_INFO, "%d count, %Ld lookups, %Ld reads, %Ld pairs, %Ld dups, %Ld shrinks", tree.count,
+    (long long int)pass1_lookups, (long long int)pass1_reads,
+    (long long int)pass1_pairs, (long long int)pass1_dups, (long long int)pass1_shrinks);
+}
+
 static void
 pass1(void)
 {
@@ -509,7 +740,7 @@ pass1(void)
   ASSERT(tree.nodes);
 
   /* initialization */
-  pass1_lookups = pass1_reads = pass1_pairs = pass1_dups = pass1_shrinks = 0;
+  pass1_lookups = pass1_reads = pass1_pairs = pass1_dups = pass1_shrinks = pass1_alloc_sum = 0;
   fb_cards = bopen("index/cards", O_RDONLY, 10000); // FIXME
   fb_card_attrs = bopen("index/card-attrs", O_RDONLY, sizeof(struct card_attr)); // FIXME
   buck2obj = buck2obj_alloc();
@@ -520,6 +751,10 @@ pass1(void)
   pass1_buf_init();
   pass1_pool = mp_new(1 << 20);
 
+  /* Hilbert sort */
+  pass1_hilbert_sort();
+  pass1_hilbert_cleanup();
+
   /* main loop */
   for (uns i = 0; i < tree.count; )
     {
@@ -539,7 +774,7 @@ pass1(void)
             {
              struct pass1_node *node2 = pass1_node_lock(oid2);
              DBG("comparing %d and %d", oid, oid2);
-             if (image_dup_compare(&node->dup, &node2->dup, IMAGE_DUP_TRANS_ALL))
+             if (image_dup_compare(&node->dup, &node2->dup, IMAGE_DUP_TRANS_ID))
                {
                  pass1_dups++;
                  log(L_DEBUG, "*** Found duplicates oid1=0x%x oid=0x%x", (uns)node->oid, (uns)node2->oid);
@@ -567,9 +802,67 @@ pass1(void)
   imo_decompress_thumbnails_done();
 
   /* print statistics */
-  log(L_INFO, "%d count, %Ld lookups, %Ld reads, %Ld pairs, %Ld dups, %Ld shrinks", tree.count,
-    (long long int)pass1_lookups, (long long int)pass1_reads,
-    (long long int)pass1_pairs, (long long int)pass1_dups, (long long int)pass1_shrinks);
+  pass1_show_stats();
+}
+
+/*********************************************************************************/
+
+static uns pass2_clusterings_count = 1;
+
+static void
+pass2_estimate_sizes(void)
+{
+  if (!vectors_count)
+    return;
+  log(L_DEBUG, "Reading image sizes");
+
+  /* FIXME: hack, these reads are not necessary, can be done in previous phases */
+  struct fastbuf *fb_cards = index_bopen("cards", O_RDONLY);
+  struct fastbuf *fb_card_attrs = index_bopen("card-attrs", O_RDONLY);
+  struct mempool *pool = mp_new(1 << 16);
+  struct buck2obj_buf *bob = buck2obj_alloc();
+
+  for (uns i = 0; i < vectors_count; i++)
+    {
+      oid_t oid = vectors[i].oid;
+      struct card_attr ca;
+      bsetpos(fb_card_attrs, (sh_off_t)oid * sizeof(ca));
+      bread(fb_card_attrs, &ca, sizeof(ca));
+      bsetpos(fb_cards, (sh_off_t)ca.card << CARD_POS_SHIFT);
+      uns buck_len = bgetl(fb_cards) - (LIZARD_COMPRESS_HEADER - 1);
+      uns buck_type = bgetc(fb_cards) + BUCKET_TYPE_PLAIN;
+      mp_flush(pool);
+      struct odes *obj = obj_read_bucket(bob, pool, buck_type, buck_len, fb_cards, NULL);
+      byte *attr = obj_find_aval(obj, 'G');
+      ASSERT(attr);
+      uns image_width, image_height, image_colors, thumb_width, thumb_height;
+      byte color_space[MAX_ATTR_SIZE];
+      sscanf(attr, "%d%d%s%d%d%d", &image_width, &image_height, color_space, &image_colors, &thumb_width, &thumb_height);
+      vectors[i].temp = image_dup_estimate_size(thumb_width, thumb_height) +
+       sizeof(struct image_data) + thumb_width * thumb_height * 3;
+    }
+  buck2obj_free(bob);
+  mp_delete(pool);
+  bclose(fb_cards);
+  bclose(fb_card_attrs);
+}
+
+static void
+pass2(void)
+{
+  // FIXME: presorts, much allocated memory when not needed
+  vectors_read();
+  pass2_estimate_sizes();
+  random_clusters_init();
+  for (uns clustering = 0; clustering < pass2_clusterings_count; clustering++)
+    {
+      random_clusters_build();
+      // FIXME
+      // - external sort
+      // - generate and compare pairs in clusters
+    }
+  random_clusters_cleanup();
+  vectors_cleanup();
 }
 
 /*********************************************************************************/
@@ -618,7 +911,8 @@ main(int argc UNUSED, char **argv)
 
   generate_signatures(20000);
   build_kd_tree();
-  pass1();
+  //pass1();
+  pass2();
 
   return 0;
 }
index 95976bc8ce85412b3f2644486b1f093e3cfff81f..6506466d4b3044d12b6794d8837405b8dc29dad1 100644 (file)
@@ -35,7 +35,7 @@ struct image_obj {
   uns thumb_format;
   byte *thumb_data;
   uns thumb_size;
-  struct image thumb;
+  struct image_data thumb;
 };
 
 static inline void
index b22b4e44b6e0ebad1986830b1e16a9f267bf728b..cd07b8a3ab0fd603eeb5719da4a5b837aa7d75b9 100644 (file)
@@ -16,7 +16,7 @@ struct block {
 };
 
 int
-compute_image_signature(struct image *image, struct image_signature *sig)
+compute_image_signature(struct image_data *image, struct image_signature *sig)
 {
   uns width = image->width;
   uns height = image->height;
index 3532262aa0df20d3daff871e26f416874feefed4..fab4cf5f718fe5f00d4875aceb830aeca03f8997 100644 (file)
@@ -59,7 +59,7 @@ struct image_leaf {
     byte *_s = (byte *) alloca(IMAGE_VEC_K * 6), *_p = _s + sprintf(_s, "%d", _v->f[0]); \
     for (uns _i = 1; _i < IMAGE_VEC_K; _i++) _p += sprintf(_p, " %d", _v->f[_i]); _s; })
 
-int compute_image_signature(struct image *image, struct image_signature *sig);
+int compute_image_signature(struct image_data *image, struct image_signature *sig);
 
 #endif
 
index 61d09bf0c90ee2fcedc35e93a53ad056642a8a85..f57c78e2046618f36c0773361703fbe81759f964 100644 (file)
@@ -5,7 +5,7 @@ enum image_flag {
   IMAGE_GRAYSCALE = 0x1,       /* grayscale image */
 };
 
-struct image {
+struct image_data {
   uns flags;                   /* enum image_flag */
   uns width;                   /* number of columns */
   uns height;                  /* number of rows */
@@ -13,6 +13,8 @@ struct image {
   byte *pixels;                        /* RGB */
 };
 
+#if 0
+
 enum image_format {
   IMAGE_FORMAT_UNDEFINED = 0,
   IMAGE_FORMAT_JPEG,
@@ -20,10 +22,12 @@ enum image_format {
   IMAGE_FORMAT_GIF
 };
 
-struct image_info {
-  uns width;
-  uns height;
+struct image_io {
+  struct mempool *pool;
+  struct fastbuf *fb;
   enum image_format format;
+  struct image_data image;
+  void *internals;
   union {
     struct {
     } jpeg;
@@ -34,8 +38,14 @@ struct image_info {
   };
 };
 
-int read_image_header(struct image_info *info);
-int read_image_data(struct image_info *info);
+void image_open(struct image_io *io, struct fastbuf *fb, struct mempool *pool);
+void image_close(struct image_io *io);
+int image_read_header(struct image_io *io);
+int image_read_data(struct image_io *io);
+int image_read(struct image_io *io);
+int image_write(struct image_io *io);
+
+#endif
 
 #endif