Leptonica 1.85.0
Image processing and image analysis suite
Loading...
Searching...
No Matches
affinecompose.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
58#ifdef HAVE_CONFIG_H
59#include <config_auto.h>
60#endif /* HAVE_CONFIG_H */
61
62#include <math.h>
63#include "allheaders.h"
64
65/*-------------------------------------------------------------*
66 * Composable coordinate transforms *
67 *-------------------------------------------------------------*/
92l_float32 *
93createMatrix2dTranslate(l_float32 transx,
94 l_float32 transy)
95{
96l_float32 *mat;
97
98 mat = (l_float32 *)LEPT_CALLOC(9, sizeof(l_float32));
99 mat[0] = mat[4] = mat[8] = 1;
100 mat[2] = transx;
101 mat[5] = transy;
102 return mat;
103}
104
105
129l_float32 *
130createMatrix2dScale(l_float32 scalex,
131 l_float32 scaley)
132{
133l_float32 *mat;
134
135 mat = (l_float32 *)LEPT_CALLOC(9, sizeof(l_float32));
136 mat[0] = scalex;
137 mat[4] = scaley;
138 mat[8] = 1;
139 return mat;
140}
141
142
178l_float32 *
180 l_float32 yc,
181 l_float32 angle)
182{
183l_float32 sina, cosa;
184l_float32 *mat;
185
186 mat = (l_float32 *)LEPT_CALLOC(9, sizeof(l_float32));
187 sina = sin(angle);
188 cosa = cos(angle);
189 mat[0] = mat[4] = cosa;
190 mat[1] = -sina;
191 mat[2] = xc * (1.0 - cosa) + yc * sina;
192 mat[3] = sina;
193 mat[5] = yc * (1.0 - cosa) - xc * sina;
194 mat[8] = 1;
195 return mat;
196}
197
198
199
200/*-------------------------------------------------------------*
201 * Special coordinate transforms on pta *
202 *-------------------------------------------------------------*/
216PTA *
218 l_float32 transx,
219 l_float32 transy)
220{
221l_int32 i, npts;
222l_float32 x, y;
223PTA *ptad;
224
225 if (!ptas)
226 return (PTA *)ERROR_PTR("ptas not defined", __func__, NULL);
227
228 npts = ptaGetCount(ptas);
229 if ((ptad = ptaCreate(npts)) == NULL)
230 return (PTA *)ERROR_PTR("ptad not made", __func__, NULL);
231 for (i = 0; i < npts; i++) {
232 ptaGetPt(ptas, i, &x, &y);
233 ptaAddPt(ptad, x + transx, y + transy);
234 }
235
236 return ptad;
237}
238
239
253PTA *
255 l_float32 scalex,
256 l_float32 scaley)
257{
258l_int32 i, npts;
259l_float32 x, y;
260PTA *ptad;
261
262 if (!ptas)
263 return (PTA *)ERROR_PTR("ptas not defined", __func__, NULL);
264
265 npts = ptaGetCount(ptas);
266 if ((ptad = ptaCreate(npts)) == NULL)
267 return (PTA *)ERROR_PTR("ptad not made", __func__, NULL);
268 for (i = 0; i < npts; i++) {
269 ptaGetPt(ptas, i, &x, &y);
270 ptaAddPt(ptad, scalex * x, scaley * y);
271 }
272
273 return ptad;
274}
275
276
302PTA *
304 l_float32 xc,
305 l_float32 yc,
306 l_float32 angle)
307{
308l_int32 i, npts;
309l_float32 x, y, xp, yp, sina, cosa;
310PTA *ptad;
311
312 if (!ptas)
313 return (PTA *)ERROR_PTR("ptas not defined", __func__, NULL);
314
315 npts = ptaGetCount(ptas);
316 if ((ptad = ptaCreate(npts)) == NULL)
317 return (PTA *)ERROR_PTR("ptad not made", __func__, NULL);
318 sina = sin(angle);
319 cosa = cos(angle);
320 for (i = 0; i < npts; i++) {
321 ptaGetPt(ptas, i, &x, &y);
322 xp = xc + (x - xc) * cosa - (y - yc) * sina;
323 yp = yc + (x - xc) * sina + (y - yc) * cosa;
324 ptaAddPt(ptad, xp, yp);
325 }
326
327 return ptad;
328}
329
330
331/*-------------------------------------------------------------*
332 * Special coordinate transforms on boxa *
333 *-------------------------------------------------------------*/
345BOXA *
347 l_float32 transx,
348 l_float32 transy)
349{
350PTA *ptas, *ptad;
351BOXA *boxad;
352
353 if (!boxas)
354 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
355
356 ptas = boxaConvertToPta(boxas, 4);
357 ptad = ptaTranslate(ptas, transx, transy);
358 boxad = ptaConvertToBoxa(ptad, 4);
359 ptaDestroy(&ptas);
360 ptaDestroy(&ptad);
361 return boxad;
362}
363
364
376BOXA *
378 l_float32 scalex,
379 l_float32 scaley)
380{
381PTA *ptas, *ptad;
382BOXA *boxad;
383
384 if (!boxas)
385 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
386
387 ptas = boxaConvertToPta(boxas, 4);
388 ptad = ptaScale(ptas, scalex, scaley);
389 boxad = ptaConvertToBoxa(ptad, 4);
390 ptaDestroy(&ptas);
391 ptaDestroy(&ptad);
392 return boxad;
393}
394
395
407BOXA *
409 l_float32 xc,
410 l_float32 yc,
411 l_float32 angle)
412{
413PTA *ptas, *ptad;
414BOXA *boxad;
415
416 if (!boxas)
417 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
418
419 ptas = boxaConvertToPta(boxas, 4);
420 ptad = ptaRotate(ptas, xc, yc, angle);
421 boxad = ptaConvertToBoxa(ptad, 4);
422 ptaDestroy(&ptas);
423 ptaDestroy(&ptad);
424 return boxad;
425}
426
427
428/*-------------------------------------------------------------*
429 * General affine coordinate transform *
430 *-------------------------------------------------------------*/
438PTA *
440 l_float32 *mat)
441{
442l_int32 i, npts;
443l_float32 vecs[3], vecd[3];
444PTA *ptad;
445
446 if (!ptas)
447 return (PTA *)ERROR_PTR("ptas not defined", __func__, NULL);
448 if (!mat)
449 return (PTA *)ERROR_PTR("transform not defined", __func__, NULL);
450
451 vecs[2] = 1;
452 npts = ptaGetCount(ptas);
453 if ((ptad = ptaCreate(npts)) == NULL)
454 return (PTA *)ERROR_PTR("ptad not made", __func__, NULL);
455 for (i = 0; i < npts; i++) {
456 ptaGetPt(ptas, i, &vecs[0], &vecs[1]);
457 l_productMatVec(mat, vecs, vecd, 3);
458 ptaAddPt(ptad, vecd[0], vecd[1]);
459 }
460
461 return ptad;
462}
463
464
472BOXA *
474 l_float32 *mat)
475{
476PTA *ptas, *ptad;
477BOXA *boxad;
478
479 if (!boxas)
480 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
481 if (!mat)
482 return (BOXA *)ERROR_PTR("transform not defined", __func__, NULL);
483
484 ptas = boxaConvertToPta(boxas, 4);
485 ptad = ptaAffineTransform(ptas, mat);
486 boxad = ptaConvertToBoxa(ptad, 4);
487 ptaDestroy(&ptas);
488 ptaDestroy(&ptad);
489 return boxad;
490}
491
492
493/*-------------------------------------------------------------*
494 * Matrix operations *
495 *-------------------------------------------------------------*/
505l_ok
506l_productMatVec(l_float32 *mat,
507 l_float32 *vecs,
508 l_float32 *vecd,
509 l_int32 size)
510{
511l_int32 i, j;
512
513 if (!mat)
514 return ERROR_INT("matrix not defined", __func__, 1);
515 if (!vecs)
516 return ERROR_INT("input vector not defined", __func__, 1);
517 if (!vecd)
518 return ERROR_INT("result vector not defined", __func__, 1);
519
520 for (i = 0; i < size; i++) {
521 vecd[i] = 0;
522 for (j = 0; j < size; j++) {
523 vecd[i] += mat[size * i + j] * vecs[j];
524 }
525 }
526 return 0;
527}
528
529
539l_ok
540l_productMat2(l_float32 *mat1,
541 l_float32 *mat2,
542 l_float32 *matd,
543 l_int32 size)
544{
545l_int32 i, j, k, index;
546
547 if (!mat1)
548 return ERROR_INT("matrix 1 not defined", __func__, 1);
549 if (!mat2)
550 return ERROR_INT("matrix 2 not defined", __func__, 1);
551 if (!matd)
552 return ERROR_INT("result matrix not defined", __func__, 1);
553
554 for (i = 0; i < size; i++) {
555 for (j = 0; j < size; j++) {
556 index = size * i + j;
557 matd[index] = 0;
558 for (k = 0; k < size; k++)
559 matd[index] += mat1[size * i + k] * mat2[size * k + j];
560 }
561 }
562 return 0;
563}
564
565
576l_ok
577l_productMat3(l_float32 *mat1,
578 l_float32 *mat2,
579 l_float32 *mat3,
580 l_float32 *matd,
581 l_int32 size)
582{
583l_float32 *matt;
584
585 if (!mat1)
586 return ERROR_INT("matrix 1 not defined", __func__, 1);
587 if (!mat2)
588 return ERROR_INT("matrix 2 not defined", __func__, 1);
589 if (!mat3)
590 return ERROR_INT("matrix 3 not defined", __func__, 1);
591 if (!matd)
592 return ERROR_INT("result matrix not defined", __func__, 1);
593
594 if ((matt = (l_float32 *)LEPT_CALLOC((size_t)size * size,
595 sizeof(l_float32))) == NULL)
596 return ERROR_INT("matt not made", __func__, 1);
597 l_productMat2(mat1, mat2, matt, size);
598 l_productMat2(matt, mat3, matd, size);
599 LEPT_FREE(matt);
600 return 0;
601}
602
603
615l_ok
616l_productMat4(l_float32 *mat1,
617 l_float32 *mat2,
618 l_float32 *mat3,
619 l_float32 *mat4,
620 l_float32 *matd,
621 l_int32 size)
622{
623l_float32 *matt;
624
625 if (!mat1)
626 return ERROR_INT("matrix 1 not defined", __func__, 1);
627 if (!mat2)
628 return ERROR_INT("matrix 2 not defined", __func__, 1);
629 if (!mat3)
630 return ERROR_INT("matrix 3 not defined", __func__, 1);
631 if (!matd)
632 return ERROR_INT("result matrix not defined", __func__, 1);
633
634 if ((matt = (l_float32 *)LEPT_CALLOC((size_t)size * size,
635 sizeof(l_float32))) == NULL)
636 return ERROR_INT("matt not made", __func__, 1);
637 l_productMat3(mat1, mat2, mat3, matt, size);
638 l_productMat2(matt, mat4, matd, size);
639 LEPT_FREE(matt);
640 return 0;
641}
l_ok l_productMat4(l_float32 *mat1, l_float32 *mat2, l_float32 *mat3, l_float32 *mat4, l_float32 *matd, l_int32 size)
l_productMat4()
PTA * ptaTranslate(PTA *ptas, l_float32 transx, l_float32 transy)
ptaTranslate()
BOXA * boxaAffineTransform(BOXA *boxas, l_float32 *mat)
boxaAffineTransform()
BOXA * boxaScale(BOXA *boxas, l_float32 scalex, l_float32 scaley)
boxaScale()
BOXA * boxaTranslate(BOXA *boxas, l_float32 transx, l_float32 transy)
boxaTranslate()
PTA * ptaScale(PTA *ptas, l_float32 scalex, l_float32 scaley)
ptaScale()
BOXA * boxaRotate(BOXA *boxas, l_float32 xc, l_float32 yc, l_float32 angle)
boxaRotate()
l_float32 * createMatrix2dTranslate(l_float32 transx, l_float32 transy)
createMatrix2dTranslate()
l_ok l_productMat3(l_float32 *mat1, l_float32 *mat2, l_float32 *mat3, l_float32 *matd, l_int32 size)
l_productMat3()
l_float32 * createMatrix2dScale(l_float32 scalex, l_float32 scaley)
createMatrix2dScale()
PTA * ptaAffineTransform(PTA *ptas, l_float32 *mat)
ptaAffineTransform()
l_float32 * createMatrix2dRotate(l_float32 xc, l_float32 yc, l_float32 angle)
createMatrix2dRotate()
l_ok l_productMatVec(l_float32 *mat, l_float32 *vecs, l_float32 *vecd, l_int32 size)
l_productMatVec()
PTA * ptaRotate(PTA *ptas, l_float32 xc, l_float32 yc, l_float32 angle)
ptaRotate()
l_ok l_productMat2(l_float32 *mat1, l_float32 *mat2, l_float32 *matd, l_int32 size)
l_productMat2()