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 
72 static l_float64 *generateRandomNumberArray(l_int32 size);
73 static 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. */
83 static const l_float32 DefaultRedWeight = 0.0;
84 static const l_float32 DefaultGreenWeight = 0.7;
85 static const l_float32 DefaultBlueWeight = 0.3;
86 
87 
88 /*----------------------------------------------------------------------*
89  * High-level example captcha interface *
90  *----------------------------------------------------------------------*/
110 PIX *
112  l_int32 border,
113  l_int32 nterms,
114  l_uint32 seed,
115  l_uint32 color,
116  l_int32 cmapflag)
117 {
118 l_int32 k;
119 l_float32 xmag[] = {7.0f, 5.0f, 4.0f, 3.0f};
120 l_float32 ymag[] = {10.0f, 8.0f, 6.0f, 5.0f};
121 l_float32 xfreq[] = {0.12f, 0.10f, 0.10f, 0.11f};
122 l_float32 yfreq[] = {0.15f, 0.13f, 0.13f, 0.11f};
123 PIX *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  *----------------------------------------------------------------------*/
184 PIX *
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 {
195 l_int32 w, h, d, i, j, wpls, wpld, val;
196 l_uint32 *datas, *datad, *lined;
197 l_float32 x, y;
198 l_float64 *randa;
199 PIX *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  *----------------------------------------------------------------------*/
240 static l_float64 *
241 generateRandomNumberArray(l_int32 size)
242 {
243 l_int32 i;
244 l_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 
264 static l_int32
265 applyWarpTransform(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 {
277 l_int32 i;
278 l_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  *----------------------------------------------------------------------*/
302 static 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);
307 static l_int32 makeSinLUT(l_int32 npts, NUMA **pna);
308 static l_float32 getSinFromLUT(l_float32 *tab, l_int32 npts,
309  l_float32 radang);
310 
331 PIX *
332 pixRandomHarmonicWarpLUT(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 {
342 l_int32 w, h, d, i, j, wpls, wpld, val, npts;
343 l_uint32 *datas, *datad, *lined;
344 l_float32 x, y;
345 l_float32 *lut;
346 l_float64 *randa;
347 NUMA *na;
348 PIX *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 
397 static l_int32
398 applyWarpTransformLUT(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 {
412 l_int32 i;
413 l_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 
437 static l_int32
438 makeSinLUT(l_int32 npts,
439  NUMA **pna)
440 {
441 l_int32 i, n;
442 l_float32 delx, fval;
443 NUMA *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 
469 static l_float32
470 getSinFromLUT(l_float32 *tab,
471  l_int32 npts,
472  l_float32 radang)
473 {
474 l_int32 index;
475 l_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  *---------------------------------------------------------------------------*/
589 PIX *
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 {
598 l_int32 w, h, zshift;
599 l_float32 angle;
600 BOX *boxleft, *boxright;
601 PIX *pix1, *pix2, *pix3, *pix4, *pixr, *pixg, *pixb;
602 PIX *pixv1, *pixv2, *pixv3, *pixv4;
603 PIX *pixrs, *pixrss;
604 PIX *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  *----------------------------------------------------------------------*/
736 PIX *
738  l_int32 dir,
739  l_int32 type,
740  l_int32 hmax,
741  l_int32 operation,
742  l_int32 incolor)
743 {
744 l_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 
788 PIX *
790  l_int32 dir,
791  l_int32 type,
792  l_int32 hmax,
793  l_int32 incolor)
794 {
795 l_int32 i, j, jd, w, wm, h, d, wpls, wpld, val;
796 l_uint32 *datas, *datad, *lines, *lined;
797 PIX *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 
886 PIX *
888  l_int32 dir,
889  l_int32 type,
890  l_int32 hmax,
891  l_int32 incolor)
892 {
893 l_int32 i, j, jd, jp, jf, w, wm, h, d, wpls, wpld, val, rval, gval, bval;
894 l_uint32 word0, word1;
895 l_uint32 *datas, *datad, *lines, *lined;
896 PIX *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  *----------------------------------------------------------------------*/
1022 PIX *
1024  l_int32 dir,
1025  l_int32 vmaxt,
1026  l_int32 vmaxb,
1027  l_int32 operation,
1028  l_int32 incolor)
1029 {
1030 l_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 
1076 PIX *
1078  l_int32 dir,
1079  l_int32 vmaxt,
1080  l_int32 vmaxb,
1081  l_int32 incolor)
1082 {
1083 l_int32 i, j, id, w, h, d, wm, hm, wpls, wpld, val;
1084 l_uint32 *datas, *datad, *lines, *lined;
1085 l_float32 delrowt, delrowb, denom1, denom2, dely;
1086 PIX *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 
1182 PIX *
1184  l_int32 dir,
1185  l_int32 vmaxt,
1186  l_int32 vmaxb,
1187  l_int32 incolor)
1188 {
1189 l_int32 i, j, id, yp, yf, w, h, d, wm, hm, wpls, wpld;
1190 l_int32 val, rval, gval, bval;
1191 l_uint32 word0, word1;
1192 l_uint32 *datas, *datad, *lines, *lined;
1193 l_float32 delrowt, delrowb, denom1, denom2, dely;
1194 PIX *pix, *pixd;
1195 PIXCMAP *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  *----------------------------------------------------------------------*/
1335 PIX *
1337  PIX *pix2,
1338  l_float32 rwt,
1339  l_float32 gwt,
1340  l_float32 bwt)
1341 {
1342 l_int32 i, j, w, h, wpl1, wpl2, rval, gval, bval;
1343 l_uint32 word1, word2;
1344 l_uint32 *data1, *data2, *datad, *line1, *line2, *lined;
1345 l_float32 sum;
1346 PIX *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
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:993
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:892
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
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 * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
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 * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
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 * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1823
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
l_ok pixSetBlackOrWhite(PIX *pixs, l_int32 op)
pixSetBlackOrWhite()
Definition: pix2.c:1021
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 * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
PIX * pixColorizeGray(PIX *pixs, l_uint32 color, l_int32 cmapflag)
pixColorizeGray()
Definition: pixconv.c:1399
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3332
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 * pixStretchHorizontalLI(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 incolor)
pixStretchHorizontalLI()
Definition: warper.c:887
PIX * pixStretchHorizontalSampled(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 incolor)
pixStretchHorizontalSampled()
Definition: warper.c:789
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 * pixQuadraticVShearSampled(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 incolor)
pixQuadraticVShearSampled()
Definition: warper.c:1077
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 * 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
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 * pixQuadraticVShearLI(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 incolor)
pixQuadraticVShearLI()
Definition: warper.c:1183
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 * pixStereoFromPair(PIX *pix1, PIX *pix2, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixStereoFromPair()
Definition: warper.c:1336
PIX * pixStretchHorizontal(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 operation, l_int32 incolor)
pixStretchHorizontal()
Definition: warper.c:737