Leptonica  1.83.1
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  if (!pixs)
291  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
292  if (!ptas)
293  return (PIX *)ERROR_PTR("ptas not defined", __func__, NULL);
294  if (!ptad)
295  return (PIX *)ERROR_PTR("ptad not defined", __func__, NULL);
296  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
297  return (PIX *)ERROR_PTR("invalid incolor", __func__, NULL);
298  if (ptaGetCount(ptas) != 3)
299  return (PIX *)ERROR_PTR("ptas count not 3", __func__, NULL);
300  if (ptaGetCount(ptad) != 3)
301  return (PIX *)ERROR_PTR("ptad count not 3", __func__, 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  if (!pixs)
341  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
342  if (!vc)
343  return (PIX *)ERROR_PTR("vc not defined", __func__, NULL);
344  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
345  return (PIX *)ERROR_PTR("invalid incolor", __func__, NULL);
346  pixGetDimensions(pixs, &w, &h, &d);
347  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 32)
348  return (PIX *)ERROR_PTR("depth not 1, 2, 4, 8 or 16", __func__, NULL);
349 
350  /* Init all dest pixels to color to be brought in from outside */
351  pixd = pixCreateTemplate(pixs);
352  if ((cmap = pixGetColormap(pixs)) != NULL) {
353  if (incolor == L_BRING_IN_WHITE)
354  color = 1;
355  else
356  color = 0;
357  pixcmapAddBlackOrWhite(cmap, color, &cmapindex);
358  pixSetAllArbitrary(pixd, cmapindex);
359  } else {
360  if ((d == 1 && incolor == L_BRING_IN_WHITE) ||
361  (d > 1 && incolor == L_BRING_IN_BLACK)) {
362  pixClearAll(pixd);
363  } else {
364  pixSetAll(pixd);
365  }
366  }
367 
368  /* Scan over the dest pixels */
369  datas = pixGetData(pixs);
370  wpls = pixGetWpl(pixs);
371  datad = pixGetData(pixd);
372  wpld = pixGetWpl(pixd);
373  for (i = 0; i < h; i++) {
374  lined = datad + i * wpld;
375  for (j = 0; j < w; j++) {
376  affineXformSampledPt(vc, j, i, &x, &y);
377  if (x < 0 || y < 0 || x >=w || y >= h)
378  continue;
379  lines = datas + y * wpls;
380  if (d == 1) {
381  val = GET_DATA_BIT(lines, x);
382  SET_DATA_BIT_VAL(lined, j, val);
383  } else if (d == 8) {
384  val = GET_DATA_BYTE(lines, x);
385  SET_DATA_BYTE(lined, j, val);
386  } else if (d == 32) {
387  lined[j] = lines[x];
388  } else if (d == 2) {
389  val = GET_DATA_DIBIT(lines, x);
390  SET_DATA_DIBIT(lined, j, val);
391  } else if (d == 4) {
392  val = GET_DATA_QBIT(lines, x);
393  SET_DATA_QBIT(lined, j, val);
394  }
395  }
396  }
397 
398  return pixd;
399 }
400 
401 
402 /*---------------------------------------------------------------------*
403  * Interpolated affine image transformation *
404  *---------------------------------------------------------------------*/
420 PIX *
422  PTA *ptad,
423  PTA *ptas,
424  l_int32 incolor)
425 {
426 l_int32 d;
427 l_uint32 colorval;
428 PIX *pixt1, *pixt2, *pixd;
429 
430  if (!pixs)
431  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
432  if (!ptas)
433  return (PIX *)ERROR_PTR("ptas not defined", __func__, NULL);
434  if (!ptad)
435  return (PIX *)ERROR_PTR("ptad not defined", __func__, NULL);
436  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
437  return (PIX *)ERROR_PTR("invalid incolor", __func__, NULL);
438  if (ptaGetCount(ptas) != 3)
439  return (PIX *)ERROR_PTR("ptas count not 3", __func__, NULL);
440  if (ptaGetCount(ptad) != 3)
441  return (PIX *)ERROR_PTR("ptad count not 3", __func__, NULL);
442 
443  if (pixGetDepth(pixs) == 1)
444  return pixAffineSampledPta(pixs, ptad, ptas, incolor);
445 
446  /* Remove cmap if it exists, and unpack to 8 bpp if necessary */
448  d = pixGetDepth(pixt1);
449  if (d < 8)
450  pixt2 = pixConvertTo8(pixt1, FALSE);
451  else
452  pixt2 = pixClone(pixt1);
453  d = pixGetDepth(pixt2);
454 
455  /* Compute actual color to bring in from edges */
456  colorval = 0;
457  if (incolor == L_BRING_IN_WHITE) {
458  if (d == 8)
459  colorval = 255;
460  else /* d == 32 */
461  colorval = 0xffffff00;
462  }
463 
464  if (d == 8)
465  pixd = pixAffinePtaGray(pixt2, ptad, ptas, colorval);
466  else /* d == 32 */
467  pixd = pixAffinePtaColor(pixt2, ptad, ptas, colorval);
468  pixDestroy(&pixt1);
469  pixDestroy(&pixt2);
470  return pixd;
471 }
472 
473 
488 PIX *
490  l_float32 *vc,
491  l_int32 incolor)
492 {
493 l_int32 d;
494 l_uint32 colorval;
495 PIX *pixt1, *pixt2, *pixd;
496 
497  if (!pixs)
498  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
499  if (!vc)
500  return (PIX *)ERROR_PTR("vc not defined", __func__, NULL);
501 
502  if (pixGetDepth(pixs) == 1)
503  return pixAffineSampled(pixs, vc, incolor);
504 
505  /* Remove cmap if it exists, and unpack to 8 bpp if necessary */
507  d = pixGetDepth(pixt1);
508  if (d < 8)
509  pixt2 = pixConvertTo8(pixt1, FALSE);
510  else
511  pixt2 = pixClone(pixt1);
512  d = pixGetDepth(pixt2);
513 
514  /* Compute actual color to bring in from edges */
515  colorval = 0;
516  if (incolor == L_BRING_IN_WHITE) {
517  if (d == 8)
518  colorval = 255;
519  else /* d == 32 */
520  colorval = 0xffffff00;
521  }
522 
523  if (d == 8)
524  pixd = pixAffineGray(pixt2, vc, colorval);
525  else /* d == 32 */
526  pixd = pixAffineColor(pixt2, vc, colorval);
527  pixDestroy(&pixt1);
528  pixDestroy(&pixt2);
529  return pixd;
530 }
531 
532 
542 PIX *
544  PTA *ptad,
545  PTA *ptas,
546  l_uint32 colorval)
547 {
548 l_float32 *vc;
549 PIX *pixd;
550 
551  if (!pixs)
552  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
553  if (!ptas)
554  return (PIX *)ERROR_PTR("ptas not defined", __func__, NULL);
555  if (!ptad)
556  return (PIX *)ERROR_PTR("ptad not defined", __func__, NULL);
557  if (pixGetDepth(pixs) != 32)
558  return (PIX *)ERROR_PTR("pixs must be 32 bpp", __func__, NULL);
559  if (ptaGetCount(ptas) != 3)
560  return (PIX *)ERROR_PTR("ptas count not 3", __func__, NULL);
561  if (ptaGetCount(ptad) != 3)
562  return (PIX *)ERROR_PTR("ptad count not 3", __func__, NULL);
563 
564  /* Get backwards transform from dest to src, and apply it */
565  getAffineXformCoeffs(ptad, ptas, &vc);
566  pixd = pixAffineColor(pixs, vc, colorval);
567  LEPT_FREE(vc);
568 
569  return pixd;
570 }
571 
572 
581 PIX *
583  l_float32 *vc,
584  l_uint32 colorval)
585 {
586 l_int32 i, j, w, h, d, wpls, wpld;
587 l_uint32 val;
588 l_uint32 *datas, *datad, *lined;
589 l_float32 x, y;
590 PIX *pix1, *pix2, *pixd;
591 
592  if (!pixs)
593  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
594  pixGetDimensions(pixs, &w, &h, &d);
595  if (d != 32)
596  return (PIX *)ERROR_PTR("pixs must be 32 bpp", __func__, NULL);
597  if (!vc)
598  return (PIX *)ERROR_PTR("vc not defined", __func__, NULL);
599 
600  datas = pixGetData(pixs);
601  wpls = pixGetWpl(pixs);
602  pixd = pixCreateTemplate(pixs);
603  pixSetAllArbitrary(pixd, colorval);
604  datad = pixGetData(pixd);
605  wpld = pixGetWpl(pixd);
606 
607  /* Iterate over destination pixels */
608  for (i = 0; i < h; i++) {
609  lined = datad + i * wpld;
610  for (j = 0; j < w; j++) {
611  /* Compute float src pixel location corresponding to (i,j) */
612  affineXformPt(vc, j, i, &x, &y);
613  linearInterpolatePixelColor(datas, wpls, w, h, x, y, colorval,
614  &val);
615  *(lined + j) = val;
616  }
617  }
618 
619  /* If rgba, transform the pixs alpha channel and insert in pixd */
620  if (pixGetSpp(pixs) == 4) {
621  pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
622  pix2 = pixAffineGray(pix1, vc, 255); /* bring in opaque */
623  pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
624  pixDestroy(&pix1);
625  pixDestroy(&pix2);
626  }
627 
628  return pixd;
629 }
630 
631 
641 PIX *
643  PTA *ptad,
644  PTA *ptas,
645  l_uint8 grayval)
646 {
647 l_float32 *vc;
648 PIX *pixd;
649 
650  if (!pixs)
651  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
652  if (!ptas)
653  return (PIX *)ERROR_PTR("ptas not defined", __func__, NULL);
654  if (!ptad)
655  return (PIX *)ERROR_PTR("ptad not defined", __func__, NULL);
656  if (pixGetDepth(pixs) != 8)
657  return (PIX *)ERROR_PTR("pixs must be 8 bpp", __func__, NULL);
658  if (ptaGetCount(ptas) != 3)
659  return (PIX *)ERROR_PTR("ptas count not 3", __func__, NULL);
660  if (ptaGetCount(ptad) != 3)
661  return (PIX *)ERROR_PTR("ptad count not 3", __func__, NULL);
662 
663  /* Get backwards transform from dest to src, and apply it */
664  getAffineXformCoeffs(ptad, ptas, &vc);
665  pixd = pixAffineGray(pixs, vc, grayval);
666  LEPT_FREE(vc);
667 
668  return pixd;
669 }
670 
671 
672 
681 PIX *
683  l_float32 *vc,
684  l_uint8 grayval)
685 {
686 l_int32 i, j, w, h, wpls, wpld, val;
687 l_uint32 *datas, *datad, *lined;
688 l_float32 x, y;
689 PIX *pixd;
690 
691  if (!pixs)
692  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
693  pixGetDimensions(pixs, &w, &h, NULL);
694  if (pixGetDepth(pixs) != 8)
695  return (PIX *)ERROR_PTR("pixs must be 8 bpp", __func__, NULL);
696  if (!vc)
697  return (PIX *)ERROR_PTR("vc not defined", __func__, NULL);
698 
699  datas = pixGetData(pixs);
700  wpls = pixGetWpl(pixs);
701  pixd = pixCreateTemplate(pixs);
702  pixSetAllArbitrary(pixd, grayval);
703  datad = pixGetData(pixd);
704  wpld = pixGetWpl(pixd);
705 
706  /* Iterate over destination pixels */
707  for (i = 0; i < h; i++) {
708  lined = datad + i * wpld;
709  for (j = 0; j < w; j++) {
710  /* Compute float src pixel location corresponding to (i,j) */
711  affineXformPt(vc, j, i, &x, &y);
712  linearInterpolatePixelGray(datas, wpls, w, h, x, y, grayval, &val);
713  SET_DATA_BYTE(lined, j, val);
714  }
715  }
716 
717  return pixd;
718 }
719 
720 
721 /*---------------------------------------------------------------------------*
722  * Affine transform including alpha (blend) component *
723  *---------------------------------------------------------------------------*/
767 PIX *
769  PTA *ptad,
770  PTA *ptas,
771  PIX *pixg,
772  l_float32 fract,
773  l_int32 border)
774 {
775 l_int32 ws, hs, d;
776 PIX *pixd, *pixb1, *pixb2, *pixg2, *pixga;
777 PTA *ptad2, *ptas2;
778 
779  if (!pixs)
780  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
781  pixGetDimensions(pixs, &ws, &hs, &d);
782  if (d != 32 && pixGetColormap(pixs) == NULL)
783  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", __func__, NULL);
784  if (pixg && pixGetDepth(pixg) != 8) {
785  L_WARNING("pixg not 8 bpp; using 'fract' transparent alpha\n",
786  __func__);
787  pixg = NULL;
788  }
789  if (!pixg && (fract < 0.0 || fract > 1.0)) {
790  L_WARNING("invalid fract; using 1.0 (fully transparent)\n", __func__);
791  fract = 1.0;
792  }
793  if (!pixg && fract == 0.0)
794  L_WARNING("fully opaque alpha; image will not be blended\n", __func__);
795  if (!ptad)
796  return (PIX *)ERROR_PTR("ptad not defined", __func__, NULL);
797  if (!ptas)
798  return (PIX *)ERROR_PTR("ptas not defined", __func__, NULL);
799 
800  /* Add border; the color doesn't matter */
801  pixb1 = pixAddBorder(pixs, border, 0);
802 
803  /* Transform the ptr arrays to work on the bordered image */
804  ptad2 = ptaTransform(ptad, border, border, 1.0, 1.0);
805  ptas2 = ptaTransform(ptas, border, border, 1.0, 1.0);
806 
807  /* Do separate affine transform of rgb channels of pixs and of pixg */
808  pixd = pixAffinePtaColor(pixb1, ptad2, ptas2, 0);
809  if (!pixg) {
810  pixg2 = pixCreate(ws, hs, 8);
811  if (fract == 1.0)
812  pixSetAll(pixg2);
813  else
814  pixSetAllArbitrary(pixg2, (l_int32)(255.0 * fract));
815  } else {
816  pixg2 = pixResizeToMatch(pixg, NULL, ws, hs);
817  }
818  if (ws > 10 && hs > 10) { /* see note 7 */
819  pixSetBorderRingVal(pixg2, 1,
820  (l_int32)(255.0 * fract * AlphaMaskBorderVals[0]));
821  pixSetBorderRingVal(pixg2, 2,
822  (l_int32)(255.0 * fract * AlphaMaskBorderVals[1]));
823 
824  }
825  pixb2 = pixAddBorder(pixg2, border, 0); /* must be black border */
826  pixga = pixAffinePtaGray(pixb2, ptad2, ptas2, 0);
827  pixSetRGBComponent(pixd, pixga, L_ALPHA_CHANNEL);
828  pixSetSpp(pixd, 4);
829 
830  pixDestroy(&pixg2);
831  pixDestroy(&pixb1);
832  pixDestroy(&pixb2);
833  pixDestroy(&pixga);
834  ptaDestroy(&ptad2);
835  ptaDestroy(&ptas2);
836  return pixd;
837 }
838 
839 
840 /*-------------------------------------------------------------*
841  * Affine coordinate transformation *
842  *-------------------------------------------------------------*/
914 l_ok
916  PTA *ptad,
917  l_float32 **pvc)
918 {
919 l_int32 i;
920 l_float32 x1, y1, x2, y2, x3, y3;
921 l_float32 *b; /* rhs vector of primed coords X'; coeffs returned in *pvc */
922 l_float32 *a[6]; /* 6x6 matrix A */
923 
924  if (!ptas)
925  return ERROR_INT("ptas not defined", __func__, 1);
926  if (!ptad)
927  return ERROR_INT("ptad not defined", __func__, 1);
928  if (!pvc)
929  return ERROR_INT("&vc not defined", __func__, 1);
930 
931  b = (l_float32 *)LEPT_CALLOC(6, sizeof(l_float32));
932  *pvc = b;
933 
934  ptaGetPt(ptas, 0, &x1, &y1);
935  ptaGetPt(ptas, 1, &x2, &y2);
936  ptaGetPt(ptas, 2, &x3, &y3);
937  ptaGetPt(ptad, 0, &b[0], &b[1]);
938  ptaGetPt(ptad, 1, &b[2], &b[3]);
939  ptaGetPt(ptad, 2, &b[4], &b[5]);
940 
941  for (i = 0; i < 6; i++)
942  a[i] = (l_float32 *)LEPT_CALLOC(6, sizeof(l_float32));
943  a[0][0] = x1;
944  a[0][1] = y1;
945  a[0][2] = 1.;
946  a[1][3] = x1;
947  a[1][4] = y1;
948  a[1][5] = 1.;
949  a[2][0] = x2;
950  a[2][1] = y2;
951  a[2][2] = 1.;
952  a[3][3] = x2;
953  a[3][4] = y2;
954  a[3][5] = 1.;
955  a[4][0] = x3;
956  a[4][1] = y3;
957  a[4][2] = 1.;
958  a[5][3] = x3;
959  a[5][4] = y3;
960  a[5][5] = 1.;
961 
962  gaussjordan(a, b, 6);
963 
964  for (i = 0; i < 6; i++)
965  LEPT_FREE(a[i]);
966 
967  return 0;
968 }
969 
970 
1002 l_ok
1003 affineInvertXform(l_float32 *vc,
1004  l_float32 **pvci)
1005 {
1006 l_int32 i;
1007 l_float32 *vci;
1008 l_float32 *a[3];
1009 l_float32 b[3] = {1.0, 1.0, 1.0}; /* anything; results ignored */
1010 
1011  if (!pvci)
1012  return ERROR_INT("&vci not defined", __func__, 1);
1013  *pvci = NULL;
1014  if (!vc)
1015  return ERROR_INT("vc not defined", __func__, 1);
1016 
1017 #if 1
1018  for (i = 0; i < 3; i++)
1019  a[i] = (l_float32 *)LEPT_CALLOC(3, sizeof(l_float32));
1020  a[0][0] = vc[0];
1021  a[0][1] = vc[1];
1022  a[0][2] = vc[2];
1023  a[1][0] = vc[3];
1024  a[1][1] = vc[4];
1025  a[1][2] = vc[5];
1026  a[2][2] = 1.0;
1027  gaussjordan(a, b, 3); /* this inverts matrix a */
1028  vci = (l_float32 *)LEPT_CALLOC(6, sizeof(l_float32));
1029  *pvci = vci;
1030  vci[0] = a[0][0];
1031  vci[1] = a[0][1];
1032  vci[2] = a[0][2];
1033  vci[3] = a[1][0];
1034  vci[4] = a[1][1];
1035  vci[5] = a[1][2];
1036  for (i = 0; i < 3; i++)
1037  LEPT_FREE(a[i]);
1038 
1039 #else
1040 
1041  /* Alternative version, inverting a 2x2 matrix */
1042  { l_float32 *a2[2];
1043  for (i = 0; i < 2; i++)
1044  a2[i] = (l_float32 *)LEPT_CALLOC(2, sizeof(l_float32));
1045  a2[0][0] = vc[0];
1046  a2[0][1] = vc[1];
1047  a2[1][0] = vc[3];
1048  a2[1][1] = vc[4];
1049  b[0] = vc[2];
1050  b[1] = vc[5];
1051  gaussjordan(a2, b, 2); /* this inverts matrix a2 */
1052  vci = (l_float32 *)LEPT_CALLOC(6, sizeof(l_float32));
1053  *pvci = vci;
1054  vci[0] = a2[0][0];
1055  vci[1] = a2[0][1];
1056  vci[2] = -b[0]; /* note sign */
1057  vci[3] = a2[1][0];
1058  vci[4] = a2[1][1];
1059  vci[5] = -b[1]; /* note sign */
1060  for (i = 0; i < 2; i++)
1061  LEPT_FREE(a2[i]);
1062  }
1063 #endif
1064 
1065  return 0;
1066 }
1067 
1068 
1083 l_ok
1084 affineXformSampledPt(l_float32 *vc,
1085  l_int32 x,
1086  l_int32 y,
1087  l_int32 *pxp,
1088  l_int32 *pyp)
1089 {
1090  if (!vc)
1091  return ERROR_INT("vc not defined", __func__, 1);
1092 
1093  *pxp = (l_int32)(vc[0] * x + vc[1] * y + vc[2] + 0.5);
1094  *pyp = (l_int32)(vc[3] * x + vc[4] * y + vc[5] + 0.5);
1095  return 0;
1096 }
1097 
1098 
1113 l_ok
1114 affineXformPt(l_float32 *vc,
1115  l_int32 x,
1116  l_int32 y,
1117  l_float32 *pxp,
1118  l_float32 *pyp)
1119 {
1120  if (!vc)
1121  return ERROR_INT("vc not defined", __func__, 1);
1122 
1123  *pxp = vc[0] * x + vc[1] * y + vc[2];
1124  *pyp = vc[3] * x + vc[4] * y + vc[5];
1125  return 0;
1126 }
1127 
1128 
1129 /*-------------------------------------------------------------*
1130  * Interpolation helper functions *
1131  *-------------------------------------------------------------*/
1152 l_ok
1154  l_int32 wpls,
1155  l_int32 w,
1156  l_int32 h,
1157  l_float32 x,
1158  l_float32 y,
1159  l_uint32 colorval,
1160  l_uint32 *pval)
1161 {
1162 l_int32 valid, xpm, ypm, xp, xp2, yp, xf, yf;
1163 l_int32 rval, gval, bval;
1164 l_uint32 word00, word01, word10, word11;
1165 l_uint32 *lines;
1166 
1167  if (!pval)
1168  return ERROR_INT("&val not defined", __func__, 1);
1169  *pval = colorval;
1170  if (!datas)
1171  return ERROR_INT("datas not defined", __func__, 1);
1172 
1173  /* Skip if x or y are invalid. (x,y) must be in the source image.
1174  * Failure to detect an invalid point will cause a mem address fault.
1175  * Occasionally, x or y will be a nan, and relational checks always
1176  * fail for nans. Therefore we check if the point is inside the pix */
1177  valid = (x >= 0.0 && y >= 0.0 && x < w && y < h);
1178  if (!valid) return 0;
1179 
1180  xpm = (l_int32)(16.0 * x);
1181  ypm = (l_int32)(16.0 * y);
1182  xp = xpm >> 4;
1183  xp2 = xp + 1 < w ? xp + 1 : xp;
1184  yp = ypm >> 4;
1185  if (yp + 1 >= h) wpls = 0;
1186  xf = xpm & 0x0f;
1187  yf = ypm & 0x0f;
1188 
1189 #if DEBUG
1190  if (xf < 0 || yf < 0)
1191  lept_stderr("xp = %d, yp = %d, xf = %d, yf = %d\n", xp, yp, xf, yf);
1192 #endif /* DEBUG */
1193 
1194  /* Do area weighting (eqiv. to linear interpolation) */
1195  lines = datas + yp * wpls;
1196  word00 = *(lines + xp);
1197  word10 = *(lines + xp2);
1198  word01 = *(lines + wpls + xp);
1199  word11 = *(lines + wpls + xp2);
1200  rval = ((16 - xf) * (16 - yf) * ((word00 >> L_RED_SHIFT) & 0xff) +
1201  xf * (16 - yf) * ((word10 >> L_RED_SHIFT) & 0xff) +
1202  (16 - xf) * yf * ((word01 >> L_RED_SHIFT) & 0xff) +
1203  xf * yf * ((word11 >> L_RED_SHIFT) & 0xff)) / 256;
1204  gval = ((16 - xf) * (16 - yf) * ((word00 >> L_GREEN_SHIFT) & 0xff) +
1205  xf * (16 - yf) * ((word10 >> L_GREEN_SHIFT) & 0xff) +
1206  (16 - xf) * yf * ((word01 >> L_GREEN_SHIFT) & 0xff) +
1207  xf * yf * ((word11 >> L_GREEN_SHIFT) & 0xff)) / 256;
1208  bval = ((16 - xf) * (16 - yf) * ((word00 >> L_BLUE_SHIFT) & 0xff) +
1209  xf * (16 - yf) * ((word10 >> L_BLUE_SHIFT) & 0xff) +
1210  (16 - xf) * yf * ((word01 >> L_BLUE_SHIFT) & 0xff) +
1211  xf * yf * ((word11 >> L_BLUE_SHIFT) & 0xff)) / 256;
1212  composeRGBPixel(rval, gval, bval, pval);
1213  return 0;
1214 }
1215 
1216 
1236 l_ok
1238  l_int32 wpls,
1239  l_int32 w,
1240  l_int32 h,
1241  l_float32 x,
1242  l_float32 y,
1243  l_int32 grayval,
1244  l_int32 *pval)
1245 {
1246 l_int32 valid, xpm, ypm, xp, xp2, yp, xf, yf, v00, v10, v01, v11;
1247 l_uint32 *lines;
1248 
1249  if (!pval)
1250  return ERROR_INT("&val not defined", __func__, 1);
1251  *pval = grayval;
1252  if (!datas)
1253  return ERROR_INT("datas not defined", __func__, 1);
1254 
1255  /* Skip if x or y is invalid. (x,y) must be in the source image.
1256  * Failure to detect an invalid point will cause a mem address fault.
1257  * Occasionally, x or y will be a nan, and relational checks always
1258  * fail for nans. Therefore we check if the point is inside the pix */
1259  valid = (x >= 0.0 && y >= 0.0 && x < w && y < h);
1260  if (!valid) return 0;
1261 
1262  xpm = (l_int32)(16.0 * x);
1263  ypm = (l_int32)(16.0 * y);
1264  xp = xpm >> 4;
1265  xp2 = xp + 1 < w ? xp + 1 : xp;
1266  yp = ypm >> 4;
1267  if (yp + 1 >= h) wpls = 0;
1268  xf = xpm & 0x0f;
1269  yf = ypm & 0x0f;
1270 
1271 #if DEBUG
1272  if (xf < 0 || yf < 0)
1273  lept_stderr("xp = %d, yp = %d, xf = %d, yf = %d\n", xp, yp, xf, yf);
1274 #endif /* DEBUG */
1275 
1276  /* Interpolate by area weighting. */
1277  lines = datas + yp * wpls;
1278  v00 = (16 - xf) * (16 - yf) * GET_DATA_BYTE(lines, xp);
1279  v10 = xf * (16 - yf) * GET_DATA_BYTE(lines, xp2);
1280  v01 = (16 - xf) * yf * GET_DATA_BYTE(lines + wpls, xp);
1281  v11 = xf * yf * GET_DATA_BYTE(lines + wpls, xp2);
1282  *pval = (v00 + v01 + v10 + v11) / 256;
1283  return 0;
1284 }
1285 
1286 
1287 
1288 /*-------------------------------------------------------------*
1289  * Gauss-jordan linear equation solver *
1290  *-------------------------------------------------------------*/
1291 #define SWAP(a,b) {temp = (a); (a) = (b); (b) = temp;}
1292 
1313 l_int32
1314 gaussjordan(l_float32 **a,
1315  l_float32 *b,
1316  l_int32 n)
1317 {
1318 l_int32 i, icol, irow, j, k, col, row, success;
1319 l_int32 *indexc, *indexr, *ipiv;
1320 l_float32 maxval, val, pivinv, temp;
1321 
1322  if (!a)
1323  return ERROR_INT("a not defined", __func__, 1);
1324  if (!b)
1325  return ERROR_INT("b not defined", __func__, 1);
1326 
1327  success = TRUE;
1328  indexc = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
1329  indexr = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
1330  ipiv = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
1331  if (!indexc || !indexr || !ipiv) {
1332  L_ERROR("array not made\n", __func__);
1333  success = FALSE;
1334  goto cleanup_arrays;
1335  }
1336 
1337  icol = irow = 0; /* silence static checker */
1338  for (i = 0; i < n; i++) {
1339  maxval = 0.0;
1340  for (j = 0; j < n; j++) {
1341  if (ipiv[j] != 1) {
1342  for (k = 0; k < n; k++) {
1343  if (ipiv[k] == 0) {
1344  if (fabs(a[j][k]) >= maxval) {
1345  maxval = fabs(a[j][k]);
1346  irow = j;
1347  icol = k;
1348  }
1349  } else if (ipiv[k] > 1) {
1350  L_ERROR("singular matrix\n", __func__);
1351  success = FALSE;
1352  goto cleanup_arrays;
1353  }
1354  }
1355  }
1356  }
1357  ++(ipiv[icol]);
1358 
1359  if (irow != icol) {
1360  for (col = 0; col < n; col++)
1361  SWAP(a[irow][col], a[icol][col]);
1362  SWAP(b[irow], b[icol]);
1363  }
1364 
1365  indexr[i] = irow;
1366  indexc[i] = icol;
1367  if (a[icol][icol] == 0.0) {
1368  L_ERROR("singular matrix\n", __func__);
1369  success = FALSE;
1370  goto cleanup_arrays;
1371  }
1372  pivinv = 1.0 / a[icol][icol];
1373  a[icol][icol] = 1.0;
1374  for (col = 0; col < n; col++)
1375  a[icol][col] *= pivinv;
1376  b[icol] *= pivinv;
1377 
1378  for (row = 0; row < n; row++) {
1379  if (row != icol) {
1380  val = a[row][icol];
1381  a[row][icol] = 0.0;
1382  for (col = 0; col < n; col++)
1383  a[row][col] -= a[icol][col] * val;
1384  b[row] -= b[icol] * val;
1385  }
1386  }
1387  }
1388 
1389  for (col = n - 1; col >= 0; col--) {
1390  if (indexr[col] != indexc[col]) {
1391  for (k = 0; k < n; k++)
1392  SWAP(a[k][indexr[col]], a[k][indexc[col]]);
1393  }
1394  }
1395 
1396 cleanup_arrays:
1397  LEPT_FREE(indexr);
1398  LEPT_FREE(indexc);
1399  LEPT_FREE(ipiv);
1400  return (success) ? 0 : 1;
1401 }
1402 
1403 
1404 /*-------------------------------------------------------------*
1405  * Sequential affine image transformation *
1406  *-------------------------------------------------------------*/
1435 PIX *
1437  PTA *ptad,
1438  PTA *ptas,
1439  l_int32 bw,
1440  l_int32 bh)
1441 {
1442 l_int32 x1, y1, x2, y2, x3, y3; /* ptas */
1443 l_int32 x1p, y1p, x2p, y2p, x3p, y3p; /* ptad */
1444 l_int32 x1sc, y1sc; /* scaled origin */
1445 l_float32 x2s, x2sp, scalex, scaley;
1446 l_float32 th3, th3p, ph2, ph2p;
1447 #if DEBUG
1448 l_float32 rad2deg;
1449 #endif /* DEBUG */
1450 PIX *pix1, *pix2, *pixd;
1451 
1452  if (!pixs)
1453  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1454  if (!ptas)
1455  return (PIX *)ERROR_PTR("ptas not defined", __func__, NULL);
1456  if (!ptad)
1457  return (PIX *)ERROR_PTR("ptad not defined", __func__, NULL);
1458 
1459  if (ptaGetCount(ptas) != 3)
1460  return (PIX *)ERROR_PTR("ptas count not 3", __func__, NULL);
1461  if (ptaGetCount(ptad) != 3)
1462  return (PIX *)ERROR_PTR("ptad count not 3", __func__, NULL);
1463  ptaGetIPt(ptas, 0, &x1, &y1);
1464  ptaGetIPt(ptas, 1, &x2, &y2);
1465  ptaGetIPt(ptas, 2, &x3, &y3);
1466  ptaGetIPt(ptad, 0, &x1p, &y1p);
1467  ptaGetIPt(ptad, 1, &x2p, &y2p);
1468  ptaGetIPt(ptad, 2, &x3p, &y3p);
1469 
1470  pix1 = pix2 = pixd = NULL;
1471 
1472  if (y1 == y3)
1473  return (PIX *)ERROR_PTR("y1 == y3!", __func__, NULL);
1474  if (y1p == y3p)
1475  return (PIX *)ERROR_PTR("y1p == y3p!", __func__, NULL);
1476 
1477  if (bw != 0 || bh != 0) {
1478  /* resize all points and add border to pixs */
1479  x1 = x1 + bw;
1480  y1 = y1 + bh;
1481  x2 = x2 + bw;
1482  y2 = y2 + bh;
1483  x3 = x3 + bw;
1484  y3 = y3 + bh;
1485  x1p = x1p + bw;
1486  y1p = y1p + bh;
1487  x2p = x2p + bw;
1488  y2p = y2p + bh;
1489  x3p = x3p + bw;
1490  y3p = y3p + bh;
1491 
1492  if ((pix1 = pixAddBorderGeneral(pixs, bw, bw, bh, bh, 0)) == NULL)
1493  return (PIX *)ERROR_PTR("pix1 not made", __func__, NULL);
1494  } else {
1495  pix1 = pixCopy(NULL, pixs);
1496  }
1497 
1498  /*-------------------------------------------------------------*
1499  The horizontal shear is done to move the 3rd point to the
1500  y axis. This moves the 2nd point either towards or away
1501  from the y axis, depending on whether it is above or below
1502  the x axis. That motion must be computed so that we know
1503  the angle of vertical shear to use to get the 2nd point
1504  on the x axis. We must also know the x coordinate of the
1505  2nd point in order to compute how much scaling is required
1506  to match points on the axis.
1507  *-------------------------------------------------------------*/
1508 
1509  /* Shear angles required to put src points on x and y axes */
1510  th3 = atan2((l_float64)(x1 - x3), (l_float64)(y1 - y3));
1511  x2s = (l_float32)(x2 - ((l_float32)(y1 - y2) * (x3 - x1)) / (y1 - y3));
1512  if (x2s == (l_float32)x1) {
1513  L_ERROR("x2s == x1!\n", __func__);
1514  goto cleanup_pix;
1515  }
1516  ph2 = atan2((l_float64)(y1 - y2), (l_float64)(x2s - x1));
1517 
1518  /* Shear angles required to put dest points on x and y axes.
1519  * Use the negative of these values to instead move the
1520  * src points from the axes to the actual dest position.
1521  * These values are also needed to scale the image. */
1522  th3p = atan2((l_float64)(x1p - x3p), (l_float64)(y1p - y3p));
1523  x2sp = (l_float32)(x2p -
1524  ((l_float32)(y1p - y2p) * (x3p - x1p)) / (y1p - y3p));
1525  if (x2sp == (l_float32)x1p) {
1526  L_ERROR("x2sp == x1p!\n", __func__);
1527  goto cleanup_pix;
1528  }
1529  ph2p = atan2((l_float64)(y1p - y2p), (l_float64)(x2sp - x1p));
1530 
1531  /* Shear image to first put src point 3 on the y axis,
1532  * and then to put src point 2 on the x axis */
1533  pixHShearIP(pix1, y1, th3, L_BRING_IN_WHITE);
1534  pixVShearIP(pix1, x1, ph2, L_BRING_IN_WHITE);
1535 
1536  /* Scale image to match dest scale. The dest scale
1537  * is calculated above from the angles th3p and ph2p
1538  * that would be required to move the dest points to
1539  * the x and y axes. */
1540  scalex = (l_float32)(x2sp - x1p) / (x2s - x1);
1541  scaley = (l_float32)(y3p - y1p) / (y3 - y1);
1542  if ((pix2 = pixScale(pix1, scalex, scaley)) == NULL) {
1543  L_ERROR("pix2 not made\n", __func__);
1544  goto cleanup_pix;
1545  }
1546 
1547 #if DEBUG
1548  rad2deg = 180. / 3.1415926535;
1549  lept_stderr("th3 = %5.1f deg, ph2 = %5.1f deg\n",
1550  rad2deg * th3, rad2deg * ph2);
1551  lept_stderr("th3' = %5.1f deg, ph2' = %5.1f deg\n",
1552  rad2deg * th3p, rad2deg * ph2p);
1553  lept_stderr("scalex = %6.3f, scaley = %6.3f\n", scalex, scaley);
1554 #endif /* DEBUG */
1555 
1556  /*-------------------------------------------------------------*
1557  Scaling moves the 1st src point, which is the origin.
1558  It must now be moved again to coincide with the origin
1559  (1st point) of the dest. After this is done, the 2nd
1560  and 3rd points must be sheared back to the original
1561  positions of the 2nd and 3rd dest points. We use the
1562  negative of the angles that were previously computed
1563  for shearing those points in the dest image to x and y
1564  axes, and take the shears in reverse order as well.
1565  *-------------------------------------------------------------*/
1566  /* Shift image to match dest origin. */
1567  x1sc = (l_int32)(scalex * x1 + 0.5); /* x comp of origin after scaling */
1568  y1sc = (l_int32)(scaley * y1 + 0.5); /* y comp of origin after scaling */
1569  pixRasteropIP(pix2, x1p - x1sc, y1p - y1sc, L_BRING_IN_WHITE);
1570 
1571  /* Shear image to take points 2 and 3 off the axis and
1572  * put them in the original dest position */
1573  pixVShearIP(pix2, x1p, -ph2p, L_BRING_IN_WHITE);
1574  pixHShearIP(pix2, y1p, -th3p, L_BRING_IN_WHITE);
1575 
1576  if (bw != 0 || bh != 0) {
1577  if ((pixd = pixRemoveBorderGeneral(pix2, bw, bw, bh, bh)) == NULL)
1578  L_ERROR("pixd not made\n", __func__);
1579  } else {
1580  pixd = pixClone(pix2);
1581  }
1582 
1583 cleanup_pix:
1584  pixDestroy(&pix1);
1585  pixDestroy(&pix2);
1586  return pixd;
1587 }
PIX * pixAffineColor(PIX *pixs, l_float32 *vc, l_uint32 colorval)
pixAffineColor()
Definition: affine.c:582
l_ok affineInvertXform(l_float32 *vc, l_float32 **pvci)
affineInvertXform()
Definition: affine.c:1003
PIX * pixAffineSequential(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 bw, l_int32 bh)
pixAffineSequential()
Definition: affine.c:1436
l_ok affineXformSampledPt(l_float32 *vc, l_int32 x, l_int32 y, l_int32 *pxp, l_int32 *pyp)
affineXformSampledPt()
Definition: affine.c:1084
PIX * pixAffinePta(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor)
pixAffinePta()
Definition: affine.c:421
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:1153
l_int32 gaussjordan(l_float32 **a, l_float32 *b, l_int32 n)
gaussjordan()
Definition: affine.c:1314
PIX * pixAffineGray(PIX *pixs, l_float32 *vc, l_uint8 grayval)
pixAffineGray()
Definition: affine.c:682
PIX * pixAffinePtaGray(PIX *pixs, PTA *ptad, PTA *ptas, l_uint8 grayval)
pixAffinePtaGray()
Definition: affine.c:642
PIX * pixAffine(PIX *pixs, l_float32 *vc, l_int32 incolor)
pixAffine()
Definition: affine.c:489
l_ok linearInterpolatePixelGray(l_uint32 *datas, l_int32 wpls, l_int32 w, l_int32 h, l_float32 x, l_float32 y, l_int32 grayval, l_int32 *pval)
linearInterpolatePixelGray()
Definition: affine.c:1237
PIX * pixAffineSampledPta(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor)
pixAffineSampledPta()
Definition: affine.c:282
l_ok affineXformPt(l_float32 *vc, l_int32 x, l_int32 y, l_float32 *pxp, l_float32 *pyp)
affineXformPt()
Definition: affine.c:1114
PIX * pixAffineSampled(PIX *pixs, l_float32 *vc, l_int32 incolor)
pixAffineSampled()
Definition: affine.c:330
l_ok getAffineXformCoeffs(PTA *ptas, PTA *ptad, l_float32 **pvc)
getAffineXformCoeffs()
Definition: affine.c:915
PIX * pixAffinePtaColor(PIX *pixs, PTA *ptad, PTA *ptas, l_uint32 colorval)
pixAffinePtaColor()
Definition: affine.c:543
PIX * pixAffinePtaWithAlpha(PIX *pixs, PTA *ptad, PTA *ptas, PIX *pixg, l_float32 fract, l_int32 border)
pixAffinePtaWithAlpha()
Definition: affine.c:768
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
#define SET_DATA_BIT_VAL(pdata, n, val)
Definition: arrayaccess.h:135
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
l_ok pixcmapAddBlackOrWhite(PIXCMAP *cmap, l_int32 color, l_int32 *pindex)
pixcmapAddBlackOrWhite()
Definition: colormap.c:618
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
l_ok pixSetBorderRingVal(PIX *pixs, l_int32 dist, l_uint32 val)
pixSetBorderRingVal()
Definition: pix2.c:1623
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2464
l_ok pixClearAll(PIX *pix)
pixClearAll()
Definition: pix2.c:773
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixRemoveBorderGeneral()
Definition: pix2.c:1996
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1773
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1863
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:799
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2728
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2521
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:929
PIX * pixResizeToMatch(PIX *pixs, PIX *pixt, l_int32 w, l_int32 h)
pixResizeToMatch()
Definition: pix5.c:1279
@ L_ALPHA_CHANNEL
Definition: pix.h:331
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:384
@ L_BRING_IN_BLACK
Definition: pix.h:663
@ L_BRING_IN_WHITE
Definition: pix.h:662
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:324
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3055
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:527
l_ok ptaGetPt(PTA *pta, l_int32 index, l_float32 *px, l_float32 *py)
ptaGetPt()
Definition: ptabasic.c:499
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:480
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
PTA * ptaTransform(PTA *ptas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
ptaTransform()
Definition: ptafunc1.c:715
l_ok pixRasteropIP(PIX *pixd, l_int32 hshift, l_int32 vshift, l_int32 incolor)
pixRasteropIP()
Definition: rop.c:467
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
l_ok pixHShearIP(PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShearIP()
Definition: shear.c:459
l_ok pixVShearIP(PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor)
pixVShearIP()
Definition: shear.c:532
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306