Leptonica 1.82.0
Image processing and image analysis suite
warper.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
65#ifdef HAVE_CONFIG_H
66#include <config_auto.h>
67#endif /* HAVE_CONFIG_H */
68
69#include <math.h>
70#include "allheaders.h"
71
72static l_float64 *generateRandomNumberArray(l_int32 size);
73static l_int32 applyWarpTransform(l_float32 xmag, l_float32 ymag,
74 l_float32 xfreq, l_float32 yfreq,
75 l_float64 *randa, l_int32 nx, l_int32 ny,
76 l_int32 xp, l_int32 yp,
77 l_float32 *px, l_float32 *py);
78
79#define USE_SIN_TABLE 0
80
81 /* Suggested input to pixStereoFromPair(). These are weighting
82 * factors for input to the red channel from the left image. */
83static const l_float32 DefaultRedWeight = 0.0;
84static const l_float32 DefaultGreenWeight = 0.7;
85static const l_float32 DefaultBlueWeight = 0.3;
86
87
88/*----------------------------------------------------------------------*
89 * High-level example captcha interface *
90 *----------------------------------------------------------------------*/
110PIX *
112 l_int32 border,
113 l_int32 nterms,
114 l_uint32 seed,
115 l_uint32 color,
116 l_int32 cmapflag)
117{
118l_int32 k;
119l_float32 xmag[] = {7.0f, 5.0f, 4.0f, 3.0f};
120l_float32 ymag[] = {10.0f, 8.0f, 6.0f, 5.0f};
121l_float32 xfreq[] = {0.12f, 0.10f, 0.10f, 0.11f};
122l_float32 yfreq[] = {0.15f, 0.13f, 0.13f, 0.11f};
123PIX *pixg, *pixgb, *pixw, *pixd;
124
125 PROCNAME("pixSimpleCaptcha");
126
127 if (!pixs)
128 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
129 if (nterms < 1 || nterms > 4)
130 return (PIX *)ERROR_PTR("nterms must be in {1,2,3,4}", procName, NULL);
131
132 k = nterms - 1;
133 pixg = pixConvertTo8(pixs, 0);
134 pixgb = pixAddBorder(pixg, border, 255);
135 pixw = pixRandomHarmonicWarp(pixgb, xmag[k], ymag[k], xfreq[k], yfreq[k],
136 nterms, nterms, seed, 255);
137 pixd = pixColorizeGray(pixw, color, cmapflag);
138
139 pixDestroy(&pixg);
140 pixDestroy(&pixgb);
141 pixDestroy(&pixw);
142 return pixd;
143}
144
145
146/*----------------------------------------------------------------------*
147 * Random sinusoidal warping *
148 *----------------------------------------------------------------------*/
184PIX *
186 l_float32 xmag,
187 l_float32 ymag,
188 l_float32 xfreq,
189 l_float32 yfreq,
190 l_int32 nx,
191 l_int32 ny,
192 l_uint32 seed,
193 l_int32 grayval)
194{
195l_int32 w, h, d, i, j, wpls, wpld, val;
196l_uint32 *datas, *datad, *lined;
197l_float32 x, y;
198l_float64 *randa;
199PIX *pixd;
200
201 PROCNAME("pixRandomHarmonicWarp");
202
203 if (!pixs)
204 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
205 pixGetDimensions(pixs, &w, &h, &d);
206 if (d != 8)
207 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
208
209 /* Compute filter output at each location. We iterate over
210 * the destination pixels. For each dest pixel, use the
211 * warp function to compute the four source pixels that
212 * contribute, at the location (x, y). Each source pixel
213 * is divided into 16 x 16 subpixels to get an approximate value. */
214 srand(seed);
215 randa = generateRandomNumberArray(5 * (nx + ny));
216 pixd = pixCreateTemplate(pixs);
217 datas = pixGetData(pixs);
218 wpls = pixGetWpl(pixs);
219 datad = pixGetData(pixd);
220 wpld = pixGetWpl(pixd);
221
222 for (i = 0; i < h; i++) {
223 lined = datad + i * wpld;
224 for (j = 0; j < w; j++) {
225 applyWarpTransform(xmag, ymag, xfreq, yfreq, randa, nx, ny,
226 j, i, &x, &y);
227 linearInterpolatePixelGray(datas, wpls, w, h, x, y, grayval, &val);
228 SET_DATA_BYTE(lined, j, val);
229 }
230 }
231
232 LEPT_FREE(randa);
233 return pixd;
234}
235
236
237/*----------------------------------------------------------------------*
238 * Static helper functions *
239 *----------------------------------------------------------------------*/
240static l_float64 *
241generateRandomNumberArray(l_int32 size)
242{
243l_int32 i;
244l_float64 *randa;
245
246 PROCNAME("generateRandomNumberArray");
247
248 if ((randa = (l_float64 *)LEPT_CALLOC(size, sizeof(l_float64))) == NULL)
249 return (l_float64 *)ERROR_PTR("calloc fail for randa", procName, NULL);
250
251 /* Return random values between 0.5 and 1.0 */
252 for (i = 0; i < size; i++)
253 randa[i] = 0.5 * (1.0 + (l_float64)rand() / (l_float64)RAND_MAX);
254 return randa;
255}
256
257
264static l_int32
265applyWarpTransform(l_float32 xmag,
266 l_float32 ymag,
267 l_float32 xfreq,
268 l_float32 yfreq,
269 l_float64 *randa,
270 l_int32 nx,
271 l_int32 ny,
272 l_int32 xp,
273 l_int32 yp,
274 l_float32 *px,
275 l_float32 *py)
276{
277l_int32 i;
278l_float64 twopi, x, y, anglex, angley;
279
280 twopi = 6.283185;
281 for (i = 0, x = xp; i < nx; i++) {
282 anglex = xfreq * randa[3 * i + 1] * xp + twopi * randa[3 * i + 2];
283 angley = yfreq * randa[3 * i + 3] * yp + twopi * randa[3 * i + 4];
284 x += xmag * randa[3 * i] * sin(anglex) * sin(angley);
285 }
286 for (i = nx, y = yp; i < nx + ny; i++) {
287 angley = yfreq * randa[3 * i + 1] * yp + twopi * randa[3 * i + 2];
288 anglex = xfreq * randa[3 * i + 3] * xp + twopi * randa[3 * i + 4];
289 y += ymag * randa[3 * i] * sin(angley) * sin(anglex);
290 }
291
292 *px = (l_float32)x;
293 *py = (l_float32)y;
294 return 0;
295}
296
297
298#if USE_SIN_TABLE
299/*----------------------------------------------------------------------*
300 * Version using a LUT for sin *
301 *----------------------------------------------------------------------*/
302static l_int32 applyWarpTransformLUT(l_float32 xmag, l_float32 ymag,
303 l_float32 xfreq, l_float32 yfreq,
304 l_float64 *randa, l_int32 nx, l_int32 ny,
305 l_int32 xp, l_int32 yp, l_float32 *lut,
306 l_int32 npts, l_float32 *px, l_float32 *py);
307static l_int32 makeSinLUT(l_int32 npts, NUMA **pna);
308static l_float32 getSinFromLUT(l_float32 *tab, l_int32 npts,
309 l_float32 radang);
310
331PIX *
332pixRandomHarmonicWarpLUT(PIX *pixs,
333 l_float32 xmag,
334 l_float32 ymag,
335 l_float32 xfreq,
336 l_float32 yfreq,
337 l_int32 nx,
338 l_int32 ny,
339 l_uint32 seed,
340 l_int32 grayval)
341{
342l_int32 w, h, d, i, j, wpls, wpld, val, npts;
343l_uint32 *datas, *datad, *lined;
344l_float32 x, y;
345l_float32 *lut;
346l_float64 *randa;
347NUMA *na;
348PIX *pixd;
349
350 PROCNAME("pixRandomHarmonicWarp");
351
352 if (!pixs)
353 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
354 pixGetDimensions(pixs, &w, &h, &d);
355 if (d != 8)
356 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
357
358 /* Compute filter output at each location. We iterate over
359 * the destination pixels. For each dest pixel, use the
360 * warp function to compute the four source pixels that
361 * contribute, at the location (x, y). Each source pixel
362 * is divided into 16 x 16 subpixels to get an approximate value. */
363 srand(seed);
364 randa = generateRandomNumberArray(5 * (nx + ny));
365 pixd = pixCreateTemplate(pixs);
366 datas = pixGetData(pixs);
367 wpls = pixGetWpl(pixs);
368 datad = pixGetData(pixd);
369 wpld = pixGetWpl(pixd);
370
371 npts = 100;
372 makeSinLUT(npts, &na);
373 lut = numaGetFArray(na, L_NOCOPY);
374 for (i = 0; i < h; i++) {
375 lined = datad + i * wpld;
376 for (j = 0; j < w; j++) {
377 applyWarpTransformLUT(xmag, ymag, xfreq, yfreq, randa, nx, ny,
378 j, i, lut, npts, &x, &y);
379 linearInterpolatePixelGray(datas, wpls, w, h, x, y, grayval, &val);
380 SET_DATA_BYTE(lined, j, val);
381 }
382 }
383
384 numaDestroy(&na);
385 LEPT_FREE(randa);
386 return pixd;
387}
388
389
397static l_int32
398applyWarpTransformLUT(l_float32 xmag,
399 l_float32 ymag,
400 l_float32 xfreq,
401 l_float32 yfreq,
402 l_float64 *randa,
403 l_int32 nx,
404 l_int32 ny,
405 l_int32 xp,
406 l_int32 yp,
407 l_float32 *lut,
408 l_int32 npts,
409 l_float32 *px,
410 l_float32 *py)
411{
412l_int32 i;
413l_float64 twopi, x, y, anglex, angley, sanglex, sangley;
414
415 twopi = 6.283185;
416 for (i = 0, x = xp; i < nx; i++) {
417 anglex = xfreq * randa[3 * i + 1] * xp + twopi * randa[3 * i + 2];
418 angley = yfreq * randa[3 * i + 3] * yp + twopi * randa[3 * i + 4];
419 sanglex = getSinFromLUT(lut, npts, anglex);
420 sangley = getSinFromLUT(lut, npts, angley);
421 x += xmag * randa[3 * i] * sanglex * sangley;
422 }
423 for (i = nx, y = yp; i < nx + ny; i++) {
424 angley = yfreq * randa[3 * i + 1] * yp + twopi * randa[3 * i + 2];
425 anglex = xfreq * randa[3 * i + 3] * xp + twopi * randa[3 * i + 4];
426 sanglex = getSinFromLUT(lut, npts, anglex);
427 sangley = getSinFromLUT(lut, npts, angley);
428 y += ymag * randa[3 * i] * sangley * sanglex;
429 }
430
431 *px = (l_float32)x;
432 *py = (l_float32)y;
433 return 0;
434}
435
436
437static l_int32
438makeSinLUT(l_int32 npts,
439 NUMA **pna)
440{
441l_int32 i, n;
442l_float32 delx, fval;
443NUMA *na;
444
445 PROCNAME("makeSinLUT");
446
447 if (!pna)
448 return ERROR_INT("&na not defined", procName, 1);
449 *pna = NULL;
450 if (npts < 2)
451 return ERROR_INT("npts < 2", procName, 1);
452 n = 2 * npts + 1;
453 na = numaCreate(n);
454 *pna = na;
455 delx = 3.14159265 / (l_float32)npts;
456 numaSetParameters(na, 0.0, delx);
457 for (i = 0; i < n / 2; i++)
458 numaAddNumber(na, (l_float32)sin((l_float64)i * delx));
459 for (i = 0; i < n / 2; i++) {
460 numaGetFValue(na, i, &fval);
461 numaAddNumber(na, -fval);
462 }
463 numaAddNumber(na, 0);
464
465 return 0;
466}
467
468
469static l_float32
470getSinFromLUT(l_float32 *tab,
471 l_int32 npts,
472 l_float32 radang)
473{
474l_int32 index;
475l_float32 twopi, invtwopi, findex, diff;
476
477 /* Restrict radang to [0, 2pi] */
478 twopi = 6.283185;
479 invtwopi = 0.1591549;
480 if (radang < 0.0)
481 radang += twopi * (1.0 - (l_int32)(-radang * invtwopi));
482 else if (radang > 0.0)
483 radang -= twopi * (l_int32)(radang * invtwopi);
484
485 /* Interpolate */
486 findex = (2.0 * (l_float32)npts) * (radang * invtwopi);
487 index = (l_int32)findex;
488 if (index == 2 * npts)
489 return tab[index];
490 diff = findex - index;
491 return (1.0 - diff) * tab[index] + diff * tab[index + 1];
492}
493#endif /* USE_SIN_TABLE */
494
495
496
497/*---------------------------------------------------------------------------*
498 * Stereoscopic warping *
499 *---------------------------------------------------------------------------*/
589PIX *
591 l_int32 zbend,
592 l_int32 zshiftt,
593 l_int32 zshiftb,
594 l_int32 ybendt,
595 l_int32 ybendb,
596 l_int32 redleft)
597{
598l_int32 w, h, zshift;
599l_float32 angle;
600BOX *boxleft, *boxright;
601PIX *pix1, *pix2, *pix3, *pix4, *pixr, *pixg, *pixb;
602PIX *pixv1, *pixv2, *pixv3, *pixv4;
603PIX *pixrs, *pixrss;
604PIX *pixd;
605
606 PROCNAME("pixWarpStereoscopic");
607
608 if (!pixs)
609 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
610
611 /* Convert to the output depth, 32 bpp. */
612 pix1 = pixConvertTo32(pixs);
613
614 /* If requested, do a quad vertical shearing, pushing pixels up
615 * or down, depending on their distance from the centerline. */
616 pixGetDimensions(pixs, &w, &h, NULL);
617 boxleft = boxCreate(0, 0, w / 2, h);
618 boxright = boxCreate(w / 2, 0, w - w / 2, h);
619 if (ybendt != 0 || ybendb != 0) {
620 pixv1 = pixClipRectangle(pix1, boxleft, NULL);
621 pixv2 = pixClipRectangle(pix1, boxright, NULL);
622 pixv3 = pixQuadraticVShear(pixv1, L_WARP_TO_LEFT, ybendt,
623 ybendb, L_INTERPOLATED,
625 pixv4 = pixQuadraticVShear(pixv2, L_WARP_TO_RIGHT, ybendt,
626 ybendb, L_INTERPOLATED,
628 pix2 = pixCreate(w, h, 32);
629 pixRasterop(pix2, 0, 0, w / 2, h, PIX_SRC, pixv3, 0, 0);
630 pixRasterop(pix2, w / 2, 0, w - w / 2, h, PIX_SRC, pixv4, 0, 0);
631 pixDestroy(&pixv1);
632 pixDestroy(&pixv2);
633 pixDestroy(&pixv3);
634 pixDestroy(&pixv4);
635 } else {
636 pix2 = pixClone(pix1);
637 }
638 pixDestroy(&pix1);
639
640 /* Split out the 3 components */
641 pixr = pixGetRGBComponent(pix2, COLOR_RED);
642 pixg = pixGetRGBComponent(pix2, COLOR_GREEN);
643 pixb = pixGetRGBComponent(pix2, COLOR_BLUE);
644 pixDestroy(&pix2);
645
646 /* The direction of the stereo disparity below is set
647 * for the red filter to be over the left eye. If the red
648 * filter is over the right eye, invert the horizontal shifts. */
649 if (redleft) {
650 zbend = -zbend;
651 zshiftt = -zshiftt;
652 zshiftb = -zshiftb;
653 }
654
655 /* Shift the red pixels horizontally by an amount that
656 * increases quadratically from the centerline. */
657 if (zbend == 0) {
658 pixrs = pixClone(pixr);
659 } else {
660 pix1 = pixClipRectangle(pixr, boxleft, NULL);
661 pix2 = pixClipRectangle(pixr, boxright, NULL);
666 pixrs = pixCreate(w, h, 8);
667 pixRasterop(pixrs, 0, 0, w / 2, h, PIX_SRC, pix3, 0, 0);
668 pixRasterop(pixrs, w / 2, 0, w - w / 2, h, PIX_SRC, pix4, 0, 0);
669 pixDestroy(&pix1);
670 pixDestroy(&pix2);
671 pixDestroy(&pix3);
672 pixDestroy(&pix4);
673 }
674
675 /* Perform a combination of horizontal shift and shear of
676 * red pixels. The causes the plane of the image to tilt and
677 * also move forward or backward. */
678 if (zshiftt == 0 && zshiftb == 0) {
679 pixrss = pixClone(pixrs);
680 } else if (zshiftt == zshiftb) {
681 pixrss = pixTranslate(NULL, pixrs, zshiftt, 0, L_BRING_IN_WHITE);
682 } else {
683 angle = (l_float32)(zshiftb - zshiftt) /
684 L_MAX(1.0, (l_float32)pixGetHeight(pixrs));
685 zshift = (zshiftt + zshiftb) / 2;
686 pix1 = pixTranslate(NULL, pixrs, zshift, 0, L_BRING_IN_WHITE);
687 pixrss = pixHShearLI(pix1, h / 2, angle, L_BRING_IN_WHITE);
688 pixDestroy(&pix1);
689 }
690
691 /* Combine the unchanged cyan (g,b) image with the shifted red */
692 pixd = pixCreateRGBImage(pixrss, pixg, pixb);
693
694 boxDestroy(&boxleft);
695 boxDestroy(&boxright);
696 pixDestroy(&pixrs);
697 pixDestroy(&pixrss);
698 pixDestroy(&pixr);
699 pixDestroy(&pixg);
700 pixDestroy(&pixb);
701 return pixd;
702}
703
704
705/*----------------------------------------------------------------------*
706 * Linear and quadratic horizontal stretching *
707 *----------------------------------------------------------------------*/
736PIX *
738 l_int32 dir,
739 l_int32 type,
740 l_int32 hmax,
741 l_int32 operation,
742 l_int32 incolor)
743{
744l_int32 d;
745
746 PROCNAME("pixStretchHorizontal");
747
748 if (!pixs)
749 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
750 d = pixGetDepth(pixs);
751 if (d != 1 && d != 8 && d != 32)
752 return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", procName, NULL);
753 if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
754 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
755 if (type != L_LINEAR_WARP && type != L_QUADRATIC_WARP)
756 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
757 if (operation != L_SAMPLED && operation != L_INTERPOLATED)
758 return (PIX *)ERROR_PTR("invalid operation", procName, NULL);
759 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
760 return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
761 if (d == 1 && operation == L_INTERPOLATED) {
762 L_WARNING("Using sampling for 1 bpp\n", procName);
763 operation = L_INTERPOLATED;
764 }
765
766 if (operation == L_SAMPLED)
767 return pixStretchHorizontalSampled(pixs, dir, type, hmax, incolor);
768 else
769 return pixStretchHorizontalLI(pixs, dir, type, hmax, incolor);
770}
771
772
788PIX *
790 l_int32 dir,
791 l_int32 type,
792 l_int32 hmax,
793 l_int32 incolor)
794{
795l_int32 i, j, jd, w, wm, h, d, wpls, wpld, val;
796l_uint32 *datas, *datad, *lines, *lined;
797PIX *pixd;
798
799 PROCNAME("pixStretchHorizontalSampled");
800
801 if (!pixs)
802 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
803 pixGetDimensions(pixs, &w, &h, &d);
804 if (d != 1 && d != 8 && d != 32)
805 return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", procName, NULL);
806 if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
807 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
808 if (type != L_LINEAR_WARP && type != L_QUADRATIC_WARP)
809 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
810 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
811 return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
812
813 pixd = pixCreateTemplate(pixs);
815 datas = pixGetData(pixs);
816 datad = pixGetData(pixd);
817 wpls = pixGetWpl(pixs);
818 wpld = pixGetWpl(pixd);
819 wm = w - 1;
820 for (jd = 0; jd < w; jd++) {
821 if (dir == L_WARP_TO_LEFT) {
822 if (type == L_LINEAR_WARP)
823 j = jd - (hmax * (wm - jd)) / wm;
824 else /* L_QUADRATIC_WARP */
825 j = jd - (hmax * (wm - jd) * (wm - jd)) / (wm * wm);
826 } else if (dir == L_WARP_TO_RIGHT) {
827 if (type == L_LINEAR_WARP)
828 j = jd - (hmax * jd) / wm;
829 else /* L_QUADRATIC_WARP */
830 j = jd - (hmax * jd * jd) / (wm * wm);
831 }
832 if (j < 0 || j > w - 1) continue;
833
834 switch (d)
835 {
836 case 1:
837 for (i = 0; i < h; i++) {
838 lines = datas + i * wpls;
839 lined = datad + i * wpld;
840 val = GET_DATA_BIT(lines, j);
841 if (val)
842 SET_DATA_BIT(lined, jd);
843 }
844 break;
845 case 8:
846 for (i = 0; i < h; i++) {
847 lines = datas + i * wpls;
848 lined = datad + i * wpld;
849 val = GET_DATA_BYTE(lines, j);
850 SET_DATA_BYTE(lined, jd, val);
851 }
852 break;
853 case 32:
854 for (i = 0; i < h; i++) {
855 lines = datas + i * wpls;
856 lined = datad + i * wpld;
857 lined[jd] = lines[j];
858 }
859 break;
860 default:
861 L_ERROR("invalid depth: %d\n", procName, d);
862 pixDestroy(&pixd);
863 return NULL;
864 }
865 }
866
867 return pixd;
868}
869
870
886PIX *
888 l_int32 dir,
889 l_int32 type,
890 l_int32 hmax,
891 l_int32 incolor)
892{
893l_int32 i, j, jd, jp, jf, w, wm, h, d, wpls, wpld, val, rval, gval, bval;
894l_uint32 word0, word1;
895l_uint32 *datas, *datad, *lines, *lined;
896PIX *pixd;
897
898 PROCNAME("pixStretchHorizontalLI");
899
900 if (!pixs)
901 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
902 pixGetDimensions(pixs, &w, &h, &d);
903 if (d != 8 && d != 32)
904 return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
905 if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
906 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
907 if (type != L_LINEAR_WARP && type != L_QUADRATIC_WARP)
908 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
909 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
910 return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
911
912 /* Standard linear interpolation, subdividing each pixel into 64 */
913 pixd = pixCreateTemplate(pixs);
915 datas = pixGetData(pixs);
916 datad = pixGetData(pixd);
917 wpls = pixGetWpl(pixs);
918 wpld = pixGetWpl(pixd);
919 wm = w - 1;
920 for (jd = 0; jd < w; jd++) {
921 if (dir == L_WARP_TO_LEFT) {
922 if (type == L_LINEAR_WARP)
923 j = 64 * jd - 64 * (hmax * (wm - jd)) / wm;
924 else /* L_QUADRATIC_WARP */
925 j = 64 * jd - 64 * (hmax * (wm - jd) * (wm - jd)) / (wm * wm);
926 } else if (dir == L_WARP_TO_RIGHT) {
927 if (type == L_LINEAR_WARP)
928 j = 64 * jd - 64 * (hmax * jd) / wm;
929 else /* L_QUADRATIC_WARP */
930 j = 64 * jd - 64 * (hmax * jd * jd) / (wm * wm);
931 }
932 jp = j / 64;
933 jf = j & 0x3f;
934 if (jp < 0 || jp > wm) continue;
935
936 switch (d)
937 {
938 case 8:
939 if (jp < wm) {
940 for (i = 0; i < h; i++) {
941 lines = datas + i * wpls;
942 lined = datad + i * wpld;
943 val = ((63 - jf) * GET_DATA_BYTE(lines, jp) +
944 jf * GET_DATA_BYTE(lines, jp + 1) + 31) / 63;
945 SET_DATA_BYTE(lined, jd, val);
946 }
947 } else { /* jp == wm */
948 for (i = 0; i < h; i++) {
949 lines = datas + i * wpls;
950 lined = datad + i * wpld;
951 val = GET_DATA_BYTE(lines, jp);
952 SET_DATA_BYTE(lined, jd, val);
953 }
954 }
955 break;
956 case 32:
957 if (jp < wm) {
958 for (i = 0; i < h; i++) {
959 lines = datas + i * wpls;
960 lined = datad + i * wpld;
961 word0 = *(lines + jp);
962 word1 = *(lines + jp + 1);
963 rval = ((63 - jf) * ((word0 >> L_RED_SHIFT) & 0xff) +
964 jf * ((word1 >> L_RED_SHIFT) & 0xff) + 31) / 63;
965 gval = ((63 - jf) * ((word0 >> L_GREEN_SHIFT) & 0xff) +
966 jf * ((word1 >> L_GREEN_SHIFT) & 0xff) + 31) / 63;
967 bval = ((63 - jf) * ((word0 >> L_BLUE_SHIFT) & 0xff) +
968 jf * ((word1 >> L_BLUE_SHIFT) & 0xff) + 31) / 63;
969 composeRGBPixel(rval, gval, bval, lined + jd);
970 }
971 } else { /* jp == wm */
972 for (i = 0; i < h; i++) {
973 lines = datas + i * wpls;
974 lined = datad + i * wpld;
975 lined[jd] = lines[jp];
976 }
977 }
978 break;
979 default:
980 L_ERROR("invalid depth: %d\n", procName, d);
981 pixDestroy(&pixd);
982 return NULL;
983 }
984 }
985
986 return pixd;
987}
988
989
990/*----------------------------------------------------------------------*
991 * Quadratic vertical shear *
992 *----------------------------------------------------------------------*/
1022PIX *
1024 l_int32 dir,
1025 l_int32 vmaxt,
1026 l_int32 vmaxb,
1027 l_int32 operation,
1028 l_int32 incolor)
1029{
1030l_int32 w, h, d;
1031
1032 PROCNAME("pixQuadraticVShear");
1033
1034 if (!pixs)
1035 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1036 pixGetDimensions(pixs, &w, &h, &d);
1037 if (d != 1 && d != 8 && d != 32)
1038 return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", procName, NULL);
1039 if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
1040 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1041 if (operation != L_SAMPLED && operation != L_INTERPOLATED)
1042 return (PIX *)ERROR_PTR("invalid operation", procName, NULL);
1043 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
1044 return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
1045
1046 if (vmaxt == 0 && vmaxb == 0)
1047 return pixCopy(NULL, pixs);
1048
1049 if (operation == L_INTERPOLATED && d == 1) {
1050 L_WARNING("no interpolation for 1 bpp; using sampling\n", procName);
1051 operation = L_SAMPLED;
1052 }
1053
1054 if (operation == L_SAMPLED)
1055 return pixQuadraticVShearSampled(pixs, dir, vmaxt, vmaxb, incolor);
1056 else /* operation == L_INTERPOLATED */
1057 return pixQuadraticVShearLI(pixs, dir, vmaxt, vmaxb, incolor);
1058}
1059
1060
1076PIX *
1078 l_int32 dir,
1079 l_int32 vmaxt,
1080 l_int32 vmaxb,
1081 l_int32 incolor)
1082{
1083l_int32 i, j, id, w, h, d, wm, hm, wpls, wpld, val;
1084l_uint32 *datas, *datad, *lines, *lined;
1085l_float32 delrowt, delrowb, denom1, denom2, dely;
1086PIX *pixd;
1087
1088 PROCNAME("pixQuadraticVShearSampled");
1089
1090 if (!pixs)
1091 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1092 pixGetDimensions(pixs, &w, &h, &d);
1093 if (d != 1 && d != 8 && d != 32)
1094 return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", procName, NULL);
1095 if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
1096 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1097 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
1098 return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
1099
1100 if (vmaxt == 0 && vmaxb == 0)
1101 return pixCopy(NULL, pixs);
1102
1103 pixd = pixCreateTemplate(pixs);
1105 datas = pixGetData(pixs);
1106 datad = pixGetData(pixd);
1107 wpls = pixGetWpl(pixs);
1108 wpld = pixGetWpl(pixd);
1109 wm = w - 1;
1110 hm = h - 1;
1111 denom1 = 1. / (l_float32)h;
1112 denom2 = 1. / (l_float32)(wm * wm);
1113 for (j = 0; j < w; j++) {
1114 if (dir == L_WARP_TO_LEFT) {
1115 delrowt = (l_float32)(vmaxt * (wm - j) * (wm - j)) * denom2;
1116 delrowb = (l_float32)(vmaxb * (wm - j) * (wm - j)) * denom2;
1117 } else if (dir == L_WARP_TO_RIGHT) {
1118 delrowt = (l_float32)(vmaxt * j * j) * denom2;
1119 delrowb = (l_float32)(vmaxb * j * j) * denom2;
1120 }
1121 switch (d)
1122 {
1123 case 1:
1124 for (id = 0; id < h; id++) {
1125 dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1126 i = id - (l_int32)(dely + 0.5);
1127 if (i < 0 || i > hm) continue;
1128 lines = datas + i * wpls;
1129 lined = datad + id * wpld;
1130 val = GET_DATA_BIT(lines, j);
1131 if (val)
1132 SET_DATA_BIT(lined, j);
1133 }
1134 break;
1135 case 8:
1136 for (id = 0; id < h; id++) {
1137 dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1138 i = id - (l_int32)(dely + 0.5);
1139 if (i < 0 || i > hm) continue;
1140 lines = datas + i * wpls;
1141 lined = datad + id * wpld;
1142 val = GET_DATA_BYTE(lines, j);
1143 SET_DATA_BYTE(lined, j, val);
1144 }
1145 break;
1146 case 32:
1147 for (id = 0; id < h; id++) {
1148 dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1149 i = id - (l_int32)(dely + 0.5);
1150 if (i < 0 || i > hm) continue;
1151 lines = datas + i * wpls;
1152 lined = datad + id * wpld;
1153 lined[j] = lines[j];
1154 }
1155 break;
1156 default:
1157 L_ERROR("invalid depth: %d\n", procName, d);
1158 pixDestroy(&pixd);
1159 return NULL;
1160 }
1161 }
1162
1163 return pixd;
1164}
1165
1166
1182PIX *
1184 l_int32 dir,
1185 l_int32 vmaxt,
1186 l_int32 vmaxb,
1187 l_int32 incolor)
1188{
1189l_int32 i, j, id, yp, yf, w, h, d, wm, hm, wpls, wpld;
1190l_int32 val, rval, gval, bval;
1191l_uint32 word0, word1;
1192l_uint32 *datas, *datad, *lines, *lined;
1193l_float32 delrowt, delrowb, denom1, denom2, dely;
1194PIX *pix, *pixd;
1195PIXCMAP *cmap;
1196
1197 PROCNAME("pixQuadraticVShearLI");
1198
1199 if (!pixs)
1200 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1201 pixGetDimensions(pixs, &w, &h, &d);
1202 if (d == 1)
1203 return (PIX *)ERROR_PTR("pixs is 1 bpp", procName, NULL);
1204 cmap = pixGetColormap(pixs);
1205 if (d != 8 && d != 32 && !cmap)
1206 return (PIX *)ERROR_PTR("pixs not 8, 32 bpp, or cmap", procName, NULL);
1207 if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
1208 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1209 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
1210 return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
1211
1212 if (vmaxt == 0 && vmaxb == 0)
1213 return pixCopy(NULL, pixs);
1214
1215 /* Remove any existing colormap */
1216 if (cmap)
1218 else
1219 pix = pixClone(pixs);
1220 d = pixGetDepth(pix);
1221 if (d != 8 && d != 32) {
1222 pixDestroy(&pix);
1223 return (PIX *)ERROR_PTR("invalid depth", procName, NULL);
1224 }
1225
1226 /* Standard linear interp: subdivide each pixel into 64 parts */
1227 pixd = pixCreateTemplate(pix);
1229 datas = pixGetData(pix);
1230 datad = pixGetData(pixd);
1231 wpls = pixGetWpl(pix);
1232 wpld = pixGetWpl(pixd);
1233 wm = w - 1;
1234 hm = h - 1;
1235 denom1 = 1.0 / (l_float32)h;
1236 denom2 = 1.0 / (l_float32)(wm * wm);
1237 for (j = 0; j < w; j++) {
1238 if (dir == L_WARP_TO_LEFT) {
1239 delrowt = (l_float32)(vmaxt * (wm - j) * (wm - j)) * denom2;
1240 delrowb = (l_float32)(vmaxb * (wm - j) * (wm - j)) * denom2;
1241 } else if (dir == L_WARP_TO_RIGHT) {
1242 delrowt = (l_float32)(vmaxt * j * j) * denom2;
1243 delrowb = (l_float32)(vmaxb * j * j) * denom2;
1244 }
1245 switch (d)
1246 {
1247 case 8:
1248 for (id = 0; id < h; id++) {
1249 dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1250 i = 64 * id - (l_int32)(64.0 * dely);
1251 yp = i / 64;
1252 yf = i & 63;
1253 if (yp < 0 || yp > hm) continue;
1254 lines = datas + yp * wpls;
1255 lined = datad + id * wpld;
1256 if (yp < hm) {
1257 val = ((63 - yf) * GET_DATA_BYTE(lines, j) +
1258 yf * GET_DATA_BYTE(lines + wpls, j) + 31) / 63;
1259 } else { /* yp == hm */
1260 val = GET_DATA_BYTE(lines, j);
1261 }
1262 SET_DATA_BYTE(lined, j, val);
1263 }
1264 break;
1265 case 32:
1266 for (id = 0; id < h; id++) {
1267 dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1268 i = 64 * id - (l_int32)(64.0 * dely);
1269 yp = i / 64;
1270 yf = i & 63;
1271 if (yp < 0 || yp > hm) continue;
1272 lines = datas + yp * wpls;
1273 lined = datad + id * wpld;
1274 if (yp < hm) {
1275 word0 = *(lines + j);
1276 word1 = *(lines + wpls + j);
1277 rval = ((63 - yf) * ((word0 >> L_RED_SHIFT) & 0xff) +
1278 yf * ((word1 >> L_RED_SHIFT) & 0xff) + 31) / 63;
1279 gval = ((63 - yf) * ((word0 >> L_GREEN_SHIFT) & 0xff) +
1280 yf * ((word1 >> L_GREEN_SHIFT) & 0xff) + 31) / 63;
1281 bval = ((63 - yf) * ((word0 >> L_BLUE_SHIFT) & 0xff) +
1282 yf * ((word1 >> L_BLUE_SHIFT) & 0xff) + 31) / 63;
1283 composeRGBPixel(rval, gval, bval, lined + j);
1284 } else { /* yp == hm */
1285 lined[j] = lines[j];
1286 }
1287 }
1288 break;
1289 default:
1290 L_ERROR("invalid depth: %d\n", procName, d);
1291 pixDestroy(&pix);
1292 pixDestroy(&pixd);
1293 return NULL;
1294 }
1295 }
1296
1297 pixDestroy(&pix);
1298 return pixd;
1299}
1300
1301
1302/*----------------------------------------------------------------------*
1303 * Stereo from a pair of images *
1304 *----------------------------------------------------------------------*/
1335PIX *
1337 PIX *pix2,
1338 l_float32 rwt,
1339 l_float32 gwt,
1340 l_float32 bwt)
1341{
1342l_int32 i, j, w, h, wpl1, wpl2, rval, gval, bval;
1343l_uint32 word1, word2;
1344l_uint32 *data1, *data2, *datad, *line1, *line2, *lined;
1345l_float32 sum;
1346PIX *pixd;
1347
1348 PROCNAME("pixStereoFromPair");
1349
1350 if (!pix1 || !pix2)
1351 return (PIX *)ERROR_PTR("pix1, pix2 not both defined", procName, NULL);
1352 if (pixGetDepth(pix1) != 32 || pixGetDepth(pix2) != 32)
1353 return (PIX *)ERROR_PTR("pix1, pix2 not both 32 bpp", procName, NULL);
1354
1355 /* Make sure the sum of weights is 1.0; otherwise, you can get
1356 * overflow in the gray value. */
1357 if (rwt == 0.0 && gwt == 0.0 && bwt == 0.0) {
1358 rwt = DefaultRedWeight;
1359 gwt = DefaultGreenWeight;
1360 bwt = DefaultBlueWeight;
1361 }
1362 sum = rwt + gwt + bwt;
1363 if (L_ABS(sum - 1.0) > 0.0001) { /* maintain ratios with sum == 1.0 */
1364 L_WARNING("weights don't sum to 1; maintaining ratios\n", procName);
1365 rwt = rwt / sum;
1366 gwt = gwt / sum;
1367 bwt = bwt / sum;
1368 }
1369
1370 pixGetDimensions(pix1, &w, &h, NULL);
1371 pixd = pixCreateTemplate(pix1);
1372 data1 = pixGetData(pix1);
1373 data2 = pixGetData(pix2);
1374 datad = pixGetData(pixd);
1375 wpl1 = pixGetWpl(pix1);
1376 wpl2 = pixGetWpl(pix2);
1377 for (i = 0; i < h; i++) {
1378 line1 = data1 + i * wpl1;
1379 line2 = data2 + i * wpl2;
1380 lined = datad + i * wpl1; /* wpl1 works for pixd */
1381 for (j = 0; j < w; j++) {
1382 word1 = *(line1 + j);
1383 word2 = *(line2 + j);
1384 rval = (l_int32)(rwt * ((word1 >> L_RED_SHIFT) & 0xff) +
1385 gwt * ((word1 >> L_GREEN_SHIFT) & 0xff) +
1386 bwt * ((word1 >> L_BLUE_SHIFT) & 0xff) + 0.5);
1387 gval = (word2 >> L_GREEN_SHIFT) & 0xff;
1388 bval = (word2 >> L_BLUE_SHIFT) & 0xff;
1389 composeRGBPixel(rval, gval, bval, lined + j);
1390 }
1391 }
1392
1393 return pixd;
1394}
l_ok linearInterpolatePixelGray(l_uint32 *datas, l_int32 wpls, l_int32 w, l_int32 h, l_float32 x, l_float32 y, l_int32 grayval, l_int32 *pval)
linearInterpolatePixelGray()
Definition: affine.c:1265
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:719
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:892
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:993
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1823
l_ok pixSetBlackOrWhite(PIX *pixs, l_int32 op)
pixSetBlackOrWhite()
Definition: pix2.c:1021
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
Definition: pix2.c:2423
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
@ COLOR_BLUE
Definition: pix.h:206
@ COLOR_RED
Definition: pix.h:204
@ COLOR_GREEN
Definition: pix.h:205
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:260
@ L_NOCOPY
Definition: pix.h:710
@ L_LINEAR_WARP
Definition: pix.h:1134
@ L_QUADRATIC_WARP
Definition: pix.h:1135
@ L_WARP_TO_RIGHT
Definition: pix.h:1129
@ L_WARP_TO_LEFT
Definition: pix.h:1128
@ L_INTERPOLATED
Definition: pix.h:1143
@ L_SAMPLED
Definition: pix.h:1144
#define PIX_SRC
Definition: pix.h:330
@ L_BRING_IN_BLACK
Definition: pix.h:870
@ L_BRING_IN_WHITE
Definition: pix.h:869
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3332
PIX * pixColorizeGray(PIX *pixs, l_uint32 color, l_int32 cmapflag)
pixColorizeGray()
Definition: pixconv.c:1399
PIX * pixTranslate(PIX *pixd, PIX *pixs, l_int32 hshift, l_int32 vshift, l_int32 incolor)
pixTranslate()
Definition: rop.c:445
l_ok pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
Definition: rop.c:204
PIX * pixHShearLI(PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShearLI()
Definition: shear.c:629
Definition: pix.h:481
Definition: array.h:71
Definition: pix.h:139
PIX * pixRandomHarmonicWarp(PIX *pixs, l_float32 xmag, l_float32 ymag, l_float32 xfreq, l_float32 yfreq, l_int32 nx, l_int32 ny, l_uint32 seed, l_int32 grayval)
pixRandomHarmonicWarp()
Definition: warper.c:185
PIX * pixStereoFromPair(PIX *pix1, PIX *pix2, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixStereoFromPair()
Definition: warper.c:1336
PIX * pixStretchHorizontalSampled(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 incolor)
pixStretchHorizontalSampled()
Definition: warper.c:789
PIX * pixQuadraticVShearLI(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 incolor)
pixQuadraticVShearLI()
Definition: warper.c:1183
PIX * pixQuadraticVShearSampled(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 incolor)
pixQuadraticVShearSampled()
Definition: warper.c:1077
static l_int32 applyWarpTransform(l_float32 xmag, l_float32 ymag, l_float32 xfreq, l_float32 yfreq, l_float64 *randa, l_int32 nx, l_int32 ny, l_int32 xp, l_int32 yp, l_float32 *px, l_float32 *py)
applyWarpTransform()
Definition: warper.c:265
PIX * pixStretchHorizontal(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 operation, l_int32 incolor)
pixStretchHorizontal()
Definition: warper.c:737
PIX * pixStretchHorizontalLI(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 incolor)
pixStretchHorizontalLI()
Definition: warper.c:887
PIX * pixSimpleCaptcha(PIX *pixs, l_int32 border, l_int32 nterms, l_uint32 seed, l_uint32 color, l_int32 cmapflag)
pixSimpleCaptcha()
Definition: warper.c:111
PIX * pixQuadraticVShear(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 operation, l_int32 incolor)
pixQuadraticVShear()
Definition: warper.c:1023
PIX * pixWarpStereoscopic(PIX *pixs, l_int32 zbend, l_int32 zshiftt, l_int32 zshiftb, l_int32 ybendt, l_int32 ybendb, l_int32 redleft)
pixWarpStereoscopic()
Definition: warper.c:590