Пример #1
0
jboolean Java_com_googlecode_leptonica_android_Pixa_nativeWriteToFileRandomCmap(JNIEnv *env,
                                                                           jclass clazz,
                                                                           jint nativePixa,
                                                                           jstring fileName,
                                                                           jint width, jint height) {
  LOGV(__FUNCTION__);

  PIX *pixtemp;
  PIXA *pixa = (PIXA *) nativePixa;

  const char *c_fileName = env->GetStringUTFChars(fileName, NULL);
  if (c_fileName == NULL) {
    LOGE("could not extract fileName string!");
    return JNI_FALSE;
  }

  if (pixaGetCount(pixa) > 0) {
    pixtemp = pixaDisplayRandomCmap(pixa, (l_int32) width, (l_int32) height);
  } else {
    pixtemp = pixCreate((l_int32) width, (l_int32) height, 1);
  }

  pixWrite(c_fileName, pixtemp, IFF_BMP);
  pixDestroy(&pixtemp);

  env->ReleaseStringUTFChars(fileName, c_fileName);

  return JNI_TRUE;
}
Пример #2
0
PIX *
MakeColorWash(l_int32  w,
              l_int32  h,
              l_int32  color)
{
l_int32    i, j, wpl;
l_uint32   val;
l_uint32  *data, *line;
PIX       *pixd;

    pixd = pixCreate(w, h, 32);
    data = pixGetData(pixd);
    wpl = pixGetWpl(pixd);
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        for (j = 0; j < w; j++) {
            if (color == COLOR_RED)
                val = ((j * 255) / w) << L_GREEN_SHIFT |
                      ((j * 255) / w) << L_BLUE_SHIFT |
                      255 << L_RED_SHIFT;
            else if (color == COLOR_GREEN)
                val = ((j * 255) / w) << L_RED_SHIFT |
                      ((j * 255) / w) << L_BLUE_SHIFT |
                      255 << L_GREEN_SHIFT;
            else
                val = ((j * 255) / w) << L_RED_SHIFT |
                      ((j * 255) / w) << L_GREEN_SHIFT |
                      255 << L_BLUE_SHIFT;
            line[j] = val;
        }
    }
    return pixd;
}
/*!
 *  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;
}
Пример #4
0
main(int    argc,
     char **argv)
{
l_int32      i, j, w, h, same, width, height, cx, cy;
l_uint32     val;
PIX         *pixs, *pixse, *pixd1, *pixd2;
SEL         *sel;
static char  mainName[] = "rasterop_reg";

    if (argc != 1)
	return ERROR_INT(" Syntax:  rasterop_reg", mainName, 1);
    pixs = pixRead("feyn.tif");

    for (width = 1; width <= 25; width += 3) {
	for (height = 1; height <= 25; height += 4) {

	    cx = width / 2;
	    cy = height / 2;

		/* Dilate using an actual sel */
	    sel = selCreateBrick(height, width, cy, cx, SEL_HIT);
	    pixd1 = pixDilate(NULL, pixs, sel);

		/* Dilate using a pix as a sel */
	    pixse = pixCreate(width, height, 1);
	    pixSetAll(pixse);
	    pixd2 = pixCopy(NULL, pixs);
	    w = pixGetWidth(pixs);
	    h = pixGetHeight(pixs);
	    for (i = 0; i < h; i++) {
		for (j = 0; j < w; j++) {
		    pixGetPixel(pixs, j, i, &val);
		    if (val)
			pixRasterop(pixd2, j - cx, i - cy, width, height,
				    PIX_SRC | PIX_DST, pixse, 0, 0);
		}
	    }

	    pixEqual(pixd1, pixd2, &same);
	    if (same == 1)
		fprintf(stderr, "Correct for (%d,%d)\n", width, height);
	    else {
		fprintf(stderr, "Error: results are different!\n");
		fprintf(stderr, "SE: width = %d, height = %d\n", width, height);
		pixWrite("/tmp/junkout1", pixd1, IFF_PNG);
		pixWrite("/tmp/junkout2", pixd2, IFF_PNG);
                return 1;
	    }

	    pixDestroy(&pixse);
	    pixDestroy(&pixd1);
	    pixDestroy(&pixd2);
	    selDestroy(&sel);
	}
    }
    pixDestroy(&pixs);
    return 0;
}
Пример #5
0
/*!
 *  pixEmbedForRotation()
 *
 *      Input:  pixs (1, 2, 4, 8, 32 bpp rgb)
 *              angle (radians; clockwise is positive)
 *              incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK)
 *              width (original width; use 0 to avoid embedding)
 *              height (original height; use 0 to avoid embedding)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) For very small rotations, just return a clone.
 *      (2) Generate larger image to embed pixs if necessary, and
 *          place the center of the input image in the center.
 *      (3) Rotation brings either white or black pixels in
 *          from outside the image.  For colormapped images where
 *          there is no white or black, a new color is added if
 *          possible for these pixels; otherwise, either the
 *          lightest or darkest color is used.  In most cases,
 *          the colormap will be removed prior to rotation.
 *      (4) The dest is to be expanded so that no image pixels
 *          are lost after rotation.  Input of the original width
 *          and height allows the expansion to stop at the maximum
 *          required size, which is a square with side equal to
 *          sqrt(w*w + h*h).
 *      (5) For an arbitrary angle, the expansion can be found by
 *          considering the UL and UR corners.  As the image is
 *          rotated, these move in an arc centered at the center of
 *          the image.  Normalize to a unit circle by dividing by half
 *          the image diagonal.  After a rotation of T radians, the UL
 *          and UR corners are at points T radians along the unit
 *          circle.  Compute the x and y coordinates of both these
 *          points and take the max of absolute values; these represent
 *          the half width and half height of the containing rectangle.
 *          The arithmetic is done using formulas for sin(a+b) and cos(a+b),
 *          where b = T.  For the UR corner, sin(a) = h/d and cos(a) = w/d.
 *          For the UL corner, replace a by (pi - a), and you have
 *          sin(pi - a) = h/d, cos(pi - a) = -w/d.  The equations
 *          given below follow directly.
 */
PIX *
pixEmbedForRotation(PIX       *pixs,
                    l_float32  angle,
                    l_int32    incolor,
                    l_int32    width,
                    l_int32    height)
{
l_int32    w, h, d, w1, h1, w2, h2, maxside, wnew, hnew, xoff, yoff, setcolor;
l_float64  sina, cosa, fw, fh;
PIX       *pixd;

    PROCNAME("pixEmbedForRotation");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
        return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
    if (L_ABS(angle) < MIN_ANGLE_TO_ROTATE)
        return pixClone(pixs);

        /* Test if big enough to hold any rotation of the original image */
    pixGetDimensions(pixs, &w, &h, &d);
    maxside = (l_int32)(sqrt((l_float64)(width * width) +
                             (l_float64)(height * height)) + 0.5);
    if (w >= maxside && h >= maxside)  /* big enough */
        return pixClone(pixs);

        /* Find the new sizes required to hold the image after rotation.
         * Note that the new dimensions must be at least as large as those
         * of pixs, because we're rasterop-ing into it before rotation. */
    cosa = cos(angle);
    sina = sin(angle);
    fw = (l_float64)w;
    fh = (l_float64)h;
    w1 = (l_int32)(L_ABS(fw * cosa - fh * sina) + 0.5);
    w2 = (l_int32)(L_ABS(-fw * cosa - fh * sina) + 0.5);
    h1 = (l_int32)(L_ABS(fw * sina + fh * cosa) + 0.5);
    h2 = (l_int32)(L_ABS(-fw * sina + fh * cosa) + 0.5);
    wnew = L_MAX(w, L_MAX(w1, w2));
    hnew = L_MAX(h, L_MAX(h1, h2));

    if ((pixd = pixCreate(wnew, hnew, d)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    pixCopyResolution(pixd, pixs);
    pixCopyColormap(pixd, pixs);
    pixCopySpp(pixd, pixs);
    pixCopyText(pixd, pixs);
    xoff = (wnew - w) / 2;
    yoff = (hnew - h) / 2;

        /* Set background to color to be rotated in */
    setcolor = (incolor == L_BRING_IN_BLACK) ? L_SET_BLACK : L_SET_WHITE;
    pixSetBlackOrWhite(pixd, setcolor);

        /* Rasterop automatically handles all 4 channels for rgba */
    pixRasterop(pixd, xoff, yoff, w, h, PIX_SRC, pixs, 0, 0);
    return pixd;
}
Пример #6
0
jint Java_com_googlecode_leptonica_android_ReadFile_nativeReadBitmap(JNIEnv *env,
    jclass clazz,
    jobject bitmap) {
  //LOGV(__FUNCTION__);

  l_int32 w, h, d;
  AndroidBitmapInfo info;
  void* pixels;
  int ret;

  if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
    LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
    return JNI_FALSE;
  }

  if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
    LOGE("Bitmap format is not RGBA_8888 !");
    return JNI_FALSE;
  }

  if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
    LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    return JNI_FALSE;
  }

  PIX *pixd = pixCreate(info.width, info.height, 8);

  l_uint32 *src = (l_uint32 *) pixels;
  l_int32 srcWpl = (info.stride / 4);
  l_uint32 *dst = pixGetData(pixd);
  l_int32 dstWpl = pixGetWpl(pixd);
  l_uint8 a, r, g, b, pixel8;

  for (int y = 0; y < info.height; y++) {
    l_uint32 *dst_line = dst + (y * dstWpl);
    l_uint32 *src_line = src + (y * srcWpl);

    for (int x = 0; x < info.width; x++) {
      // Get pixel from RGBA_8888
      r = *src_line >> SK_R32_SHIFT;
      g = *src_line >> SK_G32_SHIFT;
      b = *src_line >> SK_B32_SHIFT;
      a = *src_line >> SK_A32_SHIFT;
      pixel8 = (l_uint8) ((r + g + b) / 3);

      // Set pixel to LUMA_8
      SET_DATA_BYTE(dst_line, x, pixel8);

      // Move to the next pixel
      src_line++;
    }
  }

  AndroidBitmap_unlockPixels(env, bitmap);

  return (jint) pixd;
}
Пример #7
0
/*!
 *  pixRasteropHip()
 *
 *      Input:  pixd (in-place operation)
 *              by  (top of horizontal band)
 *              bh  (height of horizontal band)
 *              hshift (horizontal shift of band; hshift > 0 is to right)
 *              incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK)
 *      Return: 0 if OK; 1 on error
 *
 *  Notes:
 *      (1) This rasterop translates a horizontal band of the
 *          image either left or right, bringing in either white
 *          or black pixels from outside the image.
 *      (2) The horizontal band extends the full width of pixd.
 *      (3) If a colormap exists, the nearest color to white or black
 *          is brought in.
 */
l_int32
pixRasteropHip(PIX     *pixd,
               l_int32  by,
               l_int32  bh,
               l_int32  hshift,
               l_int32  incolor)
{
l_int32   w, h, d, index, op;
PIX      *pixt;
PIXCMAP  *cmap;

    PROCNAME("pixRasteropHip");

    if (!pixd)
        return ERROR_INT("pixd not defined", procName, 1);
    if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
        return ERROR_INT("invalid value for incolor", procName, 1);
    if (bh <= 0)
        return ERROR_INT("bh must be > 0", procName, 1);

    if (hshift == 0)
        return 0;

    pixGetDimensions(pixd, &w, &h, &d);
    rasteropHipLow(pixGetData(pixd), h, d, pixGetWpl(pixd), by, bh, hshift);

    cmap = pixGetColormap(pixd);
    if (!cmap) {
        if ((d == 1 && incolor == L_BRING_IN_BLACK) ||
            (d > 1 && incolor == L_BRING_IN_WHITE))
            op = PIX_SET;
        else
            op = PIX_CLR;

            /* Set the pixels brought in at left or right */
        if (hshift > 0)
            pixRasterop(pixd, 0, by, hshift, bh, op, NULL, 0, 0);
        else  /* hshift < 0 */
            pixRasterop(pixd, w + hshift, by, -hshift, bh, op, NULL, 0, 0);
        return 0;
    }

        /* Get the nearest index and fill with that */
    if (incolor == L_BRING_IN_BLACK)
        pixcmapGetRankIntensity(cmap, 0.0, &index);
    else  /* white */
        pixcmapGetRankIntensity(cmap, 1.0, &index);
    pixt = pixCreate(L_ABS(hshift), bh, d);
    pixSetAllArbitrary(pixt, index);
    if (hshift > 0)
        pixRasterop(pixd, 0, by, hshift, bh, PIX_SRC, pixt, 0, 0);
    else  /* hshift < 0 */
        pixRasterop(pixd, w + hshift, by, -hshift, bh, PIX_SRC, pixt, 0, 0);
    pixDestroy(&pixt);
    return 0;
}
Пример #8
0
jint Java_com_googlecode_leptonica_android_ReadFile_nativeReadBitmap(JNIEnv *env,
    jclass clazz,
    jobject bitmap) {
  LOGV(__FUNCTION__);

  l_int32 w, h, d;
  AndroidBitmapInfo info;
  void* pixels;
  int ret;

  if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
    LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
    return JNI_FALSE;
  }

  if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
    LOGE("Bitmap format is not RGBA_8888 !");
    return JNI_FALSE;
  }

  if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
    LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    return JNI_FALSE;
  }

  PIX *pix = pixCreate(info.width, info.height, 8);

  l_uint8 *src = (l_uint8 *) pixels;
  l_uint8 *dst = (l_uint8 *) pixGetData(pixs);
  l_int32 srcBpl = info.stride;
  l_int32 dstBpl = 4 * pixGetWpl(pixs);
  l_uint8 a, r, g, b;

  SET_PIXEL = SET_PIXEL_8;

  for (int y = 0; y < info.height; y++) {
    l_uint8 *dst_line = dst + (y * dstBpl);
    l_uint8 *src_line = src + (y * srcBpl);

    for (int x = 0; x < info.width; x++) {
      // Get pixel from ARGB_8888
      r = *src_line++;
      g = *src_line++;
      b = *src_line++;
      a = *src_line++;

      // Set pixel to LUMA_8
      *dst_line = (l_uint8) ((r + g + b) / 3);
    }
  }

  AndroidBitmap_unlockPixels(env, bitmap);

  return (jint) pix;
}
Пример #9
0
/*!
 * \brief   pixColorSegmentCluster()
 *
 * \param[in]    pixs  32 bpp; 24-bit color
 * \param[in]    maxdist max euclidean dist to existing cluster
 * \param[in]    maxcolors max number of colors allowed in first pass
 * \param[in]    debugflag  1 for debug output; 0 otherwise
 * \return  pixd 8 bit with colormap, or NULL on error
 *
 * <pre>
 * Notes:
 *      (1) This is phase 1.  See description in pixColorSegment().
 *      (2) Greedy unsupervised classification.  If the limit 'maxcolors'
 *          is exceeded, the computation is repeated with a larger
 *          allowed cluster size.
 *      (3) On each successive iteration, 'maxdist' is increased by a
 *          constant factor.  See comments in pixColorSegment() for
 *          a guideline on parameter selection.
 *          Note that the diagonal of the 8-bit rgb color cube is about
 *          440, so for 'maxdist' = 440, you are guaranteed to get 1 color!
 * </pre>
 */
PIX *
pixColorSegmentCluster(PIX     *pixs,
                       l_int32  maxdist,
                       l_int32  maxcolors,
                       l_int32  debugflag)
{
l_int32   w, h, newmaxdist, ret, niters, ncolors, success;
PIX      *pixd;
PIXCMAP  *cmap;

    PROCNAME("pixColorSegmentCluster");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 32)
        return (PIX *)ERROR_PTR("must be rgb color", procName, NULL);

    pixGetDimensions(pixs, &w, &h, NULL);
    if ((pixd = pixCreate(w, h, 8)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    cmap = pixcmapCreate(8);
    pixSetColormap(pixd, cmap);
    pixCopyResolution(pixd, pixs);

    newmaxdist = maxdist;
    niters = 0;
    success = TRUE;
    while (1) {
        ret = pixColorSegmentTryCluster(pixd, pixs, newmaxdist,
                                        maxcolors, debugflag);
        niters++;
        if (!ret) {
            ncolors = pixcmapGetCount(cmap);
            if (debugflag)
                L_INFO("Success with %d colors after %d iters\n", procName,
                       ncolors, niters);
            break;
        }
        if (niters == MAX_ALLOWED_ITERATIONS) {
            L_WARNING("too many iters; newmaxdist = %d\n",
                      procName, newmaxdist);
            success = FALSE;
            break;
        }
        newmaxdist = (l_int32)(DIST_EXPAND_FACT * (l_float32)newmaxdist);
    }

    if (!success) {
        pixDestroy(&pixd);
        return (PIX *)ERROR_PTR("failure in phase 1", procName, NULL);
    }

    return pixd;
}
Пример #10
0
/*!
 *  pixaDisplayRandomCmap()
 *
 *      Input:  pixa (of 1 bpp components, with boxa)
 *              w, h (if set to 0, determines the size from the
 *                    b.b. of the components in pixa)
 *      Return: pix (8 bpp, cmapped, with random colors on the components),
 *              or null on error
 *
 *  Notes:
 *      (1) This uses the boxes to place each pix in the rendered composite.
 *      (2) By default, the background color is: black, cmap index 0.
 *          This can be changed by pixcmapResetColor()
 */
PIX *
pixaDisplayRandomCmap(PIXA    *pixa,
                      l_int32  w,
                      l_int32  h)
{
l_int32   i, n, d, index, xb, yb, wb, hb;
BOXA     *boxa;
PIX      *pixs, *pixt, *pixd;
PIXCMAP  *cmap;

    PROCNAME("pixaDisplayRandomCmap");

    if (!pixa)
        return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
    
    n = pixaGetCount(pixa);
    if (n == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);

        /* Use the first pix in pixa to verify depth is 1 bpp  */
    pixs = pixaGetPix(pixa, 0, L_CLONE);
    d = pixGetDepth(pixs);
    pixDestroy(&pixs);
    if (d != 1)
        return (PIX *)ERROR_PTR("components not 1 bpp", procName, NULL);

        /* If w and h not input, determine the minimum size required
         * to contain the origin and all c.c. */
    if (w == 0 || h == 0) {
        boxa = pixaGetBoxa(pixa, L_CLONE);
        boxaGetExtent(boxa, &w, &h, NULL);
        boxaDestroy(&boxa);
    }

        /* Set up an 8 bpp dest pix, with a colormap with 254 random colors */
    if ((pixd = pixCreate(w, h, 8)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    cmap = pixcmapCreateRandom(8, 1, 1);
    pixSetColormap(pixd, cmap);

        /* Color each component and blit it in */
    for (i = 0; i < n; i++) {
        index = 1 + (i % 254);
        pixaGetBoxGeometry(pixa, i, &xb, &yb, &wb, &hb);
        pixs = pixaGetPix(pixa, i, L_CLONE);
        pixt = pixConvert1To8(NULL, pixs, 0, index);
        pixRasterop(pixd, xb, yb, wb, hb, PIX_PAINT, pixt, 0, 0);
        pixDestroy(&pixs);
        pixDestroy(&pixt);
    }

    return pixd;
}
/*!
 *  pixMaxDynamicRange()
 *
 *      Input:  pixs  (4, 8, 16 or 32 bpp source)
 *              type  (L_LINEAR_SCALE or L_LOG_SCALE)
 *      Return: pixd (8 bpp), or null on error
 *
 *  Notes:
 *      (1) Scales pixel values to fit maximally within the dest 8 bpp pixd
 *      (2) Uses a LUT for log scaling
 */
PIX *
pixMaxDynamicRange(PIX     *pixs,
                   l_int32  type)
{
l_uint8     dval;
l_int32     i, j, w, h, d, wpls, wpld, max, sval;
l_uint32   *datas, *datad;
l_uint32    word;
l_uint32   *lines, *lined;
l_float32   factor;
l_float32  *tab;
PIX        *pixd;

    PROCNAME("pixMaxDynamicRange");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    d = pixGetDepth(pixs);
    if (d != 4 && d != 8 && d != 16 && d != 32)
        return (PIX *)ERROR_PTR("pixs not in {4,8,16,32} bpp", procName, NULL);
    if (type != L_LINEAR_SCALE && type != L_LOG_SCALE)
        return (PIX *)ERROR_PTR("invalid type", procName, NULL);

    pixGetDimensions(pixs, &w, &h, NULL);
    if ((pixd = pixCreate(w, h, 8)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    pixCopyResolution(pixd, pixs);
    datas = pixGetData(pixs);
    datad = pixGetData(pixd);
    wpls = pixGetWpl(pixs);
    wpld = pixGetWpl(pixd);

        /* Get max */
    max = 0;
    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        for (j = 0; j < wpls; j++) {
            word = *(lines + j);
            if (d == 4) {
                max = L_MAX(max, word >> 28);
                max = L_MAX(max, (word >> 24) & 0xf);
                max = L_MAX(max, (word >> 20) & 0xf);
                max = L_MAX(max, (word >> 16) & 0xf);
                max = L_MAX(max, (word >> 12) & 0xf);
                max = L_MAX(max, (word >> 8) & 0xf);
                max = L_MAX(max, (word >> 4) & 0xf);
                max = L_MAX(max, word & 0xf);
            } else if (d == 8) {
                max = L_MAX(max, word >> 24);
                max = L_MAX(max, (word >> 16) & 0xff);
                max = L_MAX(max, (word >> 8) & 0xff);
                max = L_MAX(max, word & 0xff);
            } else if (d == 16) {
Пример #12
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;
}
Пример #13
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;
}
Пример #14
0
// Make a Pix of the correct scaled size for the TraceOutline functions.
Pix* GridReducedPix(const TBOX& box, int gridsize,
                    ICOORD bleft, int* left, int* bottom) {
  // Compute grid bounds of the outline and pad all round by 1.
  int grid_left = (box.left() - bleft.x()) / gridsize - 1;
  int grid_bottom = (box.bottom() - bleft.y()) / gridsize - 1;
  int grid_right = (box.right() - bleft.x()) / gridsize + 1;
  int grid_top = (box.top() - bleft.y()) / gridsize + 1;
  *left = grid_left;
  *bottom = grid_bottom;
  return pixCreate(grid_right - grid_left + 1,
                   grid_top - grid_bottom + 1,
                   1);
}
Пример #15
0
/*!
 *  wshedCreate()
 *
 *      Input:  pixs  (8 bpp source)
 *              pixm  (1 bpp 'marker' seed)
 *              mindepth (minimum depth; anything less is not saved)
 *              debugflag (1 for debug output)
 *      Return: WShed, or null on error
 *
 *  Notes:
 *      (1) It is not necessary for the fg pixels in the seed image
 *          be at minima, or that they be isolated.  We extract a
 *          single pixel from each connected component, and a seed
 *          anywhere in a watershed will eventually label the watershed
 *          when the filling level reaches it.
 *      (2) Set mindepth to some value to ignore noise in pixs that
 *          can create small local minima.  Any watershed shallower
 *          than mindepth, even if it has a seed, will not be saved;
 *          It will either be incorporated in another watershed or
 *          eliminated.
 */
L_WSHED *
wshedCreate(PIX     *pixs,
            PIX     *pixm,
            l_int32  mindepth,
            l_int32  debugflag)
{
l_int32   w, h;
L_WSHED  *wshed;

    PROCNAME("wshedCreate");

    if (!pixs)
        return (L_WSHED *)ERROR_PTR("pixs is not defined", procName, NULL);
    if (pixGetDepth(pixs) != 8)
        return (L_WSHED *)ERROR_PTR("pixs is not 8 bpp", procName, NULL);
    if (!pixm)
        return (L_WSHED *)ERROR_PTR("pixm is not defined", procName, NULL);
    if (pixGetDepth(pixm) != 1)
        return (L_WSHED *)ERROR_PTR("pixm is not 1 bpp", procName, NULL);
    pixGetDimensions(pixs, &w, &h, NULL);
    if (pixGetWidth(pixm) != w || pixGetHeight(pixm) != h)
        return (L_WSHED *)ERROR_PTR("pixs/m sizes are unequal", procName, NULL);

    if ((wshed = (L_WSHED *)CALLOC(1, sizeof(L_WSHED))) == NULL)
        return (L_WSHED *)ERROR_PTR("wshed not made", procName, NULL);

    wshed->pixs = pixClone(pixs);
    wshed->pixm = pixClone(pixm);
    wshed->mindepth = L_MAX(1, mindepth);
    wshed->pixlab = pixCreate(w, h, 32);
    pixSetAllArbitrary(wshed->pixlab, MAX_LABEL_VALUE);
    wshed->pixt = pixCreate(w, h, 1);
    wshed->lines8 = pixGetLinePtrs(pixs, NULL);
    wshed->linem1 = pixGetLinePtrs(pixm, NULL);
    wshed->linelab32 = pixGetLinePtrs(wshed->pixlab, NULL);
    wshed->linet1 = pixGetLinePtrs(wshed->pixt, NULL);
    wshed->debug = debugflag;
    return wshed;
}
Пример #16
0
/*!
 *  pixConnCompTransform()
 *
 *      Input:   pixs (1 bpp)
 *               connect (connectivity: 4 or 8)
 *               depth (of pixd: 8 or 16 bpp; use 0 for auto determination)
 *      Return:  pixd (8 or 16 bpp), or null on error
 *
 *  Notes:
 *      (1) pixd is 8 or 16 bpp, and the pixel values label the fg component,
 *          starting with 1.  Pixels in the bg are labelled 0.
 *      (2) If @depth = 0, the depth of pixd is 8 if the number of c.c.
 *          is less than 254, and 16 otherwise.
 *      (3) If @depth = 8, the assigned label for the n-th component is
 *          1 + n % 254.  We use mod 254 because 0 is uniquely assigned
 *          to black: e.g., see pixcmapCreateRandom().  Likewise,
 *          if @depth = 16, the assigned label uses mod(2^16 - 2).
 */
PIX *
pixConnCompTransform(PIX     *pixs,
                     l_int32  connect,
                     l_int32  depth)
{
l_int32  i, n, index, w, h, xb, yb, wb, hb;
BOXA    *boxa;
PIX     *pix1, *pix2, *pixd;
PIXA    *pixa;

    PROCNAME("pixConnCompTransform");

    if (!pixs || pixGetDepth(pixs) != 1)
        return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
    if (connect != 4 && connect != 8)
        return (PIX *)ERROR_PTR("connectivity must be 4 or 8", procName, NULL);
    if (depth != 0 && depth != 8 && depth != 16)
        return (PIX *)ERROR_PTR("depth must be 0, 8 or 16", procName, NULL);

    boxa = pixConnComp(pixs, &pixa, connect);
    n = pixaGetCount(pixa);
    boxaDestroy(&boxa);
    pixGetDimensions(pixs, &w, &h, NULL);
    if (depth == 0) {
        depth = (n < 254) ? 8 : 16;
    }
    pixd = pixCreate(w, h, depth);
    if (n == 0) {  /* no fg */
        pixaDestroy(&pixa);
        return pixd;
    }

       /* Label each component and blit it in */
    for (i = 0; i < n; i++) {
        pixaGetBoxGeometry(pixa, i, &xb, &yb, &wb, &hb);
        pix1 = pixaGetPix(pixa, i, L_CLONE);
        if (depth == 8) {
            index = 1 + (i % 254);
            pix2 = pixConvert1To8(NULL, pix1, 0, index);
        } else {  /* depth == 16 */
            index = 1 + (i % 0xfffe);
            pix2 = pixConvert1To16(NULL, pix1, 0, index);
        }
        pixRasterop(pixd, xb, yb, wb, hb, PIX_PAINT, pix2, 0, 0);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }

    pixaDestroy(&pixa);
    return pixd;
}
Пример #17
0
static PIX *
DisplayBoxa(BOXA  *boxa)
{
l_int32  w, h;
BOX     *box;
PIX     *pix1, *pix2, *pix3;
PIXA    *pixa;

    pixa = pixaCreate(2);
    boxaGetExtent(boxa, &w, &h, &box);
    pix1 = pixCreate(w, h, 1);
    pixMaskBoxa(pix1, pix1, boxa, L_SET_PIXELS);
    pixaAddPix(pixa, pix1, L_INSERT);
    pix2 = pixCreate(w, h, 32);
    pixSetAll(pix2);
    pixRenderBoxaArb(pix2, boxa, 2, 0, 255, 0);
    pixRenderBoxArb(pix2, box, 3, 255, 0, 0);
    pixaAddPix(pixa, pix2, L_INSERT);
    pix3 = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 30, 2);
    boxDestroy(&box);
    pixaDestroy(&pixa);
    return pix3;
}
Пример #18
0
/*!
 *  boxaGetCoverage()
 *
 *      Input:  boxa
 *              wc, hc (dimensions of overall clipping rectangle with UL
 *                      corner at (0, 0) that is covered by the boxes.
 *              exactflag (1 for guaranteeing an exact result; 0 for getting
 *                         an exact result only if the boxes do not overlap)
 *              &fract (<return> sum of box area as fraction of w * h)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) The boxes in boxa are clipped to the input rectangle.
 *      (2) * When @exactflag == 1, we generate a 1 bpp pix of size
 *            wc x hc, paint all the boxes black, and count the fg pixels.
 *            This can take 1 msec on a large page with many boxes.
 *          * When @exactflag == 0, we clip each box to the wc x hc region
 *            and sum the resulting areas.  This is faster.
 *          * The results are the same when none of the boxes overlap
 *            within the wc x hc region.
 */
l_int32
boxaGetCoverage(BOXA       *boxa,
                l_int32     wc,
                l_int32     hc,
                l_int32     exactflag,
                l_float32  *pfract)
{
l_int32  i, n, x, y, w, h, sum;
BOX     *box, *boxc;
PIX     *pixt;

    PROCNAME("boxaGetCoverage");

    if (!pfract)
        return ERROR_INT("&fract not defined", procName, 1);
    *pfract = 0.0;
    if (!boxa)
        return ERROR_INT("boxa not defined", procName, 1);

    n = boxaGetCount(boxa);
    if (n == 0)
        return ERROR_INT("no boxes in boxa", procName, 1);

    if (exactflag == 0) {  /* quick and dirty */
        sum = 0;
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxa, i, L_CLONE);
            if ((boxc = boxClipToRectangle(box, wc, hc)) != NULL) {
                boxGetGeometry(boxc, NULL, NULL, &w, &h);
                sum += w * h;
                boxDestroy(&boxc);
            }
            boxDestroy(&box);
        }
    }
    else {  /* slower and exact */
        pixt = pixCreate(wc, hc, 1);
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxa, i, L_CLONE);
            boxGetGeometry(box, &x, &y, &w, &h);
            pixRasterop(pixt, x, y, w, h, PIX_SET, NULL, 0, 0);
            boxDestroy(&box);
        }
        pixCountPixels(pixt, &sum, NULL);
        pixDestroy(&pixt);
    }

    *pfract = (l_float32)sum / (l_float32)(wc * hc);
    return 0;
}
Пример #19
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;
}
Пример #20
0
/*!
 *  fpixDisplayMaxDynamicRange()
 *
 *      Input:  fpixs
 *      Return: pixd (8 bpp), or null on error
 */
PIX *
fpixDisplayMaxDynamicRange(FPIX  *fpixs)
{
l_uint8     dval;
l_int32     i, j, w, h, wpls, wpld;
l_float32   factor, sval, maxval;
l_float32  *lines, *datas;
l_uint32   *lined, *datad;
PIX        *pixd;

    PROCNAME("fpixDisplayMaxDynamicRange");

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

    fpixGetDimensions(fpixs, &w, &h);
    datas = fpixGetData(fpixs);
    wpls = fpixGetWpl(fpixs);

    maxval = 0.0;
    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        for (j = 0; j < w; j++) {
            sval = *(lines + j);
            if (sval > maxval)
                maxval = sval;
        }
    }

    pixd = pixCreate(w, h, 8);
    if (maxval == 0.0)
        return pixd;  /* all pixels are 0 */

    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);
    factor = 255. / maxval;
    for (i = 0; i < h; i++) {
	lines = datas + i * wpls;
	lined = datad + i * wpld;
	for (j = 0; j < w; j++) {
	    sval = *(lines + j);
	    if (sval < 0.0) sval = 0.0;
	    dval = (l_uint8)(factor * sval + 0.5);
	    SET_DATA_BYTE(lined, j, dval);
	}
    }

    return pixd;
}
Пример #21
0
/*!
 *  pixaDisplayUnsplit()
 *
 *      Input:  pixa
 *              nx   (number of mosaic cells horizontally)
 *              ny   (number of mosaic cells vertically)
 *              borderwidth  (of added border on all sides)
 *              bordercolor  (in our RGBA format: 0xrrggbbaa)
 *      Return: pix of tiled images, or null on error
 *
 *  Notes:
 *      (1) This is a logical inverse of pixaSplitPix().  It
 *          constructs a pix from a mosaic of tiles, all of equal size.
 *      (2) For added generality, a border of arbitrary color can
 *          be added to each of the tiles.
 *      (3) In use, pixa will typically have either been generated
 *          from pixaSplitPix() or will derived from a pixa that
 *          was so generated.
 *      (4) All pix in the pixa must be of equal depth, and, if
 *          colormapped, have the same colormap.
 */
PIX *
pixaDisplayUnsplit(PIXA     *pixa,
                   l_int32   nx,
                   l_int32   ny,
                   l_int32   borderwidth,
                   l_uint32  bordercolor)
{
l_int32  w, h, d, wt, ht;
l_int32  i, j, k, x, y, n;
PIX     *pixt, *pixd;

    PROCNAME("pixaDisplayUnsplit");

    if (!pixa)
        return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
    if (nx <= 0 || ny <= 0)
        return (PIX *)ERROR_PTR("nx and ny must be > 0", procName, NULL);
    if ((n = pixaGetCount(pixa)) == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);
    if (n != nx * ny)
        return (PIX *)ERROR_PTR("n != nx * ny", procName, NULL);
    borderwidth = L_MAX(0, borderwidth);

    pixaGetPixDimensions(pixa, 0, &wt, &ht, &d);
    w = nx * (wt + 2 * borderwidth);
    h = ny * (ht + 2 * borderwidth);

    if ((pixd = pixCreate(w, h, d)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    pixt = pixaGetPix(pixa, 0, L_CLONE);
    pixCopyColormap(pixd, pixt);
    pixDestroy(&pixt);
    if (borderwidth > 0)
        pixSetAllArbitrary(pixd, bordercolor);

    y = borderwidth;
    for (i = 0, k = 0; i < ny; i++) {
        x = borderwidth;
        for (j = 0; j < nx; j++, k++) {
            pixt = pixaGetPix(pixa, k, L_CLONE);
            pixRasterop(pixd, x, y, wt, ht, PIX_SRC, pixt, 0, 0);
            pixDestroy(&pixt);
            x += wt + 2 * borderwidth;
        }
        y += ht + 2 * borderwidth;
    }

    return pixd;
}
Пример #22
0
/*!
 *  pixDeserializeFromMemory()
 *
 *      Input:  data (serialized data in memory)
 *              nbytes (number of bytes in data string)
 *      Return: pix, or NULL on error
 *
 *  Notes:
 *      (1) See pixSerializeToMemory() for the binary format.
 */
PIX *
pixDeserializeFromMemory(const l_uint32  *data,
                         size_t           nbytes)
{
char      *id;
l_int32    w, h, d, imdatasize, ncolors;
l_uint32  *imdata;  /* data in pix raster */
PIX       *pixd;
PIXCMAP   *cmap;

    PROCNAME("pixDeserializeFromMemory");

    if (!data)
        return (PIX *)ERROR_PTR("data not defined", procName, NULL);
    if (nbytes < 28)
        return (PIX *)ERROR_PTR("invalid data", procName, NULL);

    id = (char *)data;
    if (id[0] != 's' || id[1] != 'p' || id[2] != 'i' || id[3] != 'x')
        return (PIX *)ERROR_PTR("invalid id string", procName, NULL);
    w = data[1];
    h = data[2];
    d = data[3];
    if ((pixd = pixCreate(w, h, d)) == NULL)
        return (PIX *)ERROR_PTR("pix not made", procName, NULL);

    ncolors = data[5];
    if (ncolors > 0) {
        cmap = pixcmapDeserializeFromMemory((l_uint8 *)(&data[6]), 4, ncolors);
        if (!cmap)
            return (PIX *)ERROR_PTR("cmap not made", procName, NULL);
        pixSetColormap(pixd, cmap);
    }

    imdata = pixGetData(pixd);
    imdatasize = nbytes - 24 - 4 * ncolors - 4;
    if (imdatasize != data[6 + ncolors])
        L_ERROR("imdatasize is inconsistent with nbytes\n", procName);
    memcpy((char *)imdata, (char *)(data + 7 + ncolors), imdatasize);

#if  DEBUG_SERIALIZE
    fprintf(stderr, "Deserialize: "
            "raster size = %d, ncolors in cmap = %d, total bytes = %lu\n",
            imdatasize, ncolors, nbytes);
#endif  /* DEBUG_SERIALIZE */

    return pixd;
}
Пример #23
0
int main(int argc, char** argv) {
	if(argc != 5 && argc != 4) syntax();
	int startarg = 1;
	int x=INT_MAX,y=INT_MAX,xmax=INT_MIN,ymax=INT_MIN,w=-1,h=-1;
	if(strncmp(argv[1], "-dim=", 5) == 0) {
		sscanf(argv[1]+5, "%d,%d,%d,%d", &x, &y, &w, &h);
		startarg++;
	}
	const char* pic1 = argv[startarg++];
	const char* pic2 = argv[startarg++];
	const char* out = argv[startarg++];
	struct Pix* p1 = pixRead(pic1);
	struct Pix* p2 = pixRead(pic2);
	if(p1->h != p2->h || p1->w != p2->w) {
		dprintf(2, "error: both pics need same dimensions!");
		exit(1);
	}
	struct Pix* p1b = pixConvertTo32(p1);
	struct Pix* p2b = pixConvertTo32(p2);
	int X, Y, W = p1->w, H = p1->h;
	if(x == INT_MAX) {
		for(Y = 0; Y < H; Y++) {
			for(X = 0; X < W; X++) {
				if(((uint32_t*)p1b->data)[Y * W + X] != ((uint32_t*)p2b->data)[Y * W + X]) {
					if(X < x) x = X;
					if(X > xmax) xmax = X;
					if(Y < y) y = Y;
					if(Y > ymax) ymax = Y;
				}
			}
		}
		++xmax; ++ymax;
		w = xmax - x;
		h = ymax - y;
	}
	struct Pix* po = pixCreate(w,h,32);
	int ox, oy;
	for(oy = 0, Y = y; Y < y + h; oy++, Y++) for(ox = 0, X = x; X < x + w; ox++, X++) {
		if(((uint32_t*)p1b->data)[Y * W + X] != ((uint32_t*)p2b->data)[Y * W + X])
			((uint32_t*)po->data)[oy * w + ox] = ((uint32_t*)p2b->data)[Y * W + X];
		else 
			((uint32_t*)po->data)[oy * w + ox] = 0;
	}
	pixWritePng(out, po, 0);
	dprintf(1, "wrote pixels x,y,w,h: %d,%d,%d,%d to %s\n", x,y,w,h,out);
	return 0;
	
}
Пример #24
0
// Returns a full-resolution binary pix in which each cell over the given
// threshold is filled as a black square. pixDestroy after use.
// Edge cells, which have a zero 4-neighbour, are not marked.
Pix* IntGrid::ThresholdToPix(int threshold) const {
  Pix* pix = pixCreate(tright().x() - bleft().x(),
                       tright().y() - bleft().y(), 1);
  int cellsize = gridsize();
  for (int y = 0; y < gridheight(); ++y) {
    for (int x = 0; x < gridwidth(); ++x) {
      if (GridCellValue(x, y) > threshold &&
          GridCellValue(x - 1, y) > 0 && GridCellValue(x + 1, y) > 0 &&
              GridCellValue(x, y - 1) > 0 && GridCellValue(x, y + 1) > 0) {
        pixRasterop(pix, x * cellsize, tright().y() - ((y + 1) * cellsize),
                    cellsize, cellsize, PIX_SET, NULL, 0, 0);
      }
    }
  }
  return pix;
}
/*!
 *  pixInitAccumulate()
 *
 *      Input:  w, h (of accumulate array)
 *              offset (initialize the 32 bpp to have this
 *                      value; not more than 0x40000000)
 *      Return: pixd (32 bpp), or null on error
 *
 *  Notes:
 *      (1) The offset must be >= 0.
 *      (2) The offset is used so that we can do arithmetic
 *          with negative number results on l_uint32 data; it
 *          prevents the l_uint32 data from going negative.
 *      (3) Because we use l_int32 intermediate data results,
 *          these should never exceed the max of l_int32 (0x7fffffff).
 *          We do not permit the offset to be above 0x40000000,
 *          which is half way between 0 and the max of l_int32.
 *      (4) The same offset should be used for initialization,
 *          multiplication by a constant, and final extraction!
 *      (5) If you're only adding positive values, offset can be 0.
 */
PIX *
pixInitAccumulate(l_int32   w,
                  l_int32   h,
                  l_uint32  offset)
{
PIX  *pixd;

    PROCNAME("pixInitAccumulate");

    if ((pixd = pixCreate(w, h, 32)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    if (offset > 0x40000000)
        offset = 0x40000000;
    pixSetAllArbitrary(pixd, offset);
    return pixd;
}
Пример #26
0
// Helper writes a grey image to a file for use by scrollviewer.
// Normally for speed we don't display the image in the layout debug windows.
// If textord_debug_images is true, we draw the image as a background to some
// of the debug windows. printable determines whether these
// images are optimized for printing instead of screen display.
static void WriteDebugBackgroundImage(bool printable, Pix* pix_binary) {
  Pix* grey_pix = pixCreate(pixGetWidth(pix_binary),
                            pixGetHeight(pix_binary), 8);
  // Printable images are light grey on white, but for screen display
  // they are black on dark grey so the other colors show up well.
  if (printable) {
    pixSetAll(grey_pix);
    pixSetMasked(grey_pix, pix_binary, 192);
  } else {
    pixSetAllArbitrary(grey_pix, 64);
    pixSetMasked(grey_pix, pix_binary, 0);
  }
  AlignedBlob::IncrementDebugPix();
  pixWrite(AlignedBlob::textord_debug_pix().string(), grey_pix, IFF_PNG);
  pixDestroy(&grey_pix);
}
Пример #27
0
/*!
 *  pixaSplitPix()
 *
 *      Input:  pixs  (with individual components on a lattice)
 *              nx   (number of mosaic cells horizontally)
 *              ny   (number of mosaic cells vertically)
 *              borderwidth  (of added border on all sides)
 *              bordercolor  (in our RGBA format: 0xrrggbbaa)
 *      Return: pixa, or null on error
 *
 *  Notes:
 *      (1) This is a variant on pixaCreateFromPix(), where we
 *          simply divide the image up into (approximately) equal
 *          subunits.  If you want the subimages to have essentially
 *          the same aspect ratio as the input pix, use nx = ny.
 *      (2) If borderwidth is 0, we ignore the input bordercolor and
 *          redefine it to white.
 *      (3) The bordercolor is always used to initialize each tiled pix,
 *          so that if the src is clipped, the unblitted part will
 *          be this color.  This avoids 1 pixel wide black stripes at the
 *          left and lower edges.
 */
PIXA *
pixaSplitPix(PIX      *pixs,
             l_int32   nx,
             l_int32   ny,
             l_int32   borderwidth,
             l_uint32  bordercolor)
{
l_int32  w, h, d, cellw, cellh, i, j;
PIX     *pixt;
PIXA    *pixa;

    PROCNAME("pixaSplitPix");

    if (!pixs)
        return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
    if (nx <= 0 || ny <= 0)
        return (PIXA *)ERROR_PTR("nx and ny must be > 0", procName, NULL);
    borderwidth = L_MAX(0, borderwidth);

    if ((pixa = pixaCreate(nx * ny)) == NULL)
        return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    cellw = (w + nx - 1) / nx;  /* round up */
    cellh = (h + ny - 1) / ny;

    for (i = 0; i < ny; i++) {
        for (j = 0; j < nx; j++) {
            if ((pixt = pixCreate(cellw + 2 * borderwidth,
                                  cellh + 2 * borderwidth, d)) == NULL)
                return (PIXA *)ERROR_PTR("pixt not made", procName, NULL);
            pixCopyColormap(pixt, pixs);
            if (borderwidth == 0) {  /* initialize full image to white */
                if (d == 1)
                    pixClearAll(pixt);
                else
                    pixSetAll(pixt);
            }
            else
                pixSetAllArbitrary(pixt, bordercolor);
            pixRasterop(pixt, borderwidth, borderwidth, cellw, cellh,
                        PIX_SRC, pixs, j * cellw, i * cellh);
            pixaAddPix(pixa, pixt, L_INSERT);
        }
    }

    return pixa;
}
Пример #28
0
/*!
 * \brief   pixConnCompIncrInit()
 *
 * \param[in]     pixs 1 bpp
 * \param[in]     conn connectivity: 4 or 8
 * \param[out]    ppixd 32 bpp, with c.c. labelled
 * \param[out]    pptaa with pixel locations indexed by c.c.
 * \param[out]    pncc initial number of c.c.
 * \return   0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This labels the connected components in a 1 bpp pix, and
 *          additionally sets up a ptaa that lists the locations of pixels
 *          in each of the components.
 *      (2) It can be used to initialize the output image and arrays for
 *          an application that maintains information about connected
 *          components incrementally as pixels are added.
 *      (3) pixs can be empty or have some foreground pixels.
 *      (4) The connectivity is stored in pixd->special.
 *      (5) Always initialize with the first pta in ptaa being empty
 *          and representing the background value (index 0) in the pix.
 * </pre>
 */
l_int32
pixConnCompIncrInit(PIX     *pixs,
                    l_int32  conn,
                    PIX    **ppixd,
                    PTAA   **pptaa,
                    l_int32 *pncc)
{
l_int32  empty, w, h, ncc;
PIX     *pixd;
PTA     *pta;
PTAA    *ptaa;

    PROCNAME("pixConnCompIncrInit");

    if (ppixd) *ppixd = NULL;
    if (pptaa) *pptaa = NULL;
    if (pncc) *pncc = 0;
    if (!ppixd || !pptaa || !pncc)
        return ERROR_INT("&pixd, &ptaa, &ncc not all defined", procName, 1);
    if (!pixs || pixGetDepth(pixs) != 1)
        return ERROR_INT("pixs undefined or not 1 bpp", procName, 1);
    if (conn != 4 && conn != 8)
        return ERROR_INT("connectivity must be 4 or 8", procName, 1);

    pixGetDimensions(pixs, &w, &h, NULL);
    pixZero(pixs, &empty);
    if (empty) {
        *ppixd = pixCreate(w, h, 32);
        pixSetSpp(*ppixd, 1);
        pixSetSpecial(*ppixd, conn);
        *pptaa = ptaaCreate(0);
        pta = ptaCreate(1);
        ptaaAddPta(*pptaa, pta, L_INSERT);  /* reserve index 0 for background */
        return 0;
    }

        /* Set up the initial labeled image and indexed pixel arrays */
    if ((pixd = pixConnCompTransform(pixs, conn, 32)) == NULL)
        return ERROR_INT("pixd not made", procName, 1);
    pixSetSpecial(pixd, conn);
    *ppixd = pixd;
    if ((ptaa = ptaaIndexLabeledPixels(pixd, &ncc)) == NULL)
        return ERROR_INT("ptaa not made", procName, 1);
    *pptaa = ptaa;
    *pncc = ncc;
    return 0;
}
/*!
 * \brief   recogGetWindowedArea()
 *
 * \param[in]    recog
 * \param[in]    index of template
 * \param[in]    x pixel position of left hand edge of template
 * \param[out]   pdely y shift of template relative to pix1
 * \param[out]   pwsum number of fg pixels in window of pixs
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This is called after the best path has been found through
 *          the trellis, in order to produce a correlation that can be used
 *          to evaluate the confidence we have in the identification.
 *          The correlation is |1 \& 2|^2 / (|1| * |2|).
 *          |1 \& 2| is given by the count array, |2| is found from
 *          nasum_u[], and |1| is wsum returned from this function.
 * </pre>
 */
static l_int32
recogGetWindowedArea(L_RECOG  *recog,
                     l_int32   index,
                     l_int32   x,
                     l_int32  *pdely,
                     l_int32  *pwsum)
{
l_int32  w1, h1, w2, h2;
PIX     *pix1, *pix2, *pixt;
L_RDID  *did;

    PROCNAME("recogGetWindowedArea");

    if (pdely) *pdely = 0;
    if (pwsum) *pwsum = 0;
    if (!pdely || !pwsum)
        return ERROR_INT("&dely and &wsum not both defined", procName, 1);
    if (!recog)
        return ERROR_INT("recog not defined", procName, 1);
    if ((did = recogGetDid(recog)) == NULL)
        return ERROR_INT("did not defined", procName, 1);
    if (index < 0 || index >= did->narray)
        return ERROR_INT("invalid index", procName, 1);
    pix1 = did->pixs;
    pixGetDimensions(pix1, &w1, &h1, NULL);
    if (x >= w1)
        return ERROR_INT("invalid x position", procName, 1);

    pix2 = pixaGetPix(recog->pixa_u, index, L_CLONE);
    pixGetDimensions(pix2, &w2, &h2, NULL);
    if (w1 < w2) {
        L_INFO("template %d too small\n", procName, index);
        pixDestroy(&pix2);
        return 0;
    }

    *pdely = did->delya[index][x];
    pixt = pixCreate(w2, h1, 1);
    pixRasterop(pixt, 0, *pdely, w2, h2, PIX_SRC, pix2, 0, 0);
    pixRasterop(pixt, 0, 0, w2, h1, PIX_SRC & PIX_DST, pix1, x, 0);
    pixCountPixels(pixt, pwsum, recog->sumtab);
    pixDestroy(&pix2);
    pixDestroy(&pixt);
    return 0;
}
Пример #30
0
/*!
 * \brief   pixReadMemWebP()
 *
 * \param[in]  filedata    webp compressed data in memory
 * \param[in]  filesize    number of bytes in data
 * \return  pix 32 bpp, or NULL on error
 *
 * <pre>
 * Notes:
 *      (1) When the encoded data only has 3 channels (no alpha),
 *          WebPDecodeRGBAInto() generates a raster of 32-bit pixels, with
 *          the alpha channel set to opaque (255).
 *      (2) We don't need to use the gnu runtime functions like fmemopen()
 *          for redirecting data from a stream to memory, because
 *          the webp library has been written with memory-to-memory
 *          functions at the lowest level (which is good!).  And, in
 *          any event, fmemopen() doesn't work with l_binaryReadStream().
 * </pre>
 */
PIX *
pixReadMemWebP(const l_uint8  *filedata,
               size_t          filesize)
{
l_uint8   *out = NULL;
l_int32    w, h, has_alpha, wpl, stride;
l_uint32  *data;
size_t     size;
PIX       *pix;
WebPBitstreamFeatures  features;

    PROCNAME("pixReadMemWebP");

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

    if (WebPGetFeatures(filedata, filesize, &features))
        return (PIX *)ERROR_PTR("Invalid WebP file", procName, NULL);
    w = features.width;
    h = features.height;
    has_alpha = features.has_alpha;

        /* Write from compressed Y,U,V arrays to pix raster data */
    pix = pixCreate(w, h, 32);
    pixSetInputFormat(pix, IFF_WEBP);
    if (has_alpha) pixSetSpp(pix, 4);
    data = pixGetData(pix);
    wpl = pixGetWpl(pix);
    stride = wpl * 4;
    size = stride * h;
    out = WebPDecodeRGBAInto(filedata, filesize, (uint8_t *)data, size,
                             stride);
    if (out == NULL) {  /* error: out should also point to data */
        pixDestroy(&pix);
        return (PIX *)ERROR_PTR("WebP decode failed", procName, NULL);
    }

        /* The WebP API expects data in RGBA order.  The pix stores
         * in host-dependent order with R as the MSB and A as the LSB.
         * On little-endian machines, the bytes in the word must
         * be swapped; e.g., R goes from byte 0 (LSB) to byte 3 (MSB).
         * No swapping is necessary for big-endians. */
    pixEndianByteSwap(pix);
    return pix;
}