Esempio n. 1
0
/*!
 * \brief   nextOnPixelInRasterLow()
 *
 * \param[in]    data pix data
 * \param[in]    w, h width and height
 * \param[in]    wpl  words per line
 * \param[in]    xstart, ystart  starting point for search
 * \param[out]   px, py  coord value of next ON pixel
 * \return  1 if a pixel is found; 0 otherwise or on error
 */
l_int32
nextOnPixelInRasterLow(l_uint32  *data,
                       l_int32    w,
                       l_int32    h,
                       l_int32    wpl,
                       l_int32    xstart,
                       l_int32    ystart,
                       l_int32   *px,
                       l_int32   *py)
{
    l_int32    i, x, y, xend, startword;
    l_uint32  *line, *pword;

    /* Look at the first word */
    line = data + ystart * wpl;
    pword = line + (xstart / 32);
    if (*pword) {
        xend = xstart - (xstart % 32) + 31;
        for (x = xstart; x <= xend && x < w; x++) {
            if (GET_DATA_BIT(line, x)) {
                *px = x;
                *py = ystart;
                return 1;
            }
        }
    }

    /* Continue with the rest of the line */
    startword = (xstart / 32) + 1;
    x = 32 * startword;
    for (pword = line + startword; x < w; pword++, x += 32) {
        if (*pword) {
            for (i = 0; i < 32 && x < w; i++, x++) {
                if (GET_DATA_BIT(line, x)) {
                    *px = x;
                    *py = ystart;
                    return 1;
                }
            }
        }
    }

    /* Continue with following lines */
    for (y = ystart + 1; y < h; y++) {
        line = data + y * wpl;
        for (pword = line, x = 0; x < w; pword++, x += 32) {
            if (*pword) {
                for (i = 0; i < 32 && x < w; i++, x++) {
                    if (GET_DATA_BIT(line, x)) {
                        *px = x;
                        *py = y;
                        return 1;
                    }
                }
            }
        }
    }

    return 0;
}
Esempio n. 2
0
/*!
 *  dpixMeanSquareAccum()
 *
 *      Input:  pixs (1 bpp or 8 bpp grayscale)
 *      Return: dpix (64 bit array), or null on error
 *
 *  Notes:
 *      (1) This is an extension to the standard pixMeanSquareAccum()
 *          implementation provided by Leptonica, to handle 1bpp binary pix
 *          transparently.
 *      (1) Similar to pixBlockconvAccum(), this computes the
 *          sum of the squares of the pixel values in such a way
 *          that the value at (i,j) is the sum of all squares in
 *          the rectangle from the origin to (i,j).
 *      (2) The general recursion relation (v are squared pixel values) is
 *            a(i,j) = v(i,j) + a(i-1, j) + a(i, j-1) - a(i-1, j-1)
 *          For the first line, this reduces to the special case
 *            a(i,j) = v(i,j) + a(i, j-1)
 *          For the first column, the special case is
 *            a(i,j) = v(i,j) + a(i-1, j)
 */
DPIX *
dpixMeanSquareAccum(PIX  *pixs)
{
	l_int32     i, j, w, h, d, wpl, wpls, val;
	l_uint32   *datas, *lines;
	l_float64  *data, *line, *linep;
	DPIX       *dpix;
	
    PROCNAME("dpixMeanSquareAccum");
	
    if (!pixs)
        return (DPIX *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1 && d != 8)
        return (DPIX *)ERROR_PTR("pixs not 1 bpp or 8 bpp", procName, NULL);
    if ((dpix = dpixCreate(w, h)) ==  NULL)
        return (DPIX *)ERROR_PTR("dpix not made", procName, NULL);
	
    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    data = dpixGetData(dpix);
    wpl = dpixGetWpl(dpix);
	
    lines = datas;
    line = data;
    for (j = 0; j < w; j++) {   /* first line */
        val = d == 1 ? GET_DATA_BIT(lines, j) : GET_DATA_BYTE(lines, j);
        if (j == 0)
            line[0] = val * val;
        else
            line[j] = line[j - 1] + val * val;
    }
	
	/* Do the other lines */
    for (i = 1; i < h; i++) {
        lines = datas + i * wpls;
        line = data + i * wpl;  /* current dest line */
        linep = line - wpl;;  /* prev dest line */
        for (j = 0; j < w; j++) {
            val = d == 1 ? GET_DATA_BIT(lines, j) : GET_DATA_BYTE(lines, j);
            if (j == 0)
                line[0] = linep[0] + val * val;
            else
                line[j] = line[j - 1] + linep[j] - linep[j - 1] + val * val;
        }
    }
	
    return dpix;
}
Esempio n. 3
0
/*!
 *  ptaGetMeanVerticals()
 *
 *      Input:  pixs (1 bpp, single c.c.)
 *              x,y (location of UL corner of pixs with respect to page image
 *      Return: pta (mean y-values in component for each x-value,
 *                   both translated by (x,y)
 */
PTA *
pixGetMeanVerticals(PIX     *pixs,
                    l_int32  x,
                    l_int32  y)
{
l_int32    w, h, i, j, wpl, sum, count;
l_uint32  *line, *data;
PTA       *pta;

    PROCNAME("pixGetMeanVerticals");

    if (!pixs || pixGetDepth(pixs) != 1)
        return (PTA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);

    pixGetDimensions(pixs, &w, &h, NULL);
    pta = ptaCreate(w);
    data = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    for (j = 0; j < w; j++) {
        line = data;
        sum = count = 0;
        for (i = 0; i < h; i++) {
            if (GET_DATA_BIT(line, j) == 1) {
                sum += i;
                count += 1;
            }
            line += wpl;
        }
        if (count == 0) continue;
        ptaAddPt(pta, x + j, y + (sum / count));
    }

    return pta;
}
Esempio n. 4
0
/**
 * creates a raw buffer from the specified location of the pix
 */
    unsigned char *CubeUtils::GetImageData(Pix *pix, int left, int top,
                                           int wid, int hgt) {
        // skip invalid dimensions
        if (left < 0 || top < 0 || wid < 0 || hgt < 0 ||
            (left + wid) > pix->w || (top + hgt) > pix->h ||
            pix->d != 1) {
            return NULL;
        }

        // copy the char img to a temp buffer
        unsigned char *temp_buff = new unsigned char[wid * hgt];
        if (temp_buff == NULL) {
            return NULL;
        }
        l_int32 w;
        l_int32 h;
        l_int32 d;
        l_int32 wpl;
        l_uint32 *line;
        l_uint32 *data;

        pixGetDimensions(pix, &w, &h, &d);
        wpl = pixGetWpl(pix);
        data = pixGetData(pix);
        line = data + (top * wpl);

        for (int y = 0, off = 0; y < hgt; y++) {
            for (int x = 0; x < wid; x++, off++) {
                temp_buff[off] = GET_DATA_BIT(line, x + left) ? 0 : 255;
            }
            line += wpl;
        }
        return temp_buff;
    }
Esempio n. 5
0
/*!
 *  pixFindVerticalRuns()
 *
 *      Input:  pix (1 bpp)
 *              x (line to traverse)
 *              ystart (returns array of start positions for fg runs)
 *              yend (returns array of end positions for fg runs)
 *              &n   (<return> the number of runs found)
 *      Return: 0 if OK; 1 on error
 *
 *  Notes:
 *      (1) This finds foreground vertical runs on a single scanline.
 *      (2) To find background runs, use pixInvert() before applying
 *          this function.
 *      (3) The ystart and yend arrays are input.  They should be
 *          of size h/2 + 1 to insure that they can hold
 *          the maximum number of runs in the raster line.
 */
l_int32
pixFindVerticalRuns(PIX      *pix,
                    l_int32   x,
                    l_int32  *ystart,
                    l_int32  *yend,
                    l_int32  *pn)
{
l_int32    inrun;  /* boolean */
l_int32    index, w, h, d, i, wpl, val;
l_uint32  *data, *line;

    PROCNAME("pixFindVerticalRuns");

    if (!pn)
        return ERROR_INT("&n not defined", procName, 1);
    *pn = 0;
    if (!pix)
        return ERROR_INT("pix not defined", procName, 1);
    pixGetDimensions(pix, &w, &h, &d);
    if (d != 1)
        return ERROR_INT("pix not 1 bpp", procName, 1);
    if (x < 0 || x >= w)
        return ERROR_INT("x not in [0 ... w - 1]", procName, 1);
    if (!ystart)
        return ERROR_INT("ystart not defined", procName, 1);
    if (!yend)
        return ERROR_INT("yend not defined", procName, 1);

    wpl = pixGetWpl(pix);
    data = pixGetData(pix);

    inrun = FALSE;
    index = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        val = GET_DATA_BIT(line, x);
        if (!inrun) {
            if (val) {
                ystart[index] = i;
                inrun = TRUE;
            }
        }
        else {
            if (!val) {
                yend[index++] = i - 1;
                inrun = FALSE;
            }
        }
    }

        /* Finish last run if necessary */
    if (inrun)
        yend[index++] = h - 1;

    *pn = index;
    return 0;
}
/*!
 * \brief   pixFindMaxVerticalRunOnLine()
 *
 * \param[in]    pix 1 bpp
 * \param[in]    x column to traverse
 * \param[out]   pystart [optional] start position
 * \param[out]   psize  the size of the run
 * \return  0 if OK; 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This finds the longest foreground vertical run on a scanline.
 *      (2) To find background runs, use pixInvert() before applying
 *          this function.
 * </pre>
 */
l_int32
pixFindMaxVerticalRunOnLine(PIX      *pix,
                            l_int32   x,
                            l_int32  *pystart,
                            l_int32  *psize)
{
l_int32    inrun;  /* boolean */
l_int32    w, h, i, wpl, val, maxstart, maxsize, length, start;
l_uint32  *data, *line;

    PROCNAME("pixFindMaxVerticalRunOnLine");

    if (pystart) *pystart = 0;
    if (!psize)
        return ERROR_INT("&size not defined", procName, 1);
    *psize = 0;
    if (!pix || pixGetDepth(pix) != 1)
        return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
    pixGetDimensions(pix, &w, &h, NULL);
    if (x < 0 || x >= w)
        return ERROR_INT("x not in [0 ... w - 1]", procName, 1);

    wpl = pixGetWpl(pix);
    data = pixGetData(pix);
    inrun = FALSE;
    start = 0;
    maxstart = 0;
    maxsize = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        val = GET_DATA_BIT(line, x);
        if (!inrun) {
            if (val) {
                start = i;
                inrun = TRUE;
            }
        } else if (!val) {  /* run just ended */
            length = i - start;
            if (length > maxsize) {
                maxsize = length;
                maxstart = start;
            }
            inrun = FALSE;
        }
    }

    if (inrun) {  /* a run has continued to the end of the column */
        length = i - start;
        if (length > maxsize) {
            maxsize = length;
            maxstart = start;
        }
    }
    if (pystart) *pystart = maxstart;
    *psize = maxsize;
    return 0;
}
Esempio n. 7
0
/*!
 *  pixFindHorizontalRuns()
 *
 *      Input:  pix (1 bpp)
 *              y (line to traverse)
 *              xstart (returns array of start positions for fg runs)
 *              xend (returns array of end positions for fg runs)
 *              &n  (<return> the number of runs found)
 *      Return: 0 if OK; 1 on error
 *
 *  Notes:
 *      (1) This finds foreground horizontal runs on a single scanline.
 *      (2) To find background runs, use pixInvert() before applying
 *          this function.
 *      (3) The xstart and xend arrays are input.  They should be
 *          of size w/2 + 1 to insure that they can hold
 *          the maximum number of runs in the raster line.
 */
l_int32
pixFindHorizontalRuns(PIX      *pix,
                      l_int32   y,
                      l_int32  *xstart,
                      l_int32  *xend,
                      l_int32  *pn)
{
l_int32    inrun;  /* boolean */
l_int32    index, w, h, d, j, wpl, val;
l_uint32  *line;

    PROCNAME("pixFindHorizontalRuns");

    if (!pn)
        return ERROR_INT("&n not defined", procName, 1);
    *pn = 0;
    if (!pix)
        return ERROR_INT("pix not defined", procName, 1);
    pixGetDimensions(pix, &w, &h, &d);
    if (d != 1)
        return ERROR_INT("pix not 1 bpp", procName, 1);
    if (y < 0 || y >= h)
        return ERROR_INT("y not in [0 ... h - 1]", procName, 1);
    if (!xstart)
        return ERROR_INT("xstart not defined", procName, 1);
    if (!xend)
        return ERROR_INT("xend not defined", procName, 1);

    wpl = pixGetWpl(pix);
    line = pixGetData(pix) + y * wpl;

    inrun = FALSE;
    index = 0;
    for (j = 0; j < w; j++) {
        val = GET_DATA_BIT(line, j);
        if (!inrun) {
            if (val) {
                xstart[index] = j;
                inrun = TRUE;
            }
        }
        else {
            if (!val) {
                xend[index++] = j - 1;
                inrun = FALSE;
            }
        }
    }

        /* Finish last run if necessary */
    if (inrun)
        xend[index++] = w - 1;

    *pn = index;
    return 0;
}
/*!
 * \brief   pixFindMaxHorizontalRunOnLine()
 *
 * \param[in]    pix 1 bpp
 * \param[in]    y line to traverse
 * \param[out]   pxstart [optional] start position
 * \param[out]   psize  the size of the run
 * \return  0 if OK; 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This finds the longest foreground horizontal run on a scanline.
 *      (2) To find background runs, use pixInvert() before applying
 *          this function.
 * </pre>
 */
l_int32
pixFindMaxHorizontalRunOnLine(PIX      *pix,
                              l_int32   y,
                              l_int32  *pxstart,
                              l_int32  *psize)
{
l_int32    inrun;  /* boolean */
l_int32    w, h, j, wpl, val, maxstart, maxsize, length, start;
l_uint32  *line;

    PROCNAME("pixFindMaxHorizontalRunOnLine");

    if (pxstart) *pxstart = 0;
    if (!psize)
        return ERROR_INT("&size not defined", procName, 1);
    *psize = 0;
    if (!pix || pixGetDepth(pix) != 1)
        return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
    pixGetDimensions(pix, &w, &h, NULL);
    if (y < 0 || y >= h)
        return ERROR_INT("y not in [0 ... h - 1]", procName, 1);

    wpl = pixGetWpl(pix);
    line = pixGetData(pix) + y * wpl;
    inrun = FALSE;
    start = 0;
    maxstart = 0;
    maxsize = 0;
    for (j = 0; j < w; j++) {
        val = GET_DATA_BIT(line, j);
        if (!inrun) {
            if (val) {
                start = j;
                inrun = TRUE;
            }
        } else if (!val) {  /* run just ended */
            length = j - start;
            if (length > maxsize) {
                maxsize = length;
                maxstart = start;
            }
            inrun = FALSE;
        }
    }

    if (inrun) {  /* a run has continued to the end of the row */
        length = j - start;
        if (length > maxsize) {
            maxsize = length;
            maxstart = start;
        }
    }
    if (pxstart) *pxstart = maxstart;
    *psize = maxsize;
    return 0;
}
Esempio n. 9
0
// Scanning columns vertically on y=[y_start, y_end), returns the first x
// colum starting at x_start, stepping by x_step to x_end in which there is
// any black pixel.
static int VScanForBlack(uinT32* data, int wpl, int x_start, int x_end,
                         int y_start, int y_end, int x_step) {
  for (int x = x_start; x != x_end; x += x_step) {
    uinT32* line = data + y_start * wpl;
    for (int y = y_start; y < y_end; ++y, line += wpl) {
      if (GET_DATA_BIT(line, x))
        return x;
    }
  }
  return x_end;
}
Esempio n. 10
0
// Scanning rows horizontally on x=[x_start, x_end), returns the first y row
// starting at y_start, stepping by y_step to y_end in which there is
// any black pixel.
static int HScanForBlack(uinT32* data, int wpl, int x_start, int x_end,
                         int y_start, int y_end, int y_step) {
  for (int y = y_start; y != y_end; y += y_step) {
    uinT32* line = data + wpl * y;
    for (int x = x_start; x < x_end; ++x) {
      if (GET_DATA_BIT(line, x))
        return y;
    }
  }
  return y_end;
}
Esempio n. 11
0
/*!
 * \brief   pixExpandBinaryReplicate()
 *
 * \param[in]    pixs 1 bpp
 * \param[in]    xfact  integer scale factor for horiz. replicative expansion
 * \param[in]    yfact  integer scale factor for vertical replicative expansion
 * \return  pixd scaled up, or NULL on error
 */
PIX *
pixExpandBinaryReplicate(PIX     *pixs,
                         l_int32  xfact,
                         l_int32  yfact)
{
    l_int32    w, h, d, wd, hd, wpls, wpld, i, j, k, start;
    l_uint32  *datas, *datad, *lines, *lined;
    PIX       *pixd;

    PROCNAME("pixExpandBinaryReplicate");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1)
        return (PIX *)ERROR_PTR("pixs not binary", procName, NULL);
    if (xfact <= 0 || yfact <= 0)
        return (PIX *)ERROR_PTR("invalid scale factor: <= 0", procName, NULL);

    if (xfact == yfact) {
        if (xfact == 1)
            return pixCopy(NULL, pixs);
        if (xfact == 2 || xfact == 4 || xfact == 8 || xfact == 16)
            return pixExpandBinaryPower2(pixs, xfact);
    }

    wpls = pixGetWpl(pixs);
    datas = pixGetData(pixs);
    wd = xfact * w;
    hd = yfact * h;
    if ((pixd = pixCreate(wd, hd, 1)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    pixCopyResolution(pixd, pixs);
    pixScaleResolution(pixd, (l_float32)xfact, (l_float32)yfact);
    wpld = pixGetWpl(pixd);
    datad = pixGetData(pixd);

    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        lined = datad + yfact * i * wpld;
        for (j = 0; j < w; j++) {  /* replicate pixels on a single line */
            if (GET_DATA_BIT(lines, j)) {
                start = xfact * j;
                for (k = 0; k < xfact; k++)
                    SET_DATA_BIT(lined, start + k);
            }
        }
        for (k = 1; k < yfact; k++)  /* replicate the line */
            memcpy(lined + k * wpld, lined, 4 * wpld);
    }

    return pixd;
}
Esempio n. 12
0
/*!
 *  pixExpandBinaryReplicate()
 *
 *      Input:  pixs (1 bpp)
 *              factor (integer scale factor for replicative expansion)
 *      Return: pixd (scaled up), or null on error
 */
PIX *
pixExpandBinaryReplicate(PIX     *pixs,
                         l_int32  factor)
{
l_int32    w, h, d, wd, hd, wpls, wpld, i, j, k, start;
l_uint32  *datas, *datad, *lines, *lined;
PIX       *pixd;

    PROCNAME("pixExpandBinaryReplicate");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1)
        return (PIX *)ERROR_PTR("pixs not binary", procName, NULL);
    if (factor <= 0)
        return (PIX *)ERROR_PTR("factor <= 0; invalid", procName, NULL);

    if (factor == 1)
        return pixCopy(NULL, pixs);
    if (factor == 2 || factor == 4 || factor == 8 || factor == 16)
        return pixExpandBinaryPower2(pixs, factor);

    wpls = pixGetWpl(pixs);
    datas = pixGetData(pixs);
    wd = factor * w;
    hd = factor * h;
    if ((pixd = pixCreate(wd, hd, 1)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    pixCopyResolution(pixd, pixs);
    pixScaleResolution(pixd, (l_float32)factor, (l_float32)factor);
    wpld = pixGetWpl(pixd);
    datad = pixGetData(pixd);

    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        lined = datad + factor * i * wpld;
        for (j = 0; j < w; j++) {
            if (GET_DATA_BIT(lines, j)) {
                start = factor * j;
                for (k = 0; k < factor; k++)
                    SET_DATA_BIT(lined, start + k);
            }
        }
        for (k = 1; k < factor; k++)
            memcpy(lined + k * wpld, lined, 4 * wpld);
    }

    return pixd;
}
Esempio n. 13
0
// Sends for each pixel either '1' or '0'.
void ScrollView::TransferBinaryImage(PIX* image) {
  char* pixel_data = new char[image->w + 2];
  for (int y = 0; y < image->h; y++) {
    l_uint32* data = pixGetData(image) + y * pixGetWpl(image);
    for (int x = 0; x < image->w; x++) {
      if (GET_DATA_BIT(data, x))
        pixel_data[x] = '1';
      else
        pixel_data[x] = '0';
    }
    pixel_data[image->w] = '\n';
    pixel_data[image->w + 1] = '\0';
    SendRawMessage(pixel_data);
  }
  delete [] pixel_data;
}
// Methods to construct histograms from images.
void PixelHistogram::ConstructVerticalCountHist(Pix* pix) {
  Clear();
  int width = pixGetWidth(pix);
  int height = pixGetHeight(pix);
  hist_ = new int[width];
  length_ = width;
  int wpl = pixGetWpl(pix);
  l_uint32 *data = pixGetData(pix);
  for (int i = 0; i < width; ++i)
    hist_[i] = 0;
  for (int i = 0; i < height; ++i) {
    l_uint32 *line = data + i * wpl;
    for (int j = 0; j < width; ++j)
      if (GET_DATA_BIT(line, j))
        ++(hist_[j]);
  }
}
Esempio n. 15
0
/*read*/
kal_uint16 serial_read_data(void)
{ 
   kal_uint16 data=0; 
   kal_int16    i;        
   kal_uint32 savedMask;
   kal_uint32 retry=0;	

   //savedMask = SaveAndSetIRQMask();
   SET_CLK_LOW();
   SET_CLK_HIGH();
   while(GET_BUSY_BIT())
   {

 	   SET_CLK_LOW();
   	SET_CLK_HIGH();
   	retry++;
   	if(retry>1000000)/*give up the read. controller may be broken*/
   		return 0;
   	};
   for(i=11;i>=0;i--)
   {
      //SET_CLK_LOW();
      //serial_delay();
      SET_CLK_HIGH();
      serial_delay();
		if(GET_DATA_BIT())
			data |= (1<<i); 

		SET_CLK_LOW();
		serial_delay();
   }
   for(i=0;i<ZERO_FIELD_COUNT;i++)
   {
      SET_CLK_LOW();
      serial_delay();
      SET_CLK_HIGH();
      SET_CLK_LOW();  
   }
   data&=0x3fff;
   //RestoreIRQMask(savedMask);
   return data;
}
Esempio n. 16
0
void block_edges(Pix *t_pix,           // thresholded image
                 PDBLK *block,         // block in image
                 C_OUTLINE_IT* outline_it) {
  ICOORD bleft;                  // bounding box
  ICOORD tright;
  BLOCK_LINE_IT line_it = block; // line iterator

  int width = pixGetWidth(t_pix);
  int height = pixGetHeight(t_pix);
  int wpl = pixGetWpl(t_pix);
                                 // lines in progress
  CRACKEDGE **ptrline = new CRACKEDGE*[width + 1];
  CRACKEDGE *free_cracks = NULL;

  block->bounding_box(bleft, tright);  // block box
  int block_width = tright.x() - bleft.x();
  for (int x = block_width; x >= 0; x--)
    ptrline[x] = NULL;           //  no lines in progress

  uinT8* bwline = new uinT8[width];

  uinT8 margin = WHITE_PIX;

  for (int y = tright.y() - 1; y >= bleft.y() - 1; y--) {
    if (y >= bleft.y() && y < tright.y()) {
      // Get the binary pixels from the image.
      l_uint32* line = pixGetData(t_pix) + wpl * (height - 1 - y);
      for (int x = 0; x < block_width; ++x) {
        bwline[x] = GET_DATA_BIT(line, x + bleft.x()) ^ 1;
      }
      make_margins(block, &line_it, bwline, margin, bleft.x(), tright.x(), y);
    } else {
      memset(bwline, margin, block_width * sizeof(bwline[0]));
    }
    line_edges(bleft.x(), y, block_width,
               margin, bwline, ptrline, &free_cracks, outline_it);
  }

  free_crackedges(free_cracks);  // really free them
  delete[] ptrline;
  delete[] bwline;
}
Esempio n. 17
0
// Scans vertically on y=[y_start,y_end), starting with x=*x_start,
// stepping x+=x_step, until x=x_end. *x_start is input/output.
// If the number of black pixels in a column, pix_count fits this pattern:
// 0 or more cols with pix_count < min_count then
// <= mid_width cols with min_count <= pix_count <= max_count then
// a column with pix_count > max_count then
// true is returned, and *x_start = the first x with pix_count >= min_count.
static bool VScanForEdge(uinT32* data, int wpl, int y_start, int y_end,
                         int min_count, int mid_width, int max_count,
                         int x_end, int x_step, int* x_start) {
  int mid_cols = 0;
  for (int x = *x_start; x != x_end; x += x_step) {
    int pix_count = 0;
    uinT32* line = data + y_start * wpl;
    for (int y = y_start; y < y_end; ++y, line += wpl) {
      if (GET_DATA_BIT(line, x))
        ++pix_count;
    }
    if (mid_cols == 0 && pix_count < min_count)
      continue;      // In the min phase.
    if (mid_cols == 0)
      *x_start = x;  // Save the place where we came out of the min phase.
    if (pix_count > max_count)
      return true;   // found the pattern.
    ++mid_cols;
    if (mid_cols > mid_width)
      break;         // Middle too big.
  }
  return false;      // Never found max_count.
}
Esempio n. 18
0
// Scans horizontally on x=[x_start,x_end), starting with y=*y_start,
// stepping y+=y_step, until y=y_end. *ystart is input/output.
// If the number of black pixels in a row, pix_count fits this pattern:
// 0 or more rows with pix_count < min_count then
// <= mid_width rows with min_count <= pix_count <= max_count then
// a row with pix_count > max_count then
// true is returned, and *y_start = the first y with pix_count >= min_count.
static bool HScanForEdge(uinT32* data, int wpl, int x_start, int x_end,
                         int min_count, int mid_width, int max_count,
                         int y_end, int y_step, int* y_start) {
  int mid_rows = 0;
  for (int y = *y_start; y != y_end; y += y_step) {
    // Need pixCountPixelsInRow(pix, y, &pix_count, NULL) to count in a subset.
    int pix_count = 0;
    uinT32* line = data + wpl * y;
    for (int x = x_start; x < x_end; ++x) {
      if (GET_DATA_BIT(line, x))
        ++pix_count;
    }
    if (mid_rows == 0 && pix_count < min_count)
      continue;      // In the min phase.
    if (mid_rows == 0)
      *y_start = y;  // Save the y_start where we came out of the min phase.
    if (pix_count > max_count)
      return true;   // Found the pattern.
    ++mid_rows;
    if (mid_rows > mid_width)
      break;         // Middle too big.
  }
  return false;      // Never found max_count.
}
Esempio n. 19
0
int main(int    argc,
         char **argv)
{
l_int32       i, j, k, w, h, w2, w4, w8, w16, w32, wpl;
l_int32       count1, count2, count3;
l_uint32      val32, val1, val2;
l_uint32     *data1, *line1, *data2, *line2;
void        **lines1, **linet1, **linet2;
PIX          *pixs, *pix1, *pix2;
L_REGPARAMS  *rp;

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

    pixs = pixRead("feyn-fract.tif");
    pixGetDimensions(pixs, &w, &h, NULL);
    data1 = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    lines1 = pixGetLinePtrs(pixs, NULL);

        /* Get timing for the 3 different methods */
    startTimer();
    for (k = 0; k < 10; k++) {
        count1 = 0;
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                if (GET_DATA_BIT(lines1[i], j))
                    count1++;
            }
        }
    }
    fprintf(stderr, "Time with line ptrs     = %5.3f sec, count1 = %d\n",
            stopTimer(), count1);

    startTimer();
    for (k = 0; k < 10; k++) {
        count2 = 0;
        for (i = 0; i < h; i++) {
            line1 = data1 + i * wpl;
            for (j = 0; j < w; j++) {
               if (l_getDataBit(line1, j))
                    count2++;
            }
        }
    }
    fprintf(stderr, "Time with l_get*        = %5.3f sec, count2 = %d\n",
            stopTimer(), count2);

    startTimer();
    for (k = 0; k < 10; k++) {
        count3 = 0;
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                pixGetPixel(pixs, j, i, &val32);
                count3 += val32;
            }
        }
    }
    fprintf(stderr, "Time with pixGetPixel() = %5.3f sec, count3 = %d\n",
            stopTimer(), count3);

    pix1 = pixCreateTemplate(pixs);
    linet1 = pixGetLinePtrs(pix1, NULL);
    pix2 = pixCreateTemplate(pixs);
    data2 = pixGetData(pix2);
    linet2 = pixGetLinePtrs(pix2, NULL);

        /* ------------------------------------------------- */
        /*           Test different methods for 1 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            val1 = GET_DATA_BIT(lines1[i], j);
            count1 += val1;
            if (val1) SET_DATA_BIT(linet1[i], j);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w; j++) {
            val2 = l_getDataBit(line1, j);
            count2 += val2;
            if (val2) l_setDataBit(line2, j);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "1 bpp", rp);

        /* ------------------------------------------------- */
        /*           Test different methods for 2 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w2 = w / 2;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w2; j++) {
            val1 = GET_DATA_DIBIT(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbbbc;
            SET_DATA_DIBIT(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w2; j++) {
            val2 = l_getDataDibit(line1, j);
            count2 += val2;
            val2 += 0xbbbbbbbc;
            l_setDataDibit(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "2 bpp", rp);

        /* ------------------------------------------------- */
        /*           Test different methods for 4 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w4 = w / 4;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w4; j++) {
            val1 = GET_DATA_QBIT(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbbb0;
            SET_DATA_QBIT(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w4; j++) {
            val2 = l_getDataQbit(line1, j);
            count2 += val2;
            val2 += 0xbbbbbbb0;
            l_setDataQbit(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "4 bpp", rp);

        /* ------------------------------------------------- */
        /*           Test different methods for 8 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w8 = w / 8;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w8; j++) {
            val1 = GET_DATA_BYTE(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbb00;
            SET_DATA_BYTE(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w8; j++) {
            val2 = l_getDataByte(line1, j);
            count2 += val2;
            val2 += 0xbbbbbb00;
            l_setDataByte(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "8 bpp", rp);

        /* ------------------------------------------------- */
        /*          Test different methods for 16 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w16 = w / 16;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w16; j++) {
            val1 = GET_DATA_TWO_BYTES(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbb0000;
            SET_DATA_TWO_BYTES(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w16; j++) {
            val2 = l_getDataTwoBytes(line1, j);
            count2 += val2;
            val2 += 0xbbbb0000;
            l_setDataTwoBytes(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "16 bpp", rp);

        /* ------------------------------------------------- */
        /*          Test different methods for 32 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w32 = w / 32;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w32; j++) {
            val1 = GET_DATA_FOUR_BYTES(lines1[i], j);
            count1 += val1 & 0xfff;
            SET_DATA_FOUR_BYTES(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w32; j++) {
            val2 = l_getDataFourBytes(line1, j);
            count2 += val2 & 0xfff;
            l_setDataFourBytes(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "32 bpp", rp);
    pixDestroy(&pixs);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    lept_free(lines1);
    lept_free(linet1);
    lept_free(linet2);
    return regTestCleanup(rp);
}
Esempio n. 20
0
main(int    argc,
     char **argv)
{
l_int32      x, y, i, j, k, w, h, w2, w4, w8, w16, w32, wpl, nerrors;
l_int32      count1, count2, count3, ret, val1, val2;
l_uint32     val32;
l_uint32    *data, *line, *line1, *line2, *data1, *data2;
void       **lines1, **linet1, **linet2;
PIX         *pixs, *pixt1, *pixt2;
static char  mainName[] = "lowaccess_reg";

    pixs = pixRead("feyn.tif");   /* width divisible by 16 */
    pixGetDimensions(pixs, &w, &h, NULL);
    data = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    lines1 = pixGetLinePtrs(pixs, NULL);

        /* Get timing for the 3 different methods */
    startTimer();
    for (k = 0; k < 10; k++) {
        count1 = 0;
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                if (GET_DATA_BIT(lines1[i], j))
                    count1++;
            }
        }
    }
    fprintf(stderr, "Time with line ptrs     = %5.3f sec, count1 = %d\n",
            stopTimer(), count1);

    startTimer();
    for (k = 0; k < 10; k++) {
        count2 = 0;
        for (i = 0; i < h; i++) {
            line = data + i * wpl;
            for (j = 0; j < w; j++) {
               if (l_getDataBit(line, j))
                    count2++;
            }
        }
    }
    fprintf(stderr, "Time with l_get*        = %5.3f sec, count2 = %d\n",
            stopTimer(), count2);

    startTimer();
    for (k = 0; k < 10; k++) {
        count3 = 0;
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                pixGetPixel(pixs, j, i, &val32);
                count3 += val32;
            }
        }
    }
    fprintf(stderr, "Time with pixGetPixel() = %5.3f sec, count3 = %d\n",
            stopTimer(), count3);

    pixt1 = pixCreateTemplate(pixs);
    data1 = pixGetData(pixt1);
    linet1 = pixGetLinePtrs(pixt1, NULL);
    pixt2 = pixCreateTemplate(pixs);
    data2 = pixGetData(pixt2);
    linet2 = pixGetLinePtrs(pixt2, NULL);

    nerrors = 0;

        /* Test different methods for 1 bpp */
    count1 = 0;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            val1 = GET_DATA_BIT(lines1[i], j);
            count1 += val1;
            if (val1) SET_DATA_BIT(linet1[i], j);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w; j++) {
            val2 = l_getDataBit(line, j);
            count2 += val2;
            if (val2) l_setDataBit(line2, j);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "1 bpp");
    nerrors += ret;

        /* Test different methods for 2 bpp */
    count1 = 0;
    w2 = w / 2;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w2; j++) {
            val1 = GET_DATA_DIBIT(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbbbc;
            SET_DATA_DIBIT(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w2; j++) {
            val2 = l_getDataDibit(line, j);
            count2 += val2;
            val2 += 0xbbbbbbbc;
            l_setDataDibit(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "2 bpp");
    nerrors += ret;

        /* Test different methods for 4 bpp */
    count1 = 0;
    w4 = w / 4;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w4; j++) {
            val1 = GET_DATA_QBIT(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbbb0;
            SET_DATA_QBIT(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w4; j++) {
            val2 = l_getDataQbit(line, j);
            count2 += val2;
            val2 += 0xbbbbbbb0;
            l_setDataQbit(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "4 bpp");
    nerrors += ret;

        /* Test different methods for 8 bpp */
    count1 = 0;
    w8 = w / 8;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w8; j++) {
            val1 = GET_DATA_BYTE(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbb00;
            SET_DATA_BYTE(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w8; j++) {
            val2 = l_getDataByte(line, j);
            count2 += val2;
            val2 += 0xbbbbbb00;
            l_setDataByte(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "8 bpp");
    nerrors += ret;

        /* Test different methods for 16 bpp */
    count1 = 0;
    w16 = w / 16;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w16; j++) {
            val1 = GET_DATA_TWO_BYTES(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbb0000;
            SET_DATA_TWO_BYTES(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w16; j++) {
            val2 = l_getDataTwoBytes(line, j);
            count2 += val2;
            val2 += 0xbbbb0000;
            l_setDataTwoBytes(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "16 bpp");
    nerrors += ret;

        /* Test different methods for 32 bpp */
    count1 = 0;
    w32 = w / 32;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w32; j++) {
            val1 = GET_DATA_FOUR_BYTES(lines1[i], j);
            count1 += val1 & 0xfff;
            SET_DATA_FOUR_BYTES(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w32; j++) {
            val2 = l_getDataFourBytes(line, j);
            count2 += val2 & 0xfff;
            l_setDataFourBytes(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "32 bpp");
    nerrors += ret;

    if (!nerrors)
        fprintf(stderr, "****  No errors  ****\n");
    else
        fprintf(stderr, "****  %d errors found!  ****\n", nerrors);

    pixDestroy(&pixs);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    lept_free(lines1);
    lept_free(linet1);
    lept_free(linet2);
    return 0;
}
/*!
 *  pixSetSelectCmap()
 *
 *      Input:  pixs (1, 2, 4 or 8 bpp, with colormap)
 *              box (<optional> region to set color; can be NULL)
 *              sindex (colormap index of pixels to be changed)
 *              rval, gval, bval (new color to paint)
 *      Return: 0 if OK, 1 on error
 *
 *  Note:
 *      (1) This is an in-place operation.
 *      (2) It sets all pixels in region that have the color specified
 *          by the colormap index 'sindex' to the new color.
 *      (3) sindex must be in the existing colormap; otherwise an
 *          error is returned.
 *      (4) If the new color exists in the colormap, it is used;
 *          otherwise, it is added to the colormap.  If it cannot be
 *          added because the colormap is full, an error is returned.
 *      (5) If box is NULL, applies function to the entire image; otherwise,
 *          clips the operation to the intersection of the box and pix.
 *      (6) An DC of use would be to set to a specific color all
 *          the light (background) pixels within a certain region of
 *          a 3-level 2 bpp image, while leaving light pixels outside
 *          this region unchanged.
 */
l_int32
pixSetSelectCmap(PIX     *pixs,
                 BOX     *box,
                 l_int32  sindex,
                 l_int32  rval,
                 l_int32  gval,
                 l_int32  bval)
{
l_int32    i, j, w, h, d, n, x1, y1, x2, y2, bw, bh, val, wpls;
l_int32    index;  /* of new color to be set */
l_uint32  *lines, *datas;
PIXCMAP   *cmap;

    PROCNAME("pixSetSelectCmap");

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if ((cmap = pixGetColormap(pixs)) == NULL)
        return ERROR_INT("no colormap", procName, 1);
    d = pixGetDepth(pixs);
    if (d != 1 && d != 2 && d != 4 && d != 8)
        return ERROR_INT("depth not in {1,2,4,8}", procName, 1);

        /* Add new color if necessary; get index of this color in cmap */
    n = pixcmapGetCount(cmap);
    if (sindex >= n)
        return ERROR_INT("sindex too large; no cmap entry", procName, 1);
    if (pixcmapGetIndex(cmap, rval, gval, bval, &index)) { /* not found */
        if (pixcmapAddColor(cmap, rval, gval, bval))
            return ERROR_INT("error adding cmap entry", procName, 1);
        else
            index = n;  /* we've added one color */
    }

        /* Determine the region of substitution */
    pixGetDimensions(pixs, &w, &h, NULL);
    if (!box) {
        x1 = y1 = 0;
        x2 = w;
        y2 = h;
    } else {
        boxGetGeometry(box, &x1, &y1, &bw, &bh);
        x2 = x1 + bw - 1;
        y2 = y1 + bh - 1;
    }

        /* Replace pixel value sindex by index in the region */
    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    for (i = y1; i <= y2; i++) {
        if (i < 0 || i >= h)  /* clip */
            continue;
        lines = datas + i * wpls;
        for (j = x1; j <= x2; j++) {
            if (j < 0 || j >= w)  /* clip */
                continue;
            switch (d) {
            case 1:
                val = GET_DATA_BIT(lines, j);
                if (val == sindex) {
                    if (index == 0)
                        CLEAR_DATA_BIT(lines, j);
                    else
                        SET_DATA_BIT(lines, j);
                }
                break;
            case 2:
                val = GET_DATA_DIBIT(lines, j);
                if (val == sindex)
                    SET_DATA_DIBIT(lines, j, index);
                break;
            case 4:
                val = GET_DATA_QBIT(lines, j);
                if (val == sindex)
                    SET_DATA_QBIT(lines, j, index);
                break;
            case 8:
                val = GET_DATA_BYTE(lines, j);
                if (val == sindex)
                    SET_DATA_BYTE(lines, j, index);
                break;
            default:
                return ERROR_INT("depth not in {1,2,4,8}", procName, 1);
            }
        }
    }

    return 0;
}
/*!
 *  pixSetMaskedCmap()
 *
 *      Input:  pixs (2, 4 or 8 bpp, colormapped)
 *              pixm (<optional> 1 bpp mask; no-op if NULL)
 *              x, y (origin of pixm relative to pixs; can be negative)
 *              rval, gval, bval (new color to set at each masked pixel)
 *      Return: 0 if OK; 1 on error
 *
 *  Notes:
 *      (1) This is an in-place operation.
 *      (2) It paints a single color through the mask (as a stencil).
 *      (3) The mask origin is placed at (x,y) on pixs, and the
 *          operation is clipped to the intersection of the mask and pixs.
 *      (4) If pixm == NULL, a warning is given.
 *      (5) Typically, pixm is a small binary mask located somewhere
 *          on the larger pixs.
 *      (6) If the color is in the colormap, it is used.  Otherwise,
 *          it is added if possible; an error is returned if the
 *          colormap is already full.
 */
l_int32
pixSetMaskedCmap(PIX      *pixs,
                 PIX      *pixm,
                 l_int32   x,
                 l_int32   y,
                 l_int32   rval,
                 l_int32   gval,
                 l_int32   bval)
{
l_int32    w, h, d, wpl, wm, hm, wplm;
l_int32    i, j, index;
l_uint32  *data, *datam, *line, *linem;
PIXCMAP   *cmap;

    PROCNAME("pixSetMaskedCmap");

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if ((cmap = pixGetColormap(pixs)) == NULL)
        return ERROR_INT("no colormap in pixs", procName, 1);
    if (!pixm) {
        L_WARNING("no mask; nothing to do\n", procName);
        return 0;
    }
    d = pixGetDepth(pixs);
    if (d != 2 && d != 4 && d != 8)
        return ERROR_INT("depth not in {2,4,8}", procName, 1);
    if (pixGetDepth(pixm) != 1)
        return ERROR_INT("pixm not 1 bpp", procName, 1);

        /* Add new color if necessary; store in 'index' */
    if (pixcmapGetIndex(cmap, rval, gval, bval, &index)) {  /* not found */
        if (pixcmapAddColor(cmap, rval, gval, bval))
            return ERROR_INT("no room in cmap", procName, 1);
        index = pixcmapGetCount(cmap) - 1;
    }

    pixGetDimensions(pixs, &w, &h, NULL);
    wpl = pixGetWpl(pixs);
    data = pixGetData(pixs);
    pixGetDimensions(pixm, &wm, &hm, NULL);
    wplm = pixGetWpl(pixm);
    datam = pixGetData(pixm);
    for (i = 0; i < hm; i++) {
        if (i + y < 0 || i + y >= h) continue;
        line = data + (i + y) * wpl;
        linem = datam + i * wplm;
        for (j = 0; j < wm; j++) {
            if (j + x < 0  || j + x >= w) continue;
            if (GET_DATA_BIT(linem, j)) {  /* paint color */
                switch (d)
                {
                case 2:
                    SET_DATA_DIBIT(line, j + x, index);
                    break;
                case 4:
                    SET_DATA_QBIT(line, j + x, index);
                    break;
                case 8:
                    SET_DATA_BYTE(line, j + x, index);
                    break;
                default:
                    return ERROR_INT("depth not in {2,4,8}", procName, 1);
                }
            }
        }
    }

    return 0;
}
/*!
 *  pixSetSelectMaskedCmap()
 *
 *      Input:  pixs (2, 4 or 8 bpp, with colormap)
 *              pixm (<optional> 1 bpp mask; no-op if NULL)
 *              x, y (UL corner of mask relative to pixs)
 *              sindex (colormap index of pixels in pixs to be changed)
 *              rval, gval, bval (new color to substitute)
 *      Return: 0 if OK, 1 on error
 *
 *  Note:
 *      (1) This is an in-place operation.
 *      (2) This paints through the fg of pixm and replaces all pixels
 *          in pixs that have a particular value (sindex) with the new color.
 *      (3) If pixm == NULL, a warning is given.
 *      (4) sindex must be in the existing colormap; otherwise an
 *          error is returned.
 *      (5) If the new color exists in the colormap, it is used;
 *          otherwise, it is added to the colormap.  If the colormap
 *          is full, an error is returned.
 */
l_int32
pixSetSelectMaskedCmap(PIX     *pixs,
                       PIX     *pixm,
                       l_int32  x,
                       l_int32  y,
                       l_int32  sindex,
                       l_int32  rval,
                       l_int32  gval,
                       l_int32  bval)
{
l_int32    i, j, w, h, d, n, wm, hm, wpls, wplm, val;
l_int32    index;  /* of new color to be set */
l_uint32  *lines, *linem, *datas, *datam;
PIXCMAP   *cmap;

    PROCNAME("pixSetSelectMaskedCmap");

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if ((cmap = pixGetColormap(pixs)) == NULL)
        return ERROR_INT("no colormap", procName, 1);
    if (!pixm) {
        L_WARNING("no mask; nothing to do\n", procName);
        return 0;
    }

    d = pixGetDepth(pixs);
    if (d != 2 && d != 4 && d != 8)
        return ERROR_INT("depth not in {2, 4, 8}", procName, 1);

        /* add new color if necessary; get index of this color in cmap */
    n = pixcmapGetCount(cmap);
    if (sindex >= n)
        return ERROR_INT("sindex too large; no cmap entry", procName, 1);
    if (pixcmapGetIndex(cmap, rval, gval, bval, &index)) { /* not found */
        if (pixcmapAddColor(cmap, rval, gval, bval))
            return ERROR_INT("error adding cmap entry", procName, 1);
        else
            index = n;  /* we've added one color */
    }

        /* replace pixel value sindex by index when fg pixel in pixmc
         * overlays it */
    w = pixGetWidth(pixs);
    h = pixGetHeight(pixs);
    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    wm = pixGetWidth(pixm);
    hm = pixGetHeight(pixm);
    datam = pixGetData(pixm);
    wplm = pixGetWpl(pixm);
    for (i = 0; i < hm; i++) {
        if (i + y < 0 || i + y >= h) continue;
        lines = datas + (y + i) * wpls;
        linem = datam + i * wplm;
        for (j = 0; j < wm; j++) {
            if (j + x < 0  || j + x >= w) continue;
            if (GET_DATA_BIT(linem, j)) {
                switch (d) {
                case 1:
                    val = GET_DATA_BIT(lines, x + j);
                    if (val == sindex) {
                        if (index == 0)
                            CLEAR_DATA_BIT(lines, x + j);
                        else
                            SET_DATA_BIT(lines, x + j);
                    }
                    break;
                case 2:
                    val = GET_DATA_DIBIT(lines, x + j);
                    if (val == sindex)
                        SET_DATA_DIBIT(lines, x + j, index);
                    break;
                case 4:
                    val = GET_DATA_QBIT(lines, x + j);
                    if (val == sindex)
                        SET_DATA_QBIT(lines, x + j, index);
                    break;
                case 8:
                    val = GET_DATA_BYTE(lines, x + j);
                    if (val == sindex)
                        SET_DATA_BYTE(lines, x + j, index);
                    break;
                default:
                    return ERROR_INT("depth not in {1,2,4,8}", procName, 1);
                }
            }
        }
    }

    return 0;
}
/*!
 *  pixColorGrayMaskedCmap()
 *
 *      Input:  pixs (8 bpp, with colormap)
 *              pixm (1 bpp mask, through which to apply color)
 *              type (L_PAINT_LIGHT, L_PAINT_DARK)
 *              rval, gval, bval (target color)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This is an in-place operation.
 *      (2) If type == L_PAINT_LIGHT, it colorizes non-black pixels,
 *          preserving antialiasing.
 *          If type == L_PAINT_DARK, it colorizes non-white pixels,
 *          preserving antialiasing.  See pixColorGrayCmap() for details.
 *      (3) This increases the colormap size by the number of
 *          different gray (non-black or non-white) colors in the
 *          input colormap.  If there is not enough room in the colormap
 *          for this expansion, it returns 1 (error).
 */
l_int32
pixColorGrayMaskedCmap(PIX     *pixs,
                       PIX     *pixm,
                       l_int32  type,
                       l_int32  rval,
                       l_int32  gval,
                       l_int32  bval)
{
l_int32    i, j, w, h, wm, hm, wmin, hmin, wpl, wplm;
l_int32    val, nval;
l_int32   *map;
l_uint32  *line, *data, *linem, *datam;
NUMA      *na;
PIXCMAP   *cmap;

    PROCNAME("pixColorGrayMaskedCmap");

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (!pixm || pixGetDepth(pixm) != 1)
        return ERROR_INT("pixm undefined or not 1 bpp", procName, 1);
    if ((cmap = pixGetColormap(pixs)) == NULL)
        return ERROR_INT("no colormap", procName, 1);
    if (pixGetDepth(pixs) != 8)
        return ERROR_INT("depth not 8 bpp", procName, 1);
    if (type != L_PAINT_DARK && type != L_PAINT_LIGHT)
        return ERROR_INT("invalid type", procName, 1);

    if (addColorizedGrayToCmap(cmap, type, rval, gval, bval, &na))
        return ERROR_INT("no room; cmap full", procName, 1);
    map = numaGetIArray(na);
    numaDestroy(&na);
    if (!map)
        return ERROR_INT("map not made", procName, 1);

    pixGetDimensions(pixs, &w, &h, NULL);
    pixGetDimensions(pixm, &wm, &hm, NULL);
    if (wm != w)
        L_WARNING("wm = %d differs from w = %d\n", procName, wm, w);
    if (hm != h)
        L_WARNING("hm = %d differs from h = %d\n", procName, hm, h);
    wmin = L_MIN(w, wm);
    hmin = L_MIN(h, hm);

    data = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    datam = pixGetData(pixm);
    wplm = pixGetWpl(pixm);

        /* Remap gray pixels in the region */
    for (i = 0; i < hmin; i++) {
        line = data + i * wpl;
        linem = datam + i * wplm;
        for (j = 0; j < wmin; j++) {
            if (GET_DATA_BIT(linem, j) == 0)
                continue;
            val = GET_DATA_BYTE(line, j);
            nval = map[val];
            if (nval != 256)
                SET_DATA_BYTE(line, j, nval);
        }
    }

    FREE(map);
    return 0;
}
Esempio n. 25
0
/*!
 * \brief   pixSeedfill8BB()
 *
 * \param[in]    pixs 1 bpp
 * \param[in]    stack for holding fillsegs
 * \param[in]    x,y   location of seed pixel
 * \return  box or NULL on error.
 *
 * <pre>
 * Notes:
 *      (1) This is Paul Heckbert's stack-based 8-cc seedfill algorithm.
 *      (2) This operates on the input 1 bpp pix to remove the fg seed
 *          pixel, at (x,y), and all pixels that are 8-connected to it.
 *          The seed pixel at (x,y) must initially be ON.
 *      (3) Returns the bounding box of the erased 8-cc component.
 *      (4) Reference: see Paul Heckbert's stack-based seed fill algorithm
 *          in "Graphic Gems", ed. Andrew Glassner, Academic
 *          Press, 1990.  The algorithm description is given
 *          on pp. 275-277; working C code is on pp. 721-722.)
 *          The code here follows Heckbert's closely, except
 *          the leak checks are changed for 8 connectivity.
 *          See comments on pixSeedfill4BB() for more details.
 * </pre>
 */
BOX *
pixSeedfill8BB(PIX      *pixs,
               L_STACK  *stack,
               l_int32   x,
               l_int32   y)
{
    l_int32    w, h, xstart, wpl, x1, x2, dy;
    l_int32    xmax, ymax;
    l_int32    minx, maxx, miny, maxy;  /* for bounding box of this c.c. */
    l_uint32  *data, *line;
    BOX       *box;

    PROCNAME("pixSeedfill8BB");

    if (!pixs || pixGetDepth(pixs) != 1)
        return (BOX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
    if (!stack)
        return (BOX *)ERROR_PTR("stack not defined", procName, NULL);
    if (!stack->auxstack)
        stack->auxstack = lstackCreate(0);

    pixGetDimensions(pixs, &w, &h, NULL);
    xmax = w - 1;
    ymax = h - 1;
    data = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    line = data + y * wpl;

    /* Check pix value of seed; must be ON */
    if (x < 0 || x > xmax || y < 0 || y > ymax || (GET_DATA_BIT(line, x) == 0))
        return NULL;

    /* Init stack to seed:
     * Must first init b.b. values to prevent valgrind from complaining;
     * then init b.b. boundaries correctly to seed.  */
    minx = miny = 100000;
    maxx = maxy = 0;
    pushFillsegBB(stack, x, x, y, 1, ymax, &minx, &maxx, &miny, &maxy);
    pushFillsegBB(stack, x, x, y + 1, -1, ymax, &minx, &maxx, &miny, &maxy);
    minx = maxx = x;
    miny = maxy = y;

    while (lstackGetCount(stack) > 0) {
        /* Pop segment off stack and fill a neighboring scan line */
        popFillseg(stack, &x1, &x2, &y, &dy);
        line = data + y * wpl;

        /* A segment of scanline y - dy for x1 <= x <= x2 was
         * previously filled.  We now explore adjacent pixels
         * in scan line y.  There are three regions: to the
         * left of x1, between x1 and x2, and to the right of x2.
         * These regions are handled differently.  Leaks are
         * possible expansions beyond the previous segment and
         * going back in the -dy direction.  These can happen
         * for x < x1 and for x > x2.  Any "leak" segments
         * are plugged with a push in the -dy (opposite) direction.
         * And any segments found anywhere are always extended
         * in the +dy direction.  */
        for (x = x1 - 1; x >= 0 && (GET_DATA_BIT(line, x) == 1); x--)
            CLEAR_DATA_BIT(line,x);
        if (x >= x1 - 1)  /* pix at x1 - 1 was off and was not cleared */
            goto skip;
        xstart = x + 1;
        if (xstart < x1)   /* leak on left? */
            pushFillsegBB(stack, xstart, x1 - 1, y, -dy,
                          ymax, &minx, &maxx, &miny, &maxy);

        x = x1;
        do {
            for (; x <= xmax && (GET_DATA_BIT(line, x) == 1); x++)
                CLEAR_DATA_BIT(line, x);
            pushFillsegBB(stack, xstart, x - 1, y, dy,
                          ymax, &minx, &maxx, &miny, &maxy);
            if (x > x2)   /* leak on right? */
                pushFillsegBB(stack, x2 + 1, x - 1, y, -dy,
                              ymax, &minx, &maxx, &miny, &maxy);
skip:
            for (x++; x <= x2 + 1 &&
                    x <= xmax &&
                    (GET_DATA_BIT(line, x) == 0); x++)
                ;
            xstart = x;
        } while (x <= x2 + 1 && x <= xmax);
    }

    if ((box = boxCreate(minx, miny, maxx - minx + 1, maxy - miny + 1))
            == NULL)
        return (BOX *)ERROR_PTR("box not made", procName, NULL);
    return box;
}
Esempio n. 26
0
/*!
 *  accumulateLow()
 */
void
accumulateLow(l_uint32  *datad,
              l_int32    w,
              l_int32    h,
              l_int32    wpld,
              l_uint32  *datas,
              l_int32    d,
              l_int32    wpls,
              l_int32    op)
{
    l_int32    i, j;
    l_uint32  *lines, *lined;

    switch (d)
    {
    case 1:
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            if (op == L_ARITH_ADD) {
                for (j = 0; j < w; j++)
                    lined[j] += GET_DATA_BIT(lines, j);
            }
            else {  /* op == L_ARITH_SUBTRACT */
                for (j = 0; j < w; j++)
                    lined[j] -= GET_DATA_BIT(lines, j);
            }
        }
        break;
    case 8:
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            if (op == L_ARITH_ADD) {
                for (j = 0; j < w; j++)
                    lined[j] += GET_DATA_BYTE(lines, j);
            }
            else {  /* op == L_ARITH_SUBTRACT */
                for (j = 0; j < w; j++)
                    lined[j] -= GET_DATA_BYTE(lines, j);
            }
        }
        break;
    case 16:
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            if (op == L_ARITH_ADD) {
                for (j = 0; j < w; j++)
                    lined[j] += GET_DATA_TWO_BYTES(lines, j);
            }
            else {  /* op == L_ARITH_SUBTRACT */
                for (j = 0; j < w; j++)
                    lined[j] -= GET_DATA_TWO_BYTES(lines, j);
            }
        }
        break;
    case 32:
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            if (op == L_ARITH_ADD) {
                for (j = 0; j < w; j++)
                    lined[j] += lines[j];
            }
            else {  /* op == L_ARITH_SUBTRACT */
                for (j = 0; j < w; j++)
                    lined[j] -= lines[j];
            }
        }
        break;
    }
    return;
}
Esempio n. 27
0
/*!
 * \brief   pixSeedfill8()
 *
 * \param[in]    pixs 1 bpp
 * \param[in]    stack for holding fillsegs
 * \param[in]    x,y   location of seed pixel
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This is Paul Heckbert's stack-based 8-cc seedfill algorithm.
 *      (2) This operates on the input 1 bpp pix to remove the fg seed
 *          pixel, at (x,y), and all pixels that are 8-connected to it.
 *          The seed pixel at (x,y) must initially be ON.
 *      (3) Reference: see pixSeedFill8BB()
 * </pre>
 */
l_int32
pixSeedfill8(PIX      *pixs,
             L_STACK  *stack,
             l_int32   x,
             l_int32   y)
{
    l_int32    w, h, xstart, wpl, x1, x2, dy;
    l_int32    xmax, ymax;
    l_uint32  *data, *line;

    PROCNAME("pixSeedfill8");

    if (!pixs || pixGetDepth(pixs) != 1)
        return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
    if (!stack)
        return ERROR_INT("stack not defined", procName, 1);
    if (!stack->auxstack)
        stack->auxstack = lstackCreate(0);

    pixGetDimensions(pixs, &w, &h, NULL);
    xmax = w - 1;
    ymax = h - 1;
    data = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    line = data + y * wpl;

    /* Check pix value of seed; must be ON */
    if (x < 0 || x > xmax || y < 0 || y > ymax || (GET_DATA_BIT(line, x) == 0))
        return 0;

    /* Init stack to seed */
    pushFillseg(stack, x, x, y, 1, ymax);
    pushFillseg(stack, x, x, y + 1, -1, ymax);

    while (lstackGetCount(stack) > 0) {
        /* Pop segment off stack and fill a neighboring scan line */
        popFillseg(stack, &x1, &x2, &y, &dy);
        line = data + y * wpl;

        /* A segment of scanline y - dy for x1 <= x <= x2 was
         * previously filled.  We now explore adjacent pixels
         * in scan line y.  There are three regions: to the
         * left of x1, between x1 and x2, and to the right of x2.
         * These regions are handled differently.  Leaks are
         * possible expansions beyond the previous segment and
         * going back in the -dy direction.  These can happen
         * for x < x1 and for x > x2.  Any "leak" segments
         * are plugged with a push in the -dy (opposite) direction.
         * And any segments found anywhere are always extended
         * in the +dy direction.  */
        for (x = x1 - 1; x >= 0 && (GET_DATA_BIT(line, x) == 1); x--)
            CLEAR_DATA_BIT(line,x);
        if (x >= x1 - 1)  /* pix at x1 - 1 was off and was not cleared */
            goto skip;
        xstart = x + 1;
        if (xstart < x1)   /* leak on left? */
            pushFillseg(stack, xstart, x1 - 1, y, -dy, ymax);

        x = x1;
        do {
            for (; x <= xmax && (GET_DATA_BIT(line, x) == 1); x++)
                CLEAR_DATA_BIT(line, x);
            pushFillseg(stack, xstart, x - 1, y, dy, ymax);
            if (x > x2)   /* leak on right? */
                pushFillseg(stack, x2 + 1, x - 1, y, -dy, ymax);
skip:
            for (x++; x <= x2 + 1 &&
                    x <= xmax &&
                    (GET_DATA_BIT(line, x) == 0); x++)
                ;
            xstart = x;
        } while (x <= x2 + 1 && x <= xmax);
    }

    return 0;
}
Esempio n. 28
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;
}
Esempio n. 29
0
/*!
 * \brief   pixToGif()
 *
 * \param[in]    pix 1, 2, 4, 8, 16 or 32 bpp
 * \param[in]    gif  opened gif stream
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This encodes the pix to the gif stream. The stream is not
 *          closes by this function.
 *      (2) It is static to make this function private.
 * </pre>
 */
static l_int32
pixToGif(PIX *pix, GifFileType *gif)
{
char            *text;
l_int32          wpl, i, j, w, h, d, ncolor, rval, gval, bval;
l_int32          gif_ncolor = 0;
l_uint32        *data, *line;
PIX             *pixd;
PIXCMAP         *cmap;
ColorMapObject  *gif_cmap;
GifByteType     *gif_line;
#if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5
int              giferr;
#endif  /* 5.1 and beyond */

    PROCNAME("pixToGif");

    if (!pix)
        return ERROR_INT("pix not defined", procName, 1);
    if (!gif)
        return ERROR_INT("gif not defined", procName, 1);

    d = pixGetDepth(pix);
    if (d == 32) {
        pixd = pixConvertRGBToColormap(pix, 1);
    } else if (d > 1) {
        pixd = pixConvertTo8(pix, TRUE);
    } else {  /* d == 1; make sure there's a colormap */
        pixd = pixClone(pix);
        if (!pixGetColormap(pixd)) {
            cmap = pixcmapCreate(1);
            pixcmapAddColor(cmap, 255, 255, 255);
            pixcmapAddColor(cmap, 0, 0, 0);
            pixSetColormap(pixd, cmap);
        }
    }

    if (!pixd)
        return ERROR_INT("failed to convert image to indexed", procName, 1);
    d = pixGetDepth(pixd);

    if ((cmap = pixGetColormap(pixd)) == NULL) {
        pixDestroy(&pixd);
        return ERROR_INT("cmap is missing", procName, 1);
    }

        /* 'Round' the number of gif colors up to a power of 2 */
    ncolor = pixcmapGetCount(cmap);
    for (i = 0; i <= 8; i++) {
        if ((1 << i) >= ncolor) {
            gif_ncolor = (1 << i);
            break;
        }
    }
    if (gif_ncolor < 1) {
        pixDestroy(&pixd);
        return ERROR_INT("number of colors is invalid", procName, 1);
    }

        /* Save the cmap colors in a gif_cmap */
    if ((gif_cmap = GifMakeMapObject(gif_ncolor, NULL)) == NULL) {
        pixDestroy(&pixd);
        return ERROR_INT("failed to create GIF color map", procName, 1);
    }
    for (i = 0; i < gif_ncolor; i++) {
        rval = gval = bval = 0;
        if (ncolor > 0) {
            if (pixcmapGetColor(cmap, i, &rval, &gval, &bval) != 0) {
                pixDestroy(&pixd);
                GifFreeMapObject(gif_cmap);
                return ERROR_INT("failed to get color from color map",
                                 procName, 1);
            }
            ncolor--;
        }
        gif_cmap->Colors[i].Red = rval;
        gif_cmap->Colors[i].Green = gval;
        gif_cmap->Colors[i].Blue = bval;
    }

    pixGetDimensions(pixd, &w, &h, NULL);
    if (EGifPutScreenDesc(gif, w, h, gif_cmap->BitsPerPixel, 0, gif_cmap)
        != GIF_OK) {
        pixDestroy(&pixd);
        GifFreeMapObject(gif_cmap);
        return ERROR_INT("failed to write screen description", procName, 1);
    }
    GifFreeMapObject(gif_cmap); /* not needed after this point */

    if (EGifPutImageDesc(gif, 0, 0, w, h, FALSE, NULL) != GIF_OK) {
        pixDestroy(&pixd);
        return ERROR_INT("failed to image screen description", procName, 1);
    }

    data = pixGetData(pixd);
    wpl = pixGetWpl(pixd);
    if (d != 1 && d != 2 && d != 4 && d != 8) {
        pixDestroy(&pixd);
        return ERROR_INT("image depth is not in {1, 2, 4, 8}", procName, 1);
    }

    if ((gif_line = (GifByteType *)LEPT_CALLOC(sizeof(GifByteType), w))
        == NULL) {
        pixDestroy(&pixd);
        return ERROR_INT("mem alloc fail for data line", procName, 1);
    }

    for (i = 0; i < h; i++) {
        line = data + i * wpl;
            /* Gif's way of setting the raster line up for compression */
        for (j = 0; j < w; j++) {
            switch(d)
            {
            case 8:
                gif_line[j] = GET_DATA_BYTE(line, j);
                break;
            case 4:
                gif_line[j] = GET_DATA_QBIT(line, j);
                break;
            case 2:
                gif_line[j] = GET_DATA_DIBIT(line, j);
                break;
            case 1:
                gif_line[j] = GET_DATA_BIT(line, j);
                break;
            }
        }

            /* Compress and save the line */
        if (EGifPutLine(gif, gif_line, w) != GIF_OK) {
            LEPT_FREE(gif_line);
            pixDestroy(&pixd);
            return ERROR_INT("failed to write data line into GIF", procName, 1);
        }
    }

        /* Write a text comment.  This must be placed after writing the
         * data (!!)  Note that because libgif does not provide a function
         * for reading comments from file, you will need another way
         * to read comments. */
    if ((text = pixGetText(pix)) != NULL) {
        if (EGifPutComment(gif, text) != GIF_OK)
            L_WARNING("gif comment not written\n", procName);
    }

    LEPT_FREE(gif_line);
    pixDestroy(&pixd);
    return 0;
}
Esempio n. 30
0
/*!
 *  pixFindLargestRectangle()
 *
 *      Input:  pixs  (1 bpp)
 *              polarity (0 within background, 1 within foreground)
 *              &box (<return> largest rectangle, either by area or
 *                    by perimeter)
 *              debugflag (1 to output image with rectangle drawn on it)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) Why is this here?  This is a simple and elegant solution to
 *          a problem in computational geometry that at first appears
 *          quite difficult: what is the largest rectangle that can
 *          be placed in the image, covering only pixels of one polarity
 *          (bg or fg)?  The solution is O(n), where n is the number
 *          of pixels in the image, and it requires nothing more than
 *          using a simple recursion relation in a single sweep of the image.
 *      (2) In a sweep from UL to LR with left-to-right being the fast
 *          direction, calculate the largest white rectangle at (x, y),
 *          using previously calculated values at pixels #1 and #2:
 *             #1:    (x, y - 1)
 *             #2:    (x - 1, y)
 *          We also need the most recent "black" pixels that were seen
 *          in the current row and column.
 *          Consider the largest area.  There are only two possibilities:
 *             (a)  Min(w(1), horizdist) * (h(1) + 1)
 *             (b)  Min(h(2), vertdist) * (w(2) + 1)
 *          where
 *             horizdist: the distance from the rightmost "black" pixel seen
 *                        in the current row across to the current pixel
 *             vertdist: the distance from the lowest "black" pixel seen
 *                       in the current column down to the current pixel
 *          and we choose the Max of (a) and (b).
 *      (3) To convince yourself that these recursion relations are correct,
 *          it helps to draw the maximum rectangles at #1 and #2.
 *          Then for #1, you try to extend the rectangle down one line,
 *          so that the height is h(1) + 1.  Do you get the full
 *          width of #1, w(1)?  It depends on where the black pixels are
 *          in the current row.  You know the final width is bounded by w(1)
 *          and w(2) + 1, but the actual value depends on the distribution
 *          of black pixels in the current row that are at a distance
 *          from the current pixel that is between these limits.
 *          We call that value "horizdist", and the area is then given
 *          by the expression (a) above.  Using similar reasoning for #2,
 *          where you attempt to extend the rectangle to the right
 *          by 1 pixel, you arrive at (b).  The largest rectangle is
 *          then found by taking the Max.
 */
l_int32
pixFindLargestRectangle(PIX         *pixs,
                        l_int32      polarity,
                        BOX        **pbox,
                        const char  *debugfile)
{
l_int32    i, j, w, h, d, wpls, val;
l_int32    wp, hp, w1, w2, h1, h2, wmin, hmin, area1, area2;
l_int32    xmax, ymax;  /* LR corner of the largest rectangle */
l_int32    maxarea, wmax, hmax, vertdist, horizdist, prevfg;
l_int32   *lowestfg;
l_uint32  *datas, *lines;
l_uint32 **linew, **lineh;
BOX       *box;
PIX       *pixw, *pixh;  /* keeps the width and height for the largest */
                         /* rectangles whose LR corner is located there. */

    PROCNAME("pixFindLargestRectangle");

    if (!pbox)
        return ERROR_INT("&box not defined", procName, 1);
    *pbox = NULL;
    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1)
        return ERROR_INT("pixs not 1 bpp", procName, 1);
    if (polarity != 0 && polarity != 1)
        return ERROR_INT("invalid polarity", procName, 1);

        /* Initialize lowest "fg" seen so far for each column */
    lowestfg = (l_int32 *)CALLOC(w, sizeof(l_int32));
    for (i = 0; i < w; i++)
        lowestfg[i] = -1;

        /* The combination (val ^ polarity) is the color for which we
         * are searching for the maximum rectangle.  For polarity == 0,
         * we search in the bg (white). */
    pixw = pixCreate(w, h, 32);  /* stores width */
    pixh = pixCreate(w, h, 32);  /* stores height */
    linew = (l_uint32 **)pixGetLinePtrs(pixw, NULL);
    lineh = (l_uint32 **)pixGetLinePtrs(pixh, NULL);
    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    maxarea = xmax = ymax = wmax = hmax = 0;
    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        prevfg = -1;
        for (j = 0; j < w; j++) {
            val = GET_DATA_BIT(lines, j);
            if ((val ^ polarity) == 0) {  /* bg (0) if polarity == 0, etc. */
                if (i == 0 && j == 0) {
                    wp = hp = 1;
                }
                else if (i == 0) {
                    wp = linew[i][j - 1] + 1;
                    hp = 1;
                }
                else if (j == 0) {
                    wp = 1;
                    hp = lineh[i - 1][j] + 1;
                }
                else {
                        /* Expand #1 prev rectangle down */
                    w1 = linew[i - 1][j];
                    h1 = lineh[i - 1][j];
                    horizdist = j - prevfg;
                    wmin = L_MIN(w1, horizdist);  /* width of new rectangle */
                    area1 = wmin * (h1 + 1);

                        /* Expand #2 prev rectangle to right */
                    w2 = linew[i][j - 1];
                    h2 = lineh[i][j - 1];
                    vertdist = i - lowestfg[j];
                    hmin = L_MIN(h2, vertdist);  /* height of new rectangle */
                    area2 = hmin * (w2 + 1);

                    if (area1 > area2) {
                         wp = wmin;
                         hp = h1 + 1;
                    }
                    else {
                         wp = w2 + 1;
                         hp = hmin;
                    }
                }
            }
            else {  /* fg (1) if polarity == 0; bg (0) if polarity == 1 */
                prevfg = j;
                lowestfg[j] = i;
                wp = hp = 0;
            }
            linew[i][j] = wp;
            lineh[i][j] = hp;
            if (wp * hp > maxarea) {
                maxarea = wp * hp;
                xmax = j;
                ymax = i;
                wmax = wp;
                hmax = hp;
            }
        }
    }

        /* Translate from LR corner to Box coords (UL corner, w, h) */
    box = boxCreate(xmax - wmax + 1, ymax - hmax + 1, wmax, hmax);
    *pbox = box;

    if (debugfile) {
        PIX  *pixdb;
        pixdb = pixConvertTo8(pixs, TRUE);
        pixRenderHashBoxArb(pixdb, box, 6, 2, L_NEG_SLOPE_LINE, 1, 255, 0, 0);
        pixWrite(debugfile, pixdb, IFF_PNG);
        pixDestroy(&pixdb);
    }
 
    FREE(linew);
    FREE(lineh);
    FREE(lowestfg);
    pixDestroy(&pixw);
    pixDestroy(&pixh);
    return 0;
}