/*! * pixRotate3Shear() * * Input: pixs * xcen, ycen (center of rotation) * angle (radians) * incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK); * Return: pixd, or null on error. * * Notes: * (1) This rotates the image about the image center, * using the 3-shear method. It can be used for any angle, and * should be used for angles larger than MAX_2_SHEAR_ANGLE. * (2) A positive angle gives a clockwise rotation. * (3) 3-shear rotation by a specified angle is equivalent * to the sequential transformations * y' = y + tan(angle/2) * (x - xcen) for first y-shear * x' = x + sin(angle) * (y - ycen) for x-shear * y' = y + tan(angle/2) * (x - xcen) for second y-shear * (4) Computation of tan(angle) is performed in the shear operations. * (5) This brings in 'incolor' pixels from outside the image. * (6) The algorithm was published by Alan Paeth: "A Fast Algorithm * for General Raster Rotation," Graphics Interface '86, * pp. 77-81, May 1986. A description of the method, along with * an implementation, can be found in Graphics Gems, p. 179, * edited by Andrew Glassner, published by Academic Press, 1990. */ PIX * pixRotate3Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor) { l_float32 hangle; PIX *pixt, *pixd; PROCNAME("pixRotate3Shear"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK) return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", procName, NULL); if (L_ABS(angle) < VERY_SMALL_ANGLE) return pixClone(pixs); hangle = atan(sin(angle)); if ((pixd = pixVShear(NULL, pixs, xcen, angle / 2., incolor)) == NULL) return (PIX *)ERROR_PTR("pixd not made", procName, NULL); if ((pixt = pixHShear(NULL, pixd, ycen, hangle, incolor)) == NULL) return (PIX *)ERROR_PTR("pixt not made", procName, NULL); pixVShear(pixd, pixt, xcen, angle / 2., incolor); pixDestroy(&pixt); return pixd; }
/*! * \brief pixRotate3Shear() * * \param[in] pixs * \param[in] xcen, ycen center of rotation * \param[in] angle radians * \param[in] incolor L_BRING_IN_WHITE, L_BRING_IN_BLACK; * \return pixd, or NULL on error. * * <pre> * Notes: * (1) This rotates the image about the given point, using the 3-shear * method. It should only be used for angles smaller than * LIMIT_SHEAR_ANGLE. For larger angles, a warning is issued. * (2) A positive angle gives a clockwise rotation. * (3) 3-shear rotation by a specified angle is equivalent * to the sequential transformations * y' = y + tan(angle/2) * (x - xcen) for first y-shear * x' = x + sin(angle) * (y - ycen) for x-shear * y' = y + tan(angle/2) * (x - xcen) for second y-shear * (4) Computation of tan(angle) is performed in the shear operations. * (5) This brings in 'incolor' pixels from outside the image. * (6) If the image has an alpha layer, it is rotated separately by * two shears. * (7) The algorithm was published by Alan Paeth: "A Fast Algorithm * for General Raster Rotation," Graphics Interface '86, * pp. 77-81, May 1986. A description of the method, along with * an implementation, can be found in Graphics Gems, p. 179, * edited by Andrew Glassner, published by Academic Press, 1990. * </pre> */ PIX * pixRotate3Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor) { l_float32 hangle; PIX *pix1, *pix2, *pixd; PROCNAME("pixRotate3Shear"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK) return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", procName, NULL); if (L_ABS(angle) < MIN_ANGLE_TO_ROTATE) return pixClone(pixs); if (L_ABS(angle) > LIMIT_SHEAR_ANGLE) { L_WARNING("%6.2f radians; large angle for 3-shear rotation\n", procName, L_ABS(angle)); } hangle = atan(sin(angle)); if ((pixd = pixVShear(NULL, pixs, xcen, angle / 2., incolor)) == NULL) return (PIX *)ERROR_PTR("pixd not made", procName, NULL); if ((pix1 = pixHShear(NULL, pixd, ycen, hangle, incolor)) == NULL) { pixDestroy(&pixd); return (PIX *)ERROR_PTR("pix1 not made", procName, NULL); } pixVShear(pixd, pix1, xcen, angle / 2., incolor); pixDestroy(&pix1); if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4) { pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL); /* L_BRING_IN_WHITE brings in opaque for the alpha component */ pix2 = pixRotate3Shear(pix1, xcen, ycen, angle, L_BRING_IN_WHITE); pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL); pixDestroy(&pix1); pixDestroy(&pix2); } return pixd; }
int main(int argc, char **argv) { char *filein, *fileout; l_int32 i, w, h, liney, linex, same; l_float32 angle, deg2rad; PIX *pixt1, *pixt2, *pixs, *pixd; static char mainName[] = "sheartest"; if (argc != 4) return ERROR_INT(" Syntax: sheartest filein angle fileout", mainName, 1); /* Compare in-place H shear with H shear to a new pix */ pixt1 = pixRead("marge.jpg"); pixGetDimensions(pixt1, &w, &h, NULL); pixt2 = pixHShear(NULL, pixt1, (l_int32)(0.3 * h), 0.17, L_BRING_IN_WHITE); pixHShearIP(pixt1, (l_int32)(0.3 * h), 0.17, L_BRING_IN_WHITE); pixEqual(pixt1, pixt2, &same); if (same) fprintf(stderr, "Correct for H shear\n"); else fprintf(stderr, "Error for H shear\n"); pixDestroy(&pixt1); pixDestroy(&pixt2); /* Compare in-place V shear with V shear to a new pix */ pixt1 = pixRead("marge.jpg"); pixGetDimensions(pixt1, &w, &h, NULL); pixt2 = pixVShear(NULL, pixt1, (l_int32)(0.3 * w), 0.17, L_BRING_IN_WHITE); pixVShearIP(pixt1, (l_int32)(0.3 * w), 0.17, L_BRING_IN_WHITE); pixEqual(pixt1, pixt2, &same); if (same) fprintf(stderr, "Correct for V shear\n"); else fprintf(stderr, "Error for V shear\n"); pixDestroy(&pixt1); pixDestroy(&pixt2); filein = argv[1]; angle = atof(argv[2]); fileout = argv[3]; deg2rad = 3.1415926535 / 180.; if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("pix not made", mainName, 1); pixGetDimensions(pixs, &w, &h, NULL); #if 0 /* Select an operation from this list ... * ------------------------------------------ pixd = pixHShear(NULL, pixs, liney, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixVShear(NULL, pixs, linex, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixHShearCorner(NULL, pixs, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixVShearCorner(NULL, pixs, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixHShearCenter(NULL, pixs, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixVShearCenter(NULL, pixs, deg2rad * angle, L_BRING_IN_WHITE); pixHShearIP(pixs, liney, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixs; pixVShearIP(pixs, linex, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixs; pixRasteropHip(pixs, 0, h/3, -50, L_BRING_IN_WHITE); pixd = pixs; pixRasteropVip(pixs, 0, w/3, -50, L_BRING_IN_WHITE); pixd = pixs; * ------------------------------------------ * ... and use it in the following: */ pixd = pixHShear(NULL, pixs, liney, deg2rad * angle, L_BRING_IN_WHITE); pixWrite(fileout, pixd, IFF_PNG); pixDisplay(pixd, 50, 50); pixDestroy(&pixd); #endif #if 0 /* Do a horizontal shear about a line */ for (i = 0; i < NTIMES; i++) { liney = i * h / (NTIMES - 1); if (liney >= h) liney = h - 1; pixd = pixHShear(NULL, pixs, liney, deg2rad * angle, L_BRING_IN_WHITE); pixDisplay(pixd, 50 + 10 * i, 50 + 10 * i); pixDestroy(&pixd); } #endif #if 0 /* Do a vertical shear about a line */ for (i = 0; i < NTIMES; i++) { linex = i * w / (NTIMES - 1); if (linex >= w) linex = w - 1; pixd = pixVShear(NULL, pixs, linex, deg2rad * angle, L_BRING_IN_WHITE); pixDisplay(pixd, 50 + 10 * i, 50 + 10 * i); pixDestroy(&pixd); } #endif #if 0 /* Do a horizontal in-place shear about a line */ pixSetPadBits(pixs, 0); for (i = 0; i < NTIMES; i++) { pixd = pixCopy(NULL, pixs); liney = i * h / (NTIMES - 1); if (liney >= h) liney = h - 1; pixHShearIP(pixd, liney, deg2rad * angle, L_BRING_IN_WHITE); pixDisplay(pixd, 50 + 10 * i, 50 + 10 * i); pixDestroy(&pixd); } #endif #if 0 /* Do a vertical in-place shear about a line */ for (i = 0; i < NTIMES; i++) { pixd = pixCopy(NULL, pixs); linex = i * w / (NTIMES - 1); if (linex >= w) linex = w - 1; pixVShearIP(pixd, linex, deg2rad * angle, L_BRING_IN_WHITE); pixDisplay(pixd, 50 + 10 * i, 50 + 10 * i); pixDestroy(&pixd); } #endif pixDestroy(&pixs); return 0; }
int main(int argc, char **argv) { char buf[256]; l_int32 w, h, i, j, k, index, op, dir, stretch; l_float32 del, angle, angledeg; BOX *box; L_BMF *bmf; PIX *pixs, *pix1, *pix2, *pixd; PIXA *pixa; static char mainName[] = "warpertest"; if (argc != 1) return ERROR_INT("syntax: warpertest", mainName, 1); bmf = bmfCreate(NULL, 6); /* -------- Stereoscopic warping --------------*/ #if RUN_WARP pixs = pixRead("german.png"); pixGetDimensions(pixs, &w, &h, NULL); pixa = pixaCreate(50); for (i = 0; i < 50; i++) { /* need to test > 2 widths ! */ j = 7 * i; box = boxCreate(0, 0, w - j, h - j); pix1 = pixClipRectangle(pixs, box, NULL); pixd = pixWarpStereoscopic(pix1, 15, 22, 8, 30, -20, 1); pixSetChromaSampling(pixd, 0); pixaAddPix(pixa, pixd, L_INSERT); pixDestroy(&pix1); boxDestroy(&box); } pixDestroy(&pixs); pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "warp.pdf", "/tmp/warp.pdf"); pixd = pixaDisplayTiledInRows(pixa, 32, 2000, 1.0, 0, 20, 2); pixWrite("/tmp/warp.jpg", pixd, IFF_JFIF_JPEG); pixaDestroy(&pixa); pixDestroy(&pixd); #endif /* -------- Quadratic Vertical Shear --------------*/ #if RUN_QUAD_VERT_SHEAR pixs = pixCreate(501, 501, 32); pixGetDimensions(pixs, &w, &h, NULL); pixSetAll(pixs); pixRenderLineArb(pixs, 0, 30, 500, 30, 5, 0, 0, 255); pixRenderLineArb(pixs, 0, 110, 500, 110, 5, 0, 255, 0); pixRenderLineArb(pixs, 0, 190, 500, 190, 5, 0, 255, 255); pixRenderLineArb(pixs, 0, 270, 500, 270, 5, 255, 0, 0); pixRenderLineArb(pixs, 0, 360, 500, 360, 5, 255, 0, 255); pixRenderLineArb(pixs, 0, 450, 500, 450, 5, 255, 255, 0); pixa = pixaCreate(50); for (i = 0; i < 50; i++) { j = 3 * i; dir = ((i / 2) & 1) ? L_WARP_TO_RIGHT : L_WARP_TO_LEFT; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; box = boxCreate(0, 0, w - j, h - j); pix1 = pixClipRectangle(pixs, box, NULL); pix2 = pixQuadraticVShear(pix1, dir, 60, -20, op, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%s, %s", dirstr[dir], opstr[op]); pixd = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000, L_ADD_BELOW, 0); pixaAddPix(pixa, pixd, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); boxDestroy(&box); } pixDestroy(&pixs); pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0, "quad_vshear.pdf", "/tmp/quad_vshear.pdf"); pixd = pixaDisplayTiledInRows(pixa, 32, 2000, 1.0, 0, 20, 2); pixWrite("/tmp/quad_vshear.jpg", pixd, IFF_PNG); pixaDestroy(&pixa); pixDestroy(&pixd); #endif /* -------- Linear Horizontal stretching --------------*/ #if RUN_LIN_HORIZ_STRETCH pixs = pixRead("german.png"); pixa = pixaCreate(50); for (k = 0; k < 2; k++) { for (i = 0; i < 25; i++) { index = 25 * k + i; stretch = 10 + 4 * i; if (k == 0) stretch = -stretch; dir = (k == 1) ? L_WARP_TO_RIGHT : L_WARP_TO_LEFT; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; pix1 = pixStretchHorizontal(pixs, dir, L_LINEAR_WARP, stretch, op, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%s, %s", dirstr[dir], opstr[op]); pixd = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, L_ADD_BELOW, 0); pixaAddPix(pixa, pixd, L_INSERT); pixDestroy(&pix1); } } pixDestroy(&pixs); pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "linear_hstretch.pdf", "/tmp/linear_hstretch.pdf"); pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 20, 2); pixWrite("/tmp/linear_hstretch.jpg", pixd, IFF_JFIF_JPEG); pixaDestroy(&pixa); pixDestroy(&pixd); #endif /* -------- Quadratic Horizontal stretching --------------*/ #if RUN_QUAD_HORIZ_STRETCH pixs = pixRead("german.png"); pixa = pixaCreate(50); for (k = 0; k < 2; k++) { for (i = 0; i < 25; i++) { index = 25 * k + i; stretch = 10 + 4 * i; if (k == 0) stretch = -stretch; dir = (k == 1) ? L_WARP_TO_RIGHT : L_WARP_TO_LEFT; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; pix1 = pixStretchHorizontal(pixs, dir, L_QUADRATIC_WARP, stretch, op, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%s, %s", dirstr[dir], opstr[op]); pixd = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, L_ADD_BELOW, 0); pixaAddPix(pixa, pixd, L_INSERT); pixDestroy(&pix1); } } pixDestroy(&pixs); pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "quad_hstretch.pdf", "/tmp/quad_hstretch.pdf"); pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 20, 2); pixWrite("/tmp/quad_hstretch.jpg", pixd, IFF_JFIF_JPEG); pixaDestroy(&pixa); pixDestroy(&pixd); #endif /* -------- Horizontal Shear --------------*/ #if RUN_HORIZ_SHEAR pixs = pixRead("german.png"); pixGetDimensions(pixs, &w, &h, NULL); pixa = pixaCreate(50); for (i = 0; i < 25; i++) { del = 0.2 / 12.; angle = -0.2 + (i - (i & 1)) * del; angledeg = 180. * angle / 3.14159265; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; if (op == L_SAMPLED) pix1 = pixHShear(NULL, pixs, h / 2, angle, L_BRING_IN_WHITE); else pix1 = pixHShearLI(pixs, h / 2, angle, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%6.2f degree, %s", angledeg, opstr[op]); pixd = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, L_ADD_BELOW, 0); pixaAddPix(pixa, pixd, L_INSERT); pixDestroy(&pix1); } pixDestroy(&pixs); pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "hshear.pdf", "/tmp/hshear.pdf"); pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 20, 2); pixWrite("/tmp/hshear.jpg", pixd, IFF_JFIF_JPEG); pixaDestroy(&pixa); pixDestroy(&pixd); #endif /* -------- Vertical Shear --------------*/ #if RUN_VERT_SHEAR pixs = pixRead("german.png"); pixGetDimensions(pixs, &w, &h, NULL); pixa = pixaCreate(50); for (i = 0; i < 25; i++) { del = 0.2 / 12.; angle = -0.2 + (i - (i & 1)) * del; angledeg = 180. * angle / 3.14159265; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; if (op == L_SAMPLED) pix1 = pixVShear(NULL, pixs, w / 2, angle, L_BRING_IN_WHITE); else pix1 = pixVShearLI(pixs, w / 2, angle, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%6.2f degree, %s", angledeg, opstr[op]); pixd = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, L_ADD_BELOW, 0); pixaAddPix(pixa, pixd, L_INSERT); pixDestroy(&pix1); } pixDestroy(&pixs); pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "vshear.pdf", "/tmp/vshear.pdf"); pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 20, 2); pixWrite("/tmp/vshear.jpg", pixd, IFF_JFIF_JPEG); pixaDestroy(&pixa); pixDestroy(&pixd); #endif bmfDestroy(&bmf); return 0; }
static PIX * shearTest(PIX *pixs, l_int32 reduction) { l_int32 w, h, d; PIX *pixt1, *pixt2, *pixd; PIXA *pixa; PROCNAME("shearTest"); pixa = pixaCreate(0); pixGetDimensions(pixs, &w, &h, &d); pixt1 = pixHShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 32); pixt2 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixHShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); if (!pixGetColormap(pixs)) { pixt1 = pixCopy(NULL, pixs); pixHShearIP(pixt1, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixCopy(NULL, pixs); pixHShearIP(pixt2, h / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixCopy(NULL, pixs); pixHShearIP(pixt1, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixCopy(NULL, pixs); pixHShearIP(pixt2, h / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 32); pixDestroy(&pixt1); pixDestroy(&pixt2); } if (d == 8 || d == 32 || pixGetColormap(pixs)) { pixt1 = pixHShearLI(pixs, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixHShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixHShearLI(pixs, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixHShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); } pixt1 = pixVShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixVShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); if (!pixGetColormap(pixs)) { pixt1 = pixCopy(NULL, pixs); pixVShearIP(pixt1, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixCopy(NULL, pixs); pixVShearIP(pixt2, w / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixCopy(NULL, pixs); pixVShearIP(pixt1, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixCopy(NULL, pixs); pixVShearIP(pixt2, w / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 32); pixDestroy(&pixt1); pixDestroy(&pixt2); } if (d == 8 || d == 32 || pixGetColormap(pixs)) { pixt1 = pixVShearLI(pixs, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixVShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixVShearLI(pixs, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixVShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); } pixd = pixaDisplay(pixa, 0, 0); pixaDestroy(&pixa); return pixd; }
main(int argc, char **argv) { char buf[256]; l_int32 w, h, i, j, k, index, op, dir, stretch; l_float32 del, angle, angledeg; BOX *box; L_BMF *bmf; PIX *pixs, *pixt, *pixt2, *pixd; static char mainName[] = "warpertest"; if (argc != 1) exit(ERROR_INT("syntax: warpertest", mainName, 1)); /* -------- Stereoscopic warping --------------*/ #if RUN_WARP pixs = pixRead("german.png"); pixGetDimensions(pixs, &w, &h, NULL); l_jpegSetNoChromaSampling(1); for (i = 0; i < 50; i++) { /* need to test > 2 widths ! */ j = 7 * i; box = boxCreate(0, 0, w - j, h - j); pixt = pixClipRectangle(pixs, box, NULL); pixd = pixWarpStereoscopic(pixt, 15, 22, 8, 30, -20, 1); snprintf(buf, sizeof(buf), "/tmp/junkpixw.%02d.jpg", i); pixWrite(buf, pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); pixDestroy(&pixt); boxDestroy(&box); } pixDestroy(&pixs); pixDisplayMultiple("/tmp/junkpixw*.jpg"); #endif /* -------- Quadratic Vertical Shear --------------*/ #if RUN_QUAD_VERT_SHEAR pixs = pixCreate(501, 501, 32); pixGetDimensions(pixs, &w, &h, NULL); pixSetAll(pixs); pixRenderLineArb(pixs, 0, 30, 500, 30, 5, 0, 0, 255); pixRenderLineArb(pixs, 0, 110, 500, 110, 5, 0, 255, 0); pixRenderLineArb(pixs, 0, 190, 500, 190, 5, 0, 255, 255); pixRenderLineArb(pixs, 0, 270, 500, 270, 5, 255, 0, 0); pixRenderLineArb(pixs, 0, 360, 500, 360, 5, 255, 0, 255); pixRenderLineArb(pixs, 0, 450, 500, 450, 5, 255, 255, 0); bmf = bmfCreate("./fonts", 6); for (i = 0; i < 50; i++) { j = 3 * i; dir = ((i / 2) & 1) ? L_WARP_TO_RIGHT : L_WARP_TO_LEFT; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; Box *box = boxCreate(0, 0, w - j, h - j); pixt = pixClipRectangle(pixs, box, NULL); pixt2 = pixQuadraticVShear(pixt, dir, 60, -20, op, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%s, %s", dirstr[dir], opstr[op]); pixd = pixAddSingleTextblock(pixt2, bmf, buf, 0xff000000, L_ADD_BELOW, 0); snprintf(buf, sizeof(buf), "/tmp/junkpixvs.%02d.png", i); pixWrite(buf, pixd, IFF_PNG); pixDestroy(&pixd); pixDestroy(&pixt); pixDestroy(&pixt2); boxDestroy(&box); } pixDestroy(&pixs); bmfDestroy(&bmf); pixDisplayMultiple("/tmp/junkpixvs*.png"); #endif /* -------- Linear Horizontal stretching --------------*/ #if RUN_LIN_HORIZ_STRETCH pixs = pixRead("german.png"); bmf = bmfCreate("./fonts", 6); for (k = 0; k < 2; k++) { for (i = 0; i < 25; i++) { index = 25 * k + i; stretch = 10 + 4 * i; if (k == 0) stretch = -stretch; dir = (k == 1) ? L_WARP_TO_RIGHT : L_WARP_TO_LEFT; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; pixt = pixStretchHorizontal(pixs, dir, L_LINEAR_WARP, stretch, op, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%s, %s", dirstr[dir], opstr[op]); pixd = pixAddSingleTextblock(pixt, bmf, buf, 0xff000000, L_ADD_BELOW, 0); snprintf(buf, sizeof(buf), "/tmp/junkpixlhs.%02d.jpg", index); pixWrite(buf, pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); pixDestroy(&pixt); } } pixDestroy(&pixs); bmfDestroy(&bmf); pixDisplayMultiple("/tmp/junkpixlhs*.jpg"); #endif /* -------- Quadratic Horizontal stretching --------------*/ #if RUN_QUAD_HORIZ_STRETCH pixs = pixRead("german.png"); bmf = bmfCreate("./fonts", 6); for (k = 0; k < 2; k++) { for (i = 0; i < 25; i++) { index = 25 * k + i; stretch = 10 + 4 * i; if (k == 0) stretch = -stretch; dir = (k == 1) ? L_WARP_TO_RIGHT : L_WARP_TO_LEFT; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; pixt = pixStretchHorizontal(pixs, dir, L_QUADRATIC_WARP, stretch, op, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%s, %s", dirstr[dir], opstr[op]); pixd = pixAddSingleTextblock(pixt, bmf, buf, 0xff000000, L_ADD_BELOW, 0); snprintf(buf, sizeof(buf), "/tmp/junkpixqhs.%02d.jpg", index); pixWrite(buf, pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); pixDestroy(&pixt); } } pixDestroy(&pixs); bmfDestroy(&bmf); pixDisplayMultiple("/tmp/junkpixqhs*.jpg"); #endif /* -------- Horizontal Shear --------------*/ #if RUN_HORIZ_SHEAR pixs = pixRead("german.png"); pixGetDimensions(pixs, &w, &h, NULL); bmf = bmfCreate("./fonts", 6); for (i = 0; i < 25; i++) { del = 0.2 / 12.; angle = -0.2 + (i - (i & 1)) * del; angledeg = 180. * angle / 3.14159265; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; if (op == L_SAMPLED) pixt = pixHShear(NULL, pixs, h / 2, angle, L_BRING_IN_WHITE); else pixt = pixHShearLI(pixs, h / 2, angle, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%6.2f degree, %s", angledeg, opstr[op]); pixd = pixAddSingleTextblock(pixt, bmf, buf, 0xff000000, L_ADD_BELOW, 0); snprintf(buf, sizeof(buf), "/tmp/junkpixsh.%02d.jpg", i); pixWrite(buf, pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); pixDestroy(&pixt); } pixDestroy(&pixs); bmfDestroy(&bmf); pixDisplayMultiple("/tmp/junkpixsh*.jpg"); #endif /* -------- Vertical Shear --------------*/ #if RUN_VERT_SHEAR pixs = pixRead("german.png"); pixGetDimensions(pixs, &w, &h, NULL); bmf = bmfCreate("./fonts", 6); for (i = 0; i < 25; i++) { del = 0.2 / 12.; angle = -0.2 + (i - (i & 1)) * del; angledeg = 180. * angle / 3.14159265; op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; if (op == L_SAMPLED) pixt = pixVShear(NULL, pixs, w / 2, angle, L_BRING_IN_WHITE); else pixt = pixVShearLI(pixs, w / 2, angle, L_BRING_IN_WHITE); snprintf(buf, sizeof(buf), "%6.2f degree, %s", angledeg, opstr[op]); pixd = pixAddSingleTextblock(pixt, bmf, buf, 0xff000000, L_ADD_BELOW, 0); snprintf(buf, sizeof(buf), "/tmp/junkpixsv.%02d.jpg", i); pixWrite(buf, pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); pixDestroy(&pixt); } pixDestroy(&pixs); bmfDestroy(&bmf); pixDisplayMultiple("/tmp/junkpixsv*.jpg"); #endif return 0; }