From 501776384dca3e264f25475f1526b1564f2c035a Mon Sep 17 00:00:00 2001 From: Pavel Charvat Date: Wed, 2 Aug 2006 09:51:26 +0200 Subject: [PATCH] - removed testing code from io-libungif - simplified image_destroy interface - added simple tests --- images/Makefile | 5 ++ images/image-test.c | 170 +++++++++++++++++-------------------------- images/image.c | 55 +++++++++++--- images/images.h | 11 ++- images/io-libungif.c | 9 +-- 5 files changed, 126 insertions(+), 124 deletions(-) diff --git a/images/Makefile b/images/Makefile index f7d6873e..b8b00220 100644 --- a/images/Makefile +++ b/images/Makefile @@ -42,6 +42,11 @@ $(o)/images/libimages.so: $(addsuffix .oo,$(addprefix $(o)/images/,$(LIBIMAGES_M $(o)/images/image-tool: $(o)/images/image-tool.o $(LIBIMAGES) $(LIBUCW) $(o)/images/image-tool: LIBS+=$(LIBIMAGES_LIBS) +TESTS+=$(o)/images/image-test.test +$(o)/images/image-test: $(o)/images/image-test.o $(LIBIMAGES) $(LIBUCW) +$(o)/images/image-test: LIBS+=$(LIBIMAGES_LIBS) +$(o)/images/image-test.test: $(o)/images/image-test + TESTS+=$(o)/images/hilbert-test.test $(o)/images/hilbert-test: LIBS+=-lm $(LIBSH) $(o)/images/hilbert-test.test: $(o)/images/hilbert-test diff --git a/images/image-test.c b/images/image-test.c index b909ed65..1e49d284 100644 --- a/images/image-test.c +++ b/images/image-test.c @@ -1,121 +1,81 @@ #undef LOCAL_DEBUG -#include "sherlock/sherlock.h" -#include "lib/fastbuf.h" -#include "images/images.h" -//#include "images/image-sig.h" -//#include "images/kd-tree.h" -#include "sherlock/index.h" +#include "lib/lib.h" #include "lib/mempool.h" -#include "sherlock/object.h" -#include "sherlock/lizard-fb.h" -#include -#include +#include "images/images.h" +#include -#include "sherlock/sherlock.h" -#include "lib/fastbuf.h" -//#include "images/images.h" -#include "sherlock/index.h" +static uns want_image_iface; -#include -#include -#include +static void +test_image_iface(void) +{ + struct mempool *pool; + struct image_thread it; + struct image *i1, *i2; + struct image s1; + int i; -#define BEST_CNT 30 + pool = mp_new(1024); + image_thread_init(&it); -struct image_tree image_tree; + i1 = image_new(&it, 731, 327, COLOR_SPACE_RGB, NULL); + ASSERT(i1); + ASSERT(i1->pixel_size == 3); + image_destroy(i1); -static void -image_tree_init(void) -{ - DBG("Initializing image search structures"); - struct fastbuf *fb = bopen("index/image-tree", O_RDONLY, 1 << 16); /* FIXME: filename hack */ - image_tree.count = bgetl(fb); - image_tree.depth = bgetl(fb); - ASSERT(image_tree.count < 0x80000000 && image_tree.depth > 0 && image_tree.depth < 30); - image_tree.nodes = xmalloc((1 << image_tree.depth) * sizeof(struct image_node)); - image_tree.leaves = xmalloc(image_tree.count * sizeof(struct image_leaf)); - bread(fb, &image_tree.bbox, sizeof(struct image_bbox)); - bread(fb, image_tree.nodes + 1, ((1 << image_tree.depth) - 1) * sizeof(struct image_node)); - bread(fb, image_tree.leaves, image_tree.count * sizeof(struct image_leaf)); - DBG("Search tree with depth %d and %d leaves loaded", image_tree.depth, image_tree.count); - bclose(fb); -} + i1 = image_new(&it, 2214, 0, COLOR_SPACE_RGB, NULL); + ASSERT(!i1); -static void -image_tree_done(void) -{ - DBG("Freeing image search structures"); - xfree(image_tree.nodes); - xfree(image_tree.leaves); + i1 = image_new(&it, 0xffffff, 0xffffff, COLOR_SPACE_RGB, NULL); + ASSERT(!i1); + + i1 = image_new(&it, 370, 100, COLOR_SPACE_GRAYSCALE, pool); + ASSERT(i1); + ASSERT(i1->pixel_size == 1); + image_destroy(i1); + mp_flush(pool); + + i1 = image_new(&it, 373, 101, COLOR_SPACE_RGB | IMAGE_ALIGNED, NULL); + ASSERT(i1); + ASSERT(i1->pixel_size == 4); + ASSERT(IMAGE_SSE_ALIGN_SIZE >= 16); + ASSERT(!(i1->row_size & (IMAGE_SSE_ALIGN_SIZE - 1))); + ASSERT(!((addr_int_t)i1->pixels & (IMAGE_SSE_ALIGN_SIZE - 1))); + image_destroy(i1); + + i1 = image_new(&it, 283, 329, COLOR_SPACE_RGB, NULL); + ASSERT(i1); + ASSERT(i1->pixel_size == 3); + + i2 = image_clone(&it, i1, COLOR_SPACE_RGB, NULL); + ASSERT(i2); + ASSERT(i2->pixel_size == 3); + image_destroy(i2); + + i2 = image_clone(&it, i1, COLOR_SPACE_RGB | IMAGE_PIXELS_ALIGNED, NULL); + ASSERT(i2); + ASSERT(i2->pixel_size == 4); + image_destroy(i2); + + i = image_init_subimage(&it, &s1, i1, 29, 39, 283 - 29, 100); + ASSERT(i); + image_destroy(&s1); + + image_destroy(i1); + + image_thread_cleanup(&it); + mp_delete(pool); } - + int main(int argc, char **argv) { - struct image_vector query; - if (argc != IMAGE_VEC_K + 1) - die("Invalid number of arguments"); - - for (uns i = 0; i < IMAGE_VEC_K; i++) - { - uns v; - if (sscanf(argv[i + 1], "%d", &v) != 1) - die("Invalid numeric format"); - query.f[i] = v; - } - - - struct image_search is; - oid_t best[BEST_CNT]; - uns dist[BEST_CNT]; - uns cardpos[BEST_CNT]; - uns best_n = 0; - - image_tree_init(); - log(L_INFO, "Executing query (%s)", stk_print_image_vector(&query)); - image_search_init(&is, &image_tree, &query, IMAGE_SEARCH_DIST_UNLIMITED); - for (uns i = 0; i < BEST_CNT; i++) - { - if (!image_search_next(&is, best + i, dist + i)) - { - log(L_INFO, "No more images"); - break; - } - DBG("*** Found %d. best image with oid=%d", i + 1, best[i]); - best_n++; - } - image_search_done(&is); - image_tree_done(); - - log(L_INFO, "Resolving URLs"); - struct mempool *pool = mp_new(1 << 16); - struct buck2obj_buf *bob = buck2obj_alloc(); - struct fastbuf *fb = bopen("index/card-attrs", O_RDONLY, 1 << 10); - for (uns i = 0; i < best_n; i++) - { - bsetpos(fb, best[i] * sizeof(struct card_attr)); - struct card_attr ca; - bread(fb, &ca, sizeof(ca)); - cardpos[i] = ca.card; - } - bclose(fb); - fb = bopen("index/cards", O_RDONLY, 1 << 14); - for (uns i = 0; i < best_n; i++) - { - bsetpos(fb, (sh_off_t)cardpos[i] << CARD_POS_SHIFT); - uns buck_len = bgetl(fb) - (LIZARD_COMPRESS_HEADER - 1); - uns buck_type = bgetc(fb) + BUCKET_TYPE_PLAIN; - mp_flush(pool); - struct odes *obj = obj_read_bucket(bob, pool, buck_type, buck_len, fb, NULL); - - printf("%2d. match: dist=%-8d oid=%-8d url=%s\n", i + 1, dist[i], best[i], - obj_find_aval(obj_find_attr(obj, 'U' + OBJ_ATTR_SON)->son, 'U')); - } - bclose(fb); - buck2obj_free(bob); - mp_delete(pool); - + for (int i = 0; i < argc; i++) + if (!strcmp(argv[i], "image-iface")) + want_image_iface = 1; + if (want_image_iface) + test_image_iface(); return 0; } diff --git a/images/image.c b/images/image.c index 13576d8c..828313d5 100644 --- a/images/image.c +++ b/images/image.c @@ -45,13 +45,14 @@ 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); - if (cols > IMAGE_MAX_SIZE || rows > IMAGE_MAX_SIZE) + flags &= IMAGE_PIXEL_FORMAT | IMAGE_SSE_ALIGNED; + if (unlikely(!image_dimensions_valid(cols, rows))) { - image_thread_err(it, IMAGE_ERR_INVALID_DIMENSIONS, "Image dimension(s) too large"); + 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, image_size, align; + uns pixel_size, row_size, align; switch (flags & IMAGE_COLOR_SPACE) { case COLOR_SPACE_GRAYSCALE: @@ -89,17 +90,18 @@ image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool row_size = ALIGN(row_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 (bytes_64 > MAX_IMAGE_BYTES) + 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; } - img = pool ? mp_alloc(pool, (uns)bytes_64) : xmalloc((uns)bytes_64); bzero(img, sizeof(struct image)); byte *p = (byte *)img + sizeof(struct image); img->pixels = ALIGN_PTR(p, IMAGE_SSE_ALIGN_SIZE); @@ -108,7 +110,7 @@ image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool img->cols = cols; img->rows = rows; img->row_size = row_size; - img->image_size = image_size; + img->image_size = bytes_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; @@ -157,7 +159,8 @@ void image_destroy(struct image *img) { DBG("image_destroy(img=%p)", img); - xfree(img); + if (img->flags & IMAGE_NEED_DESTROY) + xfree(img); } void @@ -168,6 +171,38 @@ image_clear(struct image_thread *it UNUSED, struct image *img) bzero(img->pixels, img->image_size); } +int +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 cols=%u rows=%u row_size=%u flags=0x%x)", img, cols, rows, row_size, uns 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 0; + } + img->pixels = pixels; + img->cols = cols; + img->rows = rows; + img->row_size = row_size; + img->image_size = rows * row_size; + img->flags = flags & (IMAGE_PIXEL_FORMAT | IMAGE_SSE_ALIGNED); + return 1; +} + +int +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)"); + 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->row_size = src->row_size; + img->image_size = src->row_size * rows; + img->flags = src->flags & ~IMAGE_NEED_DESTROY; + return 1; +} + byte * color_space_to_name(enum color_space cs) { diff --git a/images/images.h b/images/images.h index 282489fd..485c3eb3 100644 --- a/images/images.h +++ b/images/images.h @@ -69,6 +69,7 @@ enum image_flag { IMAGE_ALPHA = 0x8, /* alpha channel */ IMAGE_PIXELS_ALIGNED = 0x10, /* align pixel size to the nearest power of two */ IMAGE_SSE_ALIGNED = 0x20, /* align scanlines to multiples of 16 bytes (both start and size) */ + IMAGE_NEED_DESTROY = 0x40, /* image is allocated with xmalloc */ IMAGE_CHANNELS_FORMAT = IMAGE_COLOR_SPACE | IMAGE_ALPHA, IMAGE_PIXEL_FORMAT = IMAGE_CHANNELS_FORMAT | IMAGE_PIXELS_ALIGNED, IMAGE_ALIGNED = IMAGE_PIXELS_ALIGNED | IMAGE_SSE_ALIGNED, @@ -81,7 +82,7 @@ struct image { u32 rows; /* number of rows */ u32 pixel_size; /* size of pixel (1, 2, 3 or 4) */ u32 row_size; /* scanline size in bytes */ - u32 image_size; /* size of pixels buffer (rows * rows_size) */ + u32 image_size; /* rows * rows_size */ u32 flags; /* enum image_flag */ }; @@ -89,6 +90,14 @@ struct image *image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct image *image_clone(struct image_thread *it, struct image *src, uns flags, struct mempool *pool); void image_destroy(struct image *img); /* only with NULL mempool */ void image_clear(struct image_thread *it, struct image *img); +int image_init_matrix(struct image_thread *it, struct image *img, byte *pixels, uns cols, uns rows, uns row_size, uns flags); +int image_init_subimage(struct image_thread *it, struct image *img, struct image *src, uns left, uns top, uns cols, uns rows); + +static inline int +image_dimensions_valid(uns cols, uns rows) +{ + return cols && rows && cols <= IMAGE_MAX_SIZE && rows <= IMAGE_MAX_SIZE; +} byte *color_space_to_name(enum color_space cs); byte *image_channels_format_to_name(uns format); diff --git a/images/io-libungif.c b/images/io-libungif.c index 3faf6c51..5eb7aece 100644 --- a/images/io-libungif.c +++ b/images/io-libungif.c @@ -26,14 +26,7 @@ static int libungif_read_func(GifFileType *gif, GifByteType *ptr, int len) { DBG("libungif_read_func(len=%d)", len); - uns readed, total = 0; - while (len && (readed = bread((struct fastbuf *)gif->UserData, (byte *)ptr, len))) - { - len -= readed; - ptr += readed; - total += readed; - } - return total; + return bread((struct fastbuf *)gif->UserData, (byte *)ptr, len); } static void -- 2.39.2