// Create a window and display the projection in it.
void TextlineProjection::DisplayProjection() const {
#ifndef GRAPHICS_DISABLED
  int width = pixGetWidth(pix_);
  int height = pixGetHeight(pix_);
  Pix* pixc = pixCreate(width, height, 32);
  int src_wpl = pixGetWpl(pix_);
  int col_wpl = pixGetWpl(pixc);
  uint32_t* src_data = pixGetData(pix_);
  uint32_t* col_data = pixGetData(pixc);
  for (int y = 0; y < height; ++y, src_data += src_wpl, col_data += col_wpl) {
    for (int x = 0; x < width; ++x) {
      int pixel = GET_DATA_BYTE(src_data, x);
      l_uint32 result;
      if (pixel <= 17)
        composeRGBPixel(0, 0, pixel * 15, &result);
      else if (pixel <= 145)
        composeRGBPixel(0, (pixel - 17) * 2, 255, &result);
      else
        composeRGBPixel((pixel - 145) * 2, 255, 255, &result);
      col_data[x] = result;
    }
  }
  ScrollView* win = new ScrollView("Projection", 0, 0,
                                   width, height, width, height);
  win->Image(pixc, 0, 0);
  win->Update();
  pixDestroy(&pixc);
#endif  // GRAPHICS_DISABLED
}
Exemple #2
0
void
AddTransformsYUV(PIXA    *pixa,
                 L_BMF   *bmf,
                 l_int32  yval)
{
char       textbuf[256];
l_int32    i, j, wpls;
l_uint32  *datas, *lines;
PIX       *pixs, *pixt1, *pixt2, *pixt3, *pixt4;
PIXA      *pixat;

    pixs = pixCreate(225, 225, 32);
    wpls = pixGetWpl(pixs);
    datas = pixGetData(pixs);
    for (i = 0; i < 225; i++) {   /* v */
        lines = datas + i * wpls;
        for (j = 0; j < 225; j++)  /* u */
            composeRGBPixel(yval + 16, j + 16, i + 16, lines + j);
    }

    pixat = pixaCreate(3);
    pixaAddPix(pixat, pixs, L_INSERT);
    pixt1 = pixConvertYUVToRGB(NULL, pixs);
    pixaAddPix(pixat, pixt1, L_INSERT);
    pixt2 = pixConvertRGBToYUV(NULL, pixt1);
    pixaAddPix(pixat, pixt2, L_INSERT);
    pixt3 = pixaDisplayTiledAndScaled(pixat, 32, 225, 3, 0, 20, 2);
    snprintf(textbuf, sizeof(textbuf), "yval = %d", yval);
    pixt4 = pixAddSingleTextblock(pixt3, bmf, textbuf, 0xff000000,
                                  L_ADD_BELOW, NULL);
    pixaAddPix(pixa, pixt4, L_INSERT);
    pixDestroy(&pixt3);
    pixaDestroy(&pixat);
    return;
}
/*!
 *  pixcmapToRGBTable()
 *
 *      Input:  colormap
 *              &tab (<return> table of rgba values for the colormap)
 *              &ncolors (<optional return> size of table)
 *      Return: 0 if OK; 1 on error
 */
l_int32
pixcmapToRGBTable(PIXCMAP    *cmap,
                  l_uint32  **ptab,
                  l_int32    *pncolors)
{
l_int32    i, ncolors, rval, gval, bval;
l_uint32  *tab;

    PROCNAME("pixcmapToRGBTable");

    if (!ptab)
        return ERROR_INT("&tab not defined", procName, 1);
    *ptab = NULL;
    if (!cmap)
        return ERROR_INT("cmap not defined", procName, 1);

    ncolors = pixcmapGetCount(cmap);
    if (pncolors)
        *pncolors = ncolors;
    if ((tab = (l_uint32 *)CALLOC(ncolors, sizeof(l_uint32))) == NULL)
        return ERROR_INT("tab not made", procName, 1);
    *ptab = tab;
   
    for (i = 0; i < ncolors; i++) {
        pixcmapGetColor(cmap, i, &rval, &gval, &bval);
        composeRGBPixel(rval, gval, bval, &tab[i]);
    }

/*    for (i = 0; i < ncolors; i++)
        fprintf(stderr, "Color[%d] = %x\n", i, tab[i]); */

    return 0;
}
/*!
 *  pixAddRGB()
 *
 *      Input:  pixs1, pixs2  (32 bpp RGB, or colormapped)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) Clips computation to the minimum size, aligning the UL corners.
 *      (2) Removes any colormap to RGB, and ignores the LSB of each
 *          pixel word (the alpha channel).
 *      (3) Adds each component value, pixelwise, clipping to 255.
 *      (4) This is useful to combine two images where most of the
 *          pixels are essentially black, such as in pixPerceptualDiff().
 */
PIX *
pixAddRGB(PIX  *pixs1,
          PIX  *pixs2)
{
l_int32    i, j, w, h, d, w2, h2, d2, wplc1, wplc2, wpld;
l_int32    rval1, gval1, bval1, rval2, gval2, bval2, rval, gval, bval;
l_uint32  *datac1, *datac2, *datad, *linec1, *linec2, *lined;
PIX       *pixc1, *pixc2, *pixd;

    PROCNAME("pixAddRGB");

    if (!pixs1)
        return (PIX *)ERROR_PTR("pixs1 not defined", procName, NULL);
    if (!pixs2)
        return (PIX *)ERROR_PTR("pixs2 not defined", procName, NULL);
    pixGetDimensions(pixs1, &w, &h, &d);
    pixGetDimensions(pixs2, &w2, &h2, &d2);
    if (!pixGetColormap(pixs1) && d != 32)
        return (PIX *)ERROR_PTR("pixs1 not cmapped or rgb", procName, NULL);
    if (!pixGetColormap(pixs2) && d2 != 32)
        return (PIX *)ERROR_PTR("pixs2 not cmapped or rgb", procName, NULL);
    if (pixGetColormap(pixs1))
        pixc1 = pixRemoveColormap(pixs1, REMOVE_CMAP_TO_FULL_COLOR);
    else
        pixc1 = pixClone(pixs1);
    if (pixGetColormap(pixs2))
        pixc2 = pixRemoveColormap(pixs2, REMOVE_CMAP_TO_FULL_COLOR);
    else
        pixc2 = pixClone(pixs2);

    w = L_MIN(w, w2);
    h = L_MIN(h, h2);
    pixd = pixCreate(w, h, 32);
    pixCopyResolution(pixd, pixs1);
    datac1 = pixGetData(pixc1);
    datac2 = pixGetData(pixc2);
    datad = pixGetData(pixd);
    wplc1 = pixGetWpl(pixc1);
    wplc2 = pixGetWpl(pixc2);
    wpld = pixGetWpl(pixd);
    for (i = 0; i < h; i++) {
        linec1 = datac1 + i * wplc1;
        linec2 = datac2 + i * wplc2;
        lined = datad + i * wpld;
        for (j = 0; j < w; j++) {
            extractRGBValues(linec1[j], &rval1, &gval1, &bval1);
            extractRGBValues(linec2[j], &rval2, &gval2, &bval2);
            rval = L_MIN(255, rval1 + rval2);
            gval = L_MIN(255, gval1 + gval2);
            bval = L_MIN(255, bval1 + bval2);
            composeRGBPixel(rval, gval, bval, lined + j);
        }
    }

    pixDestroy(&pixc1);
    pixDestroy(&pixc2);
    return pixd;
}
Exemple #5
0
char* ocr_bitmap(void* arg, png_color *palette,png_byte *alpha, unsigned char* indata,int w, int h)
{
	PIX	*pix = NULL;
	PIX	*cpix = NULL;
	char*text_out= NULL;
	int i,j,index;
	unsigned int wpl;
	unsigned int *data,*ppixel;
	BOOL tess_ret = FALSE;
	struct ocrCtx* ctx = arg;
	pix = pixCreate(w, h, 32);
	if(pix == NULL)
	{
		return NULL;
	}
	wpl = pixGetWpl(pix);
	data = pixGetData(pix);
#if LEPTONICA_VERSION > 69
	pixSetSpp(pix, 4);
#endif
	for (i = 0; i < h; i++)
	{
		ppixel = data + i * wpl;
		for (j = 0; j < w; j++)
		{
			index = indata[i * w + (j)];
			composeRGBPixel(palette[index].red, palette[index].green,palette[index].blue, ppixel);
			SET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL,alpha[index]);
			ppixel++;
		}
	}
	ignore_alpha_at_edge(alpha, indata, w, h, pix, &cpix);
#ifdef OCR_DEBUG
	{
	char str[128] = "";
	static int i = 0;
	sprintf(str,"temp/file_c_%d.png",i);
	pixWrite(str, cpix, IFF_PNG);
	i++;
	}
#endif
	TessBaseAPISetImage2(ctx->api, cpix);
	tess_ret = TessBaseAPIRecognize(ctx->api, NULL);
	if( tess_ret != 0)
		printf("\nsomething messy\n");

	text_out = TessBaseAPIGetUTF8Text(ctx->api);
	pixDestroy(&pix);
	pixDestroy(&cpix);

	return text_out;
}
/*!
 *  pixcmapGetColor32()
 *
 *      Input:  cmap
 *              index
 *              &val32 (<return> 32-bit rgba color value)
 *      Return: 0 if OK, 1 if not accessable (caller should check)
 *
 *  Notes:
 *      (1) The returned alpha channel value is zero, because it is
 *          not used in leptonica colormaps.
 */
l_int32
pixcmapGetColor32(PIXCMAP   *cmap,
                  l_int32    index,
                  l_uint32  *pval32)
{
l_int32  rval, gval, bval;

    PROCNAME("pixcmapGetColor32");

    if (!pval32)
        return ERROR_INT("&val32 not defined", procName, 1);
    *pval32 = 0;

    if (pixcmapGetColor(cmap, index, &rval, &gval, &bval) != 0)
        return ERROR_INT("rgb values not found", procName, 1);
    composeRGBPixel(rval, gval, bval, pval32);
    return 0;
}
Exemple #7
0
/*!
 *  pixSearchGrayMaze()
 *
 *      Input:  pixs (1 bpp, maze)
 *              xi, yi  (beginning point; use same initial point
 *                       that was used to generate the maze)
 *              xf, yf  (end point, or close to it)
 *              &ppixd (<optional return> maze with path illustrated, or
 *                     if no path possible, the part of the maze
 *                     that was searched)
 *      Return: pta (shortest path), or null if either no path
 *              exists or on error
 *
 *  Commentary:
 *      Consider first a slight generalization of the binary maze
 *      search problem.  Suppose that you can go through walls,
 *      but the cost is higher (say, an increment of 3 to go into
 *      a wall pixel rather than 1)?  You're still trying to find
 *      the shortest path.  One way to do this is with an ordered
 *      queue, and a simple way to visualize an ordered queue is as 
 *      a set of stacks, each stack being marked with the distance
 *      of each pixel in the stack from the start.  We place the
 *      start pixel in stack 0, pop it, and process its 4 children.
 *      Each pixel is given a distance that is incremented from that
 *      of its parent (0 in this case), depending on if it is a wall
 *      pixel or not.  That value may be recorded on a distance map,
 *      according to the algorithm below.  For children of the first
 *      pixel, those not on a wall go in stack 1, and wall
 *      children go in stack 3.  Stack 0 being emptied, the process
 *      then continues with pixels being popped from stack 1.
 *      Here is the algorithm for each child pixel.  The pixel's
 *      distance value, were it to be placed on a stack, is compared
 *      with the value for it that is on the distance map.  There
 *      are three possible cases:
 *         (1) If the pixel has not yet been registered, it is pushed
 *             on its stack and the distance is written to the map.
 *         (2) If it has previously been registered with a higher distance,
 *             the distance on the map is relaxed to that of the
 *             current pixel, which is then placed on its stack.
 *         (3) If it has previously been registered with an equal
 *             or lower value, the pixel is discarded.
 *      The pixels are popped and processed successively from
 *      stack 1, and when stack 1 is empty, popping starts on stack 2.
 *      This continues until the destination pixel is popped off
 *      a stack.   The minimum path is then derived from the distance map,
 *      going back from the end point as before.  This is just Dijkstra's
 *      algorithm for a directed graph; here, the underlying graph
 *      (consisting of the pixels and four edges connecting each pixel
 *      to its 4-neighbor) is a special case of a directed graph, where
 *      each edge is bi-directional.  The implementation of this generalized
 *      maze search is left as an exercise to the reader.
 *
 *      Let's generalize a bit further.  Suppose the "maze" is just
 *      a grayscale image -- think of it as an elevation map.  The cost
 *      of moving on this surface depends on the height, or the gradient,
 *      or whatever you want.  All that is required is that the cost
 *      is specified and non-negative on each link between adjacent
 *      pixels.  Now the problem becomes: find the least cost path
 *      moving on this surface between two specified end points.
 *      For example, if the cost across an edge between two pixels
 *      depends on the "gradient", you can use:
 *           cost = 1 + L_ABS(deltaV)
 *      where deltaV is the difference in value between two adjacent
 *      pixels.  If the costs are all integers, we can still use an array
 *      of stacks to avoid ordering the queue (e.g., by using a heap sort.)
 *      This is a neat problem, because you don't even have to build a
 *      maze -- you can can use it on any grayscale image!
 *    
 *      Rather than using an array of stacks, a more practical
 *      approach is to implement with a priority queue, which is
 *      a queue that is sorted so that the elements with the largest
 *      (or smallest) key values always come off first.  The
 *      priority queue is efficiently implemented as a heap, and
 *      this is how we do it.  Suppose you run the algorithm
 *      using a priority queue, doing the bookkeeping with an
 *      auxiliary image data structure that saves the distance of
 *      each pixel put on the queue as before, according to the method
 *      described above.  We implement it as a 2-way choice by
 *      initializing the distance array to a large value and putting
 *      a pixel on the queue if its distance is less than the value
 *      found on the array.  When you finally pop the end pixel from
 *      the queue, you're done, and you can trace the path backward,
 *      either always going downhill or using an auxiliary image to
 *      give you the direction to go at each step.  This is implemented
 *      here in searchGrayMaze().
 *
 *      Do we really have to use a sorted queue?  Can we solve this
 *      generalized maze with an unsorted queue of pixels?  (Or even
 *      an unsorted stack, doing a depth-first search (DFS)?)
 *      Consider a different algorithm for this generalized maze, where
 *      we travel again breadth first, but this time use a single,
 *      unsorted queue.  An auxiliary image is used as before to
 *      store the distances and to determine if pixels get pushed
 *      on the stack or dropped.  As before, we must allow pixels
 *      to be revisited, with relaxation of the distance if a shorter
 *      path arrives later.  As a result, we will in general have
 *      multiple instances of the same pixel on the stack with different
 *      distances.  However, because the queue is not ordered, some of
 *      these pixels will be popped when another instance with a lower
 *      distance is still on the stack.  Here, we're just popping them
 *      in the order they go on, rather than setting up a priority
 *      based on minimum distance.  Thus, unlike the priority queue,
 *      when a pixel is popped we have to check the distance map to
 *      see if a pixel with a lower distance has been put on the queue,
 *      and, if so, we discard the pixel we just popped.  So the
 *      "while" loop looks like this:
 *        - pop a pixel from the queue
 *        - check its distance against the distance stored in the
 *          distance map; if larger, discard
 *        - otherwise, for each of its neighbors:
 *            - compute its distance from the start pixel
 *            - compare this distance with that on the distance map:
 *                - if the distance map value higher, relax the distance
 *                  and push the pixel on the queue
 *                - if the distance map value is lower, discard the pixel
 *
 *      How does this loop terminate?  Before, with an ordered queue,
 *      it terminates when you pop the end pixel.  But with an unordered
 *      queue (or stack), the first time you hit the end pixel, the
 *      distance is not guaranteed to be correct, because the pixels
 *      along the shortest path may not have yet been visited and relaxed.
 *      Because the shortest path can theoretically go anywhere,
 *      we must keep going.  How do we know when to stop?   Dijkstra
 *      uses an ordered queue to systematically remove nodes from
 *      further consideration.  (Each time a pixel is popped, we're
 *      done with it; it's "finalized" in the Dijkstra sense because
 *      we know the shortest path to it.)  However, with an unordered
 *      queue, the brute force answer is: stop when the queue
 *      (or stack) is empty, because then every pixel in the image
 *      has been assigned its minimum "distance" from the start pixel.
 *
 *      This is similar to the situation when you use a stack for the
 *      simpler uniform-step problem: with breadth-first search (BFS)
 *      the pixels on the queue are automatically ordered, so you are
 *      done when you locate the end pixel as a neighbor of a popped pixel;
 *      whereas depth-first search (DFS), using a stack, requires,
 *      in general, a search of every accessible pixel.  Further, if
 *      a pixel is revisited with a smaller distance, that distance is
 *      recorded and the pixel is put on the stack again.
 *
 *      But surely, you ask, can't we stop sooner?  What if the
 *      start and end pixels are very close to each other?
 *      OK, suppose they are, and you have very high walls and a
 *      long snaking level path that is actually the minimum cost.
 *      That long path can wind back and forth across the entire
 *      maze many times before ending up at the end point, which
 *      could be just over a wall from the start.  With the unordered
 *      queue, you very quickly get a high distance for the end
 *      pixel, which will be relaxed to the minimum distance only
 *      after all the pixels of the path have been visited and placed
 *      on the queue, multiple times for many of them.  So that's the
 *      price for not ordering the queue!
 */
PTA *
pixSearchGrayMaze(PIX     *pixs,
                  l_int32  xi,
                  l_int32  yi,
                  l_int32  xf,
                  l_int32  yf,
                  PIX    **ppixd)
{
l_int32   x, y, w, h, d;
l_uint32  val, valr, vals, rpixel, gpixel, bpixel;
void    **lines8, **liner32, **linep8;
l_int32   cost, dist, distparent, sival, sivals;
MAZEEL   *el, *elp;
PIX      *pixd;  /* optionally plot the path on this RGB version of pixs */
PIX      *pixr;  /* for bookkeeping, to indicate the minimum distance */
                 /* to pixels already visited */
PIX      *pixp;  /* for bookkeeping, to indicate direction to parent */
L_HEAP   *lh;
PTA      *pta;

    PROCNAME("pixSearchGrayMaze");

    if (ppixd) *ppixd = NULL;
    if (!pixs)
        return (PTA *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 8)
        return (PTA *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
    if (xi <= 0 || xi >= w)
        return (PTA *)ERROR_PTR("xi not valid", procName, NULL);
    if (yi <= 0 || yi >= h)
        return (PTA *)ERROR_PTR("yi not valid", procName, NULL);
    pixd = NULL;
    pta = NULL;

    pixr = pixCreate(w, h, 32);
    pixSetAll(pixr);  /* initialize to max value */
    pixp = pixCreate(w, h, 8);  /* direction to parent stored as enum val */
    lines8 = pixGetLinePtrs(pixs, NULL);
    linep8 = pixGetLinePtrs(pixp, NULL);
    liner32 = pixGetLinePtrs(pixr, NULL);

    lh = lheapCreate(0, L_SORT_INCREASING);  /* always remove closest pixels */

        /* Prime the heap with the first pixel */
    pixGetPixel(pixs, xi, yi, &val);
    el = mazeelCreate(xi, yi, 0);  /* don't need direction here */
    el->distance = 0;
    pixGetPixel(pixs, xi, yi, &val);
    el->val = val;
    pixSetPixel(pixr, xi, yi, 0);  /* distance is 0 */
    lheapAdd(lh, el);

        /* Breadth-first search with priority queue (implemented by
           a heap), labeling direction to parents in pixp and minimum
           distance to visited pixels in pixr.  Stop when we pull
           the destination point (xf, yf) off the queue. */
    while (lheapGetCount(lh) > 0) {
        elp = (MAZEEL *)lheapRemove(lh);
        if (!elp)
            return (PTA *)ERROR_PTR("heap broken!!", procName, NULL);
        x = elp->x;
        y = elp->y;
        if (x == xf && y == yf) {  /* exit condition */
            FREE(elp);
            break;
        }
        distparent = (l_int32)elp->distance;
        val = elp->val;
        sival = val;
            
        if (x > 0) {  /* check to west */
            vals = GET_DATA_BYTE(lines8[y], x - 1);
            valr = GET_DATA_FOUR_BYTES(liner32[y], x - 1);
            sivals = (l_int32)vals;
            cost = 1 + L_ABS(sivals - sival);  /* cost to move to this pixel */
            dist = distparent + cost;
            if (dist < valr) {  /* shortest path so far to this pixel */
                SET_DATA_FOUR_BYTES(liner32[y], x - 1, dist);  /* new dist */
                SET_DATA_BYTE(linep8[y], x - 1, DIR_EAST);  /* parent to E */
                el = mazeelCreate(x - 1, y, 0);
                el->val = vals;
                el->distance = dist;
                lheapAdd(lh, el);
            }
        }
        if (y > 0) {  /* check north */
            vals = GET_DATA_BYTE(lines8[y - 1], x);
            valr = GET_DATA_FOUR_BYTES(liner32[y - 1], x);
            sivals = (l_int32)vals;
            cost = 1 + L_ABS(sivals - sival);  /* cost to move to this pixel */
            dist = distparent + cost;
            if (dist < valr) {  /* shortest path so far to this pixel */
                SET_DATA_FOUR_BYTES(liner32[y - 1], x, dist);  /* new dist */
                SET_DATA_BYTE(linep8[y - 1], x, DIR_SOUTH);  /* parent to S */
                el = mazeelCreate(x, y - 1, 0);
                el->val = vals;
                el->distance = dist;
                lheapAdd(lh, el);
            }
        }
        if (x < w - 1) {  /* check east */
            vals = GET_DATA_BYTE(lines8[y], x + 1);
            valr = GET_DATA_FOUR_BYTES(liner32[y], x + 1);
            sivals = (l_int32)vals;
            cost = 1 + L_ABS(sivals - sival);  /* cost to move to this pixel */
            dist = distparent + cost;
            if (dist < valr) {  /* shortest path so far to this pixel */
                SET_DATA_FOUR_BYTES(liner32[y], x + 1, dist);  /* new dist */
                SET_DATA_BYTE(linep8[y], x + 1, DIR_WEST);  /* parent to W */
                el = mazeelCreate(x + 1, y, 0);
                el->val = vals;
                el->distance = dist;
                lheapAdd(lh, el);
            }
        }
        if (y < h - 1) {  /* check south */
            vals = GET_DATA_BYTE(lines8[y + 1], x);
            valr = GET_DATA_FOUR_BYTES(liner32[y + 1], x);
            sivals = (l_int32)vals;
            cost = 1 + L_ABS(sivals - sival);  /* cost to move to this pixel */
            dist = distparent + cost;
            if (dist < valr) {  /* shortest path so far to this pixel */
                SET_DATA_FOUR_BYTES(liner32[y + 1], x, dist);  /* new dist */
                SET_DATA_BYTE(linep8[y + 1], x, DIR_NORTH);  /* parent to N */
                el = mazeelCreate(x, y + 1, 0);
                el->val = vals;
                el->distance = dist;
                lheapAdd(lh, el);
            }
        }
        FREE(elp);
    }

    lheapDestroy(&lh, TRUE);

    if (ppixd) {
        pixd = pixConvert8To32(pixs);
        *ppixd = pixd;
    }
    composeRGBPixel(255, 0, 0, &rpixel);  /* start point */
    composeRGBPixel(0, 255, 0, &gpixel);
    composeRGBPixel(0, 0, 255, &bpixel);  /* end point */

    x = xf;
    y = yf;
    pta = ptaCreate(0);
    while (1) {  /* write path onto pixd */
        ptaAddPt(pta, x, y);
        if (x == xi && y == yi)
            break;
        if (pixd)
            pixSetPixel(pixd, x, y, gpixel);
        pixGetPixel(pixp, x, y, &val);
        if (val == DIR_NORTH)
            y--;
        else if (val == DIR_SOUTH)
            y++;
        else if (val == DIR_EAST)
            x++;
        else if (val == DIR_WEST)
            x--;
        pixGetPixel(pixr, x, y, &val);

#if  DEBUG_PATH
        fprintf(stderr, "(x,y) = (%d, %d); dist = %d\n", x, y, val);
#endif  /* DEBUG_PATH */

    }
    if (pixd) {
        pixSetPixel(pixd, xi, yi, rpixel);
        pixSetPixel(pixd, xf, yf, bpixel);
    }

    pixDestroy(&pixp);
    pixDestroy(&pixr);
    FREE(lines8);
    FREE(linep8);
    FREE(liner32);
    return pta;
}
Exemple #8
0
/*!
 *  pixSearchBinaryMaze()
 *
 *      Input:  pixs (1 bpp, maze)
 *              xi, yi  (beginning point; use same initial point
 *                       that was used to generate the maze)
 *              xf, yf  (end point, or close to it)
 *              &ppixd (<optional return> maze with path illustrated, or
 *                     if no path possible, the part of the maze
 *                     that was searched)
 *      Return: pta (shortest path), or null if either no path
 *              exists or on error
 *
 *  Notes:
 *      (1) Because of the overhead in calling pixGetPixel() and
 *          pixSetPixel(), we have used raster line pointers and the
 *          GET_DATA* and SET_DATA* macros for many of the pix accesses.
 *      (2) Commentary:
 *            The goal is to find the shortest path between beginning and
 *          end points, without going through walls, and there are many
 *          ways to solve this problem.
 *            We use a queue to implement a breadth-first search.  Two auxiliary
 *          "image" data structures can be used: one to mark the visited
 *          pixels and one to give the direction to the parent for each
 *          visited pixels.  The first structure is used to avoid putting
 *          pixels on the queue more than once, and the second is used
 *          for retracing back to the origin, like the breadcrumbs in
 *          Hansel and Gretel.  Each pixel taken off the queue is destroyed
 *          after it is used to locate the allowed neighbors.  In fact,
 *          only one distance image is required, if you initialize it
 *          to some value that signifies "not yet visited."  (We use
 *          a binary image for marking visited pixels because it is clearer.)
 *          This method for a simple search of a binary maze is implemented in
 *          searchBinaryMaze().
 *            An alternative method would store the (manhattan) distance
 *          from the start point with each pixel on the queue.  The children
 *          of each pixel get a distance one larger than the parent.  These
 *          values can be stored in an auxiliary distance map image
 *          that is constructed simultaneously with the search.  Once the
 *          end point is reached, the distance map is used to backtrack
 *          along a minimum path.  There may be several equal length
 *          minimum paths, any one of which can be chosen this way.
 */
PTA *
pixSearchBinaryMaze(PIX     *pixs,
                    l_int32  xi,
                    l_int32  yi, 
                    l_int32  xf,
                    l_int32  yf,
                    PIX    **ppixd)
{
l_int32    i, j, x, y, w, h, d, found;
l_uint32   val, rpixel, gpixel, bpixel;
void     **lines1, **linem1, **linep8, **lined32;
MAZEEL    *el, *elp;
PIX       *pixd;  /* the shortest path written on the maze image */
PIX       *pixm;  /* for bookkeeping, to indicate pixels already visited */
PIX       *pixp;  /* for bookkeeping, to indicate direction to parent */
L_QUEUE   *lq;
PTA       *pta;

    PROCNAME("pixSearchBinaryMaze");

    if (ppixd) *ppixd = NULL;
    if (!pixs)
        return (PTA *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1)
        return (PTA *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
    if (xi <= 0 || xi >= w)
        return (PTA *)ERROR_PTR("xi not valid", procName, NULL);
    if (yi <= 0 || yi >= h)
        return (PTA *)ERROR_PTR("yi not valid", procName, NULL);
    pixGetPixel(pixs, xi, yi, &val);
    if (val != 0)
        return (PTA *)ERROR_PTR("(xi,yi) not bg pixel", procName, NULL);
    pixd = NULL;
    pta = NULL;

        /* Find a bg pixel near input point (xf, yf) */
    localSearchForBackground(pixs, &xf, &yf, 5);

#if  DEBUG_MAZE
    fprintf(stderr, "(xi, yi) = (%d, %d), (xf, yf) = (%d, %d)\n",
            xi, yi, xf, yf);
#endif  /* DEBUG_MAZE */

    pixm = pixCreate(w, h, 1);  /* initialized to OFF */
    pixp = pixCreate(w, h, 8);  /* direction to parent stored as enum val */
    lines1 = pixGetLinePtrs(pixs, NULL);
    linem1 = pixGetLinePtrs(pixm, NULL);
    linep8 = pixGetLinePtrs(pixp, NULL);

    lq = lqueueCreate(0);

        /* Prime the queue with the first pixel; it is OFF */
    el = mazeelCreate(xi, yi, 0);  /* don't need direction here */
    pixSetPixel(pixm, xi, yi, 1);  /* mark visited */
    lqueueAdd(lq, el);

        /* Fill up the pix storing directions to parents,
         * stopping when we hit the point (xf, yf)  */
    found = FALSE;
    while (lqueueGetCount(lq) > 0) {
        elp = (MAZEEL *)lqueueRemove(lq);
        x = elp->x;
        y = elp->y;
        if (x == xf && y == yf) {
            found = TRUE;
            FREE(elp);
            break;
        }
            
        if (x > 0) {  /* check to west */
            val = GET_DATA_BIT(linem1[y], x - 1);
            if (val == 0) {  /* not yet visited */
                SET_DATA_BIT(linem1[y], x - 1);  /* mark visited */
                val = GET_DATA_BIT(lines1[y], x - 1);
                if (val == 0) {  /* bg, not a wall */
                    SET_DATA_BYTE(linep8[y], x - 1, DIR_EAST);  /* parent E */
                    el = mazeelCreate(x - 1, y, 0);
                    lqueueAdd(lq, el);
                }
            }
        }
        if (y > 0) {  /* check north */
            val = GET_DATA_BIT(linem1[y - 1], x);
            if (val == 0) {  /* not yet visited */
                SET_DATA_BIT(linem1[y - 1], x);  /* mark visited */
                val = GET_DATA_BIT(lines1[y - 1], x);
                if (val == 0) {  /* bg, not a wall */
                    SET_DATA_BYTE(linep8[y - 1], x, DIR_SOUTH);  /* parent S */
                    el = mazeelCreate(x, y - 1, 0);
                    lqueueAdd(lq, el);
                }
            }
        }
        if (x < w - 1) {  /* check east */
            val = GET_DATA_BIT(linem1[y], x + 1);
            if (val == 0) {  /* not yet visited */
                SET_DATA_BIT(linem1[y], x + 1);  /* mark visited */
                val = GET_DATA_BIT(lines1[y], x + 1);
                if (val == 0) {  /* bg, not a wall */
                    SET_DATA_BYTE(linep8[y], x + 1, DIR_WEST);  /* parent W */
                    el = mazeelCreate(x + 1, y, 0);
                    lqueueAdd(lq, el);
                }
            }
        }
        if (y < h - 1) {  /* check south */
            val = GET_DATA_BIT(linem1[y + 1], x);
            if (val == 0) {  /* not yet visited */
                SET_DATA_BIT(linem1[y + 1], x);  /* mark visited */
                val = GET_DATA_BIT(lines1[y + 1], x);
                if (val == 0) {  /* bg, not a wall */
                    SET_DATA_BYTE(linep8[y + 1], x, DIR_NORTH);  /* parent N */
                    el = mazeelCreate(x, y + 1, 0);
                    lqueueAdd(lq, el);
                }
            }
        }
        FREE(elp);
    }

    lqueueDestroy(&lq, TRUE);
    pixDestroy(&pixm);
    FREE(linem1);

    if (ppixd) {
        pixd = pixUnpackBinary(pixs, 32, 1);
        *ppixd = pixd;
    }
    composeRGBPixel(255, 0, 0, &rpixel);  /* start point */
    composeRGBPixel(0, 255, 0, &gpixel);
    composeRGBPixel(0, 0, 255, &bpixel);  /* end point */


    if (!found) {
        L_INFO(" No path found", procName);
        if (pixd) {  /* paint all visited locations */
            lined32 = pixGetLinePtrs(pixd, NULL);
            for (i = 0; i < h; i++) {
                for (j = 0; j < w; j++) {
                    val = GET_DATA_BYTE(linep8[i], j);
                    if (val != 0 && pixd)
                        SET_DATA_FOUR_BYTES(lined32[i], j, gpixel);
                }
            }
            FREE(lined32);
        }
    }
    else {   /* write path onto pixd */
        L_INFO(" Path found", procName);
        pta = ptaCreate(0);
        x = xf;
        y = yf;
        while (1) {
            ptaAddPt(pta, x, y);
            if (x == xi && y == yi)
                break;
            if (pixd)
                pixSetPixel(pixd, x, y, gpixel);
            pixGetPixel(pixp, x, y, &val);
            if (val == DIR_NORTH)
                y--;
            else if (val == DIR_SOUTH)
                y++;
            else if (val == DIR_EAST)
                x++;
            else if (val == DIR_WEST)
                x--;
        }
    }
    if (pixd) {
        pixSetPixel(pixd, xi, yi, rpixel);
        pixSetPixel(pixd, xf, yf, bpixel);
    }

    pixDestroy(&pixp);
    FREE(lines1);
    FREE(linep8);
    return pta;
}
Exemple #9
0
/*!
 * \brief   pixReadStreamJpeg()
 *
 * \param[in]    fp file stream
 * \param[in]    cmapflag 0 for no colormap in returned pix;
 *                        1 to return an 8 bpp cmapped pix if spp = 3 or 4
 * \param[in]    reduction scaling factor: 1, 2, 4 or 8
 * \param[out]   pnwarn [optional] number of warnings
 * \param[in]    hint a bitwise OR of L_JPEG_* values; 0 for default
 * \return  pix, or NULL on error
 *
 *  Usage: see pixReadJpeg
 * <pre>
 * Notes:
 *      (1) The jpeg comment, if it exists, is not stored in the pix.
 * </pre>
 */
PIX *
pixReadStreamJpeg(FILE     *fp,
                  l_int32   cmapflag,
                  l_int32   reduction,
                  l_int32  *pnwarn,
                  l_int32   hint)
{
l_int32                        cyan, yellow, magenta, black, nwarn;
l_int32                        i, j, k, rval, gval, bval;
l_int32                        w, h, wpl, spp, ncolors, cindex, ycck, cmyk;
l_uint32                      *data;
l_uint32                      *line, *ppixel;
JSAMPROW                       rowbuffer;
PIX                           *pix;
PIXCMAP                       *cmap;
struct jpeg_decompress_struct  cinfo;
struct jpeg_error_mgr          jerr;
jmp_buf                        jmpbuf;  /* must be local to the function */

    PROCNAME("pixReadStreamJpeg");

    if (pnwarn) *pnwarn = 0;
    if (!fp)
        return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
    if (cmapflag != 0 && cmapflag != 1)
        cmapflag = 0;  /* default */
    if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
        return (PIX *)ERROR_PTR("reduction not in {1,2,4,8}", procName, NULL);

    if (BITS_IN_JSAMPLE != 8)  /* set in jmorecfg.h */
        return (PIX *)ERROR_PTR("BITS_IN_JSAMPLE != 8", procName, NULL);

    rewind(fp);
    pix = NULL;
    rowbuffer = NULL;

        /* Modify the jpeg error handling to catch fatal errors  */
    cinfo.err = jpeg_std_error(&jerr);
    jerr.error_exit = jpeg_error_catch_all_1;
    cinfo.client_data = (void *)&jmpbuf;
    if (setjmp(jmpbuf)) {
        pixDestroy(&pix);
        LEPT_FREE(rowbuffer);
        return (PIX *)ERROR_PTR("internal jpeg error", procName, NULL);
    }

        /* Initialize jpeg structs for decompression */
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, fp);
    jpeg_read_header(&cinfo, TRUE);
    cinfo.scale_denom = reduction;
    cinfo.scale_num = 1;
    jpeg_calc_output_dimensions(&cinfo);
    if (hint & L_JPEG_READ_LUMINANCE) {
        cinfo.out_color_space = JCS_GRAYSCALE;
        spp = 1;
        L_INFO("reading luminance channel only\n", procName);
    } else {
        spp = cinfo.out_color_components;
    }

        /* Allocate the image and a row buffer */
    w = cinfo.output_width;
    h = cinfo.output_height;
    ycck = (cinfo.jpeg_color_space == JCS_YCCK && spp == 4 && cmapflag == 0);
    cmyk = (cinfo.jpeg_color_space == JCS_CMYK && spp == 4 && cmapflag == 0);
    if (spp != 1 && spp != 3 && !ycck && !cmyk) {
        return (PIX *)ERROR_PTR("spp must be 1 or 3, or YCCK or CMYK",
                                procName, NULL);
    }
    if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {  /* rgb or 4 bpp color */
        rowbuffer = (JSAMPROW)LEPT_CALLOC(sizeof(JSAMPLE), spp * w);
        pix = pixCreate(w, h, 32);
    } else {  /* 8 bpp gray or colormapped */
        rowbuffer = (JSAMPROW)LEPT_CALLOC(sizeof(JSAMPLE), w);
        pix = pixCreate(w, h, 8);
    }
    pixSetInputFormat(pix, IFF_JFIF_JPEG);
    if (!rowbuffer || !pix) {
        LEPT_FREE(rowbuffer);
        pixDestroy(&pix);
        return (PIX *)ERROR_PTR("rowbuffer or pix not made", procName, NULL);
    }

        /* Initialize decompression.  Set up a colormap for color
         * quantization if requested. */
    if (spp == 1) {  /* Grayscale or colormapped */
        jpeg_start_decompress(&cinfo);
    } else {        /* Color; spp == 3 or YCCK or CMYK */
        if (cmapflag == 0) {   /* 24 bit color in 32 bit pix or YCCK/CMYK */
            cinfo.quantize_colors = FALSE;
            jpeg_start_decompress(&cinfo);
        } else {      /* Color quantize to 8 bits */
            cinfo.quantize_colors = TRUE;
            cinfo.desired_number_of_colors = 256;
            jpeg_start_decompress(&cinfo);

                /* Construct a pix cmap */
            cmap = pixcmapCreate(8);
            ncolors = cinfo.actual_number_of_colors;
            for (cindex = 0; cindex < ncolors; cindex++) {
                rval = cinfo.colormap[0][cindex];
                gval = cinfo.colormap[1][cindex];
                bval = cinfo.colormap[2][cindex];
                pixcmapAddColor(cmap, rval, gval, bval);
            }
            pixSetColormap(pix, cmap);
        }
    }
    wpl  = pixGetWpl(pix);
    data = pixGetData(pix);

        /* Decompress.  Unfortunately, we cannot use the return value
         * from jpeg_read_scanlines() to determine if there was a problem
         * with the data; it always appears to return 1.  We can only
         * tell from the warnings during decoding, such as "premature
         * end of data segment".  The default behavior is to return an
         * image even if there are warnings.  However, by setting the
         * hint to have the same bit flag as L_JPEG_FAIL_ON_BAD_DATA,
         * no image will be returned if there are any warnings. */
    for (i = 0; i < h; i++) {
        if (jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1) == 0) {
            L_ERROR("read error at scanline %d\n", procName, i);
            pixDestroy(&pix);
            jpeg_destroy_decompress(&cinfo);
            LEPT_FREE(rowbuffer);
            return (PIX *)ERROR_PTR("bad data", procName, NULL);
        }

            /* -- 24 bit color -- */
        if ((spp == 3 && cmapflag == 0) || ycck || cmyk) {
            ppixel = data + i * wpl;
            if (spp == 3) {
                for (j = k = 0; j < w; j++) {
                    SET_DATA_BYTE(ppixel, COLOR_RED, rowbuffer[k++]);
                    SET_DATA_BYTE(ppixel, COLOR_GREEN, rowbuffer[k++]);
                    SET_DATA_BYTE(ppixel, COLOR_BLUE, rowbuffer[k++]);
                    ppixel++;
                }
            } else {
                    /* This is a conversion from CMYK -> RGB that ignores
                       color profiles, and is invoked when the image header
                       claims to be in CMYK or YCCK colorspace.  If in YCCK,
                       libjpeg may be doing YCCK -> CMYK under the hood.
                       To understand why the colors need to be inverted on
                       read-in for the Adobe marker, see the "Special
                       color spaces" section of "Using the IJG JPEG
                       Library" by Thomas G. Lane:
                         http://www.jpegcameras.com/libjpeg/libjpeg-3.html#ss3.1
                       The non-Adobe conversion is equivalent to:
                           rval = black - black * cyan / 255
                           ...
                       The Adobe conversion is equivalent to:
                           rval = black - black * (255 - cyan) / 255
                           ...
                       Note that cyan is the complement to red, and we
                       are subtracting the complement color (weighted
                       by black) from black.  For Adobe conversions,
                       where they've already inverted the CMY but not
                       the K, we have to invert again.  The results
                       must be clipped to [0 ... 255]. */
                for (j = k = 0; j < w; j++) {
                    cyan = rowbuffer[k++];
                    magenta = rowbuffer[k++];
                    yellow = rowbuffer[k++];
                    black = rowbuffer[k++];
                    if (cinfo.saw_Adobe_marker) {
                        rval = (black * cyan) / 255;
                        gval = (black * magenta) / 255;
                        bval = (black * yellow) / 255;
                    } else {
                        rval = black * (255 - cyan) / 255;
                        gval = black * (255 - magenta) / 255;
                        bval = black * (255 - yellow) / 255;
                    }
                    rval = L_MIN(L_MAX(rval, 0), 255);
                    gval = L_MIN(L_MAX(gval, 0), 255);
                    bval = L_MIN(L_MAX(bval, 0), 255);
                    composeRGBPixel(rval, gval, bval, ppixel);
                    ppixel++;
                }
            }
        } else {    /* 8 bpp grayscale or colormapped pix */
            line = data + i * wpl;
            for (j = 0; j < w; j++)
                SET_DATA_BYTE(line, j, rowbuffer[j]);
        }
    }

    nwarn = cinfo.err->num_warnings;
    if (pnwarn) *pnwarn = nwarn;

        /* If the pixel density is neither 1 nor 2, it may not be defined.
         * In that case, don't set the resolution.  */
    if (cinfo.density_unit == 1) {  /* pixels per inch */
        pixSetXRes(pix, cinfo.X_density);
        pixSetYRes(pix, cinfo.Y_density);
    } else if (cinfo.density_unit == 2) {  /* pixels per centimeter */
        pixSetXRes(pix, (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5));
        pixSetYRes(pix, (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5));
    }

    if (cinfo.output_components != spp)
        fprintf(stderr, "output spp = %d, spp = %d\n",
                cinfo.output_components, spp);

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    LEPT_FREE(rowbuffer);

    if (nwarn > 0) {
        if (hint & L_JPEG_FAIL_ON_BAD_DATA) {
            L_ERROR("fail with %d warning(s) of bad data\n", procName, nwarn);
            pixDestroy(&pix);
        } else {
            L_WARNING("%d warning(s) of bad data\n", procName, nwarn);
        }
    }

    return pix;
}
main(int    argc,
     char **argv)
{
l_int32       i, j, x, y, rval, gval, bval;
l_uint32      pixel;
l_float32     frval, fgval, fbval;
NUMA         *nahue, *nasat, *napk;
PIX          *pixs, *pixhsv, *pixh, *pixg, *pixf, *pixd;
PIX          *pixr, *pixt1, *pixt2, *pixt3;
PIXA         *pixa, *pixapk;
PTA          *ptapk;
L_REGPARAMS  *rp;
	l_chooseDisplayProg(L_DISPLAY_WITH_XV);

    if (regTestSetup(argc, argv, &rp))
        return 1;

        /* Make a graded frame color */
    pixs = pixCreate(650, 900, 32);
    for (i = 0; i < 900; i++) {
        rval = 40 + i / 30;
        for (j = 0; j < 650; j++) {
            gval = 255 - j / 30;
            bval = 70 + j / 30;
            composeRGBPixel(rval, gval, bval, &pixel);
            pixSetPixel(pixs, j, i, pixel);
        }
    }
            
        /* Place an image inside the frame and convert to HSV */
    pixt1 = pixRead("1555-3.jpg");
    pixt2 = pixScale(pixt1, 0.5, 0.5);
    pixRasterop(pixs, 100, 100, 2000, 2000, PIX_SRC, pixt2, 0, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDisplayWithTitle(pixs, 400, 0, "Input image", rp->display);
    pixa = pixaCreate(0);
    pixhsv = pixConvertRGBToHSV(NULL, pixs);

        /* Work in the HS projection of HSV */
    pixh = pixMakeHistoHS(pixhsv, 5, &nahue, &nasat);
    pixg = pixMaxDynamicRange(pixh, L_LOG_SCALE);
    pixf = pixConvertGrayToFalseColor(pixg, 1.0);
    regTestWritePixAndCheck(rp, pixf, IFF_PNG);   /* 0 */
    pixDisplayWithTitle(pixf, 100, 0, "False color HS histo", rp->display);
    pixaAddPix(pixa, pixs, L_COPY);
    pixaAddPix(pixa, pixhsv, L_INSERT);
    pixaAddPix(pixa, pixg, L_INSERT);
    pixaAddPix(pixa, pixf, L_INSERT);
    gplotSimple1(nahue, GPLOT_PNG, "/tmp/junkhue", "Histogram of hue values");
#ifndef  _WIN32
    sleep(1);
#else
    Sleep(1000);
#endif  /* _WIN32 */
    pixt3 = pixRead("/tmp/junkhue.png");
    regTestWritePixAndCheck(rp, pixt3, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pixt3, 100, 300, "Histo of hue", rp->display);
    pixaAddPix(pixa, pixt3, L_INSERT);
    gplotSimple1(nasat, GPLOT_PNG, "/tmp/junksat",
                 "Histogram of saturation values");
#ifndef  _WIN32
    sleep(1);
#else
    Sleep(1000);
#endif  /* _WIN32 */
    pixt3 = pixRead("/tmp/junksat.png");
    regTestWritePixAndCheck(rp, pixt3, IFF_PNG);  /* 2 */
    pixDisplayWithTitle(pixt3, 100, 800, "Histo of saturation", rp->display);
    pixaAddPix(pixa, pixt3, L_INSERT);
    pixd = pixaDisplayTiledAndScaled(pixa, 32, 270, 7, 0, 30, 3);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 3 */
    pixDisplayWithTitle(pixd, 0, 400, "Hue and Saturation Mosaic", rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    numaDestroy(&nahue);
    numaDestroy(&nasat);

        /* Find all the peaks */
    pixFindHistoPeaksHSV(pixh, L_HS_HISTO, 20, 20, 6, 2.0,
                         &ptapk, &napk, &pixapk);
    numaWriteStream(stderr, napk);
    ptaWriteStream(stderr, ptapk, 1);
    pixd = pixaDisplayTiledInRows(pixapk, 32, 1400, 1.0, 0, 30, 2);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(pixd, 0, 550, "Peaks in HS", rp->display);
    pixDestroy(&pixh);
    pixDestroy(&pixd);
    pixaDestroy(&pixapk);

        /* Make masks for each of the peaks */
    pixa = pixaCreate(0);
    pixr = pixScaleBySampling(pixs, 0.4, 0.4);
    for (i = 0; i < 6; i++) {
        ptaGetIPt(ptapk, i, &x, &y);
        pixt1 = pixMakeRangeMaskHS(pixr, y, 20, x, 20, L_INCLUDE_REGION);
        pixaAddPix(pixa, pixt1, L_INSERT);
        pixGetAverageMaskedRGB(pixr, pixt1, 0, 0, 1, L_MEAN_ABSVAL,
                               &frval, &fgval, &fbval);
        composeRGBPixel((l_int32)frval, (l_int32)fgval, (l_int32)fbval,
                        &pixel);
        pixt2 = pixCreateTemplate(pixr);
        pixSetAll(pixt2);
        pixPaintThroughMask(pixt2, pixt1, 0, 0, pixel);
        pixaAddPix(pixa, pixt2, L_INSERT);
        pixt3 = pixCreateTemplate(pixr);
        pixSetAllArbitrary(pixt3, pixel);
        pixaAddPix(pixa, pixt3, L_INSERT);
    }
    pixd = pixaDisplayTiledAndScaled(pixa, 32, 225, 3, 0, 30, 3);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 5 */
    pixDisplayWithTitle(pixd, 600, 0, "Masks over peaks", rp->display);
    pixDestroy(&pixs);
    pixDestroy(&pixr);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    ptaDestroy(&ptapk);
    numaDestroy(&napk);

    regTestCleanup(rp);
    return 0;
}
int main(int    argc,
         char **argv)
{
l_int32      i, j;
l_float32    f;
l_uint32     redval, greenval;
PIX         *pixs, *pixd, *pix0, *pix1, *pix2;
static char  mainName[] = "locminmax_reg";

    if (argc != 1)
        return ERROR_INT("syntax: locminmax_reg", mainName, 1);

    pixs = pixCreate(500, 500, 8);
    for (i = 0; i < 500; i++) {
        for (j = 0; j < 500; j++) {
            f = 128.0 + 26.3 * sin(0.0438 * (l_float32)i);
            f += 33.4 * cos(0.0712 * (l_float32)i);
            f += 18.6 * sin(0.0561 * (l_float32)j);
            f += 23.6 * cos(0.0327 * (l_float32)j);
            pixSetPixel(pixs, j, i, (l_int32)f);
        }
    }
    pixDisplay(pixs, 0, 0);
    pixWrite("/tmp/junkpattern.png", pixs, IFF_PNG);

    startTimer();
/*    pixSelectedLocalExtrema(pixs, 1, &pix1, &pix2); */
    pixLocalExtrema(pixs, 0, 0, &pix1, &pix2);
    fprintf(stderr, "Time for extrema: %7.3f\n", stopTimer());
    composeRGBPixel(255, 0, 0, &redval);
    composeRGBPixel(0, 255, 0, &greenval);
    pixd = pixConvertTo32(pixs);
    pixPaintThroughMask(pixd, pix2, 0, 0, greenval);
    pixPaintThroughMask(pixd, pix1, 0, 0, redval);
    pixDisplay(pixd, 510, 0);
    pixWrite("/tmp/junkpixd.png", pixd, IFF_PNG);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pixs);
    pixDestroy(&pixd);

    pix0 = pixRead("karen8.jpg");
    pixs = pixBlockconv(pix0, 10, 10);
    pixDisplay(pixs, 0, 400);
    pixWrite("/tmp/junkconv.png", pixs, IFF_PNG);
    startTimer();
/*    pixSelectedLocalExtrema(pixs, 1, &pix1, &pix2); */
    pixLocalExtrema(pixs, 50, 100, &pix1, &pix2);
    fprintf(stderr, "Time for extrema: %7.3f\n", stopTimer());
    composeRGBPixel(255, 0, 0, &redval);
    composeRGBPixel(0, 255, 0, &greenval);
    pixd = pixConvertTo32(pixs);
    pixPaintThroughMask(pixd, pix2, 0, 0, greenval);
    pixPaintThroughMask(pixd, pix1, 0, 0, redval);
    pixDisplay(pixd, 350, 400);
    pixWrite("/tmp/junkpixd2.png", pixd, IFF_PNG);
    pixDestroy(&pix0);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pixs);
    pixDestroy(&pixd);
    return 0;
}
int main(int    argc,
         char **argv)
{
char          label[512];
l_int32       rval, gval, bval, w, h, i, j, rwhite, gwhite, bwhite, count;
l_uint32      pixel;
GPLOT        *gplot1, *gplot2;
NUMA         *naseq, *na;
NUMAA        *naa1, *naa2;
PIX          *pixs, *pixt, *pixt0, *pixt1, *pixt2;
PIX          *pixr, *pixg, *pixb;  /* for color content extraction */
PIXA         *pixa, *pixat;
PIXCMAP      *cmap;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

        /* Generate a pdf of results when called with display */
    pixa = pixaCreate(0);

        /* Generate colors by sampling hue with max sat and value.
         * This image has been saved as 19-colors.png.  */
    pixat = pixaCreate(19);
    for (i = 0; i < 19; i++) {
        convertHSVToRGB((240 * i / 18), 255, 255, &rval, &gval, &bval);
        composeRGBPixel(rval, gval, bval, &pixel);
        pixt1 = pixCreate(50, 100, 32);
        pixSetAllArbitrary(pixt1, pixel);
        pixaAddPix(pixat, pixt1, L_INSERT);
    }
    pixt2 = pixaDisplayTiledInRows(pixat, 32, 1100, 1.0, 0, 0, 0);
    regTestWritePixAndCheck(rp, pixt2, IFF_PNG);  /* 0 */
    pixaAddPix(pixa, pixt2, L_INSERT);
    pixaDestroy(&pixat);

        /* Colorspace conversion in rgb */
    pixs = pixRead("wyom.jpg");
    pixaAddPix(pixa, pixs, L_INSERT);
    pixt = pixConvertRGBToHSV(NULL, pixs);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 1 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixConvertHSVToRGB(pixt, pixt);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 2 */
    pixaAddPix(pixa, pixt, L_INSERT);

        /* Colorspace conversion on a colormap */
    pixt = pixOctreeQuantNumColors(pixs, 25, 0);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 3 */
    pixaAddPix(pixa, pixt, L_COPY);
    cmap = pixGetColormap(pixt);
    if (rp->display) pixcmapWriteStream(stderr, cmap);
    pixcmapConvertRGBToHSV(cmap);
    if (rp->display) pixcmapWriteStream(stderr, cmap);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 4 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixcmapConvertHSVToRGB(cmap);
    if (rp->display) pixcmapWriteStream(stderr, cmap);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 5 */
    pixaAddPix(pixa, pixt, L_INSERT);

        /* Color content extraction */
    pixColorContent(pixs, 0, 0, 0, 0, &pixr, &pixg, &pixb);
    regTestWritePixAndCheck(rp, pixr, IFF_JFIF_JPEG);  /* 6 */
    pixaAddPix(pixa, pixr, L_INSERT);
    regTestWritePixAndCheck(rp, pixg, IFF_JFIF_JPEG);  /* 7 */
    pixaAddPix(pixa, pixg, L_INSERT);
    regTestWritePixAndCheck(rp, pixb, IFF_JFIF_JPEG);  /* 8 */
    pixaAddPix(pixa, pixb, L_INSERT);

        /* Color content measurement.  This tests the global
         * mapping of (r,g,b) --> (white), for 20 different
         * values of (r,g,b).   For each mappings, we compute
         * the color magnitude and threshold it at six values.
         * For each of those six thresholds, we plot the
         * fraction of pixels that exceeds the threshold
         * color magnitude, where the red value (mapped to
         * white) goes between 100 and 195.  */
    pixat = pixaCreate(20);
    naseq = numaMakeSequence(100, 5, 20);
    naa1 = numaaCreate(6);
    naa2 = numaaCreate(6);
    for (i = 0; i < 6; i++) {
        na = numaCreate(20);
        numaaAddNuma(naa1, na, L_COPY);
        numaaAddNuma(naa2, na, L_INSERT);
    }
    pixGetDimensions(pixs, &w, &h, NULL);
    for (i = 0; i < 20; i++) {
        rwhite = 100 + 5 * i;
        gwhite = 200 - 5 * i;
        bwhite = 150;
        pixt0 = pixGlobalNormRGB(NULL, pixs, rwhite, gwhite, bwhite, 255);
        pixaAddPix(pixat, pixt0, L_INSERT);
        pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite,
                                  L_MAX_DIFF_FROM_AVERAGE_2);
        for (j = 0; j < 6; j++) {
            pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j);
            pixInvert(pixt2, pixt2);
            pixCountPixels(pixt2, &count, NULL);
            na = numaaGetNuma(naa1, j, L_CLONE);
            numaAddNumber(na, (l_float32)count / (l_float32)(w * h));
            numaDestroy(&na);
            pixDestroy(&pixt2);
        }
        pixDestroy(&pixt1);
        pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite,
                                  L_MAX_MIN_DIFF_FROM_2);
        for (j = 0; j < 6; j++) {
            pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j);
            pixInvert(pixt2, pixt2);
            pixCountPixels(pixt2, &count, NULL);
            na = numaaGetNuma(naa2, j, L_CLONE);
            numaAddNumber(na, (l_float32)count / (l_float32)(w * h));
            numaDestroy(&na);
            pixDestroy(&pixt2);
        }
        pixDestroy(&pixt1);
    }
    gplot1 = gplotCreate("/tmp/regout/colorspace.10", GPLOT_PNG,
                         "Fraction with given color (diff from average)",
                         "white point space for red", "amount of color");
    gplot2 = gplotCreate("/tmp/regout/colorspace.11", GPLOT_PNG,
                         "Fraction with given color (min diff)",
                         "white point space for red", "amount of color");
    for (j = 0; j < 6; j++) {
        na = numaaGetNuma(naa1, j, L_CLONE);
        sprintf(label, "thresh %d", 30 + 10 * j);
        gplotAddPlot(gplot1, naseq, na, GPLOT_LINES, label);
        numaDestroy(&na);
        na = numaaGetNuma(naa2, j, L_CLONE);
        gplotAddPlot(gplot2, naseq, na, GPLOT_LINES, label);
        numaDestroy(&na);
    }
    gplotMakeOutput(gplot1);
    gplotMakeOutput(gplot2);
    gplotDestroy(&gplot1);
    gplotDestroy(&gplot2);
    pixt1 = pixaDisplayTiledAndScaled(pixat, 32, 250, 4, 0, 10, 2);
    regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG);  /* 9 */
    pixaAddPix(pixa, pixt1, L_INSERT);
    pixDisplayWithTitle(pixt1, 0, 100, "Color magnitude", rp->display);
    pixaDestroy(&pixat);
    numaDestroy(&naseq);
    numaaDestroy(&naa1);
    numaaDestroy(&naa2);

        /* Give gnuplot time to write out the files */
#ifndef  _WIN32
    sleep(1);
#else
    Sleep(1000);
#endif  /* _WIN32 */

        /* Save as golden files, or check against them */
    regTestCheckFile(rp, "/tmp/regout/colorspace.10.png");  /* 10 */
    regTestCheckFile(rp, "/tmp/regout/colorspace.11.png");  /* 11 */

    if (rp->display) {
        pixt = pixRead("/tmp/regout/colorspace.10.png");
        pixaAddPix(pixa, pixt, L_INSERT);
        pixt = pixRead("/tmp/regout/colorspace.11.png");
        pixaAddPix(pixa, pixt, L_INSERT);
        pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "colorspace tests",
                         "/tmp/regout/colorspace.pdf");
        L_INFO("Output pdf: /tmp/regout/colorspace.pdf\n", rp->testname);
    }
    pixaDestroy(&pixa);

    return regTestCleanup(rp);
}
Exemple #13
0
void
DoWatershed(L_REGPARAMS  *rp,
            PIX          *pixs)
{
l_uint8   *data;
size_t     size;
l_int32    w, h, empty;
l_uint32   redval, greenval;
L_WSHED   *wshed;
PIX       *pixc, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8, *pix9;
PIXA      *pixa;
PTA       *pta;

        /* Find local extrema */
    pixa = pixaCreate(0);
    pixGetDimensions(pixs, &w, &h, NULL);
    regTestWritePixAndCheck(rp, pixs, IFF_PNG);  /* 0 */
    pixSaveTiled(pixs, pixa, 1.0, 1, 10, 32);
    startTimer();
    pixLocalExtrema(pixs, 0, 0, &pix1, &pix2);
    fprintf(stderr, "Time for extrema: %7.3f\n", stopTimer());
    pixSetOrClearBorder(pix1, 2, 2, 2, 2, PIX_CLR);
    composeRGBPixel(255, 0, 0, &redval);
    composeRGBPixel(0, 255, 0, &greenval);
    pixc = pixConvertTo32(pixs);
    pixPaintThroughMask(pixc, pix2, 0, 0, greenval);
    pixPaintThroughMask(pixc, pix1, 0, 0, redval);
    regTestWritePixAndCheck(rp, pixc, IFF_PNG);  /* 1 */
    pixSaveTiled(pixc, pixa, 1.0, 0, 10, 32);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 2 */
    pixSaveTiled(pix1, pixa, 1.0, 0, 10, 32);

        /* Generate seeds for watershed */
    pixSelectMinInConnComp(pixs, pix1, &pta, NULL);
    pix3 = pixGenerateFromPta(pta, w, h);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 3 */
    pixSaveTiled(pix3, pixa, 1.0, 1, 10, 32);
    pix4 = pixConvertTo32(pixs);
    pixPaintThroughMask(pix4, pix3, 0, 0, greenval);
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 4 */
    pixSaveTiled(pix4, pixa, 1.0, 0, 10, 32);
    pix5 = pixRemoveSeededComponents(NULL, pix3, pix1, 8, 2);
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 5 */
    pixSaveTiled(pix5, pixa, 1.0, 0, 10, 32);
    pixZero(pix5, &empty);
    regTestCompareValues(rp, 1, empty, 0.0);  /* 6 */

        /* Make and display watershed */
    wshed = wshedCreate(pixs, pix3, 10, 0);
    startTimer();
    wshedApply(wshed);
    fprintf(stderr, "Time for wshed: %7.3f\n", stopTimer());
    pix6 = pixaDisplayRandomCmap(wshed->pixad, w, h);
    regTestWritePixAndCheck(rp, pix6, IFF_PNG);  /* 7 */
    pixSaveTiled(pix6, pixa, 1.0, 1, 10, 32);
    numaWriteMem(&data, &size, wshed->nalevels);
    regTestWriteDataAndCheck(rp, data, size, "na");  /* 8 */
    pix7 = wshedRenderFill(wshed);
    regTestWritePixAndCheck(rp, pix7, IFF_PNG);  /* 9 */
    pixSaveTiled(pix7, pixa, 1.0, 0, 10, 32);
    pix8 = wshedRenderColors(wshed);
    regTestWritePixAndCheck(rp, pix8, IFF_PNG);  /* 10 */
    pixSaveTiled(pix8, pixa, 1.0, 0, 10, 32);
    wshedDestroy(&wshed);

    pix9 = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pix9, IFF_PNG);  /* 11 */
    pixDisplayWithTitle(pix9, 100, 100, NULL, rp->display);

    lept_free(data);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pix6);
    pixDestroy(&pix7);
    pixDestroy(&pix8);
    pixDestroy(&pix9);
    pixDestroy(&pixc);
    pixaDestroy(&pixa);
    ptaDestroy(&pta);
}
Exemple #14
0
main(int    argc,
     char **argv)
{
char        *filein, *fileout, *textstr;
l_int32      i, d, size, width, wtext, overflow;
l_uint32     val;
L_BMF       *bmf;
PIX         *pixs, *pix;
static char  mainName[] = "renderfonts";

    if (argc != 4)
	exit(ERROR_INT("Syntax: renderfonts filein size fileout", mainName, 1));

    filein = argv[1];
    size = atoi(argv[2]);
    fileout = argv[3];

    if ((pixs = pixRead(filein)) == NULL)
	exit(ERROR_INT("pixs not made", mainName, 1));
    d = pixGetDepth(pixs);
    if (d == 8)
        val = 128;
    else if (d == 16)
        val = 0x8000;
    else if (d == 32)
        composeRGBPixel(128, 0, 255, &val);
    else
	exit(ERROR_INT("pixs not 8, 16 or 32 bpp", mainName, 1));

    bmf = bmfCreate(DIRECTORY, size);

#if 0  /* render a character of text */
    pix = pixaGetPix(bmf->pixa, 45, L_CLONE);
    startTimer();
    for (i = 0; i < 10000; i++)
	pixSetMaskedGeneral(pixs, pix, val, 150, 150);
    fprintf(stderr, "time: %7.3f sec\n", stopTimer());
    pixWrite(fileout, pixs, IFF_JFIF_JPEG);
    pixDestroy(&pix);
#endif

#if 0  /* render a line of text; use marge.jpg with size 14 */
    bmfGetStringWidth(bmf, "This is a funny cat!", &width);
    fprintf(stderr, "String width: %d pixels\n", width);

    pixSetTextline(pixs, bmf, "This is a funny cat!", 0x8000ff00, 50, 250,
                   &width, &overflow);
    pixWrite(fileout, pixs, IFF_JFIF_JPEG);
    fprintf(stderr, "Text width = %d\n", width);
    if (overflow)
        fprintf(stderr, "Text overflow beyond image boundary\n");
#endif

#if 1  /* render a block of text; use marge.jpg with size 14 */
    textstr = stringNew("This is a cat! This is a funny cat! This is a funny funny cat! This is a funny funny funny cat!");

    wtext = pixGetWidth(pixs) - 70;
    pixSetTextblock(pixs, bmf, textstr, 0x4040ff00, 50, 50, wtext,
                    1, &overflow);
    pixWrite(fileout, pixs, IFF_JFIF_JPEG);
    if (overflow)
        fprintf(stderr, "Text overflow beyond image boundary\n");
    lept_free(textstr);
#endif

    pixDestroy(&pixs);
    bmfDestroy(&bmf);
    return 0;
}
int main(int    argc,
         char **argv)
{
char         label[512];
l_int32      rval, gval, bval, w, h, i, j, rwhite, gwhite, bwhite, count;
l_uint32     pixel;
GPLOT       *gplot1, *gplot2;
NUMA        *naseq, *na;
NUMAA       *naa1, *naa2;
PIX         *pixs, *pixt, *pixt0, *pixt1, *pixt2;
PIX         *pixr, *pixg, *pixb;
PIXA        *pixa;
PIXCMAP     *cmap;
static char  mainName[] = "colorspacetest";

    if (argc != 2)
        return ERROR_INT(" Syntax:  colorspacetest filein", mainName, 1);

    if ((pixs = pixRead(argv[1])) == NULL)
        return ERROR_INT("pixs not made", mainName, 1);

        /* Generate colors by sampling hue with max sat and value.
         * This was used to make the color strip 19-colors.png.  */
    pixa = pixaCreate(19);
    for (i = 0; i < 19; i++) {
        convertHSVToRGB((240 * i / 18), 255, 255, &rval, &gval, &bval);
        composeRGBPixel(rval, gval, bval, &pixel);
        pixt1 = pixCreate(50, 100, 32);
        pixSetAllArbitrary(pixt1, pixel);
        pixaAddPix(pixa, pixt1, L_INSERT);
    }
    pixt2 = pixaDisplayTiledInRows(pixa, 32, 1100, 1.0, 0, 0, 0);
    pixDisplayWrite(pixt2, 1);
    pixDestroy(&pixt2);
    pixaDestroy(&pixa);

        /* Colorspace conversion in rgb */
    pixDisplayWrite(pixs, 1);
    pixt = pixConvertRGBToHSV(NULL, pixs);
    pixDisplayWrite(pixt, 1);
    pixConvertHSVToRGB(pixt, pixt);
    pixDisplayWrite(pixt, 1);
    pixDestroy(&pixt);

        /* Colorspace conversion on a colormap */
    pixt = pixOctreeQuantNumColors(pixs, 25, 0);
    pixDisplayWrite(pixt, 1);
    cmap = pixGetColormap(pixt);
    pixcmapWriteStream(stderr, cmap);
    pixcmapConvertRGBToHSV(cmap);
    pixcmapWriteStream(stderr, cmap);
    pixDisplayWrite(pixt, 1);
    pixcmapConvertHSVToRGB(cmap);
    pixcmapWriteStream(stderr, cmap);
    pixDisplayWrite(pixt, 1);
    pixDestroy(&pixt);

        /* Color content extraction */
    pixColorContent(pixs, 0, 0, 0, 0, &pixr, &pixg, &pixb);
    pixDisplayWrite(pixr, 1);
    pixDisplayWrite(pixg, 1);
    pixDisplayWrite(pixb, 1);
    pixDestroy(&pixr);
    pixDestroy(&pixg);
    pixDestroy(&pixb);

        /* Color content measurement */
    pixa = pixaCreate(20);
    naseq = numaMakeSequence(100, 5, 20);
    naa1 = numaaCreate(6);
    naa2 = numaaCreate(6);
    for (i = 0; i < 6; i++) {
        na = numaCreate(20);
        numaaAddNuma(naa1, na, L_COPY);
        numaaAddNuma(naa2, na, L_INSERT);
    }
    pixGetDimensions(pixs, &w, &h, NULL);
    for (i = 0; i < 20; i++) {
        rwhite = 100 + 5 * i;
        gwhite = 200 - 5 * i;
        bwhite = 150;
        pixt0 = pixGlobalNormRGB(NULL, pixs, rwhite, gwhite, bwhite, 255);
        pixaAddPix(pixa, pixt0, L_INSERT);
        pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite,
                                  L_MAX_DIFF_FROM_AVERAGE_2);
        for (j = 0; j < 6; j++) {
            pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j);
            pixInvert(pixt2, pixt2);
            pixCountPixels(pixt2, &count, NULL);
            na = numaaGetNuma(naa1, j, L_CLONE);
            numaAddNumber(na, (l_float32)count / (l_float32)(w * h));
            numaDestroy(&na);
            pixDestroy(&pixt2);
        }
        pixDestroy(&pixt1);
        pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite,
                                  L_MAX_MIN_DIFF_FROM_2);
        for (j = 0; j < 6; j++) {
            pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j);
            pixInvert(pixt2, pixt2);
            pixCountPixels(pixt2, &count, NULL);
            na = numaaGetNuma(naa2, j, L_CLONE);
            numaAddNumber(na, (l_float32)count / (l_float32)(w * h));
            numaDestroy(&na);
            pixDestroy(&pixt2);
        }
        pixDestroy(&pixt1);
    }
    gplot1 = gplotCreate("/tmp/junkplot1", GPLOT_X11,
                         "Fraction with given color (diff from average)",
                         "white point space for red", "amount of color");
    gplot2 = gplotCreate("/tmp/junkplot2", GPLOT_X11,
                         "Fraction with given color (min diff)",
                         "white point space for red", "amount of color");
    for (j = 0; j < 6; j++) {
        na = numaaGetNuma(naa1, j, L_CLONE);
        sprintf(label, "thresh %d", 30 + 10 * j);
        gplotAddPlot(gplot1, naseq, na, GPLOT_LINES, label);
        numaDestroy(&na);
        na = numaaGetNuma(naa2, j, L_CLONE);
        gplotAddPlot(gplot2, naseq, na, GPLOT_LINES, label);
        numaDestroy(&na);
    }
    gplotMakeOutput(gplot1);
    gplotMakeOutput(gplot2);
    gplotDestroy(&gplot1);
    gplotDestroy(&gplot2);
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, 250, 4, 0, 10, 2);
    pixWrite("/tmp/junkcolormag", pixt1, IFF_PNG);
    pixDisplayWithTitle(pixt1, 0, 100, "Color magnitude", 1);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);
    numaDestroy(&naseq);
    numaaDestroy(&naa1);
    numaaDestroy(&naa2);

    pixDisplayMultiple("/tmp/display/file*");

    pixDestroy(&pixs);
    return 0;
}
/*!
 *  pixAbsDifference()
 *
 *      Input:  pixs1, pixs2  (both either 8 or 16 bpp gray, or 32 bpp RGB)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) The depth of pixs1 and pixs2 must be equal.
 *      (2) Clips computation to the min size, aligning the UL corners
 *      (3) For 8 and 16 bpp, assumes one gray component.
 *      (4) For 32 bpp, assumes 3 color components, and ignores the
 *          LSB of each word (the alpha channel)
 *      (5) Computes the absolute value of the difference between
 *          each component value.
 */
PIX *
pixAbsDifference(PIX  *pixs1,
                 PIX  *pixs2)
{
l_int32    i, j, w, h, w2, h2, d, wpls1, wpls2, wpld, val1, val2, diff;
l_int32    rval1, gval1, bval1, rval2, gval2, bval2, rdiff, gdiff, bdiff;
l_uint32  *datas1, *datas2, *datad, *lines1, *lines2, *lined;
PIX       *pixd;

    PROCNAME("pixAbsDifference");

    if (!pixs1)
        return (PIX *)ERROR_PTR("pixs1 not defined", procName, NULL);
    if (!pixs2)
        return (PIX *)ERROR_PTR("pixs2 not defined", procName, NULL);
    d = pixGetDepth(pixs1);
    if (d != pixGetDepth(pixs2))
        return (PIX *)ERROR_PTR("src1 and src2 depths unequal", procName, NULL);
    if (d != 8 && d != 16 && d != 32)
        return (PIX *)ERROR_PTR("depths not in {8, 16, 32}", procName, NULL);

    pixGetDimensions(pixs1, &w, &h, NULL);
    pixGetDimensions(pixs2, &w2, &h2, NULL);
    w = L_MIN(w, w2);
    h = L_MIN(h, h2);
    if ((pixd = pixCreate(w, h, d)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    pixCopyResolution(pixd, pixs1);
    datas1 = pixGetData(pixs1);
    datas2 = pixGetData(pixs2);
    datad = pixGetData(pixd);
    wpls1 = pixGetWpl(pixs1);
    wpls2 = pixGetWpl(pixs2);
    wpld = pixGetWpl(pixd);
    if (d == 8) {
        for (i = 0; i < h; i++) {
            lines1 = datas1 + i * wpls1;
            lines2 = datas2 + i * wpls2;
            lined = datad + i * wpld;
            for (j = 0; j < w; j++) {
                val1 = GET_DATA_BYTE(lines1, j);
                val2 = GET_DATA_BYTE(lines2, j);
                diff = L_ABS(val1 - val2);
                SET_DATA_BYTE(lined, j, diff);
            }
        }
    } else if (d == 16) {
        for (i = 0; i < h; i++) {
            lines1 = datas1 + i * wpls1;
            lines2 = datas2 + i * wpls2;
            lined = datad + i * wpld;
            for (j = 0; j < w; j++) {
                val1 = GET_DATA_TWO_BYTES(lines1, j);
                val2 = GET_DATA_TWO_BYTES(lines2, j);
                diff = L_ABS(val1 - val2);
                SET_DATA_TWO_BYTES(lined, j, diff);
            }
        }
    } else {  /* d == 32 */
        for (i = 0; i < h; i++) {
            lines1 = datas1 + i * wpls1;
            lines2 = datas2 + i * wpls2;
            lined = datad + i * wpld;
            for (j = 0; j < w; j++) {
                extractRGBValues(lines1[j], &rval1, &gval1, &bval1);
                extractRGBValues(lines2[j], &rval2, &gval2, &bval2);
                rdiff = L_ABS(rval1 - rval2);
                gdiff = L_ABS(gval1 - gval2);
                bdiff = L_ABS(bval1 - bval2);
                composeRGBPixel(rdiff, gdiff, bdiff, lined + j);
            }
        }
    }

    return pixd;
}
/*!
 *  pixMinOrMax()
 *
 *      Input:  pixd  (<optional> destination: this can be null,
 *                     equal to pixs1, or different from pixs1)
 *              pixs1 (can be == to pixd)
 *              pixs2
 *              type (L_CHOOSE_MIN, L_CHOOSE_MAX)
 *      Return: pixd always
 *
 *  Notes:
 *      (1) This gives the min or max of two images, component-wise.
 *      (2) The depth can be 8 or 16 bpp for 1 component, and 32 bpp
 *          for a 3 component image.  For 32 bpp, ignore the LSB
 *          of each word (the alpha channel)
 *      (3) There are 3 cases:
 *          -  if pixd == null,   Min(src1, src2) --> new pixd
 *          -  if pixd == pixs1,  Min(src1, src2) --> src1  (in-place)
 *          -  if pixd != pixs1,  Min(src1, src2) --> input pixd
 */
PIX *
pixMinOrMax(PIX     *pixd,
            PIX     *pixs1,
            PIX     *pixs2,
            l_int32  type)
{
l_int32    d, ws, hs, w, h, wpls, wpld, i, j, vals, vald, val;
l_int32    rval1, gval1, bval1, rval2, gval2, bval2, rval, gval, bval;
l_uint32  *datas, *datad, *lines, *lined;

    PROCNAME("pixMinOrMax");

    if (!pixs1)
        return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
    if (!pixs2)
        return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
    if (pixs1 == pixs2)
        return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd);
    if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX)
        return (PIX *)ERROR_PTR("invalid type", procName, pixd);
    d = pixGetDepth(pixs1);
    if (pixGetDepth(pixs2) != d)
        return (PIX *)ERROR_PTR("depths unequal", procName, pixd);
    if (d != 8 && d != 16 && d != 32)
        return (PIX *)ERROR_PTR("depth not 8, 16 or 32 bpp", procName, pixd);

    if (pixs1 != pixd)
        pixd = pixCopy(pixd, pixs1);

    pixGetDimensions(pixs2, &ws, &hs, NULL);
    pixGetDimensions(pixd, &w, &h, NULL);
    w = L_MIN(w, ws);
    h = L_MIN(h, hs);
    datas = pixGetData(pixs2);
    datad = pixGetData(pixd);
    wpls = pixGetWpl(pixs2);
    wpld = pixGetWpl(pixd);
    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        lined = datad + i * wpld;
        if (d == 8) {
            for (j = 0; j < w; j++) {
                vals = GET_DATA_BYTE(lines, j);
                vald = GET_DATA_BYTE(lined, j);
                if (type == L_CHOOSE_MIN)
                    val = L_MIN(vals, vald);
                else  /* type == L_CHOOSE_MAX */
                    val = L_MAX(vals, vald);
                SET_DATA_BYTE(lined, j, val);
            }
        } else if (d == 16) {
            for (j = 0; j < w; j++) {
                vals = GET_DATA_TWO_BYTES(lines, j);
                vald = GET_DATA_TWO_BYTES(lined, j);
                if (type == L_CHOOSE_MIN)
                    val = L_MIN(vals, vald);
                else  /* type == L_CHOOSE_MAX */
                    val = L_MAX(vals, vald);
                SET_DATA_TWO_BYTES(lined, j, val);
            }
        } else {  /* d == 32 */
            for (j = 0; j < w; j++) {
                extractRGBValues(lines[j], &rval1, &gval1, &bval1);
                extractRGBValues(lined[j], &rval2, &gval2, &bval2);
                if (type == L_CHOOSE_MIN) {
                    rval = L_MIN(rval1, rval2);
                    gval = L_MIN(gval1, gval2);
                    bval = L_MIN(bval1, bval2);
                } else {  /* type == L_CHOOSE_MAX */
                    rval = L_MAX(rval1, rval2);
                    gval = L_MAX(gval1, gval2);
                    bval = L_MAX(bval1, bval2);
                }
                composeRGBPixel(rval, gval, bval, lined + j);
            }
        }
    }

    return pixd;
}
Exemple #18
0
int main(int    argc,
         char **argv)
{
char          textstr[256];
l_int32       w, h, d, i;
l_uint32      srcval, dstval;
l_float32     scalefact, sat, fract;
L_BMF        *bmf8;
L_KERNEL     *kel;
NUMA         *na;
PIX          *pix, *pixs, *pixs1, *pixs2, *pixd;
PIX          *pixt0, *pixt1, *pixt2, *pixt3, *pixt4;
PIXA         *pixa, *pixaf;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    pix = pixRead(filein);
    pixGetDimensions(pix, &w, &h, &d);
    if (d != 32)
        return ERROR_INT("file not 32 bpp", argv[0], 1);
    scalefact = (l_float32)WIDTH / (l_float32)w;
    pixs = pixScale(pix, scalefact, scalefact);
    w = pixGetWidth(pixs);
    pixaf = pixaCreate(5);

        /* TRC: vary gamma */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixGammaTRC(NULL, pixs, 0.3 + 0.15 * i, 0, 255);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 32);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 0 */
    pixDisplayWithTitle(pixt1, 0, 100, "TRC Gamma", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* TRC: vary black point */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixGammaTRC(NULL, pixs, 1.0, 5 * i, 255);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pixt1, 300, 100, "TRC", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Vary hue */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixModifyHue(NULL, pixs, 0.01 + 0.05 * i);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 2 */
    pixDisplayWithTitle(pixt1, 600, 100, "Hue", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Vary saturation */
    pixa = pixaCreate(20);
    na = numaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixModifySaturation(NULL, pixs, -0.9 + 0.1 * i);
        pixMeasureSaturation(pixt0, 1, &sat);
        pixaAddPix(pixa, pixt0, L_INSERT);
        numaAddNumber(na, sat);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    gplotSimple1(na, GPLOT_PNG, "/tmp/regout/enhance.7", "Average Saturation");
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 3 */
    pixDisplayWithTitle(pixt1, 900, 100, "Saturation", rp->display);
    numaDestroy(&na);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Vary contrast */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixContrastTRC(NULL, pixs, 0.1 * i);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(pixt1, 0, 400, "Contrast", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Vary sharpening */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixUnsharpMasking(pixs, 3, 0.01 + 0.15 * i);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 5 */
    pixDisplayWithTitle(pixt1, 300, 400, "Sharp", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Hue constant mapping to lighter background */
    pixa = pixaCreate(11);
    bmf8 = bmfCreate("fonts", 8);
    pixt0 = pixRead("candelabrum-11.jpg");
    composeRGBPixel(230, 185, 144, &srcval);  /* select typical bg pixel */
    for (i = 0; i <= 10; i++) {
        fract = 0.10 * i;
        pixelFractionalShift(230, 185, 144, fract, &dstval);
        pixt1 = pixLinearMapToTargetColor(NULL, pixt0, srcval, dstval);
        snprintf(textstr, 50, "Fract = %5.1f", fract);
        pixt2 = pixAddSingleTextblock(pixt1, bmf8, textstr, 0xff000000,
                                      L_ADD_BELOW, NULL);
        pixSaveTiledOutline(pixt2, pixa, 1.0, (i % 4 == 0) ? 1 : 0, 30, 2, 32);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
    }
    pixDestroy(&pixt0);

    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 6 */
    pixDisplayWithTitle(pixd, 600, 400, "Constant hue", rp->display);
    bmfDestroy(&bmf8);
    pixaDestroy(&pixa);
    pixDestroy(&pixd);

        /* Delayed testing of saturation plot */
    regTestCheckFile(rp, "/tmp/regout/enhance.7.png");  /* 7 */

        /* Display results */
    pixd = pixaDisplay(pixaf, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 8 */
    pixDisplayWithTitle(pixd, 100, 100, "All", rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixaf);

    pixDestroy(&pix);
    pixDestroy(&pixs);

    /* -----------------------------------------------*
     *           Test global color transforms         *
     * -----------------------------------------------*/
        /* Make identical cmap and rgb images */
    pix = pixRead("wet-day.jpg");
    pixs1 = pixOctreeColorQuant(pix, 200, 0);
    pixs2 = pixRemoveColormap(pixs1, REMOVE_CMAP_TO_FULL_COLOR);
    regTestComparePix(rp, pixs1, pixs2);  /* 9 */

        /* Make a diagonal color transform matrix */
    kel = kernelCreate(3, 3);
    kernelSetElement(kel, 0, 0, 0.7);
    kernelSetElement(kel, 1, 1, 0.4);
    kernelSetElement(kel, 2, 2, 1.3);

        /* Apply to both cmap and rgb images. */
    pixt1 = pixMultMatrixColor(pixs1, kel);
    pixt2 = pixMultMatrixColor(pixs2, kel);
    regTestComparePix(rp, pixt1, pixt2);  /* 10 */
    kernelDestroy(&kel);

        /* Apply the same transform in the simpler interface */
    pixt3 = pixMultConstantColor(pixs1, 0.7, 0.4, 1.3);
    pixt4 = pixMultConstantColor(pixs2, 0.7, 0.4, 1.3);
    regTestComparePix(rp, pixt3, pixt4);  /* 11 */
    regTestComparePix(rp, pixt1, pixt3);  /* 12 */
    regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG);  /* 13 */

    pixDestroy(&pix);
    pixDestroy(&pixs1);
    pixDestroy(&pixs2);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);
    return regTestCleanup(rp);
}
Exemple #19
0
/*!
 * \brief   pixReadStreamPnm()
 *
 * \param[in]    fp file stream opened for read
 * \return  pix, or NULL on error
 */
PIX *
pixReadStreamPnm(FILE  *fp)
{
l_uint8    val8, rval8, gval8, bval8;
l_uint16   val16;
l_int32    w, h, d, bpl, wpl, i, j, type;
l_int32    val, rval, gval, bval;
l_uint32   rgbval;
l_uint32  *line, *data;
PIX       *pix;

    PROCNAME("pixReadStreamPnm");

    if (!fp)
        return (PIX *)ERROR_PTR("fp not defined", procName, NULL);

    if (freadHeaderPnm(fp, &w, &h, &d, &type, NULL, NULL))
        return (PIX *)ERROR_PTR( "header read failed", procName, NULL);
    if ((pix = pixCreate(w, h, d)) == NULL)
        return (PIX *)ERROR_PTR( "pix not made", procName, NULL);
    pixSetInputFormat(pix, IFF_PNM);
    data = pixGetData(pix);
    wpl = pixGetWpl(pix);

        /* Old "ascii" format */
    if (type <= 3) {
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                if (type == 1 || type == 2) {
                    if (pnmReadNextAsciiValue(fp, &val))
                        return (PIX *)ERROR_PTR( "read abend", procName, pix);
                    pixSetPixel(pix, j, i, val);
                } else {  /* type == 3 */
                    if (pnmReadNextAsciiValue(fp, &rval))
                        return (PIX *)ERROR_PTR( "read abend", procName, pix);
                    if (pnmReadNextAsciiValue(fp, &gval))
                        return (PIX *)ERROR_PTR( "read abend", procName, pix);
                    if (pnmReadNextAsciiValue(fp, &bval))
                        return (PIX *)ERROR_PTR( "read abend", procName, pix);
                    composeRGBPixel(rval, gval, bval, &rgbval);
                    pixSetPixel(pix, j, i, rgbval);
                }
            }
        }
        return pix;
    }

        /* "raw" format for 1 bpp */
    if (type == 4) {
        bpl = (d * w + 7) / 8;
        for (i = 0; i < h; i++) {
            line = data + i * wpl;
            for (j = 0; j < bpl; j++) {
                if (fread(&val8, 1, 1, fp) != 1)
                    return (PIX *)ERROR_PTR( "read error in 4", procName, pix);
                SET_DATA_BYTE(line, j, val8);
            }
        }
        return pix;
    }

        /* "raw" format for grayscale */
    if (type == 5) {
        bpl = (d * w + 7) / 8;
        for (i = 0; i < h; i++) {
            line = data + i * wpl;
            if (d != 16) {
                for (j = 0; j < w; j++) {
                    if (fread(&val8, 1, 1, fp) != 1)
                        return (PIX *)ERROR_PTR( "error in 5", procName, pix);
                    if (d == 2)
                        SET_DATA_DIBIT(line, j, val8);
                    else if (d == 4)
                        SET_DATA_QBIT(line, j, val8);
                    else  /* d == 8 */
                        SET_DATA_BYTE(line, j, val8);
                }
            } else {  /* d == 16 */
                for (j = 0; j < w; j++) {
                    if (fread(&val16, 2, 1, fp) != 1)
                        return (PIX *)ERROR_PTR( "16 bpp error", procName, pix);
                    SET_DATA_TWO_BYTES(line, j, val16);
                }
            }
        }
        return pix;
    }

        /* "raw" format, type == 6; rgb */
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        for (j = 0; j < wpl; j++) {
            if (fread(&rval8, 1, 1, fp) != 1)
                return (PIX *)ERROR_PTR( "read error type 6", procName, pix);
            if (fread(&gval8, 1, 1, fp) != 1)
                return (PIX *)ERROR_PTR( "read error type 6", procName, pix);
            if (fread(&bval8, 1, 1, fp) != 1)
                return (PIX *)ERROR_PTR( "read error type 6", procName, pix);
            composeRGBPixel(rval8, gval8, bval8, &rgbval);
            line[j] = rgbval;
        }
    }
    return pix;
}
int main(int    argc,
         char **argv)
{
    l_int32      i, j;
    l_int32      w, h, bw, bh, wpls, rval, gval, bval, same;
    l_uint32     pixel;
    l_uint32    *lines, *datas;
    l_float32    sum1, sum2, ave1, ave2, ave3, ave4, diff1, diff2;
    l_float32    var1, var2, var3;
    BOX         *box1, *box2;
    NUMA        *na, *na1, *na2, *na3, *na4;
    PIX         *pix, *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pixg, *pixd;
    PIXA        *pixa;
    static char  mainName[] = "numa2_reg";

    if (argc != 1)
        return ERROR_INT(" Syntax:  numa2_reg", mainName, 1);

    lept_mkdir("lept/numa2");

    /* -------------------------------------------------------------------*
     *                         Numa-windowed stats                        *
     * -------------------------------------------------------------------*/
#if  DO_ALL
    na = numaRead("lyra.5.na");
    numaWindowedStats(na, 5, &na1, &na2, &na3, &na4);
    gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa2/lyra6", "Original");
    gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/lyra7", "Mean");
    gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/lyra8", "Mean Square");
    gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/lyra9", "Variance");
    gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/lyra10", "RMS Difference");
    pixa = pixaCreate(5);
    pix1 = pixRead("/tmp/lept/numa2/lyra6.png");
    pix2 = pixRead("/tmp/lept/numa2/lyra7.png");
    pix3 = pixRead("/tmp/lept/numa2/lyra8.png");
    pix4 = pixRead("/tmp/lept/numa2/lyra9.png");
    pix5 = pixRead("/tmp/lept/numa2/lyra10.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    pixaAddPix(pixa, pix3, L_INSERT);
    pixaAddPix(pixa, pix4, L_INSERT);
    pixaAddPix(pixa, pix5, L_INSERT);
    pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
    pixDisplay(pixd, 100, 0);
    pixWrite("/tmp/lept/numa2/window.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    numaDestroy(&na);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    numaDestroy(&na4);
#endif

    /* -------------------------------------------------------------------*
     *                        Extraction on a line                        *
     * -------------------------------------------------------------------*/
#if  DO_ALL
    /* First, make a pretty image */
    w = h = 200;
    pixs = pixCreate(w, h, 32);
    wpls = pixGetWpl(pixs);
    datas = pixGetData(pixs);
    for (i = 0; i < 200; i++) {
        lines = datas + i * wpls;
        for (j = 0; j < 200; j++) {
            rval = (l_int32)((255. * j) / w + (255. * i) / h);
            gval = (l_int32)((255. * 2 * j) / w + (255. * 2 * i) / h) % 255;
            bval = (l_int32)((255. * 4 * j) / w + (255. * 4 * i) / h) % 255;
            composeRGBPixel(rval, gval, bval, &pixel);
            lines[j] = pixel;
        }
    }
    pixg = pixConvertTo8(pixs, 0);  /* and a grayscale version */
    pixWrite("/tmp/lept/numa_pixg.png", pixg, IFF_PNG);
    pixDisplay(pixg, 450, 100);

    na1 = pixExtractOnLine(pixg, 20, 20, 180, 20, 1);
    na2 = pixExtractOnLine(pixg, 40, 30, 40, 170, 1);
    na3 = pixExtractOnLine(pixg, 20, 170, 180, 30, 1);
    na4 = pixExtractOnLine(pixg, 20, 190, 180, 10, 1);
    gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/ext1", "Horizontal");
    gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/ext2", "Vertical");
    gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/ext3",
                 "Slightly more horizontal than vertical");
    gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/ext4",
                 "Slightly more vertical than horizontal");
    pixa = pixaCreate(4);
    pix1 = pixRead("/tmp/lept/numa2/ext1.png");
    pix2 = pixRead("/tmp/lept/numa2/ext2.png");
    pix3 = pixRead("/tmp/lept/numa2/ext3.png");
    pix4 = pixRead("/tmp/lept/numa2/ext4.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    pixaAddPix(pixa, pix3, L_INSERT);
    pixaAddPix(pixa, pix4, L_INSERT);
    pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
    pixDisplay(pixd, 100, 450);
    pixWrite("/tmp/lept/numa2/extract.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    pixDestroy(&pixg);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    numaDestroy(&na4);
#endif

    /* -------------------------------------------------------------------*
     *                     Row and column pixel sums                      *
     * -------------------------------------------------------------------*/
#if  DO_ALL
    /* Sum by columns in two halves (left and right) */
    pixs = pixRead("test8.jpg");
    pixGetDimensions(pixs, &w, &h, NULL);
    box1 = boxCreate(0, 0, w / 2, h);
    box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
    na1 = pixAverageByColumn(pixs, box1, L_BLACK_IS_MAX);
    na2 = pixAverageByColumn(pixs, box2, L_BLACK_IS_MAX);
    numaJoin(na1, na2, 0, -1);
    na3 = pixAverageByColumn(pixs, NULL, L_BLACK_IS_MAX);
    numaSimilar(na1, na3, 0.0, &same);
    if (same)
        fprintf(stderr, "Same for columns\n");
    else
        fprintf(stderr, "Error for columns\n");
    pix = pixConvertTo32(pixs);
    pixRenderPlotFromNumaGen(&pix, na3, L_HORIZONTAL_LINE, 3, h / 2, 80, 1,
                             0xff000000);
    pixRenderPlotFromNuma(&pix, na3, L_PLOT_AT_BOT, 3, 80, 0xff000000);
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);

    /* Sum by rows in two halves (top and bottom) */
    box1 = boxCreate(0, 0, w, h / 2);
    box2 = boxCreate(0, h / 2, w, h - h / 2);
    na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
    na2 = pixAverageByRow(pixs, box2, L_WHITE_IS_MAX);
    numaJoin(na1, na2, 0, -1);
    na3 = pixAverageByRow(pixs, NULL, L_WHITE_IS_MAX);
    numaSimilar(na1, na3, 0.0, &same);
    if (same)
        fprintf(stderr, "Same for rows\n");
    else
        fprintf(stderr, "Error for rows\n");
    pixRenderPlotFromNumaGen(&pix, na3, L_VERTICAL_LINE, 3, w / 2, 80, 1,
                             0x00ff0000);
    pixRenderPlotFromNuma(&pix, na3, L_PLOT_AT_RIGHT, 3, 80, 0x00ff0000);
    pixDisplay(pix, 500, 200);
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    pixDestroy(&pix);

    /* Average left by rows; right by columns; compare totals */
    box1 = boxCreate(0, 0, w / 2, h);
    box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
    na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
    na2 = pixAverageByColumn(pixs, box2, L_WHITE_IS_MAX);
    numaGetSum(na1, &sum1);  /* sum of averages of left box */
    numaGetSum(na2, &sum2);  /* sum of averages of right box */
    ave1 = sum1 / h;
    ave2 = 2.0 * sum2 / w;
    ave3 = 0.5 * (ave1 + ave2);  /* average over both halves */
    fprintf(stderr, "ave1 = %8.4f\n", sum1 / h);
    fprintf(stderr, "ave2 = %8.4f\n", 2.0 * sum2 / w);
    pixAverageInRect(pixs, NULL, &ave4);  /* entire image */
    diff1 = ave4 - ave3;
    diff2 = w * h * ave4 - (0.5 * w * sum1 + h * sum2);
    if (diff1 < 0.001)
        fprintf(stderr, "Average diffs are correct\n");
    else
        fprintf(stderr, "Average diffs are wrong: diff1 = %7.5f\n", diff1);
    if (diff2 < 20)  /* float-to-integer roundoff */
        fprintf(stderr, "Pixel sums are correct\n");
    else
        fprintf(stderr, "Pixel sums are in error: diff = %7.0f\n", diff2);

    /* Variance left and right halves.  Variance doesn't average
     * in a simple way, unlike pixel sums. */
    pixVarianceInRect(pixs, box1, &var1);  /* entire image */
    pixVarianceInRect(pixs, box2, &var2);  /* entire image */
    pixVarianceInRect(pixs, NULL, &var3);  /* entire image */
    fprintf(stderr, "0.5 * (var1 + var2) = %7.3f, var3 = %7.3f\n",
            0.5 * (var1 + var2), var3);
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaDestroy(&na1);
    numaDestroy(&na2);
#endif

    /* -------------------------------------------------------------------*
     *                     Row and column variances                       *
     * -------------------------------------------------------------------*/
#if  DO_ALL

    /* Display variance by rows and columns */
    box1 = boxCreate(415, 0, 130, 425);
    boxGetGeometry(box1, NULL, NULL, &bw, &bh);
    na1 = pixVarianceByRow(pixs, box1);
    na2 = pixVarianceByColumn(pixs, box1);
    pix = pixConvertTo32(pixs);
    pix1 = pixCopy(NULL, pix);
    pixRenderPlotFromNumaGen(&pix, na1, L_VERTICAL_LINE, 3, 415, 100, 1,
                             0xff000000);
    pixRenderPlotFromNumaGen(&pix, na2, L_HORIZONTAL_LINE, 3, bh / 2, 100, 1,
                             0x00ff0000);
    pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_LEFT, 3, 60, 0x00ff0000);
    pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_MID_VERT, 3, 60, 0x0000ff00);
    pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_RIGHT, 3, 60, 0xff000000);
    pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_TOP, 3, 60, 0x0000ff00);
    pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_MID_HORIZ, 3, 60, 0xff000000);
    pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_BOT, 3, 60, 0x00ff0000);
    pixDisplay(pix, 500, 900);
    pixDisplay(pix1, 500, 1000);
    boxDestroy(&box1);
    numaDestroy(&na1);
    numaDestroy(&na2);
    pixDestroy(&pix);
    pixDestroy(&pix1);
    pixDestroy(&pixs);

    /* Again on a different image */
    pix1 = pixRead("boxedpage.jpg");
    pix2 = pixConvertTo8(pix1, 0);
    pixGetDimensions(pix2, &w, &h, NULL);
    na1 = pixVarianceByRow(pix2, NULL);
    pix3 = pixConvertTo32(pix1);
    pixRenderPlotFromNumaGen(&pix3, na1, L_VERTICAL_LINE, 3, 0, 70, 1,
                             0xff000000);
    na2 = pixVarianceByColumn(pix2, NULL);
    pixRenderPlotFromNumaGen(&pix3, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1,
                             0x00ff0000);
    pixDisplay(pix3, 1000, 0);
    numaDestroy(&na1);
    numaDestroy(&na2);
    pixDestroy(&pix3);

    /* Again, with an erosion */
    pix3 = pixErodeGray(pix2, 3, 21);
    pixDisplay(pix3, 1400, 0);
    na1 = pixVarianceByRow(pix3, NULL);
    pix4 = pixConvertTo32(pix1);
    pixRenderPlotFromNumaGen(&pix4, na1, L_VERTICAL_LINE, 3, 30, 70, 1,
                             0xff000000);
    na2 = pixVarianceByColumn(pix3, NULL);
    pixRenderPlotFromNumaGen(&pix4, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1,
                             0x00ff0000);
    pixDisplay(pix4, 1000, 550);
    numaDestroy(&na1);
    numaDestroy(&na2);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
#endif

    /* -------------------------------------------------------------------*
     *                    Windowed variance along a line                  *
     * -------------------------------------------------------------------*/
#if  DO_ALL
    pix1 = pixRead("boxedpage.jpg");
    pix2 = pixConvertTo8(pix1, 0);
    pixGetDimensions(pix2, &w, &h, NULL);
    pix3 = pixCopy(NULL, pix1);

    /* Plot along horizontal line */
    pixWindowedVarianceOnLine(pix2, L_HORIZONTAL_LINE, h / 2 - 30, 0,
                              w, 5, &na1);
    pixRenderPlotFromNumaGen(&pix1, na1, L_HORIZONTAL_LINE, 3, h / 2 - 30,
                             80, 1, 0xff000000);
    pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_TOP, 3, 60, 0x00ff0000);
    pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_BOT, 3, 60, 0x0000ff00);

    /* Plot along vertical line */
    pixWindowedVarianceOnLine(pix2, L_VERTICAL_LINE, 0.78 * w, 0,
                              h, 5, &na2);
    pixRenderPlotFromNumaGen(&pix1, na2, L_VERTICAL_LINE, 3, 0.78 * w, 60,
                             1, 0x00ff0000);
    pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_LEFT, 3, 60, 0xff000000);
    pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_RIGHT, 3, 60, 0x00ff0000);
    pixDisplay(pix1, 1000, 1000);
    pixDisplay(pix3, 1500, 1000);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    numaDestroy(&na1);
    numaDestroy(&na2);
#endif
    return 0;
}
/*!
 *  pixReadStreamJpeg()
 *
 *      Input:  stream
 *              colormap flag (0 means return RGB image if color;
 *                             1 means create colormap and return 8 bpp
 *                               palette image if color)
 *              reduction (scaling factor: 1, 2, 4 or 8)
 *              &pnwarn (<optional return> number of warnings)
 *              hint: (a bitwise OR of L_HINT_* values); use 0 for no hints
 *      Return: pix, or null on error
 *
 *  Usage: see pixReadJpeg()
 */
PIX *
pixReadStreamJpeg(FILE     *fp,
                  l_int32   cmflag,
                  l_int32   reduction,
                  l_int32  *pnwarn,
                  l_int32   hint)
{
l_uint8                        cyan, yellow, magenta, black, white;
l_int32                        rval, gval, bval;
l_int32                        i, j, k;
l_int32                        w, h, wpl, spp, ncolors, cindex, ycck, cmyk;
l_uint32                      *data;
l_uint32                      *line, *ppixel;
JSAMPROW                       rowbuffer;
PIX                           *pix;
PIXCMAP                       *cmap;
struct jpeg_decompress_struct  cinfo;
struct jpeg_error_mgr          jerr;
l_uint8                       *comment = NULL;

    PROCNAME("pixReadStreamJpeg");

    if (!fp)
        return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
    if (pnwarn)
        *pnwarn = 0;  /* init */
    if (cmflag != 0 && cmflag != 1)
        cmflag = 0;  /* default */
    if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
        return (PIX *)ERROR_PTR("reduction not in {1,2,4,8}", procName, NULL);

    if (BITS_IN_JSAMPLE != 8)  /* set in jmorecfg.h */
        return (PIX *)ERROR_PTR("BITS_IN_JSAMPLE != 8", procName, NULL);

    rewind(fp);

    pix = NULL;  /* init */
    if (setjmp(jpeg_jmpbuf)) {
        pixDestroy(&pix);
        FREE(rowbuffer);
        return (PIX *)ERROR_PTR("internal jpeg error", procName, NULL);
    }

    rowbuffer = NULL;
    cinfo.err = jpeg_std_error(&jerr);
    jerr.error_exit = jpeg_error_do_not_exit; /* catch error; do not exit! */

    jpeg_create_decompress(&cinfo);

    cinfo.client_data = &comment;
    jpeg_set_marker_processor(&cinfo, JPEG_COM, jpeg_comment_callback);
    jpeg_stdio_src(&cinfo, fp);
    jpeg_read_header(&cinfo, TRUE);
    cinfo.scale_denom = reduction;
    cinfo.scale_num = 1;
    if (hint & L_HINT_GRAY)
        cinfo.out_color_space = JCS_GRAYSCALE;
    jpeg_calc_output_dimensions(&cinfo);

        /* Allocate the image and a row buffer */
    spp = cinfo.out_color_components;
    w = cinfo.output_width;
    h = cinfo.output_height;
    ycck = (cinfo.jpeg_color_space == JCS_YCCK && spp == 4 && cmflag == 0);
    cmyk = (cinfo.jpeg_color_space == JCS_CMYK && spp == 4 && cmflag == 0);
    if (spp != 1 && spp != 3 && !ycck && !cmyk) {
        if (comment) FREE(comment);
        return (PIX *)ERROR_PTR("spp must be 1 or 3, or YCCK or CMYK",
                                procName, NULL);
    }
    if ((spp == 3 && cmflag == 0) || ycck || cmyk) {  /* rgb or 4 bpp color */
        rowbuffer = (JSAMPROW)CALLOC(sizeof(JSAMPLE), spp * w);
        pix = pixCreate(w, h, 32);
    }
    else {  /* 8 bpp gray or colormapped */
        rowbuffer = (JSAMPROW)CALLOC(sizeof(JSAMPLE), w);
        pix = pixCreate(w, h, 8);
    }
    if (!rowbuffer || !pix) {
        if (comment) FREE(comment);
	if (rowbuffer) FREE(rowbuffer);
	pixDestroy(&pix);
        return (PIX *)ERROR_PTR("rowbuffer or pix not made", procName, NULL);
    }

    if (comment) {
        pixSetText(pix, (char *)comment);
	FREE(comment);
    }

    if (spp == 1)  /* Grayscale or colormapped */
        jpeg_start_decompress(&cinfo);
    else  {        /* Color; spp == 3 or YCCK or CMYK */
        if (cmflag == 0) {   /* -- 24 bit color in 32 bit pix or YCCK/CMYK -- */
            cinfo.quantize_colors = FALSE;
            jpeg_start_decompress(&cinfo);
        }
        else {      /* Color quantize to 8 bits */
            cinfo.quantize_colors = TRUE;
            cinfo.desired_number_of_colors = 256;
            jpeg_start_decompress(&cinfo);

                /* Construct a pix cmap */
            cmap = pixcmapCreate(8);
            ncolors = cinfo.actual_number_of_colors;
            for (cindex = 0; cindex < ncolors; cindex++)
            {
                rval = cinfo.colormap[0][cindex];
                gval = cinfo.colormap[1][cindex];
                bval = cinfo.colormap[2][cindex];
                pixcmapAddColor(cmap, rval, gval, bval);
            }
            pixSetColormap(pix, cmap);
        }
    }
    wpl  = pixGetWpl(pix);
    data = pixGetData(pix);

        /* Decompress */
    if ((spp == 3 && cmflag == 0) || ycck || cmyk) {   /* -- 24 bit color -- */
        for (i = 0; i < h; i++) {
            if (jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1) != 1)
                return (PIX *)ERROR_PTR("bad read scanline", procName, NULL);
            ppixel = data + i * wpl;
            if (spp == 3) {
                for (j = k = 0; j < w; j++) {
                    SET_DATA_BYTE(ppixel, COLOR_RED, rowbuffer[k++]);
                    SET_DATA_BYTE(ppixel, COLOR_GREEN, rowbuffer[k++]);
                    SET_DATA_BYTE(ppixel, COLOR_BLUE, rowbuffer[k++]);
                    ppixel++;
                }
            } else {
                    /* This is a conversion from CMYK -> RGB that ignores
                       color profiles, and is invoked when the image header
                       claims to be in CMYK or YCCK colorspace.  If in YCCK,
                       libjpeg may be doing YCCK -> CMYK under the hood.
                       To understand why the colors are inverted on read-in,
                       see the "Special color spaces" section of
                       "Using the IJG JPEG Library" by Thomas G. Lane.  */
                for (j = k = 0; j < w; j++) {
                    cyan = 255 - rowbuffer[k++];
                    magenta = 255 - rowbuffer[k++];
                    yellow = 255 - rowbuffer[k++];
                    white = rowbuffer[k++];
                    black = 255 - white;
                    rval = 255 - (cyan    * white) / 255 - black;
                    gval = 255 - (magenta * white) / 255 - black;
                    bval = 255 - (yellow  * white) / 255 - black;
                    rval = L_MIN(L_MAX(rval, 0), 255);
                    gval = L_MIN(L_MAX(gval, 0), 255);
                    bval = L_MIN(L_MAX(bval, 0), 255);
                    composeRGBPixel(rval, gval, bval, ppixel);
                    ppixel++;
                }
            }
        }
    }
    else {    /* 8 bpp grayscale or colormapped pix */
        for (i = 0; i < h; i++) {
            if (jpeg_read_scanlines(&cinfo, &rowbuffer, (JDIMENSION)1) != 1)
                return (PIX *)ERROR_PTR("bad read scanline", procName, NULL);
            line = data + i * wpl;
            for (j = 0; j < w; j++)
                SET_DATA_BYTE(line, j, rowbuffer[j]);
        }
    }

    if (pnwarn)
        *pnwarn = cinfo.err->num_warnings;

    switch (cinfo.density_unit)
    {
    case 1:  /* pixels per inch */
        pixSetXRes(pix, cinfo.X_density);
        pixSetYRes(pix, cinfo.Y_density);
        break;
    case 2:  /* pixels per centimeter */
        pixSetXRes(pix, (l_int32)((l_float32)cinfo.X_density * 2.54 + 0.5));
        pixSetYRes(pix, (l_int32)((l_float32)cinfo.Y_density * 2.54 + 0.5));
        break;
    default:   /* the pixel density may not be defined; ignore */
        break;
    }

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    FREE(rowbuffer);

    return pix;
}
Exemple #22
0
int main(int    argc,
         char **argv)
{
l_int32      i, j;
l_int32      w, h, bw, bh, wpls, rval, gval, bval, same;
l_uint32     pixel;
l_uint32    *lines, *datas;
l_float32    sum1, sum2, ave1, ave2, ave3, ave4, diff1, diff2;
l_float32    var1, var2, var3;
BOX         *box1, *box2;
NUMA        *na, *na1, *na2, *na3, *na4;
PIX         *pix, *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pixg, *pixd;
PIXA        *pixa;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    lept_mkdir("lept/numa2");

    /* -------------------------------------------------------------------*
     *                         Numa-windowed stats                        *
     * -------------------------------------------------------------------*/
    na = numaRead("lyra.5.na");
    numaWindowedStats(na, 5, &na1, &na2, &na3, &na4);
    gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa2/lyra1", "Original");
    gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/lyra2", "Mean");
    gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/lyra3", "Mean Square");
    gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/lyra4", "Variance");
    gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/lyra5", "RMS Difference");
    pix1 = pixRead("/tmp/lept/numa2/lyra1.png");
    pix2 = pixRead("/tmp/lept/numa2/lyra2.png");
    pix3 = pixRead("/tmp/lept/numa2/lyra3.png");
    pix4 = pixRead("/tmp/lept/numa2/lyra4.png");
    pix5 = pixRead("/tmp/lept/numa2/lyra5.png");
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 0 */
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 1 */
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 2 */
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 3 */
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 4 */
    pixa = pixaCreate(5);
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    pixaAddPix(pixa, pix3, L_INSERT);
    pixaAddPix(pixa, pix4, L_INSERT);
    pixaAddPix(pixa, pix5, L_INSERT);
    if (rp->display) {
        pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
        pixDisplayWithTitle(pixd, 0, 0, NULL, 1);
        pixDestroy(&pixd);
    }
    pixaDestroy(&pixa);
    numaDestroy(&na);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    numaDestroy(&na4);

    /* -------------------------------------------------------------------*
     *                        Extraction on a line                        *
     * -------------------------------------------------------------------*/
        /* First, make a pretty image */
    w = h = 200;
    pixs = pixCreate(w, h, 32);
    wpls = pixGetWpl(pixs);
    datas = pixGetData(pixs);
    for (i = 0; i < 200; i++) {
        lines = datas + i * wpls;
        for (j = 0; j < 200; j++) {
            rval = (l_int32)((255. * j) / w + (255. * i) / h);
            gval = (l_int32)((255. * 2 * j) / w + (255. * 2 * i) / h) % 255;
            bval = (l_int32)((255. * 4 * j) / w + (255. * 4 * i) / h) % 255;
            composeRGBPixel(rval, gval, bval, &pixel);
            lines[j] = pixel;
        }
    }
    pixg = pixConvertTo8(pixs, 0);  /* and a grayscale version */
    regTestWritePixAndCheck(rp, pixg, IFF_PNG);  /* 5 */
    pixDisplayWithTitle(pixg, 0, 300, NULL, rp->display);

    na1 = pixExtractOnLine(pixg, 20, 20, 180, 20, 1);
    na2 = pixExtractOnLine(pixg, 40, 30, 40, 170, 1);
    na3 = pixExtractOnLine(pixg, 20, 170, 180, 30, 1);
    na4 = pixExtractOnLine(pixg, 20, 190, 180, 10, 1);
    gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/ext1", "Horizontal");
    gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/ext2", "Vertical");
    gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/ext3",
                "Slightly more horizontal than vertical");
    gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/ext4",
                "Slightly more vertical than horizontal");
    pix1 = pixRead("/tmp/lept/numa2/ext1.png");
    pix2 = pixRead("/tmp/lept/numa2/ext2.png");
    pix3 = pixRead("/tmp/lept/numa2/ext3.png");
    pix4 = pixRead("/tmp/lept/numa2/ext4.png");
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 6 */
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 7 */
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 8 */
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 9 */
    pixa = pixaCreate(4);
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    pixaAddPix(pixa, pix3, L_INSERT);
    pixaAddPix(pixa, pix4, L_INSERT);
    if (rp->display) {
        pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
        pixDisplayWithTitle(pixd, 300, 0, NULL, 1);
        pixDestroy(&pixd);
    }
    pixaDestroy(&pixa);
    pixDestroy(&pixg);
    pixDestroy(&pixs);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    numaDestroy(&na4);

    /* -------------------------------------------------------------------*
     *                     Row and column pixel sums                      *
     * -------------------------------------------------------------------*/
        /* Sum by columns in two halves (left and right) */
    pixs = pixRead("test8.jpg");
    pixGetDimensions(pixs, &w, &h, NULL);
    box1 = boxCreate(0, 0, w / 2, h);
    box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
    na1 = pixAverageByColumn(pixs, box1, L_BLACK_IS_MAX);
    na2 = pixAverageByColumn(pixs, box2, L_BLACK_IS_MAX);
    numaJoin(na1, na2, 0, -1);
    na3 = pixAverageByColumn(pixs, NULL, L_BLACK_IS_MAX);
    numaSimilar(na1, na3, 0.0, &same);  /* for columns */
    regTestCompareValues(rp, 1, same, 0);  /* 10 */
    pix1 = pixConvertTo32(pixs);
    pixRenderPlotFromNumaGen(&pix1, na3, L_HORIZONTAL_LINE, 3, h / 2, 80, 1,
                             0xff000000);
    pixRenderPlotFromNuma(&pix1, na3, L_PLOT_AT_BOT, 3, 80, 0xff000000);
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);

        /* Sum by rows in two halves (top and bottom) */
    box1 = boxCreate(0, 0, w, h / 2);
    box2 = boxCreate(0, h / 2, w, h - h / 2);
    na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
    na2 = pixAverageByRow(pixs, box2, L_WHITE_IS_MAX);
    numaJoin(na1, na2, 0, -1);
    na3 = pixAverageByRow(pixs, NULL, L_WHITE_IS_MAX);
    numaSimilar(na1, na3, 0.0, &same);  /* for rows */
    regTestCompareValues(rp, 1, same, 0);  /* 11 */
    pixRenderPlotFromNumaGen(&pix1, na3, L_VERTICAL_LINE, 3, w / 2, 80, 1,
                             0x00ff0000);
    pixRenderPlotFromNuma(&pix1, na3, L_PLOT_AT_RIGHT, 3, 80, 0x00ff0000);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 12 */
    pixDisplayWithTitle(pix1, 0, 600, NULL, rp->display);
    pixDestroy(&pix1);
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);

        /* Average left by rows; right by columns; compare totals */
    box1 = boxCreate(0, 0, w / 2, h);
    box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
    na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
    na2 = pixAverageByColumn(pixs, box2, L_WHITE_IS_MAX);
    numaGetSum(na1, &sum1);  /* sum of averages of left box */
    numaGetSum(na2, &sum2);  /* sum of averages of right box */
    ave1 = sum1 / h;
    ave2 = 2.0 * sum2 / w;
    ave3 = 0.5 * (ave1 + ave2);  /* average over both halves */
    regTestCompareValues(rp, 189.59, ave1, 0.01);  /* 13 */
    regTestCompareValues(rp, 207.89, ave2, 0.01);  /* 14 */

    if (rp->display) {
        fprintf(stderr, "ave1 = %8.4f\n", sum1 / h);
        fprintf(stderr, "ave2 = %8.4f\n", 2.0 * sum2 / w);
    }
    pixAverageInRect(pixs, NULL, &ave4);  /* entire image */
    diff1 = ave4 - ave3;
    diff2 = w * h * ave4 - (0.5 * w * sum1 + h * sum2);
    regTestCompareValues(rp, 0.0, diff1, 0.001);  /* 15 */
    regTestCompareValues(rp, 10.0, diff2, 10.0);  /* 16 */

        /* Variance left and right halves.  Variance doesn't average
         * in a simple way, unlike pixel sums. */
    pixVarianceInRect(pixs, box1, &var1);  /* entire image */
    pixVarianceInRect(pixs, box2, &var2);  /* entire image */
    pixVarianceInRect(pixs, NULL, &var3);  /* entire image */
    regTestCompareValues(rp, 82.06, 0.5 * (var1 + var2), 0.01);  /* 17 */
    regTestCompareValues(rp, 82.66, var3, 0.01);  /* 18 */
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaDestroy(&na1);
    numaDestroy(&na2);

    /* -------------------------------------------------------------------*
     *                     Row and column variances                       *
     * -------------------------------------------------------------------*/
        /* Display variance by rows and columns */
    box1 = boxCreate(415, 0, 130, 425);
    boxGetGeometry(box1, NULL, NULL, &bw, &bh);
    na1 = pixVarianceByRow(pixs, box1);
    na2 = pixVarianceByColumn(pixs, box1);
    pix1 = pixConvertTo32(pixs);
    pix2 = pixCopy(NULL, pix1);
    pixRenderPlotFromNumaGen(&pix1, na1, L_VERTICAL_LINE, 3, 415, 100, 1,
                             0xff000000);
    pixRenderPlotFromNumaGen(&pix1, na2, L_HORIZONTAL_LINE, 3, bh / 2, 100, 1,
                          0x00ff0000);
    pixRenderPlotFromNuma(&pix2, na1, L_PLOT_AT_LEFT, 3, 60, 0x00ff0000);
    pixRenderPlotFromNuma(&pix2, na1, L_PLOT_AT_MID_VERT, 3, 60, 0x0000ff00);
    pixRenderPlotFromNuma(&pix2, na1, L_PLOT_AT_RIGHT, 3, 60, 0xff000000);
    pixRenderPlotFromNuma(&pix2, na2, L_PLOT_AT_TOP, 3, 60, 0x0000ff00);
    pixRenderPlotFromNuma(&pix2, na2, L_PLOT_AT_MID_HORIZ, 3, 60, 0xff000000);
    pixRenderPlotFromNuma(&pix2, na2, L_PLOT_AT_BOT, 3, 60, 0x00ff0000);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 19 */
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 20 */
    pixa = pixaCreate(2);
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    if (rp->display) {
        pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
        pixDisplayWithTitle(pixd, 400, 600, NULL, 1);
        pixDestroy(&pixd);
    }
    pixaDestroy(&pixa);
    boxDestroy(&box1);
    numaDestroy(&na1);
    numaDestroy(&na2);
    pixDestroy(&pixs);

        /* Again on a different image */
    pix1 = pixRead("boxedpage.jpg");
    pix2 = pixConvertTo8(pix1, 0);
    pixGetDimensions(pix2, &w, &h, NULL);
    na1 = pixVarianceByRow(pix2, NULL);
    pix3 = pixConvertTo32(pix1);
    pixRenderPlotFromNumaGen(&pix3, na1, L_VERTICAL_LINE, 3, 0, 70, 1,
                             0xff000000);
    na2 = pixVarianceByColumn(pix2, NULL);
    pixRenderPlotFromNumaGen(&pix3, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1,
                             0x00ff0000);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 21 */
    numaDestroy(&na1);
    numaDestroy(&na2);

        /* Again, with an erosion */
    pix4 = pixErodeGray(pix2, 3, 21);
    na1 = pixVarianceByRow(pix4, NULL);
    pix5 = pixConvertTo32(pix1);
    pixRenderPlotFromNumaGen(&pix5, na1, L_VERTICAL_LINE, 3, 30, 70, 1,
                             0xff000000);
    na2 = pixVarianceByColumn(pix4, NULL);
    pixRenderPlotFromNumaGen(&pix5, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1,
                             0x00ff0000);
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 22 */
    pixa = pixaCreate(2);
    pixaAddPix(pixa, pix3, L_INSERT);
    pixaAddPix(pixa, pix5, L_INSERT);
    if (rp->display) {
        pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
        pixDisplayWithTitle(pixd, 800, 600, NULL, 1);
        pixDestroy(&pixd);
    }
    pixaDestroy(&pixa);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix4);
    numaDestroy(&na1);
    numaDestroy(&na2);

    /* -------------------------------------------------------------------*
     *                    Windowed variance along a line                  *
     * -------------------------------------------------------------------*/
    pix1 = pixRead("boxedpage.jpg");
    pix2 = pixConvertTo8(pix1, 0);
    pixGetDimensions(pix2, &w, &h, NULL);
    pix3 = pixCopy(NULL, pix1);

        /* Plot along horizontal line */
    pixWindowedVarianceOnLine(pix2, L_HORIZONTAL_LINE, h / 2 - 30, 0,
                              w, 5, &na1);
    pixRenderPlotFromNumaGen(&pix1, na1, L_HORIZONTAL_LINE, 3, h / 2 - 30,
                             80, 1, 0xff000000);
    pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_TOP, 3, 60, 0x00ff0000);
    pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_BOT, 3, 60, 0x0000ff00);

        /* Plot along vertical line */
    pixWindowedVarianceOnLine(pix2, L_VERTICAL_LINE, 0.78 * w, 0,
                              h, 5, &na2);
    pixRenderPlotFromNumaGen(&pix1, na2, L_VERTICAL_LINE, 3, 0.78 * w, 60,
                             1, 0x00ff0000);
    pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_LEFT, 3, 60, 0xff000000);
    pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_RIGHT, 3, 60, 0x00ff0000);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 23 */
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 24 */
    pixa = pixaCreate(2);
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix3, L_INSERT);
    if (rp->display) {
        pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
        pixDisplayWithTitle(pixd, 1200, 600, NULL, 1);
        pixDestroy(&pixd);
    }
    pixaDestroy(&pixa);
    pixDestroy(&pix2);
    numaDestroy(&na1);
    numaDestroy(&na2);

    return regTestCleanup(rp);;
}
Exemple #23
0
int main(int    argc,
         char **argv)
{
l_int32       index;
l_uint32      val32;
BOX          *box, *box1, *box2, *box3, *box4, *box5;
BOXA         *boxa;
L_KERNEL     *kel;
PIX          *pixs, *pixg, *pixb, *pixd, *pixt, *pix1, *pix2, *pix3, *pix4;
PIXA         *pixa;
PIXCMAP      *cmap;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    pixa = pixaCreate(0);

        /* Color non-white pixels on RGB */
    pixs = pixRead("lucasta-frag.jpg");
    pixt = pixConvert8To32(pixs);
    box = boxCreate(120, 30, 200, 200);
    pixColorGray(pixt, box, L_PAINT_DARK, 220, 0, 0, 255);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 0 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixColorGray(pixt, NULL, L_PAINT_DARK, 220, 255, 100, 100);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 1 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Color non-white pixels on colormap */
    pixt = pixThresholdTo4bpp(pixs, 6, 1);
    box = boxCreate(120, 30, 200, 200);
    pixColorGray(pixt, box, L_PAINT_DARK, 220, 0, 0, 255);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 2 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixColorGray(pixt, NULL, L_PAINT_DARK, 220, 255, 100, 100);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 3 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Color non-black pixels on RGB */
    pixt = pixConvert8To32(pixs);
    box = boxCreate(120, 30, 200, 200);
    pixColorGray(pixt, box, L_PAINT_LIGHT, 20, 0, 0, 255);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 4 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixColorGray(pixt, NULL, L_PAINT_LIGHT, 80, 255, 100, 100);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 5 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Color non-black pixels on colormap */
    pixt = pixThresholdTo4bpp(pixs, 6, 1);
    box = boxCreate(120, 30, 200, 200);
    pixColorGray(pixt, box, L_PAINT_LIGHT, 20, 0, 0, 255);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 6 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixColorGray(pixt, NULL, L_PAINT_LIGHT, 20, 255, 100, 100);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 7 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Add highlight color to RGB */
    pixt = pixConvert8To32(pixs);
    box = boxCreate(507, 5, 385, 45);
    pixg = pixClipRectangle(pixs, box, NULL);
    pixb = pixThresholdToBinary(pixg, 180);
    pixInvert(pixb, pixb);
    pixDisplayWrite(pixb, 1);
    composeRGBPixel(50, 0, 250, &val32);
    pixPaintThroughMask(pixt, pixb, box->x, box->y, val32);
    boxDestroy(&box);
    pixDestroy(&pixg);
    pixDestroy(&pixb);
    box = boxCreate(236, 107, 262, 40);
    pixg = pixClipRectangle(pixs, box, NULL);
    pixb = pixThresholdToBinary(pixg, 180);
    pixInvert(pixb, pixb);
    composeRGBPixel(250, 0, 50, &val32);
    pixPaintThroughMask(pixt, pixb, box->x, box->y, val32);
    boxDestroy(&box);
    pixDestroy(&pixg);
    pixDestroy(&pixb);
    box = boxCreate(222, 208, 247, 43);
    pixg = pixClipRectangle(pixs, box, NULL);
    pixb = pixThresholdToBinary(pixg, 180);
    pixInvert(pixb, pixb);
    composeRGBPixel(60, 250, 60, &val32);
    pixPaintThroughMask(pixt, pixb, box->x, box->y, val32);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 8 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);
    pixDestroy(&pixg);
    pixDestroy(&pixb);

        /* Add highlight color to colormap */
    pixt = pixThresholdTo4bpp(pixs, 5, 1);
    cmap = pixGetColormap(pixt);
    pixcmapGetIndex(cmap, 255, 255, 255, &index);
    box = boxCreate(507, 5, 385, 45);
    pixSetSelectCmap(pixt, box, index, 50, 0, 250);
    boxDestroy(&box);
    box = boxCreate(236, 107, 262, 40);
    pixSetSelectCmap(pixt, box, index, 250, 0, 50);
    boxDestroy(&box);
    box = boxCreate(222, 208, 247, 43);
    pixSetSelectCmap(pixt, box, index, 60, 250, 60);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 9 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Paint lines on RGB */
    pixt = pixConvert8To32(pixs);
    pixRenderLineArb(pixt, 450, 20, 850, 320, 5, 200, 50, 125);
    pixRenderLineArb(pixt, 30, 40, 440, 40, 5, 100, 200, 25);
    box = boxCreate(70, 80, 300, 245);
    pixRenderBoxArb(pixt, box, 3, 200, 200, 25);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 10 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Paint lines on colormap */
    pixt = pixThresholdTo4bpp(pixs, 5, 1);
    pixRenderLineArb(pixt, 450, 20, 850, 320, 5, 200, 50, 125);
    pixRenderLineArb(pixt, 30, 40, 440, 40, 5, 100, 200, 25);
    box = boxCreate(70, 80, 300, 245);
    pixRenderBoxArb(pixt, box, 3, 200, 200, 25);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 11 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Blend lines on RGB */
    pixt = pixConvert8To32(pixs);
    pixRenderLineBlend(pixt, 450, 20, 850, 320, 5, 200, 50, 125, 0.35);
    pixRenderLineBlend(pixt, 30, 40, 440, 40, 5, 100, 200, 25, 0.35);
    box = boxCreate(70, 80, 300, 245);
    pixRenderBoxBlend(pixt, box, 3, 200, 200, 25, 0.6);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 12 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Colorize gray on cmapped image. */
    pix1 = pixRead("lucasta.150.jpg");
    pix2 = pixThresholdTo4bpp(pix1, 7, 1);
    box1 = boxCreate(73, 206, 140, 27);
    pixColorGrayCmap(pix2, box1, L_PAINT_LIGHT, 130, 207, 43);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 13 */
    pixaAddPix(pixa, pix2, L_COPY);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "One box added");

    box2 = boxCreate(255, 404, 197, 25);
    pixColorGrayCmap(pix2, box2, L_PAINT_LIGHT, 230, 67, 119);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 14 */
    pixaAddPix(pixa, pix2, L_COPY);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "Two boxes added");

    box3 = boxCreate(122, 756, 224, 22);
    pixColorGrayCmap(pix2, box3, L_PAINT_DARK, 230, 67, 119);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 15 */
    pixaAddPix(pixa, pix2, L_COPY);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "Three boxes added");

    box4 = boxCreate(11, 780, 147, 22);
    pixColorGrayCmap(pix2, box4, L_PAINT_LIGHT, 70, 137, 229);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 16 */
    pixaAddPix(pixa, pix2, L_COPY);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "Four boxes added");

    box5 = boxCreate(163, 605, 78, 22);
    pixColorGrayCmap(pix2, box5, L_PAINT_LIGHT, 70, 137, 229);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 17 */
    pixaAddPix(pixa, pix2, L_INSERT);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "Five boxes added");
    pixDestroy(&pix1);
    boxDestroy(&box1);
    boxDestroy(&box2);
    boxDestroy(&box3);
    boxDestroy(&box4);
    boxDestroy(&box5);
    pixDestroy(&pixs);

        /* Make a gray image and identify the fg pixels (val > 230) */
    pixs = pixRead("feyn-fract.tif");
    pix1 = pixConvertTo8(pixs, 0);
    kel = makeGaussianKernel(2, 2, 1.5, 1.0);
    pix2 = pixConvolve(pix1, kel, 8, 1);
    pix3 = pixThresholdToBinary(pix2, 230);
    boxa = pixConnComp(pix3, NULL, 8);
    pixDestroy(&pixs);
    pixDestroy(&pix1);
    pixDestroy(&pix3);
    kernelDestroy(&kel);

        /* Color the individual components in the gray image */
    pix4 = pixColorGrayRegions(pix2, boxa, L_PAINT_DARK, 230, 255, 0, 0);
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 18 */
    pixaAddPix(pixa, pix4, L_INSERT);
    pixDisplayWithTitle(pix4, 0, 0, NULL, rp->display);

        /* Threshold to 10 levels of gray */
    pix3 = pixThresholdOn8bpp(pix2, 10, 1);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 19 */
    pixaAddPix(pixa, pix3, L_COPY);

        /* Color the individual components in the cmapped image */
    pix4 = pixColorGrayRegions(pix3, boxa, L_PAINT_DARK, 230, 255, 0, 0);
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 20 */
    pixaAddPix(pixa, pix4, L_INSERT);
    pixDisplayWithTitle(pix4, 0, 100, NULL, rp->display);
    boxaDestroy(&boxa);

        /* Color the entire gray image (not component-wise) */
    pixColorGray(pix2, NULL, L_PAINT_DARK, 230, 255, 0, 0);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 21 */
    pixaAddPix(pixa, pix2, L_INSERT);

        /* Color the entire cmapped image (not component-wise) */
    pixColorGray(pix3, NULL, L_PAINT_DARK, 230, 255, 0, 0);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 22 */
    pixaAddPix(pixa, pix3, L_INSERT);

        /* Reconstruct cmapped images */
    pixd = ReconstructByValue(rp, "weasel2.4c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 23 */
    pixaAddPix(pixa, pixd, L_INSERT);
    pixd = ReconstructByValue(rp, "weasel4.11c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 24 */
    pixaAddPix(pixa, pixd, L_INSERT);
    pixd = ReconstructByValue(rp, "weasel8.240c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 25 */
    pixaAddPix(pixa, pixd, L_INSERT);

        /* Fake reconstruct cmapped images, with one color into a band */
    pixd = FakeReconstructByBand(rp, "weasel2.4c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 26 */
    pixaAddPix(pixa, pixd, L_INSERT);
    pixd = FakeReconstructByBand(rp, "weasel4.11c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 27 */
    pixaAddPix(pixa, pixd, L_INSERT);
    pixd = FakeReconstructByBand(rp, "weasel8.240c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 28 */
    pixaAddPix(pixa, pixd, L_INSERT);

        /* If in testing mode, make a pdf */
    if (rp->display) {
        pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0,
                         "Colorize and paint", "/tmp/lept/regout/paint.pdf");
        L_INFO("Output pdf: /tmp/lept/regout/paint.pdf\n", rp->testname);
    }

    pixaDestroy(&pixa);
    return regTestCleanup(rp);
}
l_int32 main(int    argc,
             char **argv)
{
char          buf[512];
l_int32       i, n, index;
l_int32       rval[4], gval[4], bval[4];
l_uint32      scolor, dcolor;
L_BMF        *bmf;
PIX          *pix0, *pix1, *pix2, *pix3, *pix4, *pix5;
PIXA         *pixa;
PIXCMAP      *cmap;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

        /* Read in the bg colors */
    for (i = 0; i < 4; i++)
        sscanf(bgcolors[i], "%d %d %d", &rval[i], &gval[i], &bval[i]);
    bmf = bmfCreate("fonts", 8);

        /* Get the input image (100 ppi resolution) */
    pix0 = pixRead("harmoniam100-11.png");
    cmap = pixGetColormap(pix0);
    pixa = pixaCreate(0);

        /* Do cmapped coloring on the white pixels only */
    pixcmapGetIndex(cmap, 255, 255, 255, &index);  /* index of white pixels */
    for (i = 0; i < 4; i++) {
        pixcmapResetColor(cmap, index, rval[i], gval[i], bval[i]);
        snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)",
                 rval[i], gval[i], bval[i]);
        pix1 = pixAddSingleTextblock(pix0, bmf, buf, 0xff000000,
                                     L_ADD_AT_BOT, NULL);
        pixaAddPix(pixa, pix1, L_INSERT);
    }

        /* Do cmapped background coloring on all the pixels */
    for (i = 0; i < 4; i++) {
        scolor = 0xffffff00;  /* source color */
        composeRGBPixel(rval[i], gval[i], bval[i], &dcolor);  /* dest color */
        pix1 = pixShiftByComponent(NULL, pix0, scolor, dcolor);
        snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)",
                 rval[i], gval[i], bval[i]);
        pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000,
                                     L_ADD_AT_BOT, NULL);
        pixaAddPix(pixa, pix2, L_INSERT);
        pixDestroy(&pix1);
    }


        /* Do background coloring on rgb */
    pix1 = pixConvertTo32(pix0);
    for (i = 0; i < 4; i++) {
        scolor = 0xffffff00;
        composeRGBPixel(rval[i], gval[i], bval[i], &dcolor);
        pix2 = pixShiftByComponent(NULL, pix1, scolor, dcolor);
        snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)",
                 rval[i], gval[i], bval[i]);
        pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
                                     L_ADD_AT_BOT, NULL);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix2);
    }
    pixDestroy(&pix1);

        /* Compare cmapped & rgb foreground coloring */
    scolor = 0x0;  /* source color */
    composeRGBPixel(200, 30, 150, &dcolor);  /* ugly fg dest color */
    pix1 = pixShiftByComponent(NULL, pix0, scolor, dcolor);  /* cmapped */
    snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)",
             200, 100, 50);
    pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000,
                                 L_ADD_AT_BOT, NULL);
    pixaAddPix(pixa, pix2, L_INSERT);
    pix3 = pixConvertTo32(pix0);
    pix4 = pixShiftByComponent(NULL, pix3, scolor, dcolor);  /* rgb */
    snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)",
             200, 100, 50);
    pix5 = pixAddSingleTextblock(pix4, bmf, buf, 0xff000000,
                                 L_ADD_AT_BOT, NULL);
    pixaAddPix(pixa, pix5, L_INSERT);
    regTestComparePix(rp, pix1, pix4);
    regTestComparePix(rp, pix2, pix5);
    pixDestroy(&pix1);
    pixDestroy(&pix3);
    pixDestroy(&pix4);

        /* Log all the results */
    n = pixaGetCount(pixa);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixa, i, L_CLONE);
        regTestWritePixAndCheck(rp, pix1, IFF_PNG);
        pixDestroy(&pix1);
    }

        /* If in testing mode, make a pdf */
    if (rp->display) {
        pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0,
                         "Colored background", "/tmp/regout/coloring.pdf");
        L_INFO("Output pdf: /tmp/regout/coloring.pdf\n", rp->testname);
    }

    pixaDestroy(&pixa);
    pixDestroy(&pix0);
    bmfDestroy(&bmf);
    return regTestCleanup(rp);
}
Exemple #25
0
int main(int argc,
         char **argv) {
    l_int32 i, j, w, h, empty;
    l_uint32 redval, greenval;
    l_float32 f;
    L_WSHED *wshed;
    PIX *pixs, *pixc, *pixd;
    PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8;
    PIXA *pixac;
    PTA *pta;
    static char mainName[] = "watershedtest";

    if (argc != 1)
        return ERROR_INT(" Syntax:  watershedtest", mainName, 1);

    pixac = pixaCreate(0);
    pixs = pixCreate(500, 500, 8);
    pixGetDimensions(pixs, &w, &h, NULL);
    for (i = 0; i < 500; i++) {
        for (j = 0; j < 500; j++) {
#if 1
            f = 128.0 + 26.3 * sin(0.0438 * (l_float32) i);
            f += 33.4 * cos(0.0712 * (l_float32) i);
            f += 18.6 * sin(0.0561 * (l_float32) j);
            f += 23.6 * cos(0.0327 * (l_float32) j);
#else
            f = 128.0 + 26.3 * sin(0.0238 * (l_float32)i);
            f += 33.4 * cos(0.0312 * (l_float32)i);
            f += 18.6 * sin(0.0261 * (l_float32)j);
            f += 23.6 * cos(0.0207 * (l_float32)j);
#endif
            pixSetPixel(pixs, j, i, (l_int32) f);
        }
    }
    pixSaveTiled(pixs, pixac, 1.0, 1, 10, 32);
    pixWrite("/tmp/pattern.png", pixs, IFF_PNG);
    startTimer();
    pixLocalExtrema(pixs, 0, 0, &pix1, &pix2);
    fprintf(stderr, "Time for extrema: %7.3f\n", stopTimer());
    pixSetOrClearBorder(pix1, 2, 2, 2, 2, PIX_CLR);
    composeRGBPixel(255, 0, 0, &redval);
    composeRGBPixel(0, 255, 0, &greenval);
    pixc = pixConvertTo32(pixs);
    pixPaintThroughMask(pixc, pix2, 0, 0, greenval);
    pixPaintThroughMask(pixc, pix1, 0, 0, redval);
    pixSaveTiled(pixc, pixac, 1.0, 0, 10, 32);
    pixWrite("/tmp/pixc.png", pixc, IFF_PNG);
    pixSaveTiled(pix1, pixac, 1.0, 0, 10, 32);
    pixSelectMinInConnComp(pixs, pix1, &pta, NULL);
/*    ptaWriteStream(stderr, pta, 1); */
    pix3 = pixGenerateFromPta(pta, w, h);
    pixSaveTiled(pix3, pixac, 1.0, 1, 10, 32);

    pix4 = pixConvertTo32(pixs);
    pixPaintThroughMask(pix4, pix3, 0, 0, greenval);
    pixSaveTiled(pix4, pixac, 1.0, 0, 10, 32);
    pix5 = pixRemoveSeededComponents(NULL, pix3, pix1, 8, 2);
    pixSaveTiled(pix5, pixac, 1.0, 0, 10, 32);
    pixZero(pix5, &empty);
    fprintf(stderr, "Is empty?  %d\n", empty);
    pixDestroy(&pix4);
    pixDestroy(&pix5);

    wshed = wshedCreate(pixs, pix3, 10, 0);
    startTimer();
    wshedApply(wshed);
    fprintf(stderr, "Time for wshed: %7.3f\n", stopTimer());
    pix6 = pixaDisplayRandomCmap(wshed->pixad, w, h);
    pixSaveTiled(pix6, pixac, 1.0, 1, 10, 32);
    numaWriteStream(stderr, wshed->nalevels);
    pix7 = wshedRenderFill(wshed);
    pixSaveTiled(pix7, pixac, 1.0, 0, 10, 32);
    pix8 = wshedRenderColors(wshed);
    pixSaveTiled(pix8, pixac, 1.0, 0, 10, 32);
    wshedDestroy(&wshed);

    pixd = pixaDisplay(pixac, 0, 0);
    pixDisplay(pixd, 100, 100);
    pixWrite("/tmp/wshed.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixac);

    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix6);
    pixDestroy(&pix7);
    pixDestroy(&pix8);
    pixDestroy(&pixs);
    pixDestroy(&pixc);
    ptaDestroy(&pta);
    return 0;
}
Exemple #26
0
/*!
 *  pixReadStreamJp2k()
 *
 *      Input:  stream
 *              reduction (scaling factor: 1, 2, 4, 8)
 *              box  (<optional> for extracting a subregion), can be null
 *              hint (a bitwise OR of L_JP2K_* values; 0 for default)
 *              debug (output callback messages, etc)
 *      Return: pix (8 or 32 bpp), or null on error
 *
 *  Notes:
 *      (1) See pixReadJp2k() for usage.
 */
PIX *
pixReadStreamJp2k(FILE     *fp,
                  l_uint32  reduction,
                  BOX      *box,
                  l_int32   hint,
                  l_int32   debug)
{
const char        *opjVersion;
l_int32            i, j, index, bx, by, bw, bh, val, rval, gval, bval, aval;
l_int32            w, h, wpl, bps, spp, xres, yres, reduce, prec, colorspace;
l_uint32           pixel;
l_uint32          *data, *line;
opj_dparameters_t  parameters;   /* decompression parameters */
opj_image_t       *image = NULL;
opj_codec_t       *l_codec = NULL;  /* handle to decompressor */
opj_stream_t      *l_stream = NULL;  /* opj stream */
PIX               *pix = NULL;

    PROCNAME("pixReadStreamJp2k");

    if (!fp)
        return (PIX *)ERROR_PTR("fp not defined", procName, NULL);

    opjVersion = opj_version();
    if (opjVersion[0] != '2') {
        L_ERROR("version is %s; must be 2.0 or higher\n", procName, opjVersion);
        return NULL;
    }
    if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) {
        L_ERROR("version %s: differs from minor = %d\n",
                procName, opjVersion, OPJ_VERSION_MINOR);
         return NULL;
     }

        /* Get the resolution and the bits/sample */
    rewind(fp);
    fgetJp2kResolution(fp, &xres, &yres);
    freadHeaderJp2k(fp, NULL, NULL, &bps, NULL);
    rewind(fp);

    if (bps > 8) {
        L_ERROR("found %d bps; can only handle 8 bps\n", procName, bps);
        return NULL;
    }

        /* Set decoding parameters to default values */
    opj_set_default_decoder_parameters(&parameters);

        /* Find and set the reduce parameter, which is log2(reduction).
         * Valid reductions are powers of 2, and are determined when the
         * compressed string is made.  A request for an invalid reduction
         * will cause an error in opj_read_header(), and no image will
         * be returned. */
    for (reduce = 0; (1L << reduce) < reduction; reduce++) { }
    if ((1L << reduce) != reduction) {
        L_ERROR("invalid reduction %d; not power of 2\n", procName, reduction);
        return NULL;
    }
    parameters.cp_reduce = reduce;

        /* Open decompression 'stream'.  In 2.0, we could call this:
         *    opj_stream_create_default_file_stream(fp, 1)
         * but the file stream interface was removed in 2.1. */
    if ((l_stream = opjCreateStream(fp, 1)) == NULL) {
        L_ERROR("failed to open the stream\n", procName);
        return NULL;
    }

    if ((l_codec = opj_create_decompress(OPJ_CODEC_JP2)) == NULL) {
        L_ERROR("failed to make the codec\n", procName);
        opj_stream_destroy(l_stream);
        return NULL;
    }

        /* Catch and report events using callbacks */
    if (debug) {
        opj_set_info_handler(l_codec, info_callback, NULL);
        opj_set_warning_handler(l_codec, warning_callback, NULL);
        opj_set_error_handler(l_codec, error_callback, NULL);
    }

        /* Setup the decoding parameters using user parameters */
    if (!opj_setup_decoder(l_codec, &parameters)){
        L_ERROR("failed to set up decoder\n", procName);
        opj_stream_destroy(l_stream);
        opj_destroy_codec(l_codec);
        return NULL;
    }

        /* Read the main header of the codestream and, if necessary,
         * the JP2 boxes */
    if(!opj_read_header(l_stream, l_codec, &image)){
        L_ERROR("failed to read the header\n", procName);
        opj_stream_destroy(l_stream);
        opj_destroy_codec(l_codec);
        opj_image_destroy(image);
        return NULL;
    }

        /* Set up to decode a rectangular region */
    if (box) {
        boxGetGeometry(box, &bx, &by, &bw, &bh);
        if (!opj_set_decode_area(l_codec, image, bx, by,
                                 bx + bw, by + bh)) {
            L_ERROR("failed to set the region for decoding\n", procName);
            opj_stream_destroy(l_stream);
            opj_destroy_codec(l_codec);
            opj_image_destroy(image);
            return NULL;
        }
    }

        /* Get the decoded image */
    if (!(opj_decode(l_codec, l_stream, image) &&
          opj_end_decompress(l_codec, l_stream))) {
        L_ERROR("failed to decode the image\n", procName);
        opj_destroy_codec(l_codec);
        opj_stream_destroy(l_stream);
        opj_image_destroy(image);
        return NULL;
    }

        /* Close the byte stream */
    opj_stream_destroy(l_stream);

        /* Get the image parameters */
    spp = image->numcomps;
    w = image->comps[0].w;
    h = image->comps[0].h;
    prec = image->comps[0].prec;
    if (prec != bps)
        L_WARNING("precision %d != bps %d!\n", procName, prec, bps);
    if (debug) {
        L_INFO("w = %d, h = %d, bps = %d, spp = %d\n",
               procName, w, h, bps, spp);
        colorspace = image->color_space;
        if (colorspace == OPJ_CLRSPC_SRGB)
            L_INFO("colorspace is sRGB\n", procName);
        else if (colorspace == OPJ_CLRSPC_GRAY)
            L_INFO("colorspace is grayscale\n", procName);
        else if (colorspace == OPJ_CLRSPC_SYCC)
            L_INFO("colorspace is YUV\n", procName);
    }

        /* Free the codec structure */
    if (l_codec)
        opj_destroy_codec(l_codec);

        /* Convert the image to a pix */
    if (spp == 1)
        pix = pixCreate(w, h, 8);
    else
        pix = pixCreate(w, h, 32);
    pixSetResolution(pix, xres, yres);
    data = pixGetData(pix);
    wpl = pixGetWpl(pix);
    index = 0;
    if (spp == 1) {
        for (i = 0; i < h; i++) {
            line = data + i * wpl;
            for (j = 0; j < w; j++) {
                val = image->comps[0].data[index];
                SET_DATA_BYTE(line, j, val);
                index++;
            }
        }
    } else if (spp == 2) {  /* convert to RGBA */
        for (i = 0; i < h; i++) {
            line = data + i * wpl;
            for (j = 0; j < w; j++) {
                val = image->comps[0].data[index];
                aval = image->comps[1].data[index];
                composeRGBAPixel(val, val, val, aval, &pixel);
                line[j] = pixel;
                index++;
            }
        }
    } else if (spp >= 3) {
        for (i = 0; i < h; i++) {
            line = data + i * wpl;
            for (j = 0; j < w; j++) {
                rval = image->comps[0].data[index];
                gval = image->comps[1].data[index];
                bval = image->comps[2].data[index];
                if (spp == 3) {
                    composeRGBPixel(rval, gval, bval, &pixel);
                } else {  /* spp == 4 */
                    aval = image->comps[3].data[index];
                    composeRGBAPixel(rval, gval, bval, aval, &pixel);
                }
                line[j] = pixel;
                index++;
            }
        }
    }

        /* Free the opj image data structure */
    opj_image_destroy(image);

    return pix;
}