Leptonica  1.73
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_int32
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_int32
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_int32
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_int32
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_int32
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  *pval = (rval << L_RED_SHIFT) | (gval << L_GREEN_SHIFT) |
1242  (bval << L_BLUE_SHIFT);
1243  return 0;
1244 }
1245 
1246 
1266 l_int32
1268  l_int32 wpls,
1269  l_int32 w,
1270  l_int32 h,
1271  l_float32 x,
1272  l_float32 y,
1273  l_int32 grayval,
1274  l_int32 *pval)
1275 {
1276 l_int32 valid, xpm, ypm, xp, xp2, yp, xf, yf, v00, v10, v01, v11;
1277 l_uint32 *lines;
1278 
1279  PROCNAME("linearInterpolatePixelGray");
1280 
1281  if (!pval)
1282  return ERROR_INT("&val not defined", procName, 1);
1283  *pval = grayval;
1284  if (!datas)
1285  return ERROR_INT("datas not defined", procName, 1);
1286 
1287  /* Skip if x or y is invalid. (x,y) must be in the source image.
1288  * Failure to detect an invalid point will cause a mem address fault.
1289  * Occasionally, x or y will be a nan, and relational checks always
1290  * fail for nans. Therefore we check if the point is inside the pix */
1291  valid = (x >= 0.0 && y >= 0.0 && x < w && y < h);
1292  if (!valid) return 0;
1293 
1294  xpm = (l_int32)(16.0 * x);
1295  ypm = (l_int32)(16.0 * y);
1296  xp = xpm >> 4;
1297  xp2 = xp + 1 < w ? xp + 1 : xp;
1298  yp = ypm >> 4;
1299  if (yp + 1 >= h) wpls = 0;
1300  xf = xpm & 0x0f;
1301  yf = ypm & 0x0f;
1302 
1303 #if DEBUG
1304  if (xf < 0 || yf < 0)
1305  fprintf(stderr, "xp = %d, yp = %d, xf = %d, yf = %d\n", xp, yp, xf, yf);
1306 #endif /* DEBUG */
1307 
1308  /* Interpolate by area weighting. */
1309  lines = datas + yp * wpls;
1310  v00 = (16 - xf) * (16 - yf) * GET_DATA_BYTE(lines, xp);
1311  v10 = xf * (16 - yf) * GET_DATA_BYTE(lines, xp2);
1312  v01 = (16 - xf) * yf * GET_DATA_BYTE(lines + wpls, xp);
1313  v11 = xf * yf * GET_DATA_BYTE(lines + wpls, xp2);
1314  *pval = (v00 + v01 + v10 + v11) / 256;
1315  return 0;
1316 }
1317 
1318 
1319 
1320 /*-------------------------------------------------------------*
1321  * Gauss-jordan linear equation solver *
1322  *-------------------------------------------------------------*/
1323 #define SWAP(a,b) {temp = (a); (a) = (b); (b) = temp;}
1324 
1345 l_int32
1346 gaussjordan(l_float32 **a,
1347  l_float32 *b,
1348  l_int32 n)
1349 {
1350 l_int32 i, icol, irow, j, k, col, row, success;
1351 l_int32 *indexc, *indexr, *ipiv;
1352 l_float32 maxval, val, pivinv, temp;
1353 
1354  PROCNAME("gaussjordan");
1355 
1356  if (!a)
1357  return ERROR_INT("a not defined", procName, 1);
1358  if (!b)
1359  return ERROR_INT("b not defined", procName, 1);
1360 
1361  success = TRUE;
1362  indexc = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
1363  indexr = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
1364  ipiv = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
1365  if (!indexc || !indexr || !ipiv) {
1366  L_ERROR("array not made\n", procName);
1367  success = FALSE;
1368  goto cleanup_arrays;
1369  }
1370 
1371  icol = irow = 0; /* silence static checker */
1372  for (i = 0; i < n; i++) {
1373  maxval = 0.0;
1374  for (j = 0; j < n; j++) {
1375  if (ipiv[j] != 1) {
1376  for (k = 0; k < n; k++) {
1377  if (ipiv[k] == 0) {
1378  if (fabs(a[j][k]) >= maxval) {
1379  maxval = fabs(a[j][k]);
1380  irow = j;
1381  icol = k;
1382  }
1383  } else if (ipiv[k] > 1) {
1384  L_ERROR("singular matrix\n", procName);
1385  success = FALSE;
1386  goto cleanup_arrays;
1387  }
1388  }
1389  }
1390  }
1391  ++(ipiv[icol]);
1392 
1393  if (irow != icol) {
1394  for (col = 0; col < n; col++)
1395  SWAP(a[irow][col], a[icol][col]);
1396  SWAP(b[irow], b[icol]);
1397  }
1398 
1399  indexr[i] = irow;
1400  indexc[i] = icol;
1401  if (a[icol][icol] == 0.0) {
1402  L_ERROR("singular matrix\n", procName);
1403  success = FALSE;
1404  goto cleanup_arrays;
1405  }
1406  pivinv = 1.0 / a[icol][icol];
1407  a[icol][icol] = 1.0;
1408  for (col = 0; col < n; col++)
1409  a[icol][col] *= pivinv;
1410  b[icol] *= pivinv;
1411 
1412  for (row = 0; row < n; row++) {
1413  if (row != icol) {
1414  val = a[row][icol];
1415  a[row][icol] = 0.0;
1416  for (col = 0; col < n; col++)
1417  a[row][col] -= a[icol][col] * val;
1418  b[row] -= b[icol] * val;
1419  }
1420  }
1421  }
1422 
1423  for (col = n - 1; col >= 0; col--) {
1424  if (indexr[col] != indexc[col]) {
1425  for (k = 0; k < n; k++)
1426  SWAP(a[k][indexr[col]], a[k][indexc[col]]);
1427  }
1428  }
1429 
1430 cleanup_arrays:
1431  LEPT_FREE(indexr);
1432  LEPT_FREE(indexc);
1433  LEPT_FREE(ipiv);
1434  return (success) ? 0 : 1;
1435 }
1436 
1437 
1438 /*-------------------------------------------------------------*
1439  * Sequential affine image transformation *
1440  *-------------------------------------------------------------*/
1469 PIX *
1471  PTA *ptad,
1472  PTA *ptas,
1473  l_int32 bw,
1474  l_int32 bh)
1475 {
1476 l_int32 x1, y1, x2, y2, x3, y3; /* ptas */
1477 l_int32 x1p, y1p, x2p, y2p, x3p, y3p; /* ptad */
1478 l_int32 x1sc, y1sc; /* scaled origin */
1479 l_float32 x2s, x2sp, scalex, scaley;
1480 l_float32 th3, th3p, ph2, ph2p;
1481 #if DEBUG
1482 l_float32 rad2deg;
1483 #endif /* DEBUG */
1484 PIX *pix1, *pix2, *pixd;
1485 
1486  PROCNAME("pixAffineSequential");
1487 
1488  if (!pixs)
1489  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1490  if (!ptas)
1491  return (PIX *)ERROR_PTR("ptas not defined", procName, NULL);
1492  if (!ptad)
1493  return (PIX *)ERROR_PTR("ptad not defined", procName, NULL);
1494 
1495  if (ptaGetCount(ptas) != 3)
1496  return (PIX *)ERROR_PTR("ptas count not 3", procName, NULL);
1497  if (ptaGetCount(ptad) != 3)
1498  return (PIX *)ERROR_PTR("ptad count not 3", procName, NULL);
1499  ptaGetIPt(ptas, 0, &x1, &y1);
1500  ptaGetIPt(ptas, 1, &x2, &y2);
1501  ptaGetIPt(ptas, 2, &x3, &y3);
1502  ptaGetIPt(ptad, 0, &x1p, &y1p);
1503  ptaGetIPt(ptad, 1, &x2p, &y2p);
1504  ptaGetIPt(ptad, 2, &x3p, &y3p);
1505 
1506  pix1 = pix2 = pixd = NULL;
1507 
1508  if (y1 == y3)
1509  return (PIX *)ERROR_PTR("y1 == y3!", procName, NULL);
1510  if (y1p == y3p)
1511  return (PIX *)ERROR_PTR("y1p == y3p!", procName, NULL);
1512 
1513  if (bw != 0 || bh != 0) {
1514  /* resize all points and add border to pixs */
1515  x1 = x1 + bw;
1516  y1 = y1 + bh;
1517  x2 = x2 + bw;
1518  y2 = y2 + bh;
1519  x3 = x3 + bw;
1520  y3 = y3 + bh;
1521  x1p = x1p + bw;
1522  y1p = y1p + bh;
1523  x2p = x2p + bw;
1524  y2p = y2p + bh;
1525  x3p = x3p + bw;
1526  y3p = y3p + bh;
1527 
1528  if ((pix1 = pixAddBorderGeneral(pixs, bw, bw, bh, bh, 0)) == NULL)
1529  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1530  } else {
1531  pix1 = pixCopy(NULL, pixs);
1532  }
1533 
1534  /*-------------------------------------------------------------*
1535  The horizontal shear is done to move the 3rd point to the
1536  y axis. This moves the 2nd point either towards or away
1537  from the y axis, depending on whether it is above or below
1538  the x axis. That motion must be computed so that we know
1539  the angle of vertical shear to use to get the 2nd point
1540  on the x axis. We must also know the x coordinate of the
1541  2nd point in order to compute how much scaling is required
1542  to match points on the axis.
1543  *-------------------------------------------------------------*/
1544 
1545  /* Shear angles required to put src points on x and y axes */
1546  th3 = atan2((l_float64)(x1 - x3), (l_float64)(y1 - y3));
1547  x2s = (l_float32)(x2 - ((l_float32)(y1 - y2) * (x3 - x1)) / (y1 - y3));
1548  if (x2s == (l_float32)x1) {
1549  L_ERROR("x2s == x1!\n", procName);
1550  goto cleanup_pix;
1551  }
1552  ph2 = atan2((l_float64)(y1 - y2), (l_float64)(x2s - x1));
1553 
1554  /* Shear angles required to put dest points on x and y axes.
1555  * Use the negative of these values to instead move the
1556  * src points from the axes to the actual dest position.
1557  * These values are also needed to scale the image. */
1558  th3p = atan2((l_float64)(x1p - x3p), (l_float64)(y1p - y3p));
1559  x2sp = (l_float32)(x2p -
1560  ((l_float32)(y1p - y2p) * (x3p - x1p)) / (y1p - y3p));
1561  if (x2sp == (l_float32)x1p) {
1562  L_ERROR("x2sp == x1p!\n", procName);
1563  goto cleanup_pix;
1564  }
1565  ph2p = atan2((l_float64)(y1p - y2p), (l_float64)(x2sp - x1p));
1566 
1567  /* Shear image to first put src point 3 on the y axis,
1568  * and then to put src point 2 on the x axis */
1569  pixHShearIP(pix1, y1, th3, L_BRING_IN_WHITE);
1570  pixVShearIP(pix1, x1, ph2, L_BRING_IN_WHITE);
1571 
1572  /* Scale image to match dest scale. The dest scale
1573  * is calculated above from the angles th3p and ph2p
1574  * that would be required to move the dest points to
1575  * the x and y axes. */
1576  scalex = (l_float32)(x2sp - x1p) / (x2s - x1);
1577  scaley = (l_float32)(y3p - y1p) / (y3 - y1);
1578  if ((pix2 = pixScale(pix1, scalex, scaley)) == NULL) {
1579  L_ERROR("pix2 not made\n", procName);
1580  goto cleanup_pix;
1581  }
1582 
1583 #if DEBUG
1584  rad2deg = 180. / 3.1415926535;
1585  fprintf(stderr, "th3 = %5.1f deg, ph2 = %5.1f deg\n",
1586  rad2deg * th3, rad2deg * ph2);
1587  fprintf(stderr, "th3' = %5.1f deg, ph2' = %5.1f deg\n",
1588  rad2deg * th3p, rad2deg * ph2p);
1589  fprintf(stderr, "scalex = %6.3f, scaley = %6.3f\n", scalex, scaley);
1590 #endif /* DEBUG */
1591 
1592  /*-------------------------------------------------------------*
1593  Scaling moves the 1st src point, which is the origin.
1594  It must now be moved again to coincide with the origin
1595  (1st point) of the dest. After this is done, the 2nd
1596  and 3rd points must be sheared back to the original
1597  positions of the 2nd and 3rd dest points. We use the
1598  negative of the angles that were previously computed
1599  for shearing those points in the dest image to x and y
1600  axes, and take the shears in reverse order as well.
1601  *-------------------------------------------------------------*/
1602  /* Shift image to match dest origin. */
1603  x1sc = (l_int32)(scalex * x1 + 0.5); /* x comp of origin after scaling */
1604  y1sc = (l_int32)(scaley * y1 + 0.5); /* y comp of origin after scaling */
1605  pixRasteropIP(pix2, x1p - x1sc, y1p - y1sc, L_BRING_IN_WHITE);
1606 
1607  /* Shear image to take points 2 and 3 off the axis and
1608  * put them in the original dest position */
1609  pixVShearIP(pix2, x1p, -ph2p, L_BRING_IN_WHITE);
1610  pixHShearIP(pix2, y1p, -th3p, L_BRING_IN_WHITE);
1611 
1612  if (bw != 0 || bh != 0) {
1613  if ((pixd = pixRemoveBorderGeneral(pix2, bw, bw, bh, bh)) == NULL)
1614  L_ERROR("pixd not made\n", procName);
1615  } else {
1616  pixd = pixClone(pix2);
1617  }
1618 
1619 cleanup_pix:
1620  pixDestroy(&pix1);
1621  pixDestroy(&pix2);
1622  return pixd;
1623 }
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:1346
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
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixRemoveBorderGeneral()
Definition: pix2.c:1906
PIX * pixAffineSampledPta(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor)
pixAffineSampledPta()
Definition: affine.c:280
l_int32 ptaGetPt(PTA *pta, l_int32 index, l_float32 *px, l_float32 *py)
ptaGetPt()
Definition: ptabasic.c:524
l_int32 pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2451
PIX * pixAffineGray(PIX *pixs, l_float32 *vc, l_uint8 grayval)
pixAffineGray()
Definition: affine.c:694
l_int32 pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:864
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
l_int32 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
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
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:162
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:503
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1602
l_int32 affineInvertXform(l_float32 *vc, l_float32 **pvci)
affineInvertXform()
Definition: affine.c:1024
l_int32 pixcmapAddBlackOrWhite(PIXCMAP *cmap, l_int32 color, l_int32 *pindex)
pixcmapAddBlackOrWhite()
Definition: colormap.c:524
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:117
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:2392
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1736
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:143
PIX * pixAffinePtaColor(PIX *pixs, PTA *ptad, PTA *ptas, l_uint32 colorval)
pixAffinePtaColor()
Definition: affine.c:549
l_int32 pixHShearIP(PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShearIP()
Definition: shear.c:459
l_int32 getAffineXformCoeffs(PTA *ptas, PTA *ptad, l_float32 **pvc)
getAffineXformCoeffs()
Definition: affine.c:931
l_int32 pixClearAll(PIX *pix)
pixClearAll()
Definition: pix2.c:700
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:192
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:158
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:182
#define SET_DATA_BIT_VAL(pdata, n, val)
Definition: arrayaccess.h:129
PIX * pixAffineSequential(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 bw, l_int32 bh)
pixAffineSequential()
Definition: affine.c:1470
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:517
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:545
l_int32 affineXformSampledPt(l_float32 *vc, l_int32 x, l_int32 y, l_int32 *pxp, l_int32 *pyp)
affineXformSampledPt()
Definition: affine.c:1107
l_int32 ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:554
PIX * pixAffine(PIX *pixs, l_float32 *vc, l_int32 incolor)
pixAffine()
Definition: affine.c:493
l_int32 affineXformPt(l_float32 *vc, l_int32 x, l_int32 y, l_float32 *pxp, l_float32 *pyp)
affineXformPt()
Definition: affine.c:1139
l_int32 pixSetBorderRingVal(PIX *pixs, l_int32 dist, l_uint32 val)
pixSetBorderRingVal()
Definition: pix2.c:1580
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:139
Definition: pix.h:134
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:630
l_int32 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:1267
PIX * pixResizeToMatch(PIX *pixs, PIX *pixt, l_int32 w, l_int32 h)
pixResizeToMatch()
Definition: pix5.c:1245
PTA * ptaTransform(PTA *ptas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
ptaTransform()
Definition: ptafunc1.c:720
l_int32 pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:729
l_int32 pixGetDimensions(PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1052
PIX * pixAffineColor(PIX *pixs, l_float32 *vc, l_uint32 colorval)
pixAffineColor()
Definition: affine.c:590
l_int32 pixVShearIP(PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor)
pixVShearIP()
Definition: shear.c:534
l_int32 pixRasteropIP(PIX *pixd, l_int32 hshift, l_int32 vshift, l_int32 incolor)
pixRasteropIP()
Definition: rop.c:461
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:243
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1830
Definition: pix.h:517