Leptonica 1.82.0
Image processing and image analysis suite
rotateshear.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
164#ifdef HAVE_CONFIG_H
165#include <config_auto.h>
166#endif /* HAVE_CONFIG_H */
167
168#include <math.h>
169#include <string.h>
170#include "allheaders.h"
171
172 /* Angle limits:
173 * angle < MinAngleToRotate ==> clone
174 * angle > MaxTwoShearAngle ==> warning for 2-angle shears
175 * angle > MaxThreeShearAngle ==> warning for 3-angle shears
176 * angle > MaxShearAngle ==> error
177 */
178static const l_float32 MinAngleToRotate = 0.001; /* radians; ~0.06 deg */
179static const l_float32 MaxTwoShearAngle = 0.06; /* radians; ~3 deg */
180static const l_float32 MaxThreeShearAngle = 0.35; /* radians; ~20 deg */
181static const l_float32 MaxShearAngle = 0.50; /* radians; ~29 deg */
182
183/*------------------------------------------------------------------*
184 * Rotations about an arbitrary point *
185 *------------------------------------------------------------------*/
207PIX *
209 l_int32 xcen,
210 l_int32 ycen,
211 l_float32 angle,
212 l_int32 incolor)
213{
214 PROCNAME("pixRotateShear");
215
216 if (!pixs)
217 return (PIX *)(PIX *)ERROR_PTR("pixs not defined", procName, NULL);
218 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
219 return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", procName, NULL);
220
221 if (L_ABS(angle) > MaxShearAngle) {
222 L_ERROR("%6.2f radians; too large for shear rotation\n", procName,
223 L_ABS(angle));
224 return NULL;
225 }
226 if (L_ABS(angle) < MinAngleToRotate)
227 return pixClone(pixs);
228
229 if (L_ABS(angle) <= MaxTwoShearAngle)
230 return pixRotate2Shear(pixs, xcen, ycen, angle, incolor);
231 else
232 return pixRotate3Shear(pixs, xcen, ycen, angle, incolor);
233}
234
235
261PIX *
263 l_int32 xcen,
264 l_int32 ycen,
265 l_float32 angle,
266 l_int32 incolor)
267{
268PIX *pix1, *pix2, *pixd;
269
270 PROCNAME("pixRotate2Shear");
271
272 if (!pixs)
273 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
274 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
275 return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", procName, NULL);
276
277 if (L_ABS(angle) > MaxShearAngle) {
278 L_ERROR("%6.2f radians; too large for shear rotation\n", procName,
279 L_ABS(angle));
280 return NULL;
281 }
282 if (L_ABS(angle) < MinAngleToRotate)
283 return pixClone(pixs);
284 if (L_ABS(angle) > MaxTwoShearAngle)
285 L_WARNING("%6.2f radians; large angle for 2-shear rotation\n",
286 procName, L_ABS(angle));
287
288 if ((pix1 = pixHShear(NULL, pixs, ycen, angle, incolor)) == NULL)
289 return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
290 pixd = pixVShear(NULL, pix1, xcen, angle, incolor);
291 pixDestroy(&pix1);
292 if (!pixd)
293 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
294
295 if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4) {
297 /* L_BRING_IN_WHITE brings in opaque for the alpha component */
298 pix2 = pixRotate2Shear(pix1, xcen, ycen, angle, L_BRING_IN_WHITE);
300 pixDestroy(&pix1);
301 pixDestroy(&pix2);
302 }
303 return pixd;
304}
305
306
338PIX *
340 l_int32 xcen,
341 l_int32 ycen,
342 l_float32 angle,
343 l_int32 incolor)
344{
345l_float32 hangle;
346PIX *pix1, *pix2, *pixd;
347
348 PROCNAME("pixRotate3Shear");
349
350 if (!pixs)
351 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
352 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
353 return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", procName, NULL);
354
355 if (L_ABS(angle) > MaxShearAngle) {
356 L_ERROR("%6.2f radians; too large for shear rotation\n", procName,
357 L_ABS(angle));
358 return NULL;
359 }
360 if (L_ABS(angle) < MinAngleToRotate)
361 return pixClone(pixs);
362 if (L_ABS(angle) > MaxThreeShearAngle) {
363 L_WARNING("%6.2f radians; large angle for 3-shear rotation\n",
364 procName, L_ABS(angle));
365 }
366
367 hangle = atan(sin(angle));
368 if ((pixd = pixVShear(NULL, pixs, xcen, angle / 2., incolor)) == NULL)
369 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
370 if ((pix1 = pixHShear(NULL, pixd, ycen, hangle, incolor)) == NULL) {
371 pixDestroy(&pixd);
372 return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
373 }
374 pixVShear(pixd, pix1, xcen, angle / 2., incolor);
375 pixDestroy(&pix1);
376
377 if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4) {
379 /* L_BRING_IN_WHITE brings in opaque for the alpha component */
380 pix2 = pixRotate3Shear(pix1, xcen, ycen, angle, L_BRING_IN_WHITE);
382 pixDestroy(&pix1);
383 pixDestroy(&pix2);
384 }
385 return pixd;
386}
387
388
389/*------------------------------------------------------------------*
390 * Rotations in-place about an arbitrary point *
391 *------------------------------------------------------------------*/
419l_ok
421 l_int32 xcen,
422 l_int32 ycen,
423 l_float32 angle,
424 l_int32 incolor)
425{
426l_float32 hangle;
427
428 PROCNAME("pixRotateShearIP");
429
430 if (!pixs)
431 return ERROR_INT("pixs not defined", procName, 1);
432 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
433 return ERROR_INT("invalid value for incolor", procName, 1);
434 if (pixGetColormap(pixs) != NULL)
435 return ERROR_INT("pixs is colormapped", procName, 1);
436
437 if (angle == 0.0)
438 return 0;
439 if (L_ABS(angle) > MaxThreeShearAngle) {
440 L_WARNING("%6.2f radians; large angle for in-place 3-shear rotation\n",
441 procName, L_ABS(angle));
442 }
443
444 hangle = atan(sin(angle));
445 pixHShearIP(pixs, ycen, angle / 2., incolor);
446 pixVShearIP(pixs, xcen, hangle, incolor);
447 pixHShearIP(pixs, ycen, angle / 2., incolor);
448 return 0;
449}
450
451
452/*------------------------------------------------------------------*
453 * Rotations about the image center *
454 *------------------------------------------------------------------*/
463PIX *
465 l_float32 angle,
466 l_int32 incolor)
467{
468 PROCNAME("pixRotateShearCenter");
469
470 if (!pixs)
471 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
472
473 return pixRotateShear(pixs, pixGetWidth(pixs) / 2,
474 pixGetHeight(pixs) / 2, angle, incolor);
475}
476
477
486l_ok
488 l_float32 angle,
489 l_int32 incolor)
490{
491 PROCNAME("pixRotateShearCenterIP");
492
493 if (!pixs)
494 return ERROR_INT("pixs not defined", procName, 1);
495
496 return pixRotateShearIP(pixs, pixGetWidth(pixs) / 2,
497 pixGetHeight(pixs) / 2, angle, incolor);
498}
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2538
@ L_ALPHA_CHANNEL
Definition: pix.h:207
@ L_BRING_IN_BLACK
Definition: pix.h:870
@ L_BRING_IN_WHITE
Definition: pix.h:869
PIX * pixRotate3Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate3Shear()
Definition: rotateshear.c:339
l_ok pixRotateShearIP(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShearIP()
Definition: rotateshear.c:420
PIX * pixRotateShear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShear()
Definition: rotateshear.c:208
PIX * pixRotateShearCenter(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateShearCenter()
Definition: rotateshear.c:464
PIX * pixRotate2Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate2Shear()
Definition: rotateshear.c:262
l_ok pixRotateShearCenterIP(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateShearCenterIP()
Definition: rotateshear.c:487
l_ok pixHShearIP(PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShearIP()
Definition: shear.c:471
PIX * pixHShear(PIX *pixd, PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShear()
Definition: shear.c:117
l_ok pixVShearIP(PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor)
pixVShearIP()
Definition: shear.c:546
PIX * pixVShear(PIX *pixd, PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor)
pixVShear()
Definition: shear.c:238
Definition: pix.h:139