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