Leptonica 1.85.0
Image processing and image analysis suite
Loading...
Searching...
No Matches
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.001f; /* radians; ~0.06 deg */
179static const l_float32 MaxTwoShearAngle = 0.06f; /* radians; ~3 deg */
180static const l_float32 MaxThreeShearAngle = 0.35f; /* radians; ~20 deg */
181static const l_float32 MaxShearAngle = 0.50f; /* 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 if (!pixs)
215 return (PIX *)(PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
216 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
217 return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", __func__, NULL);
218
219 if (L_ABS(angle) > MaxShearAngle) {
220 L_ERROR("%6.2f radians; too large for shear rotation\n", __func__,
221 L_ABS(angle));
222 return NULL;
223 }
224 if (L_ABS(angle) < MinAngleToRotate)
225 return pixClone(pixs);
226
227 if (L_ABS(angle) <= MaxTwoShearAngle)
228 return pixRotate2Shear(pixs, xcen, ycen, angle, incolor);
229 else
230 return pixRotate3Shear(pixs, xcen, ycen, angle, incolor);
231}
232
233
259PIX *
261 l_int32 xcen,
262 l_int32 ycen,
263 l_float32 angle,
264 l_int32 incolor)
265{
266PIX *pix1, *pix2, *pixd;
267
268 if (!pixs)
269 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
270 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
271 return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", __func__, NULL);
272
273 if (L_ABS(angle) > MaxShearAngle) {
274 L_ERROR("%6.2f radians; too large for shear rotation\n", __func__,
275 L_ABS(angle));
276 return NULL;
277 }
278 if (L_ABS(angle) < MinAngleToRotate)
279 return pixClone(pixs);
280 if (L_ABS(angle) > MaxTwoShearAngle)
281 L_WARNING("%6.2f radians; large angle for 2-shear rotation\n",
282 __func__, L_ABS(angle));
283
284 if ((pix1 = pixHShear(NULL, pixs, ycen, angle, incolor)) == NULL)
285 return (PIX *)ERROR_PTR("pix1 not made", __func__, NULL);
286 pixd = pixVShear(NULL, pix1, xcen, angle, incolor);
287 pixDestroy(&pix1);
288 if (!pixd)
289 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
290
291 if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4) {
292 pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
293 /* L_BRING_IN_WHITE brings in opaque for the alpha component */
294 pix2 = pixRotate2Shear(pix1, xcen, ycen, angle, L_BRING_IN_WHITE);
295 pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
296 pixDestroy(&pix1);
297 pixDestroy(&pix2);
298 }
299 return pixd;
300}
301
302
334PIX *
336 l_int32 xcen,
337 l_int32 ycen,
338 l_float32 angle,
339 l_int32 incolor)
340{
341l_float32 hangle;
342PIX *pix1, *pix2, *pixd;
343
344 if (!pixs)
345 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
346 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
347 return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", __func__, NULL);
348
349 if (L_ABS(angle) > MaxShearAngle) {
350 L_ERROR("%6.2f radians; too large for shear rotation\n", __func__,
351 L_ABS(angle));
352 return NULL;
353 }
354 if (L_ABS(angle) < MinAngleToRotate)
355 return pixClone(pixs);
356 if (L_ABS(angle) > MaxThreeShearAngle) {
357 L_WARNING("%6.2f radians; large angle for 3-shear rotation\n",
358 __func__, L_ABS(angle));
359 }
360
361 hangle = atan(sin(angle));
362 if ((pixd = pixVShear(NULL, pixs, xcen, angle / 2.f, incolor)) == NULL)
363 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
364 if ((pix1 = pixHShear(NULL, pixd, ycen, hangle, incolor)) == NULL) {
365 pixDestroy(&pixd);
366 return (PIX *)ERROR_PTR("pix1 not made", __func__, NULL);
367 }
368 pixVShear(pixd, pix1, xcen, angle / 2.f, incolor);
369 pixDestroy(&pix1);
370
371 if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4) {
372 pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
373 /* L_BRING_IN_WHITE brings in opaque for the alpha component */
374 pix2 = pixRotate3Shear(pix1, xcen, ycen, angle, L_BRING_IN_WHITE);
375 pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
376 pixDestroy(&pix1);
377 pixDestroy(&pix2);
378 }
379 return pixd;
380}
381
382
383/*------------------------------------------------------------------*
384 * Rotations in-place about an arbitrary point *
385 *------------------------------------------------------------------*/
413l_ok
415 l_int32 xcen,
416 l_int32 ycen,
417 l_float32 angle,
418 l_int32 incolor)
419{
420l_float32 hangle;
421
422 if (!pixs)
423 return ERROR_INT("pixs not defined", __func__, 1);
424 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
425 return ERROR_INT("invalid value for incolor", __func__, 1);
426 if (pixGetColormap(pixs) != NULL)
427 return ERROR_INT("pixs is colormapped", __func__, 1);
428
429 if (angle == 0.0)
430 return 0;
431 if (L_ABS(angle) > MaxThreeShearAngle) {
432 L_WARNING("%6.2f radians; large angle for in-place 3-shear rotation\n",
433 __func__, L_ABS(angle));
434 }
435
436 hangle = atan(sin(angle));
437 pixHShearIP(pixs, ycen, angle / 2.f, incolor);
438 pixVShearIP(pixs, xcen, hangle, incolor);
439 pixHShearIP(pixs, ycen, angle / 2.f, incolor);
440 return 0;
441}
442
443
444/*------------------------------------------------------------------*
445 * Rotations about the image center *
446 *------------------------------------------------------------------*/
455PIX *
457 l_float32 angle,
458 l_int32 incolor)
459{
460 if (!pixs)
461 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
462
463 return pixRotateShear(pixs, pixGetWidth(pixs) / 2,
464 pixGetHeight(pixs) / 2, angle, incolor);
465}
466
467
476l_ok
478 l_float32 angle,
479 l_int32 incolor)
480{
481 if (!pixs)
482 return ERROR_INT("pixs not defined", __func__, 1);
483
484 return pixRotateShearIP(pixs, pixGetWidth(pixs) / 2,
485 pixGetHeight(pixs) / 2, angle, incolor);
486}
@ L_ALPHA_CHANNEL
Definition pix.h:331
@ L_BRING_IN_BLACK
Definition pix.h:663
@ L_BRING_IN_WHITE
Definition pix.h:662
PIX * pixRotate3Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate3Shear()
l_ok pixRotateShearIP(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShearIP()
PIX * pixRotateShear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShear()
PIX * pixRotateShearCenter(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateShearCenter()
PIX * pixRotate2Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate2Shear()
l_ok pixRotateShearCenterIP(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateShearCenterIP()