/*! * pixProjectivePtaGammaXform() * * Input: pixs (32 bpp rgb) * gamma (gamma correction; must be > 0.0) * ptad (3 pts of final coordinate space) * ptas (3 pts of initial coordinate space) * fract (between 0.0 and 1.0, with 1.0 fully transparent) * border (of pixels to capture transformed source pixels) * Return: pixd, or null on error * * Notes: * (1) This wraps a gamma/inverse-gamma photometric transform around * pixProjectivePtaWithAlpha(). * (2) For usage, see notes in pixProjectivePtaWithAlpha() and * pixGammaTRCWithAlpha(). * (3) The basic idea of a gamma/inverse-gamma transform is to remove * any gamma correction before the projective transform, and restore * it afterward. The effects can be subtle, but important for * some applications. For example, using gamma > 1.0 will * cause the dark areas to become somewhat lighter and slightly * reduce aliasing effects when blending using the alpha channel. */ PIX * pixProjectivePtaGammaXform(PIX *pixs, l_float32 gamma, PTA *ptad, PTA *ptas, l_float32 fract, l_int32 border) { PIX *pixg, *pixd; PROCNAME("pixProjectivePtaGammaXform"); if (!pixs || (pixGetDepth(pixs) != 32)) return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL); if (fract == 0.0) L_WARNING("fully opaque alpha; image cannot be blended", procName); if (gamma <= 0.0) { L_WARNING("gamma must be > 0.0; setting to 1.0", procName); gamma = 1.0; } pixg = pixGammaTRCWithAlpha(NULL, pixs, 1.0 / gamma, 0, 255); pixd = pixProjectivePtaWithAlpha(pixg, ptad, ptas, NULL, fract, border); pixGammaTRCWithAlpha(pixd, pixd, gamma, 0, 255); pixDestroy(&pixg); return pixd; }
int main(int argc, char **argv) { PIX *pixs2, *pixs3, *pixb1, *pixb2, *pixb3; PIX *pixr2, *pixr3; PIX *pixc1, *pixc2, *pixc3, *pixcs1, *pixcs2, *pixcs3; PIX *pixd, *pixt1, *pixt2, *pixt3; PTA *ptas1, *ptas2, *ptas3, *ptad1, *ptad2, *ptad3; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pixc1 = pixRead("test24.jpg"); pixc2 = pixRead("wyom.jpg"); pixc3 = pixRead("marge.jpg"); /* Test alpha blend scaling */ pixd = pixCreate(900, 400, 32); pixSetAll(pixd); pixs2 = pixScaleWithAlpha(pixc2, 0.5, 0.5, NULL, 0.3); pixs3 = pixScaleWithAlpha(pixc3, 0.4, 0.4, NULL, 0.7); pixb1 = pixBlendWithGrayMask(pixd, pixs3, NULL, 100, 100); pixb2 = pixBlendWithGrayMask(pixb1, pixs2, NULL, 300, 130); pixb3 = pixBlendWithGrayMask(pixb2, pixs3, NULL, 600, 160); regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 0 */ pixDisplayWithTitle(pixb3, 900, 100, NULL, rp->display); pixDestroy(&pixd); pixDestroy(&pixs2); pixDestroy(&pixs3); pixDestroy(&pixb1); pixDestroy(&pixb2); pixDestroy(&pixb3); /* Test alpha blend rotation */ pixd = pixCreate(1200, 800, 32); pixSetAll(pixd); pixr3 = pixRotateWithAlpha(pixc3, -0.3, NULL, 1.0); pixr2 = pixRotateWithAlpha(pixc2, +0.3, NULL, 1.0); pixb3 = pixBlendWithGrayMask(pixd, pixr3, NULL, 100, 100); pixb2 = pixBlendWithGrayMask(pixb3, pixr2, NULL, 400, 100); regTestWritePixAndCheck(rp, pixb2, IFF_PNG); /* 1 */ pixDisplayWithTitle(pixb2, 500, 100, NULL, rp->display); pixDestroy(&pixd); pixDestroy(&pixr3); pixDestroy(&pixr2); pixDestroy(&pixb3); pixDestroy(&pixb2); pixcs1 = pixScale(pixc1, 0.35, 0.35); pixcs2 = pixScale(pixc2, 0.55, 0.55); pixcs3 = pixScale(pixc3, 0.65, 0.65); /* Test alpha blend affine */ pixd = pixCreate(800, 900, 32); pixSetAll(pixd); MakePtas(2, 3, &ptas1, &ptad1); MakePtas(4, 3, &ptas2, &ptad2); MakePtas(3, 3, &ptas3, &ptad3); pixt1 = pixAffinePtaWithAlpha(pixcs1, ptad1, ptas1, NULL, 1.0, 300); pixt2 = pixAffinePtaWithAlpha(pixcs2, ptad2, ptas2, NULL, 0.8, 400); pixt3 = pixAffinePtaWithAlpha(pixcs3, ptad3, ptas3, NULL, 0.7, 300); pixb1 = pixBlendWithGrayMask(pixd, pixt1, NULL, -250, 20); pixb2 = pixBlendWithGrayMask(pixb1, pixt2, NULL, -150, -250); pixb3 = pixBlendWithGrayMask(pixb2, pixt3, NULL, -100, 220); regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 2 */ pixDisplayWithTitle(pixb3, 100, 100, NULL, rp->display); pixDestroy(&pixd); pixDestroy(&pixb1); pixDestroy(&pixb2); pixDestroy(&pixb3); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); ptaDestroy(&ptas1); ptaDestroy(&ptas2); ptaDestroy(&ptas3); ptaDestroy(&ptad1); ptaDestroy(&ptad2); ptaDestroy(&ptad3); /* Test alpha blend projective */ pixd = pixCreate(900, 900, 32); pixSetAll(pixd); MakePtas(2, 4, &ptas1, &ptad1); MakePtas(4, 4, &ptas2, &ptad2); MakePtas(3, 4, &ptas3, &ptad3); pixt1 = pixProjectivePtaWithAlpha(pixcs1, ptad1, ptas1, NULL, 1.0, 300); pixt2 = pixProjectivePtaWithAlpha(pixcs2, ptad2, ptas2, NULL, 0.8, 400); pixt3 = pixProjectivePtaWithAlpha(pixcs3, ptad3, ptas3, NULL, 0.7, 400); pixb1 = pixBlendWithGrayMask(pixd, pixt1, NULL, -150, 20); pixb2 = pixBlendWithGrayMask(pixb1, pixt2, NULL, -50, -250); pixb3 = pixBlendWithGrayMask(pixb2, pixt3, NULL, -100, 220); regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 3 */ pixDisplayWithTitle(pixb3, 300, 100, NULL, rp->display); pixDestroy(&pixd); pixDestroy(&pixb1); pixDestroy(&pixb2); pixDestroy(&pixb3); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); ptaDestroy(&ptas1); ptaDestroy(&ptas2); ptaDestroy(&ptas3); ptaDestroy(&ptad1); ptaDestroy(&ptad2); ptaDestroy(&ptad3); /* Test alpha blend bilinear */ pixd = pixCreate(900, 900, 32); pixSetAll(pixd); MakePtas(2, 4, &ptas1, &ptad1); MakePtas(4, 4, &ptas2, &ptad2); MakePtas(3, 4, &ptas3, &ptad3); pixt1 = pixBilinearPtaWithAlpha(pixcs1, ptad1, ptas1, NULL, 1.0, 300); pixt2 = pixBilinearPtaWithAlpha(pixcs2, ptad2, ptas2, NULL, 0.8, 400); pixt3 = pixBilinearPtaWithAlpha(pixcs3, ptad3, ptas3, NULL, 0.7, 400); pixb1 = pixBlendWithGrayMask(pixd, pixt1, NULL, -150, 20); pixb2 = pixBlendWithGrayMask(pixb1, pixt2, NULL, -50, -250); pixb3 = pixBlendWithGrayMask(pixb2, pixt3, NULL, -100, 220); regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 4 */ pixDisplayWithTitle(pixb3, 500, 100, NULL, rp->display); pixDestroy(&pixd); pixDestroy(&pixb1); pixDestroy(&pixb2); pixDestroy(&pixb3); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); ptaDestroy(&ptas1); ptaDestroy(&ptas2); ptaDestroy(&ptas3); ptaDestroy(&ptad1); ptaDestroy(&ptad2); ptaDestroy(&ptad3); pixDestroy(&pixc1); pixDestroy(&pixc2); pixDestroy(&pixc3); pixDestroy(&pixcs1); pixDestroy(&pixcs2); pixDestroy(&pixcs3); return regTestCleanup(rp); }