Leptonica 1.68
C Image Processing Library

quadtree.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*
00017  *  quadtree.c
00018  *
00019  *      Top level quadtree linear statistics
00020  *          l_int32   pixQuadtreeMean()
00021  *          l_int32   pixQuadtreeVariance()
00022  *
00023  *      Statistics in an arbitrary rectangle
00024  *          l_int32   pixMeanInRectangle()
00025  *          l_int32   pixVarianceInRectangle()
00026  *
00027  *      Quadtree regions
00028  *          BOXAA    *boxaaQuadtreeRegions()
00029  *
00030  *      Quadtree access
00031  *          l_int32   quadtreeGetParent()
00032  *          l_int32   quadtreeGetChildren()
00033  *          l_int32   quadtreeMaxLevels()
00034  *
00035  *      Display quadtree
00036  *          PIX      *fpixaDisplayQuadtree()
00037  *
00038  *
00039  *  There are many other statistical quantities that can be computed
00040  *  in a quadtree, such as rank values, and these can be added as
00041  *  the need arises.
00042  *
00043  *  Similar results that can approximate a single level of the quadtree
00044  *  can be generated by pixGetAverageTiled().  There we specify the
00045  *  tile size over which the mean, mean square, and root variance
00046  *  are generated; the results are saved in a (reduced size) pix.
00047  *  Because the tile dimensions are integers, it is usually not possible
00048  *  to obtain tilings that are a power of 2, as required for quadtrees.
00049  */
00050 
00051 #include <math.h>
00052 #include "allheaders.h"
00053 
00054 #ifndef  NO_CONSOLE_IO
00055 #define  DEBUG_BOXES       0
00056 #endif  /* !NO_CONSOLE_IO */
00057 
00058 
00059 /*----------------------------------------------------------------------*
00060  *                  Top-level quadtree linear statistics                *
00061  *----------------------------------------------------------------------*/
00062 /*!
00063  *  pixQuadtreeMean()
00064  *
00065  *      Input:  pixs (8 bpp, no colormap)
00066  *              nlevels (in quadtree; max allowed depends on image size)
00067  *             *pix_ma (input mean accumulator; can be null)
00068  *             *pfpixa (<return> mean values in quadtree)
00069  *      Return: 0 if OK, 1 on error
00070  *
00071  *  Notes:
00072  *      (1) The returned fpixa has @nlevels of fpix, each containing
00073  *          the mean values at its level.  Level 0 has a
00074  *          single value; level 1 has 4 values; level 2 has 16; etc.
00075  */
00076 l_int32
00077 pixQuadtreeMean(PIX     *pixs,
00078                 l_int32  nlevels,
00079                 PIX     *pix_ma,
00080                 FPIXA  **pfpixa)
00081 {
00082 l_int32    i, j, w, h, size, n;
00083 l_float32  val;
00084 BOX       *box;
00085 BOXA      *boxa;
00086 BOXAA     *baa;
00087 FPIX      *fpix;
00088 PIX       *pix_mac;
00089 
00090     PROCNAME("pixQuadtreeMean");
00091 
00092     if (!pfpixa)
00093         return ERROR_INT("&fpixa not defined", procName, 1);
00094     *pfpixa = NULL;
00095     if (!pixs || pixGetDepth(pixs) != 8)
00096         return ERROR_INT("pixs not defined or not 8 bpp", procName, 1);
00097     pixGetDimensions(pixs, &w, &h, NULL);
00098     if (nlevels > quadtreeMaxLevels(w, h))
00099         return ERROR_INT("nlevels too large for image", procName, 1);
00100 
00101     if (!pix_ma)
00102         pix_mac = pixBlockconvAccum(pixs);
00103     else
00104         pix_mac = pixClone(pix_ma);
00105     if (!pix_mac)
00106         return ERROR_INT("pix_mac not made", procName, 1);
00107 
00108     if ((baa = boxaaQuadtreeRegions(w, h, nlevels)) == NULL) {
00109         pixDestroy(&pix_mac);
00110         return ERROR_INT("baa not made", procName, 1);
00111     }
00112 
00113     *pfpixa = fpixaCreate(nlevels);
00114     for (i = 0; i < nlevels; i++) {
00115         boxa = boxaaGetBoxa(baa, i, L_CLONE);
00116         size = 1 << i;
00117         n = boxaGetCount(boxa);  /* n == size * size */
00118         fpix = fpixCreate(size, size);
00119         for (j = 0; j < n; j++) {
00120             box = boxaGetBox(boxa, j, L_CLONE);
00121             pixMeanInRectangle(pixs, box, pix_mac, &val);
00122             fpixSetPixel(fpix, j % size, j / size, val);
00123             boxDestroy(&box);
00124         }
00125         fpixaAddFPix(*pfpixa, fpix, L_INSERT);
00126         boxaDestroy(&boxa);
00127     }
00128 
00129     pixDestroy(&pix_mac);
00130     boxaaDestroy(&baa);
00131     return 0;
00132 }
00133 
00134 
00135 /*!
00136  *  pixQuadtreeVariance()
00137  *
00138  *      Input:  pixs (8 bpp, no colormap)
00139  *              nlevels (in quadtree)
00140  *             *pix_ma (input mean accumulator; can be null)
00141  *             *dpix_msa (input mean square accumulator; can be null)
00142  *             *pfpixa_v (<optional return> variance values in quadtree)
00143  *             *pfpixa_rv (<optional return> root variance values in quadtree)
00144  *      Return: 0 if OK, 1 on error
00145  *
00146  *  Notes:
00147  *      (1) The returned fpixav and fpixarv have @nlevels of fpix,
00148  *          each containing at the respective levels the variance
00149  *          and root variance values.
00150  */
00151 l_int32
00152 pixQuadtreeVariance(PIX     *pixs,
00153                     l_int32  nlevels,
00154                     PIX     *pix_ma,
00155                     DPIX    *dpix_msa,
00156                     FPIXA  **pfpixa_v,
00157                     FPIXA  **pfpixa_rv)
00158 {
00159 l_int32    i, j, w, h, size, n;
00160 l_float32  var, rvar;
00161 BOX       *box;
00162 BOXA      *boxa;
00163 BOXAA     *baa;
00164 FPIX      *fpixv, *fpixrv;
00165 PIX       *pix_mac;  /* copy of mean accumulator */
00166 DPIX      *dpix_msac;  /* msa clone */
00167 
00168     PROCNAME("pixQuadtreeVariance");
00169 
00170     if (!pfpixa_v && !pfpixa_rv)
00171         return ERROR_INT("neither &fpixav nor &fpixarv defined", procName, 1);
00172     if (pfpixa_v) *pfpixa_v = NULL;
00173     if (pfpixa_rv) *pfpixa_rv = NULL;
00174     if (!pixs || pixGetDepth(pixs) != 8)
00175         return ERROR_INT("pixs not defined or not 8 bpp", procName, 1);
00176     pixGetDimensions(pixs, &w, &h, NULL);
00177     if (nlevels > quadtreeMaxLevels(w, h))
00178         return ERROR_INT("nlevels too large for image", procName, 1);
00179 
00180     if (!pix_ma)
00181         pix_mac = pixBlockconvAccum(pixs);
00182     else
00183         pix_mac = pixClone(pix_ma);
00184     if (!pix_mac)
00185         return ERROR_INT("pix_mac not made", procName, 1);
00186     if (!dpix_msa)
00187         dpix_msac = pixMeanSquareAccum(pixs);
00188     else
00189         dpix_msac = dpixClone(dpix_msa);
00190     if (!dpix_msac)
00191         return ERROR_INT("dpix_msac not made", procName, 1);
00192 
00193     if ((baa = boxaaQuadtreeRegions(w, h, nlevels)) == NULL) {
00194         pixDestroy(&pix_mac);
00195         dpixDestroy(&dpix_msac);
00196         return ERROR_INT("baa not made", procName, 1);
00197     }
00198 
00199     if (pfpixa_v) *pfpixa_v = fpixaCreate(nlevels);
00200     if (pfpixa_rv) *pfpixa_rv = fpixaCreate(nlevels);
00201     for (i = 0; i < nlevels; i++) {
00202         boxa = boxaaGetBoxa(baa, i, L_CLONE);
00203         size = 1 << i;
00204         n = boxaGetCount(boxa);  /* n == size * size */
00205         if (pfpixa_v) fpixv = fpixCreate(size, size);
00206         if (pfpixa_rv) fpixrv = fpixCreate(size, size);
00207         for (j = 0; j < n; j++) {
00208             box = boxaGetBox(boxa, j, L_CLONE);
00209             pixVarianceInRectangle(pixs, box, pix_mac, dpix_msac, &var, &rvar);
00210             if (pfpixa_v) fpixSetPixel(fpixv, j % size, j / size, var);
00211             if (pfpixa_rv) fpixSetPixel(fpixrv, j % size, j / size, rvar);
00212             boxDestroy(&box);
00213         }
00214         if (pfpixa_v) fpixaAddFPix(*pfpixa_v, fpixv, L_INSERT);
00215         if (pfpixa_rv) fpixaAddFPix(*pfpixa_rv, fpixrv, L_INSERT);
00216         boxaDestroy(&boxa);
00217     }
00218 
00219     pixDestroy(&pix_mac);
00220     dpixDestroy(&dpix_msac);
00221     boxaaDestroy(&baa);
00222     return 0;
00223 }
00224 
00225 
00226 /*----------------------------------------------------------------------*
00227  *                  Statistics in an arbitrary rectangle                *
00228  *----------------------------------------------------------------------*/
00229 /*!
00230  *  pixMeanInRectangle()
00231  *
00232  *      Input:  pix (8 bpp)
00233  *              box (region to compute mean value)
00234  *              pixma (mean accumulator)
00235  *              &val (<return> mean value
00236  *      Return: 0 if OK, 1 on error
00237  *
00238  *  Notes:
00239  *      (1) This function is intended to be used for many rectangles
00240  *          on the same image.  It can find the mean within a
00241  *          rectangle in O(1), independent of the size of the rectangle.
00242  */
00243 l_int32
00244 pixMeanInRectangle(PIX        *pixs,
00245                    BOX        *box,
00246                    PIX        *pixma,
00247                    l_float32  *pval)
00248 {
00249 l_int32    w, h, bx, by, bw, bh;
00250 l_uint32   val00, val01, val10, val11;
00251 l_float32  norm;
00252 BOX       *boxc;
00253 
00254     PROCNAME("pixMeanInRectangle");
00255 
00256     if (!pval)
00257         return ERROR_INT("&val not defined", procName, 1);
00258     *pval = 0.0;
00259     if (!pixs || pixGetDepth(pixs) != 8)
00260         return ERROR_INT("pixs not defined", procName, 1);
00261     if (!box)
00262         return ERROR_INT("box not defined", procName, 1);
00263     if (!pixma)
00264         return ERROR_INT("pixma not defined", procName, 1);
00265 
00266         /* Clip rectangle to image */
00267     pixGetDimensions(pixs, &w, &h, NULL);
00268     boxc = boxClipToRectangle(box, w, h);
00269     boxGetGeometry(boxc, &bx, &by, &bw, &bh);
00270     boxDestroy(&boxc);
00271 
00272     if (bw == 0 || bh == 0)
00273         return ERROR_INT("no pixels in box", procName, 1);
00274 
00275         /* Use up to 4 points in the accumulator */
00276     norm = 1.0 / (bw * bh);
00277     if (bx > 0 && by > 0) {
00278         pixGetPixel(pixma, bx + bw - 1, by + bh - 1, &val11);
00279         pixGetPixel(pixma, bx + bw - 1, by - 1, &val10);
00280         pixGetPixel(pixma, bx - 1, by + bh - 1, &val01);
00281         pixGetPixel(pixma, bx - 1, by - 1, &val00);
00282         *pval = norm * (val11 - val01 + val00 - val10);
00283     }
00284     else if (by > 0) {  /* bx == 0 */
00285         pixGetPixel(pixma, bw - 1, by + bh - 1, &val11);
00286         pixGetPixel(pixma, bw - 1, by - 1, &val10);
00287         *pval = norm * (val11 - val10);
00288     }
00289     else if (bx > 0) {  /* by == 0 */
00290         pixGetPixel(pixma, bx + bw - 1, bh - 1, &val11);
00291         pixGetPixel(pixma, bx - 1, bh - 1, &val01);
00292         *pval = norm * (val11 - val01);
00293     }
00294     else {  /* bx == 0 && by == 0 */
00295         pixGetPixel(pixma, bw - 1, bh - 1, &val11);
00296         *pval = norm * val11;
00297     }
00298 
00299     return 0;
00300 }
00301 
00302 
00303 /*!
00304  *  pixVarianceInRectangle()
00305  *
00306  *      Input:  pix (8 bpp)
00307  *              box (region to compute variance and/or root variance)
00308  *              pix_ma (mean accumulator)
00309  *              dpix_msa (mean square accumulator)
00310  *              &var (<optional return> variance)
00311  *              &rvar (<optional return> root variance)
00312  *      Return: 0 if OK, 1 on error
00313  *
00314  *  Notes:
00315  *      (1) This function is intended to be used for many rectangles
00316  *          on the same image.  It can find the variance and/or the
00317  *          square root of the variance within a rectangle in O(1),
00318  *          independent of the size of the rectangle.
00319  */
00320 l_int32
00321 pixVarianceInRectangle(PIX        *pixs,
00322                        BOX        *box,
00323                        PIX        *pix_ma,
00324                        DPIX       *dpix_msa,
00325                        l_float32  *pvar,
00326                        l_float32  *prvar)
00327 {
00328 l_int32    w, h, bx, by, bw, bh;
00329 l_uint32   val00, val01, val10, val11;
00330 l_float64  dval00, dval01, dval10, dval11, mval, msval, var, norm;
00331 BOX       *boxc;
00332 
00333     PROCNAME("pixVarianceInRectangle");
00334 
00335     if (!pvar && !prvar)
00336         return ERROR_INT("neither &var nor &rvar defined", procName, 1);
00337     if (pvar) *pvar = 0.0;
00338     if (prvar) *prvar = 0.0;
00339     if (!pixs || pixGetDepth(pixs) != 8)
00340         return ERROR_INT("pixs not defined", procName, 1);
00341     if (!box)
00342         return ERROR_INT("box not defined", procName, 1);
00343     if (!pix_ma)
00344         return ERROR_INT("pix_ma not defined", procName, 1);
00345     if (!dpix_msa)
00346         return ERROR_INT("dpix_msa not defined", procName, 1);
00347 
00348         /* Clip rectangle to image */
00349     pixGetDimensions(pixs, &w, &h, NULL);
00350     boxc = boxClipToRectangle(box, w, h);
00351     boxGetGeometry(boxc, &bx, &by, &bw, &bh);
00352     boxDestroy(&boxc);
00353 
00354     if (bw == 0 || bh == 0)
00355         return ERROR_INT("no pixels in box", procName, 1);
00356 
00357         /* Use up to 4 points in the accumulators */
00358     norm = 1.0 / (bw * bh);
00359     if (bx > 0 && by > 0) {
00360         pixGetPixel(pix_ma, bx + bw - 1, by + bh - 1, &val11);
00361         pixGetPixel(pix_ma, bx + bw - 1, by - 1, &val10);
00362         pixGetPixel(pix_ma, bx - 1, by + bh - 1, &val01);
00363         pixGetPixel(pix_ma, bx - 1, by - 1, &val00);
00364         dpixGetPixel(dpix_msa, bx + bw - 1, by + bh - 1, &dval11);
00365         dpixGetPixel(dpix_msa, bx + bw - 1, by - 1, &dval10);
00366         dpixGetPixel(dpix_msa, bx - 1, by + bh - 1, &dval01);
00367         dpixGetPixel(dpix_msa, bx - 1, by - 1, &dval00);
00368         mval = norm * (val11 - val01 + val00 - val10);
00369         msval = norm * (dval11 - dval01 + dval00 - dval10);
00370         var = (msval - mval * mval);
00371         if (pvar) *pvar = (l_float32)var;
00372         if (prvar) *prvar = (l_float32)(sqrt(var));
00373     }
00374     else if (by > 0) {  /* bx == 0 */
00375         pixGetPixel(pix_ma, bw - 1, by + bh - 1, &val11);
00376         pixGetPixel(pix_ma, bw - 1, by - 1, &val10);
00377         dpixGetPixel(dpix_msa, bw - 1, by + bh - 1, &dval11);
00378         dpixGetPixel(dpix_msa, bw - 1, by - 1, &dval10);
00379         mval = norm * (val11 - val10);
00380         msval = norm * (dval11 - dval10);
00381         var = (msval - mval * mval);
00382         if (pvar) *pvar = (l_float32)var;
00383         if (prvar) *prvar = (l_float32)(sqrt(var));
00384     }
00385     else if (bx > 0) {  /* by == 0 */
00386         pixGetPixel(pix_ma, bx + bw - 1, bh - 1, &val11);
00387         pixGetPixel(pix_ma, bx - 1, bh - 1, &val01);
00388         dpixGetPixel(dpix_msa, bx + bw - 1, bh - 1, &dval11);
00389         dpixGetPixel(dpix_msa, bx - 1, bh - 1, &dval01);
00390         mval = norm * (val11 - val01);
00391         msval = norm * (dval11 - dval01);
00392         var = (msval - mval * mval);
00393         if (pvar) *pvar = (l_float32)var;
00394         if (prvar) *prvar = (l_float32)(sqrt(var));
00395     }
00396     else {  /* bx == 0 && by == 0 */
00397         pixGetPixel(pix_ma, bw - 1, bh - 1, &val11);
00398         dpixGetPixel(dpix_msa, bw - 1, bh - 1, &dval11);
00399         mval = norm * val11;
00400         msval = norm * dval11;
00401         var = (msval - mval * mval);
00402         if (pvar) *pvar = (l_float32)var;
00403         if (prvar) *prvar = (l_float32)(sqrt(var));
00404     }
00405 
00406     return 0;
00407 }
00408 
00409 
00410 /*----------------------------------------------------------------------*
00411  *                            Quadtree regions                          *
00412  *----------------------------------------------------------------------*/
00413 /*!
00414  *  boxaaQuadtreeRegions()
00415  *
00416  *      Input:  w, h (of pix that is being quadtree-ized)
00417  *              nlevels (in quadtree)
00418  *      Return: baa (for quadtree regions at each level), or null on error
00419  *
00420  *  Notes:
00421  *      (1) The returned boxaa has @nlevels of boxa, each containing
00422  *          the set of rectangles at that level.  The rectangle at
00423  *          level 0 is the entire region; at level 1 the region is
00424  *          divided into 4 rectangles, and at level n there are n^4
00425  *          rectangles.
00426  *      (2) At each level, the rectangles in the boxa are in "raster"
00427  *          order, with LR (fast scan) and TB (slow scan).
00428  */
00429 BOXAA *
00430 boxaaQuadtreeRegions(l_int32  w,
00431                      l_int32  h,
00432                      l_int32  nlevels)
00433 {
00434 l_int32   i, j, k, maxpts, nside, nbox, bw, bh;
00435 l_int32  *xstart, *xend, *ystart, *yend;
00436 BOX      *box;
00437 BOXA     *boxa;
00438 BOXAA    *baa;
00439 
00440     PROCNAME("boxaaQuadtreeRegions");
00441 
00442     if (nlevels < 1)
00443         return (BOXAA *)ERROR_PTR("nlevels must be >= 1", procName, NULL);
00444     if (w < (1 << (nlevels - 1)))
00445         return (BOXAA *)ERROR_PTR("w doesn't support nlevels", procName, NULL);
00446     if (h < (1 << (nlevels - 1)))
00447         return (BOXAA *)ERROR_PTR("h doesn't support nlevels", procName, NULL);
00448 
00449     baa = boxaaCreate(nlevels);
00450     maxpts = 1 << (nlevels - 1);
00451     xstart = (l_int32 *)CALLOC(maxpts, sizeof(l_int32));
00452     xend = (l_int32 *)CALLOC(maxpts, sizeof(l_int32));
00453     ystart = (l_int32 *)CALLOC(maxpts, sizeof(l_int32));
00454     yend = (l_int32 *)CALLOC(maxpts, sizeof(l_int32));
00455     for (k = 0; k < nlevels; k++) {
00456         nside = 1 << k;  /* number of boxes in each direction */
00457         for (i = 0; i < nside; i++) {
00458             xstart[i] = (w - 1) * i / nside;
00459             if (i > 0) xstart[i]++;
00460             xend[i] = (w - 1) * (i + 1) / nside;
00461             ystart[i] = (h - 1) * i / nside;
00462             if (i > 0) ystart[i]++;
00463             yend[i] = (h - 1) * (i + 1) / nside;
00464 #if DEBUG_BOXES
00465             fprintf(stderr,
00466                "k = %d, xs[%d] = %d, xe[%d] = %d, ys[%d] = %d, ye[%d] = %d\n",
00467                     k, i, xstart[i], i, xend[i], i, ystart[i], i, yend[i]);
00468 #endif  /* DEBUG_BOXES */
00469         }
00470         nbox = 1 << (2 * k);
00471         boxa = boxaCreate(nbox);
00472         for (i = 0; i < nside; i++) {
00473             bh = yend[i] - ystart[i] + 1;
00474             for (j = 0; j < nside; j++) {
00475                 bw = xend[j] - xstart[j] + 1;
00476                 box = boxCreate(xstart[j], ystart[i], bw, bh);
00477                 boxaAddBox(boxa, box, L_INSERT);
00478             }
00479         }
00480         boxaaAddBoxa(baa, boxa, L_INSERT);
00481     }
00482 
00483     FREE(xstart);
00484     FREE(xend);
00485     FREE(ystart);
00486     FREE(yend);
00487     return baa;
00488 }
00489 
00490 
00491 /*----------------------------------------------------------------------*
00492  *                            Quadtree access                           *
00493  *----------------------------------------------------------------------*/
00494 /*!
00495  *  quadtreeGetParent()
00496  *
00497  *      Input:  fpixa (mean, variance or root variance)
00498  *              level, x, y (of current pixel)
00499  *              &val (<return> parent pixel value), or 0.0 on error.
00500  *      Return: 0 if OK, 1 on error
00501  *
00502  *  Notes:
00503  *      (1) Check return value for error.  On error, val is returned as 0.0.
00504  *      (2) The parent is located at:
00505  *             level - 1
00506  *             (x/2, y/2)
00507  */
00508 l_int32
00509 quadtreeGetParent(FPIXA      *fpixa,
00510                   l_int32     level,
00511                   l_int32     x,
00512                   l_int32     y,
00513                   l_float32  *pval)
00514 {
00515 l_int32  n;
00516 
00517     PROCNAME("quadtreeGetParent");
00518 
00519     if (!pval)
00520         return ERROR_INT("&val not defined", procName, 1);
00521     *pval = 0.0;
00522     if (!fpixa)
00523         return ERROR_INT("fpixa not defined", procName, 1);
00524     n = fpixaGetCount(fpixa);
00525     if (level < 1 || level >= n)
00526         return ERROR_INT("invalid level", procName, 1);
00527 
00528     if (fpixaGetPixel(fpixa, level - 1, x / 2, y / 2, pval) != 0)
00529         return ERROR_INT("invalid coordinates", procName, 1);
00530     return 0;
00531 }
00532 
00533 
00534 /*!
00535  *  quadtreeGetChildren()
00536  *
00537  *      Input:  fpixa (mean, variance or root variance)
00538  *              level, x, y (of current pixel)
00539  *              &val00, val01, val10, val11  (<return> child pixel values)
00540  *      Return: 0 if OK, 1 on error
00541  *
00542  *  Notes:
00543  *      (1) Check return value for error.  On error, all return vals are 0.0.
00544  *      (2) The returned child pixels are located at:
00545  *             level + 1 
00546  *             (2x, 2y), (2x+1, 2y), (2x, 2y+1), (2x+1, 2y+1)
00547  */
00548 l_int32
00549 quadtreeGetChildren(FPIXA      *fpixa,
00550                     l_int32     level,
00551                     l_int32     x,
00552                     l_int32     y,
00553                     l_float32  *pval00,
00554                     l_float32  *pval10,
00555                     l_float32  *pval01,
00556                     l_float32  *pval11)
00557 {
00558 l_int32  n;
00559 
00560     PROCNAME("quadtreeGetChildren");
00561 
00562     if (!pval00 || !pval01 || !pval10 || !pval11)
00563         return ERROR_INT("&val* not all defined", procName, 1);
00564     *pval00 = *pval10 = *pval01 = *pval11 = 0.0;
00565     if (!fpixa)
00566         return ERROR_INT("fpixa not defined", procName, 1);
00567     n = fpixaGetCount(fpixa);
00568     if (level < 0 || level >= n - 1)
00569         return ERROR_INT("invalid level", procName, 1);
00570 
00571     if (fpixaGetPixel(fpixa, level + 1, 2 * x, 2 * y, pval00) != 0)
00572         return ERROR_INT("invalid coordinates", procName, 1);
00573     fpixaGetPixel(fpixa, level + 1, 2 * x + 1, 2 * y, pval10);
00574     fpixaGetPixel(fpixa, level + 1, 2 * x, 2 * y + 1, pval01);
00575     fpixaGetPixel(fpixa, level + 1, 2 * x + 1, 2 * y + 1, pval11);
00576     return 0;
00577 }
00578 
00579 
00580 /*!
00581  *  quadtreeMaxLevels()
00582  *
00583  *      Input:  w, h (of image)
00584  *      Return: maxlevels (maximum number of levels allowed), or -1 on error
00585  *
00586  *  Notes:
00587  *      (1) The criterion for maxlevels is that the subdivision not
00588  *          go down below the single pixel level.  The 1.5 factor
00589  *          is intended to keep any rectangle from accidentally
00590  *          having zero dimension due to integer truncation.
00591  */
00592 l_int32
00593 quadtreeMaxLevels(l_int32  w,
00594                   l_int32  h)
00595 {
00596 l_int32  i, minside;
00597 
00598     minside = L_MIN(w, h);
00599     for (i = 0; i < 20; i++) {  /* 2^10 = one million */
00600         if (minside < (1.5 * (1 << i)))
00601             return i - 1;
00602     }
00603 
00604     return -1;  /* fail if the image has over a trillion pixels! */
00605 }
00606 
00607 
00608 /*----------------------------------------------------------------------*
00609  *                            Display quadtree                          *
00610  *----------------------------------------------------------------------*/
00611 /*!
00612  *  fpixaDisplayQuadtree()
00613  *
00614  *      Input:  fpixa (mean, variance or root variance)
00615  *              factor (replication factor at lowest level)
00616  *      Return: pixd (8 bpp, mosaic of quadtree images), or null on error
00617  *
00618  *  Notes:
00619  *      (1) The mean and root variance fall naturally in the 8 bpp range,
00620  *          but the variance is typically outside the range.  This
00621  *          function displays 8 bpp pix clipped to 255, so the image
00622  *          pixels will mostly be 255 (white).
00623  */
00624 PIX *
00625 fpixaDisplayQuadtree(FPIXA    *fpixa,
00626                      l_int32   factor)
00627 {
00628 char       buf[256];
00629 l_int32    nlevels, i, mag, w;
00630 L_BMF     *bmf;
00631 FPIX      *fpix;
00632 PIX       *pixt1, *pixt2, *pixt3, *pixt4, *pixd;
00633 PIXA      *pixat;
00634 
00635     PROCNAME("fpixaDisplayQuadtree");
00636 
00637     if (!fpixa)
00638         return (PIX *)ERROR_PTR("fpixa not defined", procName, NULL);
00639 
00640     if ((nlevels = fpixaGetCount(fpixa)) == 0)
00641         return (PIX *)ERROR_PTR("pixas empty", procName, NULL);
00642 
00643     bmf = bmfCreate("./fonts", 6);
00644     pixat = pixaCreate(nlevels);
00645     for (i = 0; i < nlevels; i++) {
00646         fpix = fpixaGetFPix(fpixa, i, L_CLONE);
00647         pixt1 = fpixConvertToPix(fpix, 8, L_CLIP_TO_ZERO, 0);
00648         mag = factor * (1 << (nlevels - i - 1));
00649         pixt2 = pixExpandReplicate(pixt1, mag);
00650         pixt3 = pixConvertTo32(pixt2);
00651         snprintf(buf, sizeof(buf), "Level %d\n", i);
00652         pixt4 = pixAddSingleTextblock(pixt3, bmf, buf, 0xff000000,
00653                                       L_ADD_BELOW, NULL);
00654         pixaAddPix(pixat, pixt4, L_INSERT);
00655         fpixDestroy(&fpix);
00656         pixDestroy(&pixt1);
00657         pixDestroy(&pixt2);
00658         pixDestroy(&pixt3);
00659     }
00660     w = pixGetWidth(pixt4);
00661     pixd = pixaDisplayTiledInRows(pixat, 32, nlevels * (w + 80), 1.0, 0, 30, 2);
00662 
00663     pixaDestroy(&pixat);
00664     bmfDestroy(&bmf);
00665     return pixd;
00666 }
00667 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines