/*! * pixProjectiveSampledPta() * * Input: pixs (all depths) * ptad (4 pts of final coordinate space) * ptas (4 pts of initial coordinate space) * incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) * Return: pixd, or null on error * * Notes: * (1) Brings in either black or white pixels from the boundary. * (2) Retains colormap, which you can do for a sampled transform.. * (3) No 3 of the 4 points may be collinear. * (4) For 8 and 32 bpp pix, better quality is obtained by the * somewhat slower pixProjectivePta(). See that * function for relative timings between sampled and interpolated. */ PIX * pixProjectiveSampledPta(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor) { l_float32 *vc; PIX *pixd; PROCNAME("pixProjectiveSampledPta"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if (!ptas) return (PIX *)ERROR_PTR("ptas not defined", procName, NULL); if (!ptad) return (PIX *)ERROR_PTR("ptad not defined", procName, NULL); if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK) return (PIX *)ERROR_PTR("invalid incolor", procName, NULL); if (ptaGetCount(ptas) != 4) return (PIX *)ERROR_PTR("ptas count not 4", procName, NULL); if (ptaGetCount(ptad) != 4) return (PIX *)ERROR_PTR("ptad count not 4", procName, NULL); /* Get backwards transform from dest to src, and apply it */ getProjectiveXformCoeffs(ptad, ptas, &vc); pixd = pixProjectiveSampled(pixs, vc, incolor); FREE(vc); return pixd; }
/*! * pixProjective() * * Input: pixs (all depths; colormap ok) * vc (vector of 8 coefficients for projective transformation) * incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) * Return: pixd, or null on error * * Notes: * (1) Brings in either black or white pixels from the boundary * (2) Removes any existing colormap, if necessary, before transforming */ PIX * pixProjective(PIX *pixs, l_float32 *vc, l_int32 incolor) { l_int32 d; l_uint32 colorval; PIX *pixt1, *pixt2, *pixd; PROCNAME("pixProjective"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if (!vc) return (PIX *)ERROR_PTR("vc not defined", procName, NULL); if (pixGetDepth(pixs) == 1) return pixProjectiveSampled(pixs, vc, incolor); /* Remove cmap if it exists, and unpack to 8 bpp if necessary */ pixt1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); d = pixGetDepth(pixt1); if (d < 8) pixt2 = pixConvertTo8(pixt1, FALSE); else pixt2 = pixClone(pixt1); d = pixGetDepth(pixt2); /* Compute actual color to bring in from edges */ colorval = 0; if (incolor == L_BRING_IN_WHITE) { if (d == 8) colorval = 255; else /* d == 32 */ colorval = 0xffffff00; } if (d == 8) pixd = pixProjectiveGray(pixt2, vc, colorval); else /* d == 32 */ pixd = pixProjectiveColor(pixt2, vc, colorval); pixDestroy(&pixt1); pixDestroy(&pixt2); return pixd; }
int main(int argc, char **argv) { l_int32 w, h, x, y, i, n; l_float32 *vc; PIX *pix1, *pix2, *pix3, *pix4, *pix5; PIXA *pixas, *pixa; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pixas = pixaCreate(11); for (i = 0; i < 10; i++) { /* this preserves any alpha */ pix1 = pixRead(fnames[i]); pix2 = pixScaleBySamplingToSize(pix1, 250, 150); pixaAddPix(pixas, pix2, L_INSERT); pixDestroy(&pix1); } /* Add a transparent grid over the rgb image */ pix1 = pixaGetPix(pixas, 8, L_COPY); pixGetDimensions(pix1, &w, &h, NULL); pix2 = pixCreate(w, h, 1); for (i = 0; i < 5; i++) { y = h * (i + 1) / 6; pixRenderLine(pix2, 0, y, w, y, 3, L_SET_PIXELS); } for (i = 0; i < 7; i++) { x = w * (i + 1) / 8; pixRenderLine(pix2, x, 0, x, h, 3, L_SET_PIXELS); } pix3 = pixConvertTo8(pix2, 0); /* 1 --> 0 ==> transparent */ pixSetRGBComponent(pix1, pix3, L_ALPHA_CHANNEL); pixaAddPix(pixas, pix1, L_INSERT); n = pixaGetCount(pixas); pixDestroy(&pix2); pixDestroy(&pix3); #if DO_ALL /* Display with and without removing alpha with white bg */ pix1 = pixaDisplayTiledInRows(pixas, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); pixDestroy(&pix1); pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixRemoveAlpha(pix1); pixaAddPix(pixa, pix2, L_INSERT); pixDestroy(&pix1); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ pixDisplayWithTitle(pix1, 200, 0, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Setting to gray */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pixSetAllGray(pix1, 170); pix2 = pixRemoveAlpha(pix1); pixaAddPix(pixa, pix2, L_INSERT); pixDestroy(&pix1); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ pixDisplayWithTitle(pix1, 400, 0, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* General scaling */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixScaleToSize(pix1, 350, 650); pix3 = pixScaleToSize(pix2, 200, 200); pix4 = pixRemoveAlpha(pix3); pixaAddPix(pixa, pix4, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Scaling by sampling */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixScaleBySamplingToSize(pix1, 350, 650); pix3 = pixScaleBySamplingToSize(pix2, 200, 200); pix4 = pixRemoveAlpha(pix3); pixaAddPix(pixa, pix4, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ pixDisplayWithTitle(pix1, 800, 0, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Rotation by area mapping; no embedding */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixRotate(pix1, 0.25, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 0, 0); pix3 = pixRotate(pix2, -0.35, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 0, 0); pix4 = pixRemoveAlpha(pix3); pixaAddPix(pixa, pix4, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 5 */ pixDisplayWithTitle(pix1, 1000, 0, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Rotation by area mapping; with embedding */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixRotate(pix1, 0.25, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 250, 150); pix3 = pixRotate(pix2, -0.35, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 250, 150); pix4 = pixRemoveBorderToSize(pix3, 250, 150); pix5 = pixRemoveAlpha(pix4); pixaAddPix(pixa, pix5, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ pixDisplayWithTitle(pix1, 0, 400, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Rotation by 3-shear; no embedding */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixRotate(pix1, 0.25, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0); pix3 = pixRotate(pix2, -0.35, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0); pix4 = pixRemoveAlpha(pix3); pixaAddPix(pixa, pix4, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 7 */ pixDisplayWithTitle(pix1, 200, 400, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Rotation by 3-shear; with embedding */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixRotate(pix1, 0.25, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 250, 150); pix3 = pixRotate(pix2, -0.35, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 250, 150); pix4 = pixRemoveBorderToSize(pix3, 250, 150); pix5 = pixRemoveAlpha(pix4); pixaAddPix(pixa, pix5, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ pixDisplayWithTitle(pix1, 400, 400, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Rotation by 2-shear about the center */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pixGetDimensions(pix1, &w, &h, NULL); pix2 = pixRotate2Shear(pix1, w / 2, h / 2, 0.25, L_BRING_IN_WHITE); pix3 = pixRotate2Shear(pix2, w / 2, h / 2, -0.35, L_BRING_IN_WHITE); pix4 = pixRemoveAlpha(pix3); pixaAddPix(pixa, pix4, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 9 */ pixDisplayWithTitle(pix1, 600, 400, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Rotation by sampling; no embedding */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixRotate(pix1, 0.25, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, 0, 0); pix3 = pixRotate(pix2, -0.35, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, 0, 0); pix4 = pixRemoveAlpha(pix3); pixaAddPix(pixa, pix4, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ pixDisplayWithTitle(pix1, 800, 400, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Rotation by sampling; with embedding */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixRotate(pix1, 0.25, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, 250, 150); pix3 = pixRotate(pix2, -0.35, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, 250, 150); pix4 = pixRemoveBorderToSize(pix3, 250, 150); pix5 = pixRemoveAlpha(pix4); pixaAddPix(pixa, pix5, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ pixDisplayWithTitle(pix1, 1000, 400, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Rotation by area mapping at corner */ pixa = pixaCreate(n); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixRotateAMCorner(pix1, 0.25, L_BRING_IN_WHITE); pix3 = pixRotateAMCorner(pix2, -0.35, L_BRING_IN_WHITE); pix4 = pixRemoveAlpha(pix3); pixaAddPix(pixa, pix4, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ pixDisplayWithTitle(pix1, 0, 800, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); #endif #if DO_ALL /* Affine transform by interpolation */ pixa = pixaCreate(n); vc = Generate3PtTransformVector(); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixAffine(pix1, vc, L_BRING_IN_WHITE); /* pix2 = pixAffineSampled(pix1, vc, L_BRING_IN_WHITE); */ pix3 = pixRemoveAlpha(pix2); pixaAddPix(pixa, pix3, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 13 */ pixDisplayWithTitle(pix1, 200, 800, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); lept_free(vc); #endif #if DO_ALL /* Projective transform by sampling */ pixa = pixaCreate(n); vc = Generate4PtTransformVector(PROJECTIVE); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixProjectiveSampled(pix1, vc, L_BRING_IN_WHITE); pix3 = pixRemoveAlpha(pix2); pixaAddPix(pixa, pix3, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 14 */ pixDisplayWithTitle(pix1, 400, 800, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); lept_free(vc); #endif #if DO_ALL /* Projective transform by interpolation */ pixa = pixaCreate(n); vc = Generate4PtTransformVector(PROJECTIVE); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixProjective(pix1, vc, L_BRING_IN_WHITE); pix3 = pixRemoveAlpha(pix2); pixaAddPix(pixa, pix3, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 15 */ pixDisplayWithTitle(pix1, 600, 800, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); lept_free(vc); #endif #if DO_ALL /* Bilinear transform by interpolation */ pixa = pixaCreate(n); vc = Generate4PtTransformVector(BILINEAR); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixas, i, L_COPY); pix2 = pixBilinear(pix1, vc, L_BRING_IN_WHITE); pix3 = pixRemoveAlpha(pix2); pixaAddPix(pixa, pix3, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); } pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 16 */ pixDisplayWithTitle(pix1, 800, 800, NULL, rp->display); pixDestroy(&pix1); pixaDestroy(&pixa); lept_free(vc); #endif pixaDestroy(&pixas); return regTestCleanup(rp); }