Leptonica  1.83.1
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  if (!pixs)
126  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
127  if (nterms < 1 || nterms > 4)
128  return (PIX *)ERROR_PTR("nterms must be in {1,2,3,4}", __func__, NULL);
129 
130  k = nterms - 1;
131  pixg = pixConvertTo8(pixs, 0);
132  pixgb = pixAddBorder(pixg, border, 255);
133  pixw = pixRandomHarmonicWarp(pixgb, xmag[k], ymag[k], xfreq[k], yfreq[k],
134  nterms, nterms, seed, 255);
135  pixd = pixColorizeGray(pixw, color, cmapflag);
136 
137  pixDestroy(&pixg);
138  pixDestroy(&pixgb);
139  pixDestroy(&pixw);
140  return pixd;
141 }
142 
143 
144 /*----------------------------------------------------------------------*
145  * Random sinusoidal warping *
146  *----------------------------------------------------------------------*/
182 PIX *
184  l_float32 xmag,
185  l_float32 ymag,
186  l_float32 xfreq,
187  l_float32 yfreq,
188  l_int32 nx,
189  l_int32 ny,
190  l_uint32 seed,
191  l_int32 grayval)
192 {
193 l_int32 w, h, d, i, j, wpls, wpld, val;
194 l_uint32 *datas, *datad, *lined;
195 l_float32 x, y;
196 l_float64 *randa;
197 PIX *pixd;
198 
199  if (!pixs)
200  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
201  pixGetDimensions(pixs, &w, &h, &d);
202  if (d != 8)
203  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
204 
205  /* Compute filter output at each location. We iterate over
206  * the destination pixels. For each dest pixel, use the
207  * warp function to compute the four source pixels that
208  * contribute, at the location (x, y). Each source pixel
209  * is divided into 16 x 16 subpixels to get an approximate value. */
210  srand(seed);
211  randa = generateRandomNumberArray(5 * (nx + ny));
212  pixd = pixCreateTemplate(pixs);
213  datas = pixGetData(pixs);
214  wpls = pixGetWpl(pixs);
215  datad = pixGetData(pixd);
216  wpld = pixGetWpl(pixd);
217 
218  for (i = 0; i < h; i++) {
219  lined = datad + i * wpld;
220  for (j = 0; j < w; j++) {
221  applyWarpTransform(xmag, ymag, xfreq, yfreq, randa, nx, ny,
222  j, i, &x, &y);
223  linearInterpolatePixelGray(datas, wpls, w, h, x, y, grayval, &val);
224  SET_DATA_BYTE(lined, j, val);
225  }
226  }
227 
228  LEPT_FREE(randa);
229  return pixd;
230 }
231 
232 
233 /*----------------------------------------------------------------------*
234  * Static helper functions *
235  *----------------------------------------------------------------------*/
236 static l_float64 *
237 generateRandomNumberArray(l_int32 size)
238 {
239 l_int32 i;
240 l_float64 *randa;
241 
242  if ((randa = (l_float64 *)LEPT_CALLOC(size, sizeof(l_float64))) == NULL)
243  return (l_float64 *)ERROR_PTR("calloc fail for randa", __func__, NULL);
244 
245  /* Return random values between 0.5 and 1.0 */
246  for (i = 0; i < size; i++)
247  randa[i] = 0.5 * (1.0 + (l_float64)rand() / (l_float64)RAND_MAX);
248  return randa;
249 }
250 
251 
258 static l_int32
259 applyWarpTransform(l_float32 xmag,
260  l_float32 ymag,
261  l_float32 xfreq,
262  l_float32 yfreq,
263  l_float64 *randa,
264  l_int32 nx,
265  l_int32 ny,
266  l_int32 xp,
267  l_int32 yp,
268  l_float32 *px,
269  l_float32 *py)
270 {
271 l_int32 i;
272 l_float64 twopi, x, y, anglex, angley;
273 
274  twopi = 6.283185;
275  for (i = 0, x = xp; i < nx; i++) {
276  anglex = xfreq * randa[3 * i + 1] * xp + twopi * randa[3 * i + 2];
277  angley = yfreq * randa[3 * i + 3] * yp + twopi * randa[3 * i + 4];
278  x += xmag * randa[3 * i] * sin(anglex) * sin(angley);
279  }
280  for (i = nx, y = yp; i < nx + ny; i++) {
281  angley = yfreq * randa[3 * i + 1] * yp + twopi * randa[3 * i + 2];
282  anglex = xfreq * randa[3 * i + 3] * xp + twopi * randa[3 * i + 4];
283  y += ymag * randa[3 * i] * sin(angley) * sin(anglex);
284  }
285 
286  *px = (l_float32)x;
287  *py = (l_float32)y;
288  return 0;
289 }
290 
291 
292 #if USE_SIN_TABLE
293 /*----------------------------------------------------------------------*
294  * Version using a LUT for sin *
295  *----------------------------------------------------------------------*/
296 static l_int32 applyWarpTransformLUT(l_float32 xmag, l_float32 ymag,
297  l_float32 xfreq, l_float32 yfreq,
298  l_float64 *randa, l_int32 nx, l_int32 ny,
299  l_int32 xp, l_int32 yp, l_float32 *lut,
300  l_int32 npts, l_float32 *px, l_float32 *py);
301 static l_int32 makeSinLUT(l_int32 npts, NUMA **pna);
302 static l_float32 getSinFromLUT(l_float32 *tab, l_int32 npts,
303  l_float32 radang);
304 
325 PIX *
326 pixRandomHarmonicWarpLUT(PIX *pixs,
327  l_float32 xmag,
328  l_float32 ymag,
329  l_float32 xfreq,
330  l_float32 yfreq,
331  l_int32 nx,
332  l_int32 ny,
333  l_uint32 seed,
334  l_int32 grayval)
335 {
336 l_int32 w, h, d, i, j, wpls, wpld, val, npts;
337 l_uint32 *datas, *datad, *lined;
338 l_float32 x, y;
339 l_float32 *lut;
340 l_float64 *randa;
341 NUMA *na;
342 PIX *pixd;
343 
344  if (!pixs)
345  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
346  pixGetDimensions(pixs, &w, &h, &d);
347  if (d != 8)
348  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
349 
350  /* Compute filter output at each location. We iterate over
351  * the destination pixels. For each dest pixel, use the
352  * warp function to compute the four source pixels that
353  * contribute, at the location (x, y). Each source pixel
354  * is divided into 16 x 16 subpixels to get an approximate value. */
355  srand(seed);
356  randa = generateRandomNumberArray(5 * (nx + ny));
357  pixd = pixCreateTemplate(pixs);
358  datas = pixGetData(pixs);
359  wpls = pixGetWpl(pixs);
360  datad = pixGetData(pixd);
361  wpld = pixGetWpl(pixd);
362 
363  npts = 100;
364  makeSinLUT(npts, &na);
365  lut = numaGetFArray(na, L_NOCOPY);
366  for (i = 0; i < h; i++) {
367  lined = datad + i * wpld;
368  for (j = 0; j < w; j++) {
369  applyWarpTransformLUT(xmag, ymag, xfreq, yfreq, randa, nx, ny,
370  j, i, lut, npts, &x, &y);
371  linearInterpolatePixelGray(datas, wpls, w, h, x, y, grayval, &val);
372  SET_DATA_BYTE(lined, j, val);
373  }
374  }
375 
376  numaDestroy(&na);
377  LEPT_FREE(randa);
378  return pixd;
379 }
380 
381 
389 static l_int32
390 applyWarpTransformLUT(l_float32 xmag,
391  l_float32 ymag,
392  l_float32 xfreq,
393  l_float32 yfreq,
394  l_float64 *randa,
395  l_int32 nx,
396  l_int32 ny,
397  l_int32 xp,
398  l_int32 yp,
399  l_float32 *lut,
400  l_int32 npts,
401  l_float32 *px,
402  l_float32 *py)
403 {
404 l_int32 i;
405 l_float64 twopi, x, y, anglex, angley, sanglex, sangley;
406 
407  twopi = 6.283185;
408  for (i = 0, x = xp; i < nx; i++) {
409  anglex = xfreq * randa[3 * i + 1] * xp + twopi * randa[3 * i + 2];
410  angley = yfreq * randa[3 * i + 3] * yp + twopi * randa[3 * i + 4];
411  sanglex = getSinFromLUT(lut, npts, anglex);
412  sangley = getSinFromLUT(lut, npts, angley);
413  x += xmag * randa[3 * i] * sanglex * sangley;
414  }
415  for (i = nx, y = yp; i < nx + ny; i++) {
416  angley = yfreq * randa[3 * i + 1] * yp + twopi * randa[3 * i + 2];
417  anglex = xfreq * randa[3 * i + 3] * xp + twopi * randa[3 * i + 4];
418  sanglex = getSinFromLUT(lut, npts, anglex);
419  sangley = getSinFromLUT(lut, npts, angley);
420  y += ymag * randa[3 * i] * sangley * sanglex;
421  }
422 
423  *px = (l_float32)x;
424  *py = (l_float32)y;
425  return 0;
426 }
427 
428 
429 static l_int32
430 makeSinLUT(l_int32 npts,
431  NUMA **pna)
432 {
433 l_int32 i, n;
434 l_float32 delx, fval;
435 NUMA *na;
436 
437  if (!pna)
438  return ERROR_INT("&na not defined", __func__, 1);
439  *pna = NULL;
440  if (npts < 2)
441  return ERROR_INT("npts < 2", __func__, 1);
442  n = 2 * npts + 1;
443  na = numaCreate(n);
444  *pna = na;
445  delx = 3.14159265 / (l_float32)npts;
446  numaSetParameters(na, 0.0, delx);
447  for (i = 0; i < n / 2; i++)
448  numaAddNumber(na, (l_float32)sin((l_float64)i * delx));
449  for (i = 0; i < n / 2; i++) {
450  numaGetFValue(na, i, &fval);
451  numaAddNumber(na, -fval);
452  }
453  numaAddNumber(na, 0);
454 
455  return 0;
456 }
457 
458 
459 static l_float32
460 getSinFromLUT(l_float32 *tab,
461  l_int32 npts,
462  l_float32 radang)
463 {
464 l_int32 index;
465 l_float32 twopi, invtwopi, findex, diff;
466 
467  /* Restrict radang to [0, 2pi] */
468  twopi = 6.283185;
469  invtwopi = 0.1591549;
470  if (radang < 0.0)
471  radang += twopi * (1.0 - (l_int32)(-radang * invtwopi));
472  else if (radang > 0.0)
473  radang -= twopi * (l_int32)(radang * invtwopi);
474 
475  /* Interpolate */
476  findex = (2.0 * (l_float32)npts) * (radang * invtwopi);
477  index = (l_int32)findex;
478  if (index == 2 * npts)
479  return tab[index];
480  diff = findex - index;
481  return (1.0 - diff) * tab[index] + diff * tab[index + 1];
482 }
483 #endif /* USE_SIN_TABLE */
484 
485 
486 
487 /*---------------------------------------------------------------------------*
488  * Stereoscopic warping *
489  *---------------------------------------------------------------------------*/
579 PIX *
581  l_int32 zbend,
582  l_int32 zshiftt,
583  l_int32 zshiftb,
584  l_int32 ybendt,
585  l_int32 ybendb,
586  l_int32 redleft)
587 {
588 l_int32 w, h, zshift;
589 l_float32 angle;
590 BOX *boxleft, *boxright;
591 PIX *pix1, *pix2, *pix3, *pix4, *pixr, *pixg, *pixb;
592 PIX *pixv1, *pixv2, *pixv3, *pixv4;
593 PIX *pixrs, *pixrss;
594 PIX *pixd;
595 
596  if (!pixs)
597  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
598 
599  /* Convert to the output depth, 32 bpp. */
600  pix1 = pixConvertTo32(pixs);
601 
602  /* If requested, do a quad vertical shearing, pushing pixels up
603  * or down, depending on their distance from the centerline. */
604  pixGetDimensions(pixs, &w, &h, NULL);
605  boxleft = boxCreate(0, 0, w / 2, h);
606  boxright = boxCreate(w / 2, 0, w - w / 2, h);
607  if (ybendt != 0 || ybendb != 0) {
608  pixv1 = pixClipRectangle(pix1, boxleft, NULL);
609  pixv2 = pixClipRectangle(pix1, boxright, NULL);
610  pixv3 = pixQuadraticVShear(pixv1, L_WARP_TO_LEFT, ybendt,
611  ybendb, L_INTERPOLATED,
613  pixv4 = pixQuadraticVShear(pixv2, L_WARP_TO_RIGHT, ybendt,
614  ybendb, L_INTERPOLATED,
616  pix2 = pixCreate(w, h, 32);
617  pixRasterop(pix2, 0, 0, w / 2, h, PIX_SRC, pixv3, 0, 0);
618  pixRasterop(pix2, w / 2, 0, w - w / 2, h, PIX_SRC, pixv4, 0, 0);
619  pixDestroy(&pixv1);
620  pixDestroy(&pixv2);
621  pixDestroy(&pixv3);
622  pixDestroy(&pixv4);
623  } else {
624  pix2 = pixClone(pix1);
625  }
626  pixDestroy(&pix1);
627 
628  /* Split out the 3 components */
629  pixr = pixGetRGBComponent(pix2, COLOR_RED);
630  pixg = pixGetRGBComponent(pix2, COLOR_GREEN);
631  pixb = pixGetRGBComponent(pix2, COLOR_BLUE);
632  pixDestroy(&pix2);
633 
634  /* The direction of the stereo disparity below is set
635  * for the red filter to be over the left eye. If the red
636  * filter is over the right eye, invert the horizontal shifts. */
637  if (redleft) {
638  zbend = -zbend;
639  zshiftt = -zshiftt;
640  zshiftb = -zshiftb;
641  }
642 
643  /* Shift the red pixels horizontally by an amount that
644  * increases quadratically from the centerline. */
645  if (zbend == 0) {
646  pixrs = pixClone(pixr);
647  } else {
648  pix1 = pixClipRectangle(pixr, boxleft, NULL);
649  pix2 = pixClipRectangle(pixr, boxright, NULL);
654  pixrs = pixCreate(w, h, 8);
655  pixRasterop(pixrs, 0, 0, w / 2, h, PIX_SRC, pix3, 0, 0);
656  pixRasterop(pixrs, w / 2, 0, w - w / 2, h, PIX_SRC, pix4, 0, 0);
657  pixDestroy(&pix1);
658  pixDestroy(&pix2);
659  pixDestroy(&pix3);
660  pixDestroy(&pix4);
661  }
662 
663  /* Perform a combination of horizontal shift and shear of
664  * red pixels. The causes the plane of the image to tilt and
665  * also move forward or backward. */
666  if (zshiftt == 0 && zshiftb == 0) {
667  pixrss = pixClone(pixrs);
668  } else if (zshiftt == zshiftb) {
669  pixrss = pixTranslate(NULL, pixrs, zshiftt, 0, L_BRING_IN_WHITE);
670  } else {
671  angle = (l_float32)(zshiftb - zshiftt) /
672  L_MAX(1.0, (l_float32)pixGetHeight(pixrs));
673  zshift = (zshiftt + zshiftb) / 2;
674  pix1 = pixTranslate(NULL, pixrs, zshift, 0, L_BRING_IN_WHITE);
675  pixrss = pixHShearLI(pix1, h / 2, angle, L_BRING_IN_WHITE);
676  pixDestroy(&pix1);
677  }
678 
679  /* Combine the unchanged cyan (g,b) image with the shifted red */
680  pixd = pixCreateRGBImage(pixrss, pixg, pixb);
681 
682  boxDestroy(&boxleft);
683  boxDestroy(&boxright);
684  pixDestroy(&pixrs);
685  pixDestroy(&pixrss);
686  pixDestroy(&pixr);
687  pixDestroy(&pixg);
688  pixDestroy(&pixb);
689  return pixd;
690 }
691 
692 
693 /*----------------------------------------------------------------------*
694  * Linear and quadratic horizontal stretching *
695  *----------------------------------------------------------------------*/
724 PIX *
726  l_int32 dir,
727  l_int32 type,
728  l_int32 hmax,
729  l_int32 operation,
730  l_int32 incolor)
731 {
732 l_int32 d;
733 
734  if (!pixs)
735  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
736  d = pixGetDepth(pixs);
737  if (d != 1 && d != 8 && d != 32)
738  return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", __func__, NULL);
739  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
740  return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
741  if (type != L_LINEAR_WARP && type != L_QUADRATIC_WARP)
742  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
743  if (operation != L_SAMPLED && operation != L_INTERPOLATED)
744  return (PIX *)ERROR_PTR("invalid operation", __func__, NULL);
745  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
746  return (PIX *)ERROR_PTR("invalid incolor", __func__, NULL);
747  if (d == 1 && operation == L_INTERPOLATED) {
748  L_WARNING("Using sampling for 1 bpp\n", __func__);
749  operation = L_INTERPOLATED;
750  }
751 
752  if (operation == L_SAMPLED)
753  return pixStretchHorizontalSampled(pixs, dir, type, hmax, incolor);
754  else
755  return pixStretchHorizontalLI(pixs, dir, type, hmax, incolor);
756 }
757 
758 
774 PIX *
776  l_int32 dir,
777  l_int32 type,
778  l_int32 hmax,
779  l_int32 incolor)
780 {
781 l_int32 i, j, jd, w, wm, h, d, wpls, wpld, val;
782 l_uint32 *datas, *datad, *lines, *lined;
783 PIX *pixd;
784 
785  if (!pixs)
786  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
787  pixGetDimensions(pixs, &w, &h, &d);
788  if (d != 1 && d != 8 && d != 32)
789  return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", __func__, NULL);
790  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
791  return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
792  if (type != L_LINEAR_WARP && type != L_QUADRATIC_WARP)
793  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
794  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
795  return (PIX *)ERROR_PTR("invalid incolor", __func__, NULL);
796 
797  pixd = pixCreateTemplate(pixs);
799  datas = pixGetData(pixs);
800  datad = pixGetData(pixd);
801  wpls = pixGetWpl(pixs);
802  wpld = pixGetWpl(pixd);
803  wm = w - 1;
804  for (jd = 0; jd < w; jd++) {
805  if (dir == L_WARP_TO_LEFT) {
806  if (type == L_LINEAR_WARP)
807  j = jd - (hmax * (wm - jd)) / wm;
808  else /* L_QUADRATIC_WARP */
809  j = jd - (hmax * (wm - jd) * (wm - jd)) / (wm * wm);
810  } else if (dir == L_WARP_TO_RIGHT) {
811  if (type == L_LINEAR_WARP)
812  j = jd - (hmax * jd) / wm;
813  else /* L_QUADRATIC_WARP */
814  j = jd - (hmax * jd * jd) / (wm * wm);
815  }
816  if (j < 0 || j > w - 1) continue;
817 
818  switch (d)
819  {
820  case 1:
821  for (i = 0; i < h; i++) {
822  lines = datas + i * wpls;
823  lined = datad + i * wpld;
824  val = GET_DATA_BIT(lines, j);
825  if (val)
826  SET_DATA_BIT(lined, jd);
827  }
828  break;
829  case 8:
830  for (i = 0; i < h; i++) {
831  lines = datas + i * wpls;
832  lined = datad + i * wpld;
833  val = GET_DATA_BYTE(lines, j);
834  SET_DATA_BYTE(lined, jd, val);
835  }
836  break;
837  case 32:
838  for (i = 0; i < h; i++) {
839  lines = datas + i * wpls;
840  lined = datad + i * wpld;
841  lined[jd] = lines[j];
842  }
843  break;
844  default:
845  L_ERROR("invalid depth: %d\n", __func__, d);
846  pixDestroy(&pixd);
847  return NULL;
848  }
849  }
850 
851  return pixd;
852 }
853 
854 
870 PIX *
872  l_int32 dir,
873  l_int32 type,
874  l_int32 hmax,
875  l_int32 incolor)
876 {
877 l_int32 i, j, jd, jp, jf, w, wm, h, d, wpls, wpld, val, rval, gval, bval;
878 l_uint32 word0, word1;
879 l_uint32 *datas, *datad, *lines, *lined;
880 PIX *pixd;
881 
882  if (!pixs)
883  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
884  pixGetDimensions(pixs, &w, &h, &d);
885  if (d != 8 && d != 32)
886  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", __func__, NULL);
887  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
888  return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
889  if (type != L_LINEAR_WARP && type != L_QUADRATIC_WARP)
890  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
891  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
892  return (PIX *)ERROR_PTR("invalid incolor", __func__, NULL);
893 
894  /* Standard linear interpolation, subdividing each pixel into 64 */
895  pixd = pixCreateTemplate(pixs);
897  datas = pixGetData(pixs);
898  datad = pixGetData(pixd);
899  wpls = pixGetWpl(pixs);
900  wpld = pixGetWpl(pixd);
901  wm = w - 1;
902  for (jd = 0; jd < w; jd++) {
903  if (dir == L_WARP_TO_LEFT) {
904  if (type == L_LINEAR_WARP)
905  j = 64 * jd - 64 * (hmax * (wm - jd)) / wm;
906  else /* L_QUADRATIC_WARP */
907  j = 64 * jd - 64 * (hmax * (wm - jd) * (wm - jd)) / (wm * wm);
908  } else if (dir == L_WARP_TO_RIGHT) {
909  if (type == L_LINEAR_WARP)
910  j = 64 * jd - 64 * (hmax * jd) / wm;
911  else /* L_QUADRATIC_WARP */
912  j = 64 * jd - 64 * (hmax * jd * jd) / (wm * wm);
913  }
914  jp = j / 64;
915  jf = j & 0x3f;
916  if (jp < 0 || jp > wm) continue;
917 
918  switch (d)
919  {
920  case 8:
921  if (jp < wm) {
922  for (i = 0; i < h; i++) {
923  lines = datas + i * wpls;
924  lined = datad + i * wpld;
925  val = ((63 - jf) * GET_DATA_BYTE(lines, jp) +
926  jf * GET_DATA_BYTE(lines, jp + 1) + 31) / 63;
927  SET_DATA_BYTE(lined, jd, val);
928  }
929  } else { /* jp == wm */
930  for (i = 0; i < h; i++) {
931  lines = datas + i * wpls;
932  lined = datad + i * wpld;
933  val = GET_DATA_BYTE(lines, jp);
934  SET_DATA_BYTE(lined, jd, val);
935  }
936  }
937  break;
938  case 32:
939  if (jp < wm) {
940  for (i = 0; i < h; i++) {
941  lines = datas + i * wpls;
942  lined = datad + i * wpld;
943  word0 = *(lines + jp);
944  word1 = *(lines + jp + 1);
945  rval = ((63 - jf) * ((word0 >> L_RED_SHIFT) & 0xff) +
946  jf * ((word1 >> L_RED_SHIFT) & 0xff) + 31) / 63;
947  gval = ((63 - jf) * ((word0 >> L_GREEN_SHIFT) & 0xff) +
948  jf * ((word1 >> L_GREEN_SHIFT) & 0xff) + 31) / 63;
949  bval = ((63 - jf) * ((word0 >> L_BLUE_SHIFT) & 0xff) +
950  jf * ((word1 >> L_BLUE_SHIFT) & 0xff) + 31) / 63;
951  composeRGBPixel(rval, gval, bval, lined + jd);
952  }
953  } else { /* jp == wm */
954  for (i = 0; i < h; i++) {
955  lines = datas + i * wpls;
956  lined = datad + i * wpld;
957  lined[jd] = lines[jp];
958  }
959  }
960  break;
961  default:
962  L_ERROR("invalid depth: %d\n", __func__, d);
963  pixDestroy(&pixd);
964  return NULL;
965  }
966  }
967 
968  return pixd;
969 }
970 
971 
972 /*----------------------------------------------------------------------*
973  * Quadratic vertical shear *
974  *----------------------------------------------------------------------*/
1004 PIX *
1006  l_int32 dir,
1007  l_int32 vmaxt,
1008  l_int32 vmaxb,
1009  l_int32 operation,
1010  l_int32 incolor)
1011 {
1012 l_int32 w, h, d;
1013 
1014  if (!pixs)
1015  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1016  pixGetDimensions(pixs, &w, &h, &d);
1017  if (d != 1 && d != 8 && d != 32)
1018  return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", __func__, NULL);
1019  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
1020  return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
1021  if (operation != L_SAMPLED && operation != L_INTERPOLATED)
1022  return (PIX *)ERROR_PTR("invalid operation", __func__, NULL);
1023  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
1024  return (PIX *)ERROR_PTR("invalid incolor", __func__, NULL);
1025 
1026  if (vmaxt == 0 && vmaxb == 0)
1027  return pixCopy(NULL, pixs);
1028 
1029  if (operation == L_INTERPOLATED && d == 1) {
1030  L_WARNING("no interpolation for 1 bpp; using sampling\n", __func__);
1031  operation = L_SAMPLED;
1032  }
1033 
1034  if (operation == L_SAMPLED)
1035  return pixQuadraticVShearSampled(pixs, dir, vmaxt, vmaxb, incolor);
1036  else /* operation == L_INTERPOLATED */
1037  return pixQuadraticVShearLI(pixs, dir, vmaxt, vmaxb, incolor);
1038 }
1039 
1040 
1056 PIX *
1058  l_int32 dir,
1059  l_int32 vmaxt,
1060  l_int32 vmaxb,
1061  l_int32 incolor)
1062 {
1063 l_int32 i, j, id, w, h, d, wm, hm, wpls, wpld, val;
1064 l_uint32 *datas, *datad, *lines, *lined;
1065 l_float32 delrowt, delrowb, denom1, denom2, dely;
1066 PIX *pixd;
1067 
1068  if (!pixs)
1069  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1070  pixGetDimensions(pixs, &w, &h, &d);
1071  if (d != 1 && d != 8 && d != 32)
1072  return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", __func__, NULL);
1073  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
1074  return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
1075  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
1076  return (PIX *)ERROR_PTR("invalid incolor", __func__, NULL);
1077 
1078  if (vmaxt == 0 && vmaxb == 0)
1079  return pixCopy(NULL, pixs);
1080 
1081  pixd = pixCreateTemplate(pixs);
1083  datas = pixGetData(pixs);
1084  datad = pixGetData(pixd);
1085  wpls = pixGetWpl(pixs);
1086  wpld = pixGetWpl(pixd);
1087  wm = w - 1;
1088  hm = h - 1;
1089  denom1 = 1. / (l_float32)h;
1090  denom2 = 1. / (l_float32)(wm * wm);
1091  for (j = 0; j < w; j++) {
1092  if (dir == L_WARP_TO_LEFT) {
1093  delrowt = (l_float32)(vmaxt * (wm - j) * (wm - j)) * denom2;
1094  delrowb = (l_float32)(vmaxb * (wm - j) * (wm - j)) * denom2;
1095  } else if (dir == L_WARP_TO_RIGHT) {
1096  delrowt = (l_float32)(vmaxt * j * j) * denom2;
1097  delrowb = (l_float32)(vmaxb * j * j) * denom2;
1098  }
1099  switch (d)
1100  {
1101  case 1:
1102  for (id = 0; id < h; id++) {
1103  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1104  i = id - (l_int32)(dely + 0.5);
1105  if (i < 0 || i > hm) continue;
1106  lines = datas + i * wpls;
1107  lined = datad + id * wpld;
1108  val = GET_DATA_BIT(lines, j);
1109  if (val)
1110  SET_DATA_BIT(lined, j);
1111  }
1112  break;
1113  case 8:
1114  for (id = 0; id < h; id++) {
1115  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1116  i = id - (l_int32)(dely + 0.5);
1117  if (i < 0 || i > hm) continue;
1118  lines = datas + i * wpls;
1119  lined = datad + id * wpld;
1120  val = GET_DATA_BYTE(lines, j);
1121  SET_DATA_BYTE(lined, j, val);
1122  }
1123  break;
1124  case 32:
1125  for (id = 0; id < h; id++) {
1126  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1127  i = id - (l_int32)(dely + 0.5);
1128  if (i < 0 || i > hm) continue;
1129  lines = datas + i * wpls;
1130  lined = datad + id * wpld;
1131  lined[j] = lines[j];
1132  }
1133  break;
1134  default:
1135  L_ERROR("invalid depth: %d\n", __func__, d);
1136  pixDestroy(&pixd);
1137  return NULL;
1138  }
1139  }
1140 
1141  return pixd;
1142 }
1143 
1144 
1160 PIX *
1162  l_int32 dir,
1163  l_int32 vmaxt,
1164  l_int32 vmaxb,
1165  l_int32 incolor)
1166 {
1167 l_int32 i, j, id, yp, yf, w, h, d, wm, hm, wpls, wpld;
1168 l_int32 val, rval, gval, bval;
1169 l_uint32 word0, word1;
1170 l_uint32 *datas, *datad, *lines, *lined;
1171 l_float32 delrowt, delrowb, denom1, denom2, dely;
1172 PIX *pix, *pixd;
1173 PIXCMAP *cmap;
1174 
1175  if (!pixs)
1176  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1177  pixGetDimensions(pixs, &w, &h, &d);
1178  if (d == 1)
1179  return (PIX *)ERROR_PTR("pixs is 1 bpp", __func__, NULL);
1180  cmap = pixGetColormap(pixs);
1181  if (d != 8 && d != 32 && !cmap)
1182  return (PIX *)ERROR_PTR("pixs not 8, 32 bpp, or cmap", __func__, NULL);
1183  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
1184  return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
1185  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
1186  return (PIX *)ERROR_PTR("invalid incolor", __func__, NULL);
1187 
1188  if (vmaxt == 0 && vmaxb == 0)
1189  return pixCopy(NULL, pixs);
1190 
1191  /* Remove any existing colormap */
1192  if (cmap)
1194  else
1195  pix = pixClone(pixs);
1196  d = pixGetDepth(pix);
1197  if (d != 8 && d != 32) {
1198  pixDestroy(&pix);
1199  return (PIX *)ERROR_PTR("invalid depth", __func__, NULL);
1200  }
1201 
1202  /* Standard linear interp: subdivide each pixel into 64 parts */
1203  pixd = pixCreateTemplate(pix);
1205  datas = pixGetData(pix);
1206  datad = pixGetData(pixd);
1207  wpls = pixGetWpl(pix);
1208  wpld = pixGetWpl(pixd);
1209  wm = w - 1;
1210  hm = h - 1;
1211  denom1 = 1.0 / (l_float32)h;
1212  denom2 = 1.0 / (l_float32)(wm * wm);
1213  for (j = 0; j < w; j++) {
1214  if (dir == L_WARP_TO_LEFT) {
1215  delrowt = (l_float32)(vmaxt * (wm - j) * (wm - j)) * denom2;
1216  delrowb = (l_float32)(vmaxb * (wm - j) * (wm - j)) * denom2;
1217  } else if (dir == L_WARP_TO_RIGHT) {
1218  delrowt = (l_float32)(vmaxt * j * j) * denom2;
1219  delrowb = (l_float32)(vmaxb * j * j) * denom2;
1220  }
1221  switch (d)
1222  {
1223  case 8:
1224  for (id = 0; id < h; id++) {
1225  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1226  i = 64 * id - (l_int32)(64.0 * dely);
1227  yp = i / 64;
1228  yf = i & 63;
1229  if (yp < 0 || yp > hm) continue;
1230  lines = datas + yp * wpls;
1231  lined = datad + id * wpld;
1232  if (yp < hm) {
1233  val = ((63 - yf) * GET_DATA_BYTE(lines, j) +
1234  yf * GET_DATA_BYTE(lines + wpls, j) + 31) / 63;
1235  } else { /* yp == hm */
1236  val = GET_DATA_BYTE(lines, j);
1237  }
1238  SET_DATA_BYTE(lined, j, val);
1239  }
1240  break;
1241  case 32:
1242  for (id = 0; id < h; id++) {
1243  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1244  i = 64 * id - (l_int32)(64.0 * dely);
1245  yp = i / 64;
1246  yf = i & 63;
1247  if (yp < 0 || yp > hm) continue;
1248  lines = datas + yp * wpls;
1249  lined = datad + id * wpld;
1250  if (yp < hm) {
1251  word0 = *(lines + j);
1252  word1 = *(lines + wpls + j);
1253  rval = ((63 - yf) * ((word0 >> L_RED_SHIFT) & 0xff) +
1254  yf * ((word1 >> L_RED_SHIFT) & 0xff) + 31) / 63;
1255  gval = ((63 - yf) * ((word0 >> L_GREEN_SHIFT) & 0xff) +
1256  yf * ((word1 >> L_GREEN_SHIFT) & 0xff) + 31) / 63;
1257  bval = ((63 - yf) * ((word0 >> L_BLUE_SHIFT) & 0xff) +
1258  yf * ((word1 >> L_BLUE_SHIFT) & 0xff) + 31) / 63;
1259  composeRGBPixel(rval, gval, bval, lined + j);
1260  } else { /* yp == hm */
1261  lined[j] = lines[j];
1262  }
1263  }
1264  break;
1265  default:
1266  L_ERROR("invalid depth: %d\n", __func__, d);
1267  pixDestroy(&pix);
1268  pixDestroy(&pixd);
1269  return NULL;
1270  }
1271  }
1272 
1273  pixDestroy(&pix);
1274  return pixd;
1275 }
1276 
1277 
1278 /*----------------------------------------------------------------------*
1279  * Stereo from a pair of images *
1280  *----------------------------------------------------------------------*/
1311 PIX *
1313  PIX *pix2,
1314  l_float32 rwt,
1315  l_float32 gwt,
1316  l_float32 bwt)
1317 {
1318 l_int32 i, j, w, h, wpl1, wpl2, rval, gval, bval;
1319 l_uint32 word1, word2;
1320 l_uint32 *data1, *data2, *datad, *line1, *line2, *lined;
1321 l_float32 sum;
1322 PIX *pixd;
1323 
1324  if (!pix1 || !pix2)
1325  return (PIX *)ERROR_PTR("pix1, pix2 not both defined", __func__, NULL);
1326  if (pixGetDepth(pix1) != 32 || pixGetDepth(pix2) != 32)
1327  return (PIX *)ERROR_PTR("pix1, pix2 not both 32 bpp", __func__, NULL);
1328 
1329  /* Make sure the sum of weights is 1.0; otherwise, you can get
1330  * overflow in the gray value. */
1331  if (rwt == 0.0 && gwt == 0.0 && bwt == 0.0) {
1332  rwt = DefaultRedWeight;
1333  gwt = DefaultGreenWeight;
1334  bwt = DefaultBlueWeight;
1335  }
1336  sum = rwt + gwt + bwt;
1337  if (L_ABS(sum - 1.0) > 0.0001) { /* maintain ratios with sum == 1.0 */
1338  L_WARNING("weights don't sum to 1; maintaining ratios\n", __func__);
1339  rwt = rwt / sum;
1340  gwt = gwt / sum;
1341  bwt = bwt / sum;
1342  }
1343 
1344  pixGetDimensions(pix1, &w, &h, NULL);
1345  pixd = pixCreateTemplate(pix1);
1346  data1 = pixGetData(pix1);
1347  data2 = pixGetData(pix2);
1348  datad = pixGetData(pixd);
1349  wpl1 = pixGetWpl(pix1);
1350  wpl2 = pixGetWpl(pix2);
1351  for (i = 0; i < h; i++) {
1352  line1 = data1 + i * wpl1;
1353  line2 = data2 + i * wpl2;
1354  lined = datad + i * wpl1; /* wpl1 works for pixd */
1355  for (j = 0; j < w; j++) {
1356  word1 = *(line1 + j);
1357  word2 = *(line2 + j);
1358  rval = (l_int32)(rwt * ((word1 >> L_RED_SHIFT) & 0xff) +
1359  gwt * ((word1 >> L_GREEN_SHIFT) & 0xff) +
1360  bwt * ((word1 >> L_BLUE_SHIFT) & 0xff) + 0.5);
1361  gval = (word2 >> L_GREEN_SHIFT) & 0xff;
1362  bval = (word2 >> L_BLUE_SHIFT) & 0xff;
1363  composeRGBPixel(rval, gval, bval, lined + j);
1364  }
1365  }
1366 
1367  return pixd;
1368 }
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:1237
#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:273
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:171
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:687
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:910
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:850
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2464
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
Definition: pix2.c:2410
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1773
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2728
l_ok pixSetBlackOrWhite(PIX *pixs, l_int32 op)
pixSetBlackOrWhite()
Definition: pix2.c:997
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:994
@ COLOR_BLUE
Definition: pix.h:330
@ COLOR_RED
Definition: pix.h:328
@ COLOR_GREEN
Definition: pix.h:329
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:384
@ L_NOCOPY
Definition: pix.h:503
@ L_LINEAR_WARP
Definition: pix.h:927
@ L_QUADRATIC_WARP
Definition: pix.h:928
@ L_WARP_TO_RIGHT
Definition: pix.h:922
@ L_WARP_TO_LEFT
Definition: pix.h:921
@ L_INTERPOLATED
Definition: pix.h:936
@ L_SAMPLED
Definition: pix.h:937
#define PIX_SRC
Definition: pix.h:444
@ L_BRING_IN_BLACK
Definition: pix.h:663
@ L_BRING_IN_WHITE
Definition: pix.h:662
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:324
PIX * pixColorizeGray(PIX *pixs, l_uint32 color, l_int32 cmapflag)
pixColorizeGray()
Definition: pixconv.c:1371
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3055
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3246
PIX * pixTranslate(PIX *pixd, PIX *pixs, l_int32 hshift, l_int32 vshift, l_int32 incolor)
pixTranslate()
Definition: rop.c:439
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:613
PIX * pixStretchHorizontalLI(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 incolor)
pixStretchHorizontalLI()
Definition: warper.c:871
PIX * pixStretchHorizontalSampled(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 incolor)
pixStretchHorizontalSampled()
Definition: warper.c:775
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:183
PIX * pixQuadraticVShearSampled(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 incolor)
pixQuadraticVShearSampled()
Definition: warper.c:1057
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:580
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:259
PIX * pixQuadraticVShearLI(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 incolor)
pixQuadraticVShearLI()
Definition: warper.c:1161
PIX * pixQuadraticVShear(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 operation, l_int32 incolor)
pixQuadraticVShear()
Definition: warper.c:1005
PIX * pixStereoFromPair(PIX *pix1, PIX *pix2, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixStereoFromPair()
Definition: warper.c:1312
PIX * pixStretchHorizontal(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 operation, l_int32 incolor)
pixStretchHorizontal()
Definition: warper.c:725