summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'leptonica/prog/maptest.c')
-rw-r--r--leptonica/prog/maptest.c426
1 files changed, 426 insertions, 0 deletions
diff --git a/leptonica/prog/maptest.c b/leptonica/prog/maptest.c
new file mode 100644
index 00000000..b1ac52df
--- /dev/null
+++ b/leptonica/prog/maptest.c
@@ -0,0 +1,426 @@
+/*====================================================================*
+ - Copyright (C) 2001 Leptonica. All rights reserved.
+ -
+ - Redistribution and use in source and binary forms, with or without
+ - modification, are permitted provided that the following conditions
+ - are met:
+ - 1. Redistributions of source code must retain the above copyright
+ - notice, this list of conditions and the following disclaimer.
+ - 2. Redistributions in binary form must reproduce the above
+ - copyright notice, this list of conditions and the following
+ - disclaimer in the documentation and/or other materials
+ - provided with the distribution.
+ -
+ - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
+ - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *====================================================================*/
+
+/*
+ * maptest.c
+ *
+ * Tests map function for RGB (uint32) keys and count (int32) values.
+ * The underlying rbtree takes 64 bit keys and values, so it also works
+ * transparently with 32 bit keys and values.
+ *
+ * We take a colormapped image and use the map to accumulate a
+ * histogram of the colors, using the 32-bit rgb value as the key.
+ * The value is the number of pixels with that color that we have seen.
+ *
+ * Also:
+ * * test the forward and backward iterators on the map
+ * * build an inverse colormap table using a map.
+ * * test RGB histogram and counting functions in pix4.c
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config_auto.h>
+#endif /* HAVE_CONFIG_H */
+
+#include "allheaders.h"
+
+static L_AMAP *BuildMapHistogram(PIX *pix, l_int32 factor, l_int32 print);
+static void DisplayMapHistogram(L_AMAP *m, PIXCMAP *cmap,
+ const char *rootname);
+static void DisplayMapRGBHistogram(L_AMAP *m, const char *rootname);
+static void TestMapIterator1(L_AMAP *m, l_int32 print);
+static void TestMapIterator2(L_AMAP *m, l_int32 print);
+static void TestMapIterator3(L_AMAP *m, l_int32 print);
+static void TestMapIterator4(L_AMAP *m, l_int32 print);
+static void TestMapIterator5(L_AMAP *m, l_int32 print);
+
+
+l_int32 main(int argc,
+ char **argv)
+{
+l_int32 i, n, w, h, ncolors;
+l_uint32 val32;
+L_AMAP *m;
+NUMA *na;
+PIX *pix;
+PIXCMAP *cmap;
+RB_TYPE key, value;
+RB_TYPE *pval;
+
+ setLeptDebugOK(1);
+ lept_mkdir("lept/map");
+
+ pix = pixRead("weasel8.240c.png");
+ pixGetDimensions(pix, &w, &h, NULL);
+ lept_stderr("Image area in pixels: %d\n", w * h);
+ cmap = pixGetColormap(pix);
+
+ /* Build the histogram, stored in a map. Then compute
+ * and display the histogram as the number of pixels vs
+ * the colormap index */
+ m = BuildMapHistogram(pix, 1, FALSE);
+ TestMapIterator1(m, FALSE);
+ TestMapIterator2(m, FALSE);
+ DisplayMapHistogram(m, cmap, "/tmp/lept/map/map1");
+ l_amapDestroy(&m);
+
+ /* Ditto, but just with a few pixels */
+ m = BuildMapHistogram(pix, 14, TRUE);
+ DisplayMapHistogram(m, cmap, "/tmp/lept/map/map2");
+ l_amapDestroy(&m);
+
+ /* Do in-order tranversals, using the iterators */
+ m = BuildMapHistogram(pix, 7, FALSE);
+ TestMapIterator1(m, TRUE);
+ TestMapIterator2(m, TRUE);
+ l_amapDestroy(&m);
+
+ /* Do in-order tranversals, with iterators and destroying the map */
+ m = BuildMapHistogram(pix, 7, FALSE);
+ TestMapIterator3(m, TRUE);
+ lept_free(m);
+ m = BuildMapHistogram(pix, 7, FALSE);
+ TestMapIterator4(m, TRUE);
+ lept_free(m);
+
+ /* Do in-order tranversals, with iterators and reversing the map */
+ m = BuildMapHistogram(pix, 7, FALSE);
+ TestMapIterator5(m, TRUE);
+ l_amapDestroy(&m);
+
+ /* Build a histogram the old-fashioned way */
+ na = pixGetCmapHistogram(pix, 1);
+ numaWrite("/tmp/lept/map/map2.na", na);
+ gplotSimple1(na, GPLOT_PNG, "/tmp/lept/map/map3", NULL);
+ numaDestroy(&na);
+
+ /* Build a separate map from (rgb) --> colormap index ... */
+ m = l_amapCreate(L_UINT_TYPE);
+ n = pixcmapGetCount(cmap);
+ for (i = 0; i < n; i++) {
+ pixcmapGetColor32(cmap, i, &val32);
+ key.utype = val32;
+ value.itype = i;
+ l_amapInsert(m, key, value);
+ }
+ /* ... and test the map */
+ for (i = 0; i < n; i++) {
+ pixcmapGetColor32(cmap, i, &val32);
+ key.utype = val32;
+ pval = l_amapFind(m, key);
+ if (pval && (i != pval->itype))
+ lept_stderr("i = %d != val = %llx\n", i, pval->itype);
+ }
+ l_amapDestroy(&m);
+ pixDestroy(&pix);
+
+ /* Build and display a real RGB histogram */
+ pix = pixRead("wyom.jpg");
+ m = pixGetColorAmapHistogram(pix, 1);
+ DisplayMapRGBHistogram(m, "/tmp/lept/map/map4");
+ pixNumColors(pix, 1, &ncolors);
+ lept_stderr(" Using pixNumColors: %d\n", ncolors);
+ pixCountRGBColors(pix, 1, &ncolors);
+ lept_stderr(" Using pixCountRGBColors: %d\n", ncolors);
+ l_amapDestroy(&m);
+ pixDestroy(&pix);
+
+ return 0;
+}
+
+static L_AMAP *
+BuildMapHistogram(PIX *pix,
+ l_int32 factor,
+ l_int32 print)
+{
+l_int32 i, j, w, h, wpl, val;
+l_uint32 val32;
+l_uint32 *data, *line;
+L_AMAP *m;
+PIXCMAP *cmap;
+RB_TYPE key, value;
+RB_TYPE *pval;
+
+ lept_stderr("\n --------------- Begin building map --------------\n");
+ m = l_amapCreate(L_UINT_TYPE);
+ data = pixGetData(pix);
+ wpl = pixGetWpl(pix);
+ cmap = pixGetColormap(pix);
+ pixGetDimensions(pix, &w, &h, NULL);
+ for (i = 0; i < h; i += factor) {
+ line = data + i * wpl;
+ for (j = 0; j < w; j += factor) {
+ val = GET_DATA_BYTE(line, j);
+ pixcmapGetColor32(cmap, val, &val32);
+ key.utype = val32;
+ pval = l_amapFind(m, key);
+ if (!pval)
+ value.itype = 1;
+ else
+ value.itype = 1 + pval->itype;
+ if (print)
+ lept_stderr("key = %llx, val = %lld\n", key.utype, value.itype);
+ l_amapInsert(m, key, value);
+ }
+ }
+ lept_stderr("Size: %d\n", l_amapSize(m));
+ if (print)
+ l_rbtreePrint(stderr, m);
+ lept_stderr(" ----------- End Building map -----------------\n");
+
+ return m;
+}
+
+
+static void
+DisplayMapHistogram(L_AMAP *m,
+ PIXCMAP *cmap,
+ const char *rootname)
+{
+char buf[128];
+l_int32 i, n, ival;
+l_uint32 val32;
+NUMA *na;
+RB_TYPE key;
+RB_TYPE *pval;
+
+ n = pixcmapGetCount(cmap);
+ na = numaCreate(n);
+ for (i = 0; i < n; i++) {
+ pixcmapGetColor32(cmap, i, &val32);
+ key.utype = val32;
+ pval = l_amapFind(m, key);
+ if (pval) {
+ ival = pval->itype;
+ numaAddNumber(na, ival);
+ }
+ }
+ gplotSimple1(na, GPLOT_PNG, rootname, NULL);
+ snprintf(buf, sizeof(buf), "%s.png", rootname);
+ l_fileDisplay(buf, 700, 0, 1.0);
+ numaDestroy(&na);
+ return;
+}
+
+static void
+DisplayMapRGBHistogram(L_AMAP *m,
+ const char *rootname)
+{
+char buf[128];
+l_int32 ncolors, npix, ival, maxn, maxn2;
+l_uint32 maxcolor;
+L_AMAP_NODE *n;
+NUMA *na;
+
+ lept_stderr("\n --------------- Display RGB histogram ------------\n");
+ na = numaCreate(0);
+ ncolors = npix = 0;
+ maxn = 0;
+ maxcolor = 0;
+ n = l_amapGetFirst(m);
+ while (n) {
+ ncolors++;
+ ival = n->value.itype;
+ if (ival > maxn) {
+ maxn = ival;
+ maxcolor = n->key.utype;
+ }
+ numaAddNumber(na, ival);
+ npix += ival;
+ n = l_amapGetNext(n);
+ }
+ lept_stderr(" Num colors = %d, Num pixels = %d\n", ncolors, npix);
+ lept_stderr(" Color %x has count %d\n", maxcolor, maxn);
+ maxn2 = amapGetCountForColor(m, maxcolor);
+ if (maxn != maxn2)
+ lept_stderr(" Error: maxn2 = %d; not equal to %d\n", maxn, maxn2);
+ gplotSimple1(na, GPLOT_PNG, rootname, NULL);
+ snprintf(buf, sizeof(buf), "%s.png", rootname);
+ l_fileDisplay(buf, 1400, 0, 1.0);
+ numaDestroy(&na);
+ return;
+}
+
+static void
+TestMapIterator1(L_AMAP *m,
+ l_int32 print) /* forward iterator; fixed tree */
+{
+l_int32 count, npix, ival;
+l_uint32 ukey;
+L_AMAP_NODE *n;
+
+ n = l_amapGetFirst(m);
+ count = 0;
+ npix = 0;
+ lept_stderr("\n ---------- Begin forward iter listing -----------\n");
+ while (n) {
+ count++;
+ ukey = n->key.utype;
+ ival = n->value.itype;
+ npix += ival;
+ if (print)
+ lept_stderr("key = %x, val = %d\n", ukey, ival);
+ n = l_amapGetNext(n);
+ }
+ lept_stderr("Count from iterator: %d\n", count);
+ lept_stderr("Number of pixels: %d\n", npix);
+ lept_stderr(" ------------ End forward iter listing -----------\n");
+ return;
+}
+
+static void
+TestMapIterator2(L_AMAP *m,
+ l_int32 print) /* reverse iterator; fixed tree */
+{
+l_int32 count, npix, ival;
+l_uint32 ukey;
+L_AMAP_NODE *n;
+
+ n = l_amapGetLast(m);
+ count = 0;
+ npix = 0;
+ lept_stderr("\n ---------- Begin reverse iter listing -----------\n");
+ while (n) {
+ count++;
+ ukey = n->key.utype;
+ ival = n->value.itype;
+ npix += ival;
+ if (print)
+ lept_stderr("key = %x, val = %d\n", ukey, ival);
+ n = l_amapGetPrev(n);
+ }
+ lept_stderr("Count from iterator: %d\n", count);
+ lept_stderr("Number of pixels: %d\n", npix);
+ lept_stderr(" ------------ End reverse iter listing -----------\n");
+ return;
+}
+
+static void
+TestMapIterator3(L_AMAP *m,
+ l_int32 print) /* forward iterator; delete the tree */
+{
+l_int32 count, npix, ival;
+l_uint32 ukey;
+L_AMAP_NODE *n, *nn;
+
+ n = l_amapGetFirst(m);
+ count = 0;
+ npix = 0;
+ lept_stderr("\n ------ Begin forward iter; delete tree ---------\n");
+ while (n) {
+ nn = l_amapGetNext(n);
+ count++;
+ ukey = n->key.utype;
+ ival = n->value.itype;
+ npix += ival;
+ if (print)
+ lept_stderr("key = %x, val = %d\n", ukey, ival);
+ l_amapDelete(m, n->key);
+ n = nn;
+ }
+ lept_stderr("Count from iterator: %d\n", count);
+ lept_stderr("Number of pixels: %d\n", npix);
+ lept_stderr(" ------ End forward iter; delete tree ---------\n");
+ return;
+}
+
+static void
+TestMapIterator4(L_AMAP *m,
+ l_int32 print) /* reverse iterator; delete the tree */
+{
+l_int32 count, npix, ival;
+l_uint32 ukey;
+L_AMAP_NODE *n, *np;
+
+ n = l_amapGetLast(m);
+ count = 0;
+ npix = 0;
+ lept_stderr("\n ------- Begin reverse iter; delete tree --------\n");
+ while (n) {
+ np = l_amapGetPrev(n);
+ count++;
+ ukey = n->key.utype;
+ ival = n->value.itype;
+ npix += ival;
+ if (print)
+ lept_stderr("key = %x, val = %d\n", ukey, ival);
+ l_amapDelete(m, n->key);
+ n = np;
+ }
+ lept_stderr("Count from iterator: %d\n", count);
+ lept_stderr("Number of pixels: %d\n", npix);
+ lept_stderr(" ------- End reverse iter; delete tree --------\n");
+ return;
+}
+
+static void
+TestMapIterator5(L_AMAP *m,
+ l_int32 print) /* reverse iterator; rebuild the tree */
+{
+l_int32 count, npix, ival;
+l_uint32 ukey;
+L_AMAP *m2;
+L_AMAP_NODE *n, *np;
+
+ m2 = l_amapCreate(L_UINT_TYPE);
+ n = l_amapGetLast(m);
+ count = npix = 0;
+ lept_stderr("\n ------- Begin reverse iter; rebuild tree --------\n");
+ while (n) {
+ np = l_amapGetPrev(n);
+ count++;
+ ukey = n->key.utype;
+ ival = n->value.itype;
+ l_amapInsert(m2, n->key, n->value);
+ npix += ival;
+ if (print)
+ lept_stderr("key = %x, val = %d\n", ukey, ival);
+ l_amapDelete(m, n->key);
+ n = np;
+ }
+ m->root = m2->root;
+ lept_free(m2);
+ lept_stderr("Count from iterator: %d\n", count);
+ lept_stderr("Number of pixels: %d\n", npix);
+ count = npix = 0;
+ n = l_amapGetLast(m);
+ while (n) {
+ np = l_amapGetPrev(n);
+ count++;
+ ukey = n->key.utype;
+ ival = n->value.itype;
+ npix += ival;
+ if (print)
+ lept_stderr("key = %x, val = %d\n", ukey, ival);
+ n = np;
+ }
+ lept_stderr("Count from iterator: %d\n", count);
+ lept_stderr("Number of pixels: %d\n", npix);
+ lept_stderr(" ------- End reverse iter; rebuild tree --------\n");
+ return;
+}
+
+