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