Leptonica  1.82.0
Image processing and image analysis suite
affine.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 
27 
234 #ifdef HAVE_CONFIG_H
235 #include <config_auto.h>
236 #endif /* HAVE_CONFIG_H */
237 
238 #include <string.h>
239 #include <math.h>
240 #include "allheaders.h"
241 
242 extern l_float32 AlphaMaskBorderVals[2];
243 
244 #ifndef NO_CONSOLE_IO
245 #define DEBUG 0
246 #endif /* ~NO_CONSOLE_IO */
247 
248 /*-------------------------------------------------------------*
249  * Sampled affine image transformation *
250  *-------------------------------------------------------------*/
281 PIX *
283  PTA *ptad,
284  PTA *ptas,
285  l_int32 incolor)
286 {
287 l_float32 *vc;
288 PIX *pixd;
289 
290  PROCNAME("pixAffineSampledPta");
291 
292  if (!pixs)
293  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
294  if (!ptas)
295  return (PIX *)ERROR_PTR("ptas not defined", procName, NULL);
296  if (!ptad)
297  return (PIX *)ERROR_PTR("ptad not defined", procName, NULL);
298  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
299  return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
300  if (ptaGetCount(ptas) != 3)
301  return (PIX *)ERROR_PTR("ptas count not 3", procName, NULL);
302  if (ptaGetCount(ptad) != 3)
303  return (PIX *)ERROR_PTR("ptad count not 3", procName, NULL);
304 
305  /* Get backwards transform from dest to src, and apply it */
306  getAffineXformCoeffs(ptad, ptas, &vc);
307  pixd = pixAffineSampled(pixs, vc, incolor);
308  LEPT_FREE(vc);
309 
310  return pixd;
311 }
312 
313 
331 PIX *
333  l_float32 *vc,
334  l_int32 incolor)
335 {
336 l_int32 i, j, w, h, d, x, y, wpls, wpld, color, cmapindex;
337 l_uint32 val;
338 l_uint32 *datas, *datad, *lines, *lined;
339 PIX *pixd;
340 PIXCMAP *cmap;
341 
342  PROCNAME("pixAffineSampled");
343 
344  if (!pixs)
345  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
346  if (!vc)
347  return (PIX *)ERROR_PTR("vc not defined", procName, NULL);
348  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
349  return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
350  pixGetDimensions(pixs, &w, &h, &d);
351  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 32)
352  return (PIX *)ERROR_PTR("depth not 1, 2, 4, 8 or 16", procName, NULL);
353 
354  /* Init all dest pixels to color to be brought in from outside */
355  pixd = pixCreateTemplate(pixs);
356  if ((cmap = pixGetColormap(pixs)) != NULL) {
357  if (incolor == L_BRING_IN_WHITE)
358  color = 1;
359  else
360  color = 0;
361  pixcmapAddBlackOrWhite(cmap, color, &cmapindex);
362  pixSetAllArbitrary(pixd, cmapindex);
363  } else {
364  if ((d == 1 && incolor == L_BRING_IN_WHITE) ||
365  (d > 1 && incolor == L_BRING_IN_BLACK)) {
366  pixClearAll(pixd);
367  } else {
368  pixSetAll(pixd);
369  }
370  }
371 
372  /* Scan over the dest pixels */
373  datas = pixGetData(pixs);
374  wpls = pixGetWpl(pixs);
375  datad = pixGetData(pixd);
376  wpld = pixGetWpl(pixd);
377  for (i = 0; i < h; i++) {
378  lined = datad + i * wpld;
379  for (j = 0; j < w; j++) {
380  affineXformSampledPt(vc, j, i, &x, &y);
381  if (x < 0 || y < 0 || x >=w || y >= h)
382  continue;
383  lines = datas + y * wpls;
384  if (d == 1) {
385  val = GET_DATA_BIT(lines, x);
386  SET_DATA_BIT_VAL(lined, j, val);
387  } else if (d == 8) {
388  val = GET_DATA_BYTE(lines, x);
389  SET_DATA_BYTE(lined, j, val);
390  } else if (d == 32) {
391  lined[j] = lines[x];
392  } else if (d == 2) {
393  val = GET_DATA_DIBIT(lines, x);
394  SET_DATA_DIBIT(lined, j, val);
395  } else if (d == 4) {
396  val = GET_DATA_QBIT(lines, x);
397  SET_DATA_QBIT(lined, j, val);
398  }
399  }
400  }
401 
402  return pixd;
403 }
404 
405 
406 /*---------------------------------------------------------------------*
407  * Interpolated affine image transformation *
408  *---------------------------------------------------------------------*/
424 PIX *
426  PTA *ptad,
427  PTA *ptas,
428  l_int32 incolor)
429 {
430 l_int32 d;
431 l_uint32 colorval;
432 PIX *pixt1, *pixt2, *pixd;
433 
434  PROCNAME("pixAffinePta");
435 
436  if (!pixs)
437  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
438  if (!ptas)
439  return (PIX *)ERROR_PTR("ptas not defined", procName, NULL);
440  if (!ptad)
441  return (PIX *)ERROR_PTR("ptad not defined", procName, NULL);
442  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
443  return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
444  if (ptaGetCount(ptas) != 3)
445  return (PIX *)ERROR_PTR("ptas count not 3", procName, NULL);
446  if (ptaGetCount(ptad) != 3)
447  return (PIX *)ERROR_PTR("ptad count not 3", procName, NULL);
448 
449  if (pixGetDepth(pixs) == 1)
450  return pixAffineSampledPta(pixs, ptad, ptas, incolor);
451 
452  /* Remove cmap if it exists, and unpack to 8 bpp if necessary */
454  d = pixGetDepth(pixt1);
455  if (d < 8)
456  pixt2 = pixConvertTo8(pixt1, FALSE);
457  else
458  pixt2 = pixClone(pixt1);
459  d = pixGetDepth(pixt2);
460 
461  /* Compute actual color to bring in from edges */
462  colorval = 0;
463  if (incolor == L_BRING_IN_WHITE) {
464  if (d == 8)
465  colorval = 255;
466  else /* d == 32 */
467  colorval = 0xffffff00;
468  }
469 
470  if (d == 8)
471  pixd = pixAffinePtaGray(pixt2, ptad, ptas, colorval);
472  else /* d == 32 */
473  pixd = pixAffinePtaColor(pixt2, ptad, ptas, colorval);
474  pixDestroy(&pixt1);
475  pixDestroy(&pixt2);
476  return pixd;
477 }
478 
479 
494 PIX *
496  l_float32 *vc,
497  l_int32 incolor)
498 {
499 l_int32 d;
500 l_uint32 colorval;
501 PIX *pixt1, *pixt2, *pixd;
502 
503  PROCNAME("pixAffine");
504 
505  if (!pixs)
506  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
507  if (!vc)
508  return (PIX *)ERROR_PTR("vc not defined", procName, NULL);
509 
510  if (pixGetDepth(pixs) == 1)
511  return pixAffineSampled(pixs, vc, incolor);
512 
513  /* Remove cmap if it exists, and unpack to 8 bpp if necessary */
515  d = pixGetDepth(pixt1);
516  if (d < 8)
517  pixt2 = pixConvertTo8(pixt1, FALSE);
518  else
519  pixt2 = pixClone(pixt1);
520  d = pixGetDepth(pixt2);
521 
522  /* Compute actual color to bring in from edges */
523  colorval = 0;
524  if (incolor == L_BRING_IN_WHITE) {
525  if (d == 8)
526  colorval = 255;
527  else /* d == 32 */
528  colorval = 0xffffff00;
529  }
530 
531  if (d == 8)
532  pixd = pixAffineGray(pixt2, vc, colorval);
533  else /* d == 32 */
534  pixd = pixAffineColor(pixt2, vc, colorval);
535  pixDestroy(&pixt1);
536  pixDestroy(&pixt2);
537  return pixd;
538 }
539 
540 
550 PIX *
552  PTA *ptad,
553  PTA *ptas,
554  l_uint32 colorval)
555 {
556 l_float32 *vc;
557 PIX *pixd;
558 
559  PROCNAME("pixAffinePtaColor");
560 
561  if (!pixs)
562  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
563  if (!ptas)
564  return (PIX *)ERROR_PTR("ptas not defined", procName, NULL);
565  if (!ptad)
566  return (PIX *)ERROR_PTR("ptad not defined", procName, NULL);
567  if (pixGetDepth(pixs) != 32)
568  return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
569  if (ptaGetCount(ptas) != 3)
570  return (PIX *)ERROR_PTR("ptas count not 3", procName, NULL);
571  if (ptaGetCount(ptad) != 3)
572  return (PIX *)ERROR_PTR("ptad count not 3", procName, NULL);
573 
574  /* Get backwards transform from dest to src, and apply it */
575  getAffineXformCoeffs(ptad, ptas, &vc);
576  pixd = pixAffineColor(pixs, vc, colorval);
577  LEPT_FREE(vc);
578 
579  return pixd;
580 }
581 
582 
591 PIX *
593  l_float32 *vc,
594  l_uint32 colorval)
595 {
596 l_int32 i, j, w, h, d, wpls, wpld;
597 l_uint32 val;
598 l_uint32 *datas, *datad, *lined;
599 l_float32 x, y;
600 PIX *pix1, *pix2, *pixd;
601 
602  PROCNAME("pixAffineColor");
603 
604  if (!pixs)
605  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
606  pixGetDimensions(pixs, &w, &h, &d);
607  if (d != 32)
608  return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
609  if (!vc)
610  return (PIX *)ERROR_PTR("vc not defined", procName, NULL);
611 
612  datas = pixGetData(pixs);
613  wpls = pixGetWpl(pixs);
614  pixd = pixCreateTemplate(pixs);
615  pixSetAllArbitrary(pixd, colorval);
616  datad = pixGetData(pixd);
617  wpld = pixGetWpl(pixd);
618 
619  /* Iterate over destination pixels */
620  for (i = 0; i < h; i++) {
621  lined = datad + i * wpld;
622  for (j = 0; j < w; j++) {
623  /* Compute float src pixel location corresponding to (i,j) */
624  affineXformPt(vc, j, i, &x, &y);
625  linearInterpolatePixelColor(datas, wpls, w, h, x, y, colorval,
626  &val);
627  *(lined + j) = val;
628  }
629  }
630 
631  /* If rgba, transform the pixs alpha channel and insert in pixd */
632  if (pixGetSpp(pixs) == 4) {
633  pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
634  pix2 = pixAffineGray(pix1, vc, 255); /* bring in opaque */
635  pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
636  pixDestroy(&pix1);
637  pixDestroy(&pix2);
638  }
639 
640  return pixd;
641 }
642 
643 
653 PIX *
655  PTA *ptad,
656  PTA *ptas,
657  l_uint8 grayval)
658 {
659 l_float32 *vc;
660 PIX *pixd;
661 
662  PROCNAME("pixAffinePtaGray");
663 
664  if (!pixs)
665  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
666  if (!ptas)
667  return (PIX *)ERROR_PTR("ptas not defined", procName, NULL);
668  if (!ptad)
669  return (PIX *)ERROR_PTR("ptad not defined", procName, NULL);
670  if (pixGetDepth(pixs) != 8)
671  return (PIX *)ERROR_PTR("pixs must be 8 bpp", procName, NULL);
672  if (ptaGetCount(ptas) != 3)
673  return (PIX *)ERROR_PTR("ptas count not 3", procName, NULL);
674  if (ptaGetCount(ptad) != 3)
675  return (PIX *)ERROR_PTR("ptad count not 3", procName, NULL);
676 
677  /* Get backwards transform from dest to src, and apply it */
678  getAffineXformCoeffs(ptad, ptas, &vc);
679  pixd = pixAffineGray(pixs, vc, grayval);
680  LEPT_FREE(vc);
681 
682  return pixd;
683 }
684 
685 
686 
695 PIX *
697  l_float32 *vc,
698  l_uint8 grayval)
699 {
700 l_int32 i, j, w, h, wpls, wpld, val;
701 l_uint32 *datas, *datad, *lined;
702 l_float32 x, y;
703 PIX *pixd;
704 
705  PROCNAME("pixAffineGray");
706 
707  if (!pixs)
708  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
709  pixGetDimensions(pixs, &w, &h, NULL);
710  if (pixGetDepth(pixs) != 8)
711  return (PIX *)ERROR_PTR("pixs must be 8 bpp", procName, NULL);
712  if (!vc)
713  return (PIX *)ERROR_PTR("vc not defined", procName, NULL);
714 
715  datas = pixGetData(pixs);
716  wpls = pixGetWpl(pixs);
717  pixd = pixCreateTemplate(pixs);
718  pixSetAllArbitrary(pixd, grayval);
719  datad = pixGetData(pixd);
720  wpld = pixGetWpl(pixd);
721 
722  /* Iterate over destination pixels */
723  for (i = 0; i < h; i++) {
724  lined = datad + i * wpld;
725  for (j = 0; j < w; j++) {
726  /* Compute float src pixel location corresponding to (i,j) */
727  affineXformPt(vc, j, i, &x, &y);
728  linearInterpolatePixelGray(datas, wpls, w, h, x, y, grayval, &val);
729  SET_DATA_BYTE(lined, j, val);
730  }
731  }
732 
733  return pixd;
734 }
735 
736 
737 /*---------------------------------------------------------------------------*
738  * Affine transform including alpha (blend) component *
739  *---------------------------------------------------------------------------*/
783 PIX *
785  PTA *ptad,
786  PTA *ptas,
787  PIX *pixg,
788  l_float32 fract,
789  l_int32 border)
790 {
791 l_int32 ws, hs, d;
792 PIX *pixd, *pixb1, *pixb2, *pixg2, *pixga;
793 PTA *ptad2, *ptas2;
794 
795  PROCNAME("pixAffinePtaWithAlpha");
796 
797  if (!pixs)
798  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
799  pixGetDimensions(pixs, &ws, &hs, &d);
800  if (d != 32 && pixGetColormap(pixs) == NULL)
801  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
802  if (pixg && pixGetDepth(pixg) != 8) {
803  L_WARNING("pixg not 8 bpp; using 'fract' transparent alpha\n",
804  procName);
805  pixg = NULL;
806  }
807  if (!pixg && (fract < 0.0 || fract > 1.0)) {
808  L_WARNING("invalid fract; using 1.0 (fully transparent)\n", procName);
809  fract = 1.0;
810  }
811  if (!pixg && fract == 0.0)
812  L_WARNING("fully opaque alpha; image will not be blended\n", procName);
813  if (!ptad)
814  return (PIX *)ERROR_PTR("ptad not defined", procName, NULL);
815  if (!ptas)
816  return (PIX *)ERROR_PTR("ptas not defined", procName, NULL);
817 
818  /* Add border; the color doesn't matter */
819  pixb1 = pixAddBorder(pixs, border, 0);
820 
821  /* Transform the ptr arrays to work on the bordered image */
822  ptad2 = ptaTransform(ptad, border, border, 1.0, 1.0);
823  ptas2 = ptaTransform(ptas, border, border, 1.0, 1.0);
824 
825  /* Do separate affine transform of rgb channels of pixs and of pixg */
826  pixd = pixAffinePtaColor(pixb1, ptad2, ptas2, 0);
827  if (!pixg) {
828  pixg2 = pixCreate(ws, hs, 8);
829  if (fract == 1.0)
830  pixSetAll(pixg2);
831  else
832  pixSetAllArbitrary(pixg2, (l_int32)(255.0 * fract));
833  } else {
834  pixg2 = pixResizeToMatch(pixg, NULL, ws, hs);
835  }
836  if (ws > 10 && hs > 10) { /* see note 7 */
837  pixSetBorderRingVal(pixg2, 1,
838  (l_int32)(255.0 * fract * AlphaMaskBorderVals[0]));
839  pixSetBorderRingVal(pixg2, 2,
840  (l_int32)(255.0 * fract * AlphaMaskBorderVals[1]));
841 
842  }
843  pixb2 = pixAddBorder(pixg2, border, 0); /* must be black border */
844  pixga = pixAffinePtaGray(pixb2, ptad2, ptas2, 0);
845  pixSetRGBComponent(pixd, pixga, L_ALPHA_CHANNEL);
846  pixSetSpp(pixd, 4);
847 
848  pixDestroy(&pixg2);
849  pixDestroy(&pixb1);
850  pixDestroy(&pixb2);
851  pixDestroy(&pixga);
852  ptaDestroy(&ptad2);
853  ptaDestroy(&ptas2);
854  return pixd;
855 }
856 
857 
858 /*-------------------------------------------------------------*
859  * Affine coordinate transformation *
860  *-------------------------------------------------------------*/
932 l_ok
934  PTA *ptad,
935  l_float32 **pvc)
936 {
937 l_int32 i;
938 l_float32 x1, y1, x2, y2, x3, y3;
939 l_float32 *b; /* rhs vector of primed coords X'; coeffs returned in *pvc */
940 l_float32 *a[6]; /* 6x6 matrix A */
941 
942  PROCNAME("getAffineXformCoeffs");
943 
944  if (!ptas)
945  return ERROR_INT("ptas not defined", procName, 1);
946  if (!ptad)
947  return ERROR_INT("ptad not defined", procName, 1);
948  if (!pvc)
949  return ERROR_INT("&vc not defined", procName, 1);
950 
951  b = (l_float32 *)LEPT_CALLOC(6, sizeof(l_float32));
952  *pvc = b;
953 
954  ptaGetPt(ptas, 0, &x1, &y1);
955  ptaGetPt(ptas, 1, &x2, &y2);
956  ptaGetPt(ptas, 2, &x3, &y3);
957  ptaGetPt(ptad, 0, &b[0], &b[1]);
958  ptaGetPt(ptad, 1, &b[2], &b[3]);
959  ptaGetPt(ptad, 2, &b[4], &b[5]);
960 
961  for (i = 0; i < 6; i++)
962  a[i] = (l_float32 *)LEPT_CALLOC(6, sizeof(l_float32));
963  a[0][0] = x1;
964  a[0][1] = y1;
965  a[0][2] = 1.;
966  a[1][3] = x1;
967  a[1][4] = y1;
968  a[1][5] = 1.;
969  a[2][0] = x2;
970  a[2][1] = y2;
971  a[2][2] = 1.;
972  a[3][3] = x2;
973  a[3][4] = y2;
974  a[3][5] = 1.;
975  a[4][0] = x3;
976  a[4][1] = y3;
977  a[4][2] = 1.;
978  a[5][3] = x3;
979  a[5][4] = y3;
980  a[5][5] = 1.;
981 
982  gaussjordan(a, b, 6);
983 
984  for (i = 0; i < 6; i++)
985  LEPT_FREE(a[i]);
986 
987  return 0;
988 }
989 
990 
1022 l_ok
1023 affineInvertXform(l_float32 *vc,
1024  l_float32 **pvci)
1025 {
1026 l_int32 i;
1027 l_float32 *vci;
1028 l_float32 *a[3];
1029 l_float32 b[3] = {1.0, 1.0, 1.0}; /* anything; results ignored */
1030 
1031  PROCNAME("affineInvertXform");
1032 
1033  if (!pvci)
1034  return ERROR_INT("&vci not defined", procName, 1);
1035  *pvci = NULL;
1036  if (!vc)
1037  return ERROR_INT("vc not defined", procName, 1);
1038 
1039 #if 1
1040  for (i = 0; i < 3; i++)
1041  a[i] = (l_float32 *)LEPT_CALLOC(3, sizeof(l_float32));
1042  a[0][0] = vc[0];
1043  a[0][1] = vc[1];
1044  a[0][2] = vc[2];
1045  a[1][0] = vc[3];
1046  a[1][1] = vc[4];
1047  a[1][2] = vc[5];
1048  a[2][2] = 1.0;
1049  gaussjordan(a, b, 3); /* this inverts matrix a */
1050  vci = (l_float32 *)LEPT_CALLOC(6, sizeof(l_float32));
1051  *pvci = vci;
1052  vci[0] = a[0][0];
1053  vci[1] = a[0][1];
1054  vci[2] = a[0][2];
1055  vci[3] = a[1][0];
1056  vci[4] = a[1][1];
1057  vci[5] = a[1][2];
1058  for (i = 0; i < 3; i++)
1059  LEPT_FREE(a[i]);
1060 
1061 #else
1062 
1063  /* Alternative version, inverting a 2x2 matrix */
1064  { l_float32 *a2[2];
1065  for (i = 0; i < 2; i++)
1066  a2[i] = (l_float32 *)LEPT_CALLOC(2, sizeof(l_float32));
1067  a2[0][0] = vc[0];
1068  a2[0][1] = vc[1];
1069  a2[1][0] = vc[3];
1070  a2[1][1] = vc[4];
1071  b[0] = vc[2];
1072  b[1] = vc[5];
1073  gaussjordan(a2, b, 2); /* this inverts matrix a2 */
1074  vci = (l_float32 *)LEPT_CALLOC(6, sizeof(l_float32));
1075  *pvci = vci;
1076  vci[0] = a2[0][0];
1077  vci[1] = a2[0][1];
1078  vci[2] = -b[0]; /* note sign */
1079  vci[3] = a2[1][0];
1080  vci[4] = a2[1][1];
1081  vci[5] = -b[1]; /* note sign */
1082  for (i = 0; i < 2; i++)
1083  LEPT_FREE(a2[i]);
1084  }
1085 #endif
1086 
1087  return 0;
1088 }
1089 
1090 
1105 l_ok
1106 affineXformSampledPt(l_float32 *vc,
1107  l_int32 x,
1108  l_int32 y,
1109  l_int32 *pxp,
1110  l_int32 *pyp)
1111 {
1112  PROCNAME("affineXformSampledPt");
1113 
1114  if (!vc)
1115  return ERROR_INT("vc not defined", procName, 1);
1116 
1117  *pxp = (l_int32)(vc[0] * x + vc[1] * y + vc[2] + 0.5);
1118  *pyp = (l_int32)(vc[3] * x + vc[4] * y + vc[5] + 0.5);
1119  return 0;
1120 }
1121 
1122 
1137 l_ok
1138 affineXformPt(l_float32 *vc,
1139  l_int32 x,
1140  l_int32 y,
1141  l_float32 *pxp,
1142  l_float32 *pyp)
1143 {
1144  PROCNAME("affineXformPt");
1145 
1146  if (!vc)
1147  return ERROR_INT("vc not defined", procName, 1);
1148 
1149  *pxp = vc[0] * x + vc[1] * y + vc[2];
1150  *pyp = vc[3] * x + vc[4] * y + vc[5];
1151  return 0;
1152 }
1153 
1154 
1155 /*-------------------------------------------------------------*
1156  * Interpolation helper functions *
1157  *-------------------------------------------------------------*/
1178 l_ok
1180  l_int32 wpls,
1181  l_int32 w,
1182  l_int32 h,
1183  l_float32 x,
1184  l_float32 y,
1185  l_uint32 colorval,
1186  l_uint32 *pval)
1187 {
1188 l_int32 valid, xpm, ypm, xp, xp2, yp, xf, yf;
1189 l_int32 rval, gval, bval;
1190 l_uint32 word00, word01, word10, word11;
1191 l_uint32 *lines;
1192 
1193  PROCNAME("linearInterpolatePixelColor");
1194 
1195  if (!pval)
1196  return ERROR_INT("&val not defined", procName, 1);
1197  *pval = colorval;
1198  if (!datas)
1199  return ERROR_INT("datas not defined", procName, 1);
1200 
1201  /* Skip if x or y are invalid. (x,y) must be in the source image.
1202  * Failure to detect an invalid point will cause a mem address fault.
1203  * Occasionally, x or y will be a nan, and relational checks always
1204  * fail for nans. Therefore we check if the point is inside the pix */
1205  valid = (x >= 0.0 && y >= 0.0 && x < w && y < h);
1206  if (!valid) return 0;
1207 
1208  xpm = (l_int32)(16.0 * x);
1209  ypm = (l_int32)(16.0 * y);
1210  xp = xpm >> 4;
1211  xp2 = xp + 1 < w ? xp + 1 : xp;
1212  yp = ypm >> 4;
1213  if (yp + 1 >= h) wpls = 0;
1214  xf = xpm & 0x0f;
1215  yf = ypm & 0x0f;
1216 
1217 #if DEBUG
1218  if (xf < 0 || yf < 0)
1219  lept_stderr("xp = %d, yp = %d, xf = %d, yf = %d\n", xp, yp, xf, yf);
1220 #endif /* DEBUG */
1221 
1222  /* Do area weighting (eqiv. to linear interpolation) */
1223  lines = datas + yp * wpls;
1224  word00 = *(lines + xp);
1225  word10 = *(lines + xp2);
1226  word01 = *(lines + wpls + xp);
1227  word11 = *(lines + wpls + xp2);
1228  rval = ((16 - xf) * (16 - yf) * ((word00 >> L_RED_SHIFT) & 0xff) +
1229  xf * (16 - yf) * ((word10 >> L_RED_SHIFT) & 0xff) +
1230  (16 - xf) * yf * ((word01 >> L_RED_SHIFT) & 0xff) +
1231  xf * yf * ((word11 >> L_RED_SHIFT) & 0xff)) / 256;
1232  gval = ((16 - xf) * (16 - yf) * ((word00 >> L_GREEN_SHIFT) & 0xff) +
1233  xf * (16 - yf) * ((word10 >> L_GREEN_SHIFT) & 0xff) +
1234  (16 - xf) * yf * ((word01 >> L_GREEN_SHIFT) & 0xff) +
1235  xf * yf * ((word11 >> L_GREEN_SHIFT) & 0xff)) / 256;
1236  bval = ((16 - xf) * (16 - yf) * ((word00 >> L_BLUE_SHIFT) & 0xff) +
1237  xf * (16 - yf) * ((word10 >> L_BLUE_SHIFT) & 0xff) +
1238  (16 - xf) * yf * ((word01 >> L_BLUE_SHIFT) & 0xff) +
1239  xf * yf * ((word11 >> L_BLUE_SHIFT) & 0xff)) / 256;
1240  composeRGBPixel(rval, gval, bval, pval);
1241  return 0;
1242 }
1243 
1244 
1264 l_ok
1266  l_int32 wpls,
1267  l_int32 w,
1268  l_int32 h,
1269  l_float32 x,
1270  l_float32 y,
1271  l_int32 grayval,
1272  l_int32 *pval)
1273 {
1274 l_int32 valid, xpm, ypm, xp, xp2, yp, xf, yf, v00, v10, v01, v11;
1275 l_uint32 *lines;
1276 
1277  PROCNAME("linearInterpolatePixelGray");
1278 
1279  if (!pval)
1280  return ERROR_INT("&val not defined", procName, 1);
1281  *pval = grayval;
1282  if (!datas)
1283  return ERROR_INT("datas not defined", procName, 1);
1284 
1285  /* Skip if x or y is invalid. (x,y) must be in the source image.
1286  * Failure to detect an invalid point will cause a mem address fault.
1287  * Occasionally, x or y will be a nan, and relational checks always
1288  * fail for nans. Therefore we check if the point is inside the pix */
1289  valid = (x >= 0.0 && y >= 0.0 && x < w && y < h);
1290  if (!valid) return 0;
1291 
1292  xpm = (l_int32)(16.0 * x);
1293  ypm = (l_int32)(16.0 * y);
1294  xp = xpm >> 4;
1295  xp2 = xp + 1 < w ? xp + 1 : xp;
1296  yp = ypm >> 4;
1297  if (yp + 1 >= h) wpls = 0;
1298  xf = xpm & 0x0f;
1299  yf = ypm & 0x0f;
1300 
1301 #if DEBUG
1302  if (xf < 0 || yf < 0)
1303  lept_stderr("xp = %d, yp = %d, xf = %d, yf = %d\n", xp, yp, xf, yf);
1304 #endif /* DEBUG */
1305 
1306  /* Interpolate by area weighting. */
1307  lines = datas + yp * wpls;
1308  v00 = (16 - xf) * (16 - yf) * GET_DATA_BYTE(lines, xp);
1309  v10 = xf * (16 - yf) * GET_DATA_BYTE(lines, xp2);
1310  v01 = (16 - xf) * yf * GET_DATA_BYTE(lines + wpls, xp);
1311  v11 = xf * yf * GET_DATA_BYTE(lines + wpls, xp2);
1312  *pval = (v00 + v01 + v10 + v11) / 256;
1313  return 0;
1314 }
1315 
1316 
1317 
1318 /*-------------------------------------------------------------*
1319  * Gauss-jordan linear equation solver *
1320  *-------------------------------------------------------------*/
1321 #define SWAP(a,b) {temp = (a); (a) = (b); (b) = temp;}
1322 
1343 l_int32
1344 gaussjordan(l_float32 **a,
1345  l_float32 *b,
1346  l_int32 n)
1347 {
1348 l_int32 i, icol, irow, j, k, col, row, success;
1349 l_int32 *indexc, *indexr, *ipiv;
1350 l_float32 maxval, val, pivinv, temp;
1351 
1352  PROCNAME("gaussjordan");
1353 
1354  if (!a)
1355  return ERROR_INT("a not defined", procName, 1);
1356  if (!b)
1357  return ERROR_INT("b not defined", procName, 1);
1358 
1359  success = TRUE;
1360  indexc = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
1361  indexr = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
1362  ipiv = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
1363  if (!indexc || !indexr || !ipiv) {
1364  L_ERROR("array not made\n", procName);
1365  success = FALSE;
1366  goto cleanup_arrays;
1367  }
1368 
1369  icol = irow = 0; /* silence static checker */
1370  for (i = 0; i < n; i++) {
1371  maxval = 0.0;
1372  for (j = 0; j < n; j++) {
1373  if (ipiv[j] != 1) {
1374  for (k = 0; k < n; k++) {
1375  if (ipiv[k] == 0) {
1376  if (fabs(a[j][k]) >= maxval) {
1377  maxval = fabs(a[j][k]);
1378  irow = j;
1379  icol = k;
1380  }
1381  } else if (ipiv[k] > 1) {
1382  L_ERROR("singular matrix\n", procName);
1383  success = FALSE;
1384  goto cleanup_arrays;
1385  }
1386  }
1387  }
1388  }
1389  ++(ipiv[icol]);
1390 
1391  if (irow != icol) {
1392  for (col = 0; col < n; col++)
1393  SWAP(a[irow][col], a[icol][col]);
1394  SWAP(b[irow], b[icol]);
1395  }
1396 
1397  indexr[i] = irow;
1398  indexc[i] = icol;
1399  if (a[icol][icol] == 0.0) {
1400  L_ERROR("singular matrix\n", procName);
1401  success = FALSE;
1402  goto cleanup_arrays;
1403  }
1404  pivinv = 1.0 / a[icol][icol];
1405  a[icol][icol] = 1.0;
1406  for (col = 0; col < n; col++)
1407  a[icol][col] *= pivinv;
1408  b[icol] *= pivinv;
1409 
1410  for (row = 0; row < n; row++) {
1411  if (row != icol) {
1412  val = a[row][icol];
1413  a[row][icol] = 0.0;
1414  for (col = 0; col < n; col++)
1415  a[row][col] -= a[icol][col] * val;
1416  b[row] -= b[icol] * val;
1417  }
1418  }
1419  }
1420 
1421  for (col = n - 1; col >= 0; col--) {
1422  if (indexr[col] != indexc[col]) {
1423  for (k = 0; k < n; k++)
1424  SWAP(a[k][indexr[col]], a[k][indexc[col]]);
1425  }
1426  }
1427 
1428 cleanup_arrays:
1429  LEPT_FREE(indexr);
1430  LEPT_FREE(indexc);
1431  LEPT_FREE(ipiv);
1432  return (success) ? 0 : 1;
1433 }
1434 
1435 
1436 /*-------------------------------------------------------------*
1437  * Sequential affine image transformation *
1438  *-------------------------------------------------------------*/
1467 PIX *
1469  PTA *ptad,
1470  PTA *ptas,
1471  l_int32 bw,
1472  l_int32 bh)
1473 {
1474 l_int32 x1, y1, x2, y2, x3, y3; /* ptas */
1475 l_int32 x1p, y1p, x2p, y2p, x3p, y3p; /* ptad */
1476 l_int32 x1sc, y1sc; /* scaled origin */
1477 l_float32 x2s, x2sp, scalex, scaley;
1478 l_float32 th3, th3p, ph2, ph2p;
1479 #if DEBUG
1480 l_float32 rad2deg;
1481 #endif /* DEBUG */
1482 PIX *pix1, *pix2, *pixd;
1483 
1484  PROCNAME("pixAffineSequential");
1485 
1486  if (!pixs)
1487  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1488  if (!ptas)
1489  return (PIX *)ERROR_PTR("ptas not defined", procName, NULL);
1490  if (!ptad)
1491  return (PIX *)ERROR_PTR("ptad not defined", procName, NULL);
1492 
1493  if (ptaGetCount(ptas) != 3)
1494  return (PIX *)ERROR_PTR("ptas count not 3", procName, NULL);
1495  if (ptaGetCount(ptad) != 3)
1496  return (PIX *)ERROR_PTR("ptad count not 3", procName, NULL);
1497  ptaGetIPt(ptas, 0, &x1, &y1);
1498  ptaGetIPt(ptas, 1, &x2, &y2);
1499  ptaGetIPt(ptas, 2, &x3, &y3);
1500  ptaGetIPt(ptad, 0, &x1p, &y1p);
1501  ptaGetIPt(ptad, 1, &x2p, &y2p);
1502  ptaGetIPt(ptad, 2, &x3p, &y3p);
1503 
1504  pix1 = pix2 = pixd = NULL;
1505 
1506  if (y1 == y3)
1507  return (PIX *)ERROR_PTR("y1 == y3!", procName, NULL);
1508  if (y1p == y3p)
1509  return (PIX *)ERROR_PTR("y1p == y3p!", procName, NULL);
1510 
1511  if (bw != 0 || bh != 0) {
1512  /* resize all points and add border to pixs */
1513  x1 = x1 + bw;
1514  y1 = y1 + bh;
1515  x2 = x2 + bw;
1516  y2 = y2 + bh;
1517  x3 = x3 + bw;
1518  y3 = y3 + bh;
1519  x1p = x1p + bw;
1520  y1p = y1p + bh;
1521  x2p = x2p + bw;
1522  y2p = y2p + bh;
1523  x3p = x3p + bw;
1524  y3p = y3p + bh;
1525 
1526  if ((pix1 = pixAddBorderGeneral(pixs, bw, bw, bh, bh, 0)) == NULL)
1527  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1528  } else {
1529  pix1 = pixCopy(NULL, pixs);
1530  }
1531 
1532  /*-------------------------------------------------------------*
1533  The horizontal shear is done to move the 3rd point to the
1534  y axis. This moves the 2nd point either towards or away
1535  from the y axis, depending on whether it is above or below
1536  the x axis. That motion must be computed so that we know
1537  the angle of vertical shear to use to get the 2nd point
1538  on the x axis. We must also know the x coordinate of the
1539  2nd point in order to compute how much scaling is required
1540  to match points on the axis.
1541  *-------------------------------------------------------------*/
1542 
1543  /* Shear angles required to put src points on x and y axes */
1544  th3 = atan2((l_float64)(x1 - x3), (l_float64)(y1 - y3));
1545  x2s = (l_float32)(x2 - ((l_float32)(y1 - y2) * (x3 - x1)) / (y1 - y3));
1546  if (x2s == (l_float32)x1) {
1547  L_ERROR("x2s == x1!\n", procName);
1548  goto cleanup_pix;
1549  }
1550  ph2 = atan2((l_float64)(y1 - y2), (l_float64)(x2s - x1));
1551 
1552  /* Shear angles required to put dest points on x and y axes.
1553  * Use the negative of these values to instead move the
1554  * src points from the axes to the actual dest position.
1555  * These values are also needed to scale the image. */
1556  th3p = atan2((l_float64)(x1p - x3p), (l_float64)(y1p - y3p));
1557  x2sp = (l_float32)(x2p -
1558  ((l_float32)(y1p - y2p) * (x3p - x1p)) / (y1p - y3p));
1559  if (x2sp == (l_float32)x1p) {
1560  L_ERROR("x2sp == x1p!\n", procName);
1561  goto cleanup_pix;
1562  }
1563  ph2p = atan2((l_float64)(y1p - y2p), (l_float64)(x2sp - x1p));
1564 
1565  /* Shear image to first put src point 3 on the y axis,
1566  * and then to put src point 2 on the x axis */
1567  pixHShearIP(pix1, y1, th3, L_BRING_IN_WHITE);
1568  pixVShearIP(pix1, x1, ph2, L_BRING_IN_WHITE);
1569 
1570  /* Scale image to match dest scale. The dest scale
1571  * is calculated above from the angles th3p and ph2p
1572  * that would be required to move the dest points to
1573  * the x and y axes. */
1574  scalex = (l_float32)(x2sp - x1p) / (x2s - x1);
1575  scaley = (l_float32)(y3p - y1p) / (y3 - y1);
1576  if ((pix2 = pixScale(pix1, scalex, scaley)) == NULL) {
1577  L_ERROR("pix2 not made\n", procName);
1578  goto cleanup_pix;
1579  }
1580 
1581 #if DEBUG
1582  rad2deg = 180. / 3.1415926535;
1583  lept_stderr("th3 = %5.1f deg, ph2 = %5.1f deg\n",
1584  rad2deg * th3, rad2deg * ph2);
1585  lept_stderr("th3' = %5.1f deg, ph2' = %5.1f deg\n",
1586  rad2deg * th3p, rad2deg * ph2p);
1587  lept_stderr("scalex = %6.3f, scaley = %6.3f\n", scalex, scaley);
1588 #endif /* DEBUG */
1589 
1590  /*-------------------------------------------------------------*
1591  Scaling moves the 1st src point, which is the origin.
1592  It must now be moved again to coincide with the origin
1593  (1st point) of the dest. After this is done, the 2nd
1594  and 3rd points must be sheared back to the original
1595  positions of the 2nd and 3rd dest points. We use the
1596  negative of the angles that were previously computed
1597  for shearing those points in the dest image to x and y
1598  axes, and take the shears in reverse order as well.
1599  *-------------------------------------------------------------*/
1600  /* Shift image to match dest origin. */
1601  x1sc = (l_int32)(scalex * x1 + 0.5); /* x comp of origin after scaling */
1602  y1sc = (l_int32)(scaley * y1 + 0.5); /* y comp of origin after scaling */
1603  pixRasteropIP(pix2, x1p - x1sc, y1p - y1sc, L_BRING_IN_WHITE);
1604 
1605  /* Shear image to take points 2 and 3 off the axis and
1606  * put them in the original dest position */
1607  pixVShearIP(pix2, x1p, -ph2p, L_BRING_IN_WHITE);
1608  pixHShearIP(pix2, y1p, -th3p, L_BRING_IN_WHITE);
1609 
1610  if (bw != 0 || bh != 0) {
1611  if ((pixd = pixRemoveBorderGeneral(pix2, bw, bw, bh, bh)) == NULL)
1612  L_ERROR("pixd not made\n", procName);
1613  } else {
1614  pixd = pixClone(pix2);
1615  }
1616 
1617 cleanup_pix:
1618  pixDestroy(&pix1);
1619  pixDestroy(&pix2);
1620  return pixd;
1621 }
PIX * pixAffinePta(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor)
pixAffinePta()
Definition: affine.c:425
l_int32 gaussjordan(l_float32 **a, l_float32 *b, l_int32 n)
gaussjordan()
Definition: affine.c:1344
PIX * pixAffineSampled(PIX *pixs, l_float32 *vc, l_int32 incolor)
pixAffineSampled()
Definition: affine.c:332
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2538
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixRemoveBorderGeneral()
Definition: pix2.c:1993
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
l_ok affineXformPt(l_float32 *vc, l_int32 x, l_int32 y, l_float32 *pxp, l_float32 *pyp)
affineXformPt()
Definition: affine.c:1138
PIX * pixAffineSampledPta(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor)
pixAffineSampledPta()
Definition: affine.c:282
PIX * pixAffineGray(PIX *pixs, l_float32 *vc, l_uint8 grayval)
pixAffineGray()
Definition: affine.c:696
l_ok pixRasteropIP(PIX *pixd, l_int32 hshift, l_int32 vshift, l_int32 incolor)
pixRasteropIP()
Definition: rop.c:475
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
PIX * pixAffinePtaGray(PIX *pixs, PTA *ptad, PTA *ptas, l_uint8 grayval)
pixAffinePtaGray()
Definition: affine.c:654
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
l_ok pixVShearIP(PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor)
pixVShearIP()
Definition: shear.c:546
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:527
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
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 GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
l_ok affineXformSampledPt(l_float32 *vc, l_int32 x, l_int32 y, l_int32 *pxp, l_int32 *pyp)
affineXformSampledPt()
Definition: affine.c:1106
PIX * pixAffinePtaWithAlpha(PIX *pixs, PTA *ptad, PTA *ptas, PIX *pixg, l_float32 fract, l_int32 border)
pixAffinePtaWithAlpha()
Definition: affine.c:784
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1823
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
l_ok linearInterpolatePixelColor(l_uint32 *datas, l_int32 wpls, l_int32 w, l_int32 h, l_float32 x, l_float32 y, l_uint32 colorval, l_uint32 *pval)
linearInterpolatePixelColor()
Definition: affine.c:1179
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:951
PIX * pixAffinePtaColor(PIX *pixs, PTA *ptad, PTA *ptas, l_uint32 colorval)
pixAffinePtaColor()
Definition: affine.c:551
l_ok pixHShearIP(PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShearIP()
Definition: shear.c:471
l_ok pixClearAll(PIX *pix)
pixClearAll()
Definition: pix2.c:789
l_ok pixSetBorderRingVal(PIX *pixs, l_int32 dist, l_uint32 val)
pixSetBorderRingVal()
Definition: pix2.c:1667
l_ok ptaGetPt(PTA *pta, l_int32 index, l_float32 *px, l_float32 *py)
ptaGetPt()
Definition: ptabasic.c:548
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define SET_DATA_BIT_VAL(pdata, n, val)
Definition: arrayaccess.h:135
PIX * pixAffineSequential(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 bw, l_int32 bh)
pixAffineSequential()
Definition: affine.c:1468
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
l_ok getAffineXformCoeffs(PTA *ptas, PTA *ptad, l_float32 **pvc)
getAffineXformCoeffs()
Definition: affine.c:933
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 * pixAffine(PIX *pixs, l_float32 *vc, l_int32 incolor)
pixAffine()
Definition: affine.c:495
l_ok pixcmapAddBlackOrWhite(PIXCMAP *cmap, l_int32 color, l_int32 *pindex)
pixcmapAddBlackOrWhite()
Definition: colormap.c:639
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
Definition: pix.h:138
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
PIX * pixResizeToMatch(PIX *pixs, PIX *pixt, l_int32 w, l_int32 h)
pixResizeToMatch()
Definition: pix5.c:1321
PTA * ptaTransform(PTA *ptas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
ptaTransform()
Definition: ptafunc1.c:740
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:578
PIX * pixAffineColor(PIX *pixs, l_float32 *vc, l_uint32 colorval)
pixAffineColor()
Definition: affine.c:592
l_ok affineInvertXform(l_float32 *vc, l_float32 **pvci)
affineInvertXform()
Definition: affine.c:1023
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1917
Definition: pix.h:516