Leptonica  1.77.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 #include <math.h>
66 #include "allheaders.h"
67 
68 static l_float64 *generateRandomNumberArray(l_int32 size);
69 static l_int32 applyWarpTransform(l_float32 xmag, l_float32 ymag,
70  l_float32 xfreq, l_float32 yfreq,
71  l_float64 *randa, l_int32 nx, l_int32 ny,
72  l_int32 xp, l_int32 yp,
73  l_float32 *px, l_float32 *py);
74 
75 #define USE_SIN_TABLE 0
76 
77  /* Suggested input to pixStereoFromPair(). These are weighting
78  * factors for input to the red channel from the left image. */
79 static const l_float32 L_DEFAULT_RED_WEIGHT = 0.0;
80 static const l_float32 L_DEFAULT_GREEN_WEIGHT = 0.7;
81 static const l_float32 L_DEFAULT_BLUE_WEIGHT = 0.3;
82 
83 
84 /*----------------------------------------------------------------------*
85  * High-level example captcha interface *
86  *----------------------------------------------------------------------*/
106 PIX *
108  l_int32 border,
109  l_int32 nterms,
110  l_uint32 seed,
111  l_uint32 color,
112  l_int32 cmapflag)
113 {
114 l_int32 k;
115 l_float32 xmag[] = {7.0f, 5.0f, 4.0f, 3.0f};
116 l_float32 ymag[] = {10.0f, 8.0f, 6.0f, 5.0f};
117 l_float32 xfreq[] = {0.12f, 0.10f, 0.10f, 0.11f};
118 l_float32 yfreq[] = {0.15f, 0.13f, 0.13f, 0.11f};
119 PIX *pixg, *pixgb, *pixw, *pixd;
120 
121  PROCNAME("pixSimpleCaptcha");
122 
123  if (!pixs)
124  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
125  if (nterms < 1 || nterms > 4)
126  return (PIX *)ERROR_PTR("nterms must be in {1,2,3,4}", procName, NULL);
127 
128  k = nterms - 1;
129  pixg = pixConvertTo8(pixs, 0);
130  pixgb = pixAddBorder(pixg, border, 255);
131  pixw = pixRandomHarmonicWarp(pixgb, xmag[k], ymag[k], xfreq[k], yfreq[k],
132  nterms, nterms, seed, 255);
133  pixd = pixColorizeGray(pixw, color, cmapflag);
134 
135  pixDestroy(&pixg);
136  pixDestroy(&pixgb);
137  pixDestroy(&pixw);
138  return pixd;
139 }
140 
141 
142 /*----------------------------------------------------------------------*
143  * Random sinusoidal warping *
144  *----------------------------------------------------------------------*/
180 PIX *
182  l_float32 xmag,
183  l_float32 ymag,
184  l_float32 xfreq,
185  l_float32 yfreq,
186  l_int32 nx,
187  l_int32 ny,
188  l_uint32 seed,
189  l_int32 grayval)
190 {
191 l_int32 w, h, d, i, j, wpls, wpld, val;
192 l_uint32 *datas, *datad, *lined;
193 l_float32 x, y;
194 l_float64 *randa;
195 PIX *pixd;
196 
197  PROCNAME("pixRandomHarmonicWarp");
198 
199  if (!pixs)
200  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
201  pixGetDimensions(pixs, &w, &h, &d);
202  if (d != 8)
203  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, 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  PROCNAME("generateRandomNumberArray");
243 
244  if ((randa = (l_float64 *)LEPT_CALLOC(size, sizeof(l_float64))) == NULL)
245  return (l_float64 *)ERROR_PTR("calloc fail for randa", procName, NULL);
246 
247  /* Return random values between 0.5 and 1.0 */
248  for (i = 0; i < size; i++)
249  randa[i] = 0.5 * (1.0 + (l_float64)rand() / (l_float64)RAND_MAX);
250  return randa;
251 }
252 
253 
260 static l_int32
261 applyWarpTransform(l_float32 xmag,
262  l_float32 ymag,
263  l_float32 xfreq,
264  l_float32 yfreq,
265  l_float64 *randa,
266  l_int32 nx,
267  l_int32 ny,
268  l_int32 xp,
269  l_int32 yp,
270  l_float32 *px,
271  l_float32 *py)
272 {
273 l_int32 i;
274 l_float64 twopi, x, y, anglex, angley;
275 
276  twopi = 6.283185;
277  for (i = 0, x = xp; i < nx; i++) {
278  anglex = xfreq * randa[3 * i + 1] * xp + twopi * randa[3 * i + 2];
279  angley = yfreq * randa[3 * i + 3] * yp + twopi * randa[3 * i + 4];
280  x += xmag * randa[3 * i] * sin(anglex) * sin(angley);
281  }
282  for (i = nx, y = yp; i < nx + ny; i++) {
283  angley = yfreq * randa[3 * i + 1] * yp + twopi * randa[3 * i + 2];
284  anglex = xfreq * randa[3 * i + 3] * xp + twopi * randa[3 * i + 4];
285  y += ymag * randa[3 * i] * sin(angley) * sin(anglex);
286  }
287 
288  *px = (l_float32)x;
289  *py = (l_float32)y;
290  return 0;
291 }
292 
293 
294 #if USE_SIN_TABLE
295 /*----------------------------------------------------------------------*
296  * Version using a LUT for sin *
297  *----------------------------------------------------------------------*/
298 static l_int32 applyWarpTransformLUT(l_float32 xmag, l_float32 ymag,
299  l_float32 xfreq, l_float32 yfreq,
300  l_float64 *randa, l_int32 nx, l_int32 ny,
301  l_int32 xp, l_int32 yp, l_float32 *lut,
302  l_int32 npts, l_float32 *px, l_float32 *py);
303 static l_int32 makeSinLUT(l_int32 npts, NUMA **pna);
304 static l_float32 getSinFromLUT(l_float32 *tab, l_int32 npts,
305  l_float32 radang);
306 
327 PIX *
328 pixRandomHarmonicWarpLUT(PIX *pixs,
329  l_float32 xmag,
330  l_float32 ymag,
331  l_float32 xfreq,
332  l_float32 yfreq,
333  l_int32 nx,
334  l_int32 ny,
335  l_uint32 seed,
336  l_int32 grayval)
337 {
338 l_int32 w, h, d, i, j, wpls, wpld, val, npts;
339 l_uint32 *datas, *datad, *lined;
340 l_float32 x, y;
341 l_float32 *lut;
342 l_float64 *randa;
343 NUMA *na;
344 PIX *pixd;
345 
346  PROCNAME("pixRandomHarmonicWarp");
347 
348  if (!pixs)
349  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
350  pixGetDimensions(pixs, &w, &h, &d);
351  if (d != 8)
352  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
353 
354  /* Compute filter output at each location. We iterate over
355  * the destination pixels. For each dest pixel, use the
356  * warp function to compute the four source pixels that
357  * contribute, at the location (x, y). Each source pixel
358  * is divided into 16 x 16 subpixels to get an approximate value. */
359  srand(seed);
360  randa = generateRandomNumberArray(5 * (nx + ny));
361  pixd = pixCreateTemplate(pixs);
362  datas = pixGetData(pixs);
363  wpls = pixGetWpl(pixs);
364  datad = pixGetData(pixd);
365  wpld = pixGetWpl(pixd);
366 
367  npts = 100;
368  makeSinLUT(npts, &na);
369  lut = numaGetFArray(na, L_NOCOPY);
370  for (i = 0; i < h; i++) {
371  lined = datad + i * wpld;
372  for (j = 0; j < w; j++) {
373  applyWarpTransformLUT(xmag, ymag, xfreq, yfreq, randa, nx, ny,
374  j, i, lut, npts, &x, &y);
375  linearInterpolatePixelGray(datas, wpls, w, h, x, y, grayval, &val);
376  SET_DATA_BYTE(lined, j, val);
377  }
378  }
379 
380  numaDestroy(&na);
381  LEPT_FREE(randa);
382  return pixd;
383 }
384 
385 
393 static l_int32
394 applyWarpTransformLUT(l_float32 xmag,
395  l_float32 ymag,
396  l_float32 xfreq,
397  l_float32 yfreq,
398  l_float64 *randa,
399  l_int32 nx,
400  l_int32 ny,
401  l_int32 xp,
402  l_int32 yp,
403  l_float32 *lut,
404  l_int32 npts,
405  l_float32 *px,
406  l_float32 *py)
407 {
408 l_int32 i;
409 l_float64 twopi, x, y, anglex, angley, sanglex, sangley;
410 
411  twopi = 6.283185;
412  for (i = 0, x = xp; i < nx; i++) {
413  anglex = xfreq * randa[3 * i + 1] * xp + twopi * randa[3 * i + 2];
414  angley = yfreq * randa[3 * i + 3] * yp + twopi * randa[3 * i + 4];
415  sanglex = getSinFromLUT(lut, npts, anglex);
416  sangley = getSinFromLUT(lut, npts, angley);
417  x += xmag * randa[3 * i] * sanglex * sangley;
418  }
419  for (i = nx, y = yp; i < nx + ny; i++) {
420  angley = yfreq * randa[3 * i + 1] * yp + twopi * randa[3 * i + 2];
421  anglex = xfreq * randa[3 * i + 3] * xp + twopi * randa[3 * i + 4];
422  sanglex = getSinFromLUT(lut, npts, anglex);
423  sangley = getSinFromLUT(lut, npts, angley);
424  y += ymag * randa[3 * i] * sangley * sanglex;
425  }
426 
427  *px = (l_float32)x;
428  *py = (l_float32)y;
429  return 0;
430 }
431 
432 
433 static l_int32
434 makeSinLUT(l_int32 npts,
435  NUMA **pna)
436 {
437 l_int32 i, n;
438 l_float32 delx, fval;
439 NUMA *na;
440 
441  PROCNAME("makeSinLUT");
442 
443  if (!pna)
444  return ERROR_INT("&na not defined", procName, 1);
445  *pna = NULL;
446  if (npts < 2)
447  return ERROR_INT("npts < 2", procName, 1);
448  n = 2 * npts + 1;
449  na = numaCreate(n);
450  *pna = na;
451  delx = 3.14159265 / (l_float32)npts;
452  numaSetParameters(na, 0.0, delx);
453  for (i = 0; i < n / 2; i++)
454  numaAddNumber(na, (l_float32)sin((l_float64)i * delx));
455  for (i = 0; i < n / 2; i++) {
456  numaGetFValue(na, i, &fval);
457  numaAddNumber(na, -fval);
458  }
459  numaAddNumber(na, 0);
460 
461  return 0;
462 }
463 
464 
465 static l_float32
466 getSinFromLUT(l_float32 *tab,
467  l_int32 npts,
468  l_float32 radang)
469 {
470 l_int32 index;
471 l_float32 twopi, invtwopi, findex, diff;
472 
473  /* Restrict radang to [0, 2pi] */
474  twopi = 6.283185;
475  invtwopi = 0.1591549;
476  if (radang < 0.0)
477  radang += twopi * (1.0 - (l_int32)(-radang * invtwopi));
478  else if (radang > 0.0)
479  radang -= twopi * (l_int32)(radang * invtwopi);
480 
481  /* Interpolate */
482  findex = (2.0 * (l_float32)npts) * (radang * invtwopi);
483  index = (l_int32)findex;
484  if (index == 2 * npts)
485  return tab[index];
486  diff = findex - index;
487  return (1.0 - diff) * tab[index] + diff * tab[index + 1];
488 }
489 #endif /* USE_SIN_TABLE */
490 
491 
492 
493 /*---------------------------------------------------------------------------*
494  * Stereoscopic warping *
495  *---------------------------------------------------------------------------*/
585 PIX *
587  l_int32 zbend,
588  l_int32 zshiftt,
589  l_int32 zshiftb,
590  l_int32 ybendt,
591  l_int32 ybendb,
592  l_int32 redleft)
593 {
594 l_int32 w, h, zshift;
595 l_float32 angle;
596 BOX *boxleft, *boxright;
597 PIX *pix1, *pix2, *pix3, *pix4, *pixr, *pixg, *pixb;
598 PIX *pixv1, *pixv2, *pixv3, *pixv4;
599 PIX *pixrs, *pixrss;
600 PIX *pixd;
601 
602  PROCNAME("pixWarpStereoscopic");
603 
604  if (!pixs)
605  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
606 
607  /* Convert to the output depth, 32 bpp. */
608  pix1 = pixConvertTo32(pixs);
609 
610  /* If requested, do a quad vertical shearing, pushing pixels up
611  * or down, depending on their distance from the centerline. */
612  pixGetDimensions(pixs, &w, &h, NULL);
613  boxleft = boxCreate(0, 0, w / 2, h);
614  boxright = boxCreate(w / 2, 0, w - w / 2, h);
615  if (ybendt != 0 || ybendb != 0) {
616  pixv1 = pixClipRectangle(pix1, boxleft, NULL);
617  pixv2 = pixClipRectangle(pix1, boxright, NULL);
618  pixv3 = pixQuadraticVShear(pixv1, L_WARP_TO_LEFT, ybendt,
619  ybendb, L_INTERPOLATED,
621  pixv4 = pixQuadraticVShear(pixv2, L_WARP_TO_RIGHT, ybendt,
622  ybendb, L_INTERPOLATED,
624  pix2 = pixCreate(w, h, 32);
625  pixRasterop(pix2, 0, 0, w / 2, h, PIX_SRC, pixv3, 0, 0);
626  pixRasterop(pix2, w / 2, 0, w - w / 2, h, PIX_SRC, pixv4, 0, 0);
627  pixDestroy(&pixv1);
628  pixDestroy(&pixv2);
629  pixDestroy(&pixv3);
630  pixDestroy(&pixv4);
631  } else {
632  pix2 = pixClone(pix1);
633  }
634  pixDestroy(&pix1);
635 
636  /* Split out the 3 components */
637  pixr = pixGetRGBComponent(pix2, COLOR_RED);
638  pixg = pixGetRGBComponent(pix2, COLOR_GREEN);
639  pixb = pixGetRGBComponent(pix2, COLOR_BLUE);
640  pixDestroy(&pix2);
641 
642  /* The direction of the stereo disparity below is set
643  * for the red filter to be over the left eye. If the red
644  * filter is over the right eye, invert the horizontal shifts. */
645  if (redleft) {
646  zbend = -zbend;
647  zshiftt = -zshiftt;
648  zshiftb = -zshiftb;
649  }
650 
651  /* Shift the red pixels horizontally by an amount that
652  * increases quadratically from the centerline. */
653  if (zbend == 0) {
654  pixrs = pixClone(pixr);
655  } else {
656  pix1 = pixClipRectangle(pixr, boxleft, NULL);
657  pix2 = pixClipRectangle(pixr, boxright, NULL);
662  pixrs = pixCreate(w, h, 8);
663  pixRasterop(pixrs, 0, 0, w / 2, h, PIX_SRC, pix3, 0, 0);
664  pixRasterop(pixrs, w / 2, 0, w - w / 2, h, PIX_SRC, pix4, 0, 0);
665  pixDestroy(&pix1);
666  pixDestroy(&pix2);
667  pixDestroy(&pix3);
668  pixDestroy(&pix4);
669  }
670 
671  /* Perform a combination of horizontal shift and shear of
672  * red pixels. The causes the plane of the image to tilt and
673  * also move forward or backward. */
674  if (zshiftt == 0 && zshiftb == 0) {
675  pixrss = pixClone(pixrs);
676  } else if (zshiftt == zshiftb) {
677  pixrss = pixTranslate(NULL, pixrs, zshiftt, 0, L_BRING_IN_WHITE);
678  } else {
679  angle = (l_float32)(zshiftb - zshiftt) /
680  L_MAX(1.0, (l_float32)pixGetHeight(pixrs));
681  zshift = (zshiftt + zshiftb) / 2;
682  pix1 = pixTranslate(NULL, pixrs, zshift, 0, L_BRING_IN_WHITE);
683  pixrss = pixHShearLI(pix1, h / 2, angle, L_BRING_IN_WHITE);
684  pixDestroy(&pix1);
685  }
686 
687  /* Combine the unchanged cyan (g,b) image with the shifted red */
688  pixd = pixCreateRGBImage(pixrss, pixg, pixb);
689 
690  boxDestroy(&boxleft);
691  boxDestroy(&boxright);
692  pixDestroy(&pixrs);
693  pixDestroy(&pixrss);
694  pixDestroy(&pixr);
695  pixDestroy(&pixg);
696  pixDestroy(&pixb);
697  return pixd;
698 }
699 
700 
701 /*----------------------------------------------------------------------*
702  * Linear and quadratic horizontal stretching *
703  *----------------------------------------------------------------------*/
732 PIX *
734  l_int32 dir,
735  l_int32 type,
736  l_int32 hmax,
737  l_int32 operation,
738  l_int32 incolor)
739 {
740 l_int32 d;
741 
742  PROCNAME("pixStretchHorizontal");
743 
744  if (!pixs)
745  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
746  d = pixGetDepth(pixs);
747  if (d != 1 && d != 8 && d != 32)
748  return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", procName, NULL);
749  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
750  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
751  if (type != L_LINEAR_WARP && type != L_QUADRATIC_WARP)
752  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
753  if (operation != L_SAMPLED && operation != L_INTERPOLATED)
754  return (PIX *)ERROR_PTR("invalid operation", procName, NULL);
755  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
756  return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
757  if (d == 1 && operation == L_INTERPOLATED) {
758  L_WARNING("Using sampling for 1 bpp\n", procName);
759  operation = L_INTERPOLATED;
760  }
761 
762  if (operation == L_SAMPLED)
763  return pixStretchHorizontalSampled(pixs, dir, type, hmax, incolor);
764  else
765  return pixStretchHorizontalLI(pixs, dir, type, hmax, incolor);
766 }
767 
768 
784 PIX *
786  l_int32 dir,
787  l_int32 type,
788  l_int32 hmax,
789  l_int32 incolor)
790 {
791 l_int32 i, j, jd, w, wm, h, d, wpls, wpld, val;
792 l_uint32 *datas, *datad, *lines, *lined;
793 PIX *pixd;
794 
795  PROCNAME("pixStretchHorizontalSampled");
796 
797  if (!pixs)
798  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
799  pixGetDimensions(pixs, &w, &h, &d);
800  if (d != 1 && d != 8 && d != 32)
801  return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", procName, NULL);
802  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
803  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
804  if (type != L_LINEAR_WARP && type != L_QUADRATIC_WARP)
805  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
806  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
807  return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
808 
809  pixd = pixCreateTemplate(pixs);
811  datas = pixGetData(pixs);
812  datad = pixGetData(pixd);
813  wpls = pixGetWpl(pixs);
814  wpld = pixGetWpl(pixd);
815  wm = w - 1;
816  for (jd = 0; jd < w; jd++) {
817  if (dir == L_WARP_TO_LEFT) {
818  if (type == L_LINEAR_WARP)
819  j = jd - (hmax * (wm - jd)) / wm;
820  else /* L_QUADRATIC_WARP */
821  j = jd - (hmax * (wm - jd) * (wm - jd)) / (wm * wm);
822  } else if (dir == L_WARP_TO_RIGHT) {
823  if (type == L_LINEAR_WARP)
824  j = jd - (hmax * jd) / wm;
825  else /* L_QUADRATIC_WARP */
826  j = jd - (hmax * jd * jd) / (wm * wm);
827  }
828  if (j < 0 || j > w - 1) continue;
829 
830  switch (d)
831  {
832  case 1:
833  for (i = 0; i < h; i++) {
834  lines = datas + i * wpls;
835  lined = datad + i * wpld;
836  val = GET_DATA_BIT(lines, j);
837  if (val)
838  SET_DATA_BIT(lined, jd);
839  }
840  break;
841  case 8:
842  for (i = 0; i < h; i++) {
843  lines = datas + i * wpls;
844  lined = datad + i * wpld;
845  val = GET_DATA_BYTE(lines, j);
846  SET_DATA_BYTE(lined, jd, val);
847  }
848  break;
849  case 32:
850  for (i = 0; i < h; i++) {
851  lines = datas + i * wpls;
852  lined = datad + i * wpld;
853  lined[jd] = lines[j];
854  }
855  break;
856  default:
857  L_ERROR("invalid depth: %d\n", procName, d);
858  pixDestroy(&pixd);
859  return NULL;
860  }
861  }
862 
863  return pixd;
864 }
865 
866 
882 PIX *
884  l_int32 dir,
885  l_int32 type,
886  l_int32 hmax,
887  l_int32 incolor)
888 {
889 l_int32 i, j, jd, jp, jf, w, wm, h, d, wpls, wpld, val, rval, gval, bval;
890 l_uint32 word0, word1;
891 l_uint32 *datas, *datad, *lines, *lined;
892 PIX *pixd;
893 
894  PROCNAME("pixStretchHorizontalLI");
895 
896  if (!pixs)
897  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
898  pixGetDimensions(pixs, &w, &h, &d);
899  if (d != 8 && d != 32)
900  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
901  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
902  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
903  if (type != L_LINEAR_WARP && type != L_QUADRATIC_WARP)
904  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
905  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
906  return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
907 
908  /* Standard linear interpolation, subdividing each pixel into 64 */
909  pixd = pixCreateTemplate(pixs);
911  datas = pixGetData(pixs);
912  datad = pixGetData(pixd);
913  wpls = pixGetWpl(pixs);
914  wpld = pixGetWpl(pixd);
915  wm = w - 1;
916  for (jd = 0; jd < w; jd++) {
917  if (dir == L_WARP_TO_LEFT) {
918  if (type == L_LINEAR_WARP)
919  j = 64 * jd - 64 * (hmax * (wm - jd)) / wm;
920  else /* L_QUADRATIC_WARP */
921  j = 64 * jd - 64 * (hmax * (wm - jd) * (wm - jd)) / (wm * wm);
922  } else if (dir == L_WARP_TO_RIGHT) {
923  if (type == L_LINEAR_WARP)
924  j = 64 * jd - 64 * (hmax * jd) / wm;
925  else /* L_QUADRATIC_WARP */
926  j = 64 * jd - 64 * (hmax * jd * jd) / (wm * wm);
927  }
928  jp = j / 64;
929  jf = j & 0x3f;
930  if (jp < 0 || jp > wm) continue;
931 
932  switch (d)
933  {
934  case 8:
935  if (jp < wm) {
936  for (i = 0; i < h; i++) {
937  lines = datas + i * wpls;
938  lined = datad + i * wpld;
939  val = ((63 - jf) * GET_DATA_BYTE(lines, jp) +
940  jf * GET_DATA_BYTE(lines, jp + 1) + 31) / 63;
941  SET_DATA_BYTE(lined, jd, val);
942  }
943  } else { /* jp == wm */
944  for (i = 0; i < h; i++) {
945  lines = datas + i * wpls;
946  lined = datad + i * wpld;
947  val = GET_DATA_BYTE(lines, jp);
948  SET_DATA_BYTE(lined, jd, val);
949  }
950  }
951  break;
952  case 32:
953  if (jp < wm) {
954  for (i = 0; i < h; i++) {
955  lines = datas + i * wpls;
956  lined = datad + i * wpld;
957  word0 = *(lines + jp);
958  word1 = *(lines + jp + 1);
959  rval = ((63 - jf) * ((word0 >> L_RED_SHIFT) & 0xff) +
960  jf * ((word1 >> L_RED_SHIFT) & 0xff) + 31) / 63;
961  gval = ((63 - jf) * ((word0 >> L_GREEN_SHIFT) & 0xff) +
962  jf * ((word1 >> L_GREEN_SHIFT) & 0xff) + 31) / 63;
963  bval = ((63 - jf) * ((word0 >> L_BLUE_SHIFT) & 0xff) +
964  jf * ((word1 >> L_BLUE_SHIFT) & 0xff) + 31) / 63;
965  composeRGBPixel(rval, gval, bval, lined + jd);
966  }
967  } else { /* jp == wm */
968  for (i = 0; i < h; i++) {
969  lines = datas + i * wpls;
970  lined = datad + i * wpld;
971  lined[jd] = lines[jp];
972  }
973  }
974  break;
975  default:
976  L_ERROR("invalid depth: %d\n", procName, d);
977  pixDestroy(&pixd);
978  return NULL;
979  }
980  }
981 
982  return pixd;
983 }
984 
985 
986 /*----------------------------------------------------------------------*
987  * Quadratic vertical shear *
988  *----------------------------------------------------------------------*/
1018 PIX *
1020  l_int32 dir,
1021  l_int32 vmaxt,
1022  l_int32 vmaxb,
1023  l_int32 operation,
1024  l_int32 incolor)
1025 {
1026 l_int32 w, h, d;
1027 
1028  PROCNAME("pixQuadraticVShear");
1029 
1030  if (!pixs)
1031  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1032  pixGetDimensions(pixs, &w, &h, &d);
1033  if (d != 1 && d != 8 && d != 32)
1034  return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", procName, NULL);
1035  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
1036  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1037  if (operation != L_SAMPLED && operation != L_INTERPOLATED)
1038  return (PIX *)ERROR_PTR("invalid operation", procName, NULL);
1039  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
1040  return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
1041 
1042  if (vmaxt == 0 && vmaxb == 0)
1043  return pixCopy(NULL, pixs);
1044 
1045  if (operation == L_INTERPOLATED && d == 1) {
1046  L_WARNING("no interpolation for 1 bpp; using sampling\n", procName);
1047  operation = L_SAMPLED;
1048  }
1049 
1050  if (operation == L_SAMPLED)
1051  return pixQuadraticVShearSampled(pixs, dir, vmaxt, vmaxb, incolor);
1052  else /* operation == L_INTERPOLATED */
1053  return pixQuadraticVShearLI(pixs, dir, vmaxt, vmaxb, incolor);
1054 }
1055 
1056 
1072 PIX *
1074  l_int32 dir,
1075  l_int32 vmaxt,
1076  l_int32 vmaxb,
1077  l_int32 incolor)
1078 {
1079 l_int32 i, j, id, w, h, d, wm, hm, wpls, wpld, val;
1080 l_uint32 *datas, *datad, *lines, *lined;
1081 l_float32 delrowt, delrowb, denom1, denom2, dely;
1082 PIX *pixd;
1083 
1084  PROCNAME("pixQuadraticVShearSampled");
1085 
1086  if (!pixs)
1087  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1088  pixGetDimensions(pixs, &w, &h, &d);
1089  if (d != 1 && d != 8 && d != 32)
1090  return (PIX *)ERROR_PTR("pixs not 1, 8 or 32 bpp", procName, NULL);
1091  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
1092  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1093  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
1094  return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
1095 
1096  if (vmaxt == 0 && vmaxb == 0)
1097  return pixCopy(NULL, pixs);
1098 
1099  pixd = pixCreateTemplate(pixs);
1101  datas = pixGetData(pixs);
1102  datad = pixGetData(pixd);
1103  wpls = pixGetWpl(pixs);
1104  wpld = pixGetWpl(pixd);
1105  wm = w - 1;
1106  hm = h - 1;
1107  denom1 = 1. / (l_float32)h;
1108  denom2 = 1. / (l_float32)(wm * wm);
1109  for (j = 0; j < w; j++) {
1110  if (dir == L_WARP_TO_LEFT) {
1111  delrowt = (l_float32)(vmaxt * (wm - j) * (wm - j)) * denom2;
1112  delrowb = (l_float32)(vmaxb * (wm - j) * (wm - j)) * denom2;
1113  } else if (dir == L_WARP_TO_RIGHT) {
1114  delrowt = (l_float32)(vmaxt * j * j) * denom2;
1115  delrowb = (l_float32)(vmaxb * j * j) * denom2;
1116  }
1117  switch (d)
1118  {
1119  case 1:
1120  for (id = 0; id < h; id++) {
1121  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1122  i = id - (l_int32)(dely + 0.5);
1123  if (i < 0 || i > hm) continue;
1124  lines = datas + i * wpls;
1125  lined = datad + id * wpld;
1126  val = GET_DATA_BIT(lines, j);
1127  if (val)
1128  SET_DATA_BIT(lined, j);
1129  }
1130  break;
1131  case 8:
1132  for (id = 0; id < h; id++) {
1133  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1134  i = id - (l_int32)(dely + 0.5);
1135  if (i < 0 || i > hm) continue;
1136  lines = datas + i * wpls;
1137  lined = datad + id * wpld;
1138  val = GET_DATA_BYTE(lines, j);
1139  SET_DATA_BYTE(lined, j, val);
1140  }
1141  break;
1142  case 32:
1143  for (id = 0; id < h; id++) {
1144  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1145  i = id - (l_int32)(dely + 0.5);
1146  if (i < 0 || i > hm) continue;
1147  lines = datas + i * wpls;
1148  lined = datad + id * wpld;
1149  lined[j] = lines[j];
1150  }
1151  break;
1152  default:
1153  L_ERROR("invalid depth: %d\n", procName, d);
1154  pixDestroy(&pixd);
1155  return NULL;
1156  }
1157  }
1158 
1159  return pixd;
1160 }
1161 
1162 
1178 PIX *
1180  l_int32 dir,
1181  l_int32 vmaxt,
1182  l_int32 vmaxb,
1183  l_int32 incolor)
1184 {
1185 l_int32 i, j, id, yp, yf, w, h, d, wm, hm, wpls, wpld;
1186 l_int32 val, rval, gval, bval;
1187 l_uint32 word0, word1;
1188 l_uint32 *datas, *datad, *lines, *lined;
1189 l_float32 delrowt, delrowb, denom1, denom2, dely;
1190 PIX *pix, *pixd;
1191 PIXCMAP *cmap;
1192 
1193  PROCNAME("pixQuadraticVShearLI");
1194 
1195  if (!pixs)
1196  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1197  pixGetDimensions(pixs, &w, &h, &d);
1198  if (d == 1)
1199  return (PIX *)ERROR_PTR("pixs is 1 bpp", procName, NULL);
1200  cmap = pixGetColormap(pixs);
1201  if (d != 8 && d != 32 && !cmap)
1202  return (PIX *)ERROR_PTR("pixs not 8, 32 bpp, or cmap", procName, NULL);
1203  if (dir != L_WARP_TO_LEFT && dir != L_WARP_TO_RIGHT)
1204  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1205  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
1206  return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
1207 
1208  if (vmaxt == 0 && vmaxb == 0)
1209  return pixCopy(NULL, pixs);
1210 
1211  /* Remove any existing colormap */
1212  if (cmap)
1214  else
1215  pix = pixClone(pixs);
1216  d = pixGetDepth(pix);
1217  if (d != 8 && d != 32) {
1218  pixDestroy(&pix);
1219  return (PIX *)ERROR_PTR("invalid depth", procName, NULL);
1220  }
1221 
1222  /* Standard linear interp: subdivide each pixel into 64 parts */
1223  pixd = pixCreateTemplate(pix);
1225  datas = pixGetData(pix);
1226  datad = pixGetData(pixd);
1227  wpls = pixGetWpl(pix);
1228  wpld = pixGetWpl(pixd);
1229  wm = w - 1;
1230  hm = h - 1;
1231  denom1 = 1.0 / (l_float32)h;
1232  denom2 = 1.0 / (l_float32)(wm * wm);
1233  for (j = 0; j < w; j++) {
1234  if (dir == L_WARP_TO_LEFT) {
1235  delrowt = (l_float32)(vmaxt * (wm - j) * (wm - j)) * denom2;
1236  delrowb = (l_float32)(vmaxb * (wm - j) * (wm - j)) * denom2;
1237  } else if (dir == L_WARP_TO_RIGHT) {
1238  delrowt = (l_float32)(vmaxt * j * j) * denom2;
1239  delrowb = (l_float32)(vmaxb * j * j) * denom2;
1240  }
1241  switch (d)
1242  {
1243  case 8:
1244  for (id = 0; id < h; id++) {
1245  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1246  i = 64 * id - (l_int32)(64.0 * dely);
1247  yp = i / 64;
1248  yf = i & 63;
1249  if (yp < 0 || yp > hm) continue;
1250  lines = datas + yp * wpls;
1251  lined = datad + id * wpld;
1252  if (yp < hm) {
1253  val = ((63 - yf) * GET_DATA_BYTE(lines, j) +
1254  yf * GET_DATA_BYTE(lines + wpls, j) + 31) / 63;
1255  } else { /* yp == hm */
1256  val = GET_DATA_BYTE(lines, j);
1257  }
1258  SET_DATA_BYTE(lined, j, val);
1259  }
1260  break;
1261  case 32:
1262  for (id = 0; id < h; id++) {
1263  dely = (delrowt * (hm - id) + delrowb * id) * denom1;
1264  i = 64 * id - (l_int32)(64.0 * dely);
1265  yp = i / 64;
1266  yf = i & 63;
1267  if (yp < 0 || yp > hm) continue;
1268  lines = datas + yp * wpls;
1269  lined = datad + id * wpld;
1270  if (yp < hm) {
1271  word0 = *(lines + j);
1272  word1 = *(lines + wpls + j);
1273  rval = ((63 - yf) * ((word0 >> L_RED_SHIFT) & 0xff) +
1274  yf * ((word1 >> L_RED_SHIFT) & 0xff) + 31) / 63;
1275  gval = ((63 - yf) * ((word0 >> L_GREEN_SHIFT) & 0xff) +
1276  yf * ((word1 >> L_GREEN_SHIFT) & 0xff) + 31) / 63;
1277  bval = ((63 - yf) * ((word0 >> L_BLUE_SHIFT) & 0xff) +
1278  yf * ((word1 >> L_BLUE_SHIFT) & 0xff) + 31) / 63;
1279  composeRGBPixel(rval, gval, bval, lined + j);
1280  } else { /* yp == hm */
1281  lined[j] = lines[j];
1282  }
1283  }
1284  break;
1285  default:
1286  L_ERROR("invalid depth: %d\n", procName, d);
1287  pixDestroy(&pix);
1288  pixDestroy(&pixd);
1289  return NULL;
1290  }
1291  }
1292 
1293  pixDestroy(&pix);
1294  return pixd;
1295 }
1296 
1297 
1298 /*----------------------------------------------------------------------*
1299  * Stereo from a pair of images *
1300  *----------------------------------------------------------------------*/
1331 PIX *
1333  PIX *pix2,
1334  l_float32 rwt,
1335  l_float32 gwt,
1336  l_float32 bwt)
1337 {
1338 l_int32 i, j, w, h, wpl1, wpl2, rval, gval, bval;
1339 l_uint32 word1, word2;
1340 l_uint32 *data1, *data2, *datad, *line1, *line2, *lined;
1341 l_float32 sum;
1342 PIX *pixd;
1343 
1344  PROCNAME("pixStereoFromPair");
1345 
1346  if (!pix1 || !pix2)
1347  return (PIX *)ERROR_PTR("pix1, pix2 not both defined", procName, NULL);
1348  if (pixGetDepth(pix1) != 32 || pixGetDepth(pix2) != 32)
1349  return (PIX *)ERROR_PTR("pix1, pix2 not both 32 bpp", procName, NULL);
1350 
1351  /* Make sure the sum of weights is 1.0; otherwise, you can get
1352  * overflow in the gray value. */
1353  if (rwt == 0.0 && gwt == 0.0 && bwt == 0.0) {
1354  rwt = L_DEFAULT_RED_WEIGHT;
1355  gwt = L_DEFAULT_GREEN_WEIGHT;
1356  bwt = L_DEFAULT_BLUE_WEIGHT;
1357  }
1358  sum = rwt + gwt + bwt;
1359  if (L_ABS(sum - 1.0) > 0.0001) { /* maintain ratios with sum == 1.0 */
1360  L_WARNING("weights don't sum to 1; maintaining ratios\n", procName);
1361  rwt = rwt / sum;
1362  gwt = gwt / sum;
1363  bwt = bwt / sum;
1364  }
1365 
1366  pixGetDimensions(pix1, &w, &h, NULL);
1367  pixd = pixCreateTemplate(pix1);
1368  data1 = pixGetData(pix1);
1369  data2 = pixGetData(pix2);
1370  datad = pixGetData(pixd);
1371  wpl1 = pixGetWpl(pix1);
1372  wpl2 = pixGetWpl(pix2);
1373  for (i = 0; i < h; i++) {
1374  line1 = data1 + i * wpl1;
1375  line2 = data2 + i * wpl2;
1376  lined = datad + i * wpl1; /* wpl1 works for pixd */
1377  for (j = 0; j < w; j++) {
1378  word1 = *(line1 + j);
1379  word2 = *(line2 + j);
1380  rval = (l_int32)(rwt * ((word1 >> L_RED_SHIFT) & 0xff) +
1381  gwt * ((word1 >> L_GREEN_SHIFT) & 0xff) +
1382  bwt * ((word1 >> L_BLUE_SHIFT) & 0xff) + 0.5);
1383  gval = (word2 >> L_GREEN_SHIFT) & 0xff;
1384  bval = (word2 >> L_BLUE_SHIFT) & 0xff;
1385  composeRGBPixel(rval, gval, bval, lined + j);
1386  }
1387  }
1388 
1389  return pixd;
1390 }
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:586
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:692
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:322
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3233
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
PIX * pixSimpleCaptcha(PIX *pixs, l_int32 border, l_int32 nterms, l_uint32 seed, l_uint32 color, l_int32 cmapflag)
pixSimpleCaptcha()
Definition: warper.c:107
Definition: pix.h:716
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:193
PIX * pixQuadraticVShearLI(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 incolor)
pixQuadraticVShearLI()
Definition: warper.c:1179
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
PIX * pixHShearLI(PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShearLI()
Definition: shear.c:617
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
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:1266
PIX * pixStretchHorizontalSampled(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 incolor)
pixStretchHorizontalSampled()
Definition: warper.c:785
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:261
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:367
PIX * pixColorizeGray(PIX *pixs, l_uint32 color, l_int32 cmapflag)
pixColorizeGray()
Definition: pixconv.c:1323
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1020
PIX * pixQuadraticVShear(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 operation, l_int32 incolor)
pixQuadraticVShear()
Definition: warper.c:1019
PIX * pixStretchHorizontalLI(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 incolor)
pixStretchHorizontalLI()
Definition: warper.c:883
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2404
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1748
Definition: array.h:59
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
l_ok pixSetBlackOrWhite(PIX *pixs, l_int32 op)
pixSetBlackOrWhite()
Definition: pix2.c:946
PIX * pixStereoFromPair(PIX *pix1, PIX *pix2, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixStereoFromPair()
Definition: warper.c:1332
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:966
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
Definition: pix2.c:2348
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
PIX * pixQuadraticVShearSampled(PIX *pixs, l_int32 dir, l_int32 vmaxt, l_int32 vmaxb, l_int32 incolor)
pixQuadraticVShearSampled()
Definition: warper.c:1073
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:181
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:865
PIX * pixStretchHorizontal(PIX *pixs, l_int32 dir, l_int32 type, l_int32 hmax, l_int32 operation, l_int32 incolor)
pixStretchHorizontal()
Definition: warper.c:733
Definition: pix.h:134
#define PIX_SRC
Definition: pix.h:327
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
Definition: pix.h:201
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
PIX * pixTranslate(PIX *pixd, PIX *pixs, l_int32 hshift, l_int32 vshift, l_int32 incolor)
pixTranslate()
Definition: rop.c:431
Definition: pix.h:480
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:165
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127