Leptonica  1.83.1
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  */
178 static const l_float32 MinAngleToRotate = 0.001; /* radians; ~0.06 deg */
179 static const l_float32 MaxTwoShearAngle = 0.06; /* radians; ~3 deg */
180 static const l_float32 MaxThreeShearAngle = 0.35; /* radians; ~20 deg */
181 static const l_float32 MaxShearAngle = 0.50; /* radians; ~29 deg */
182 
183 /*------------------------------------------------------------------*
184  * Rotations about an arbitrary point *
185  *------------------------------------------------------------------*/
207 PIX *
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 
259 PIX *
261  l_int32 xcen,
262  l_int32 ycen,
263  l_float32 angle,
264  l_int32 incolor)
265 {
266 PIX *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 
334 PIX *
336  l_int32 xcen,
337  l_int32 ycen,
338  l_float32 angle,
339  l_int32 incolor)
340 {
341 l_float32 hangle;
342 PIX *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., 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., 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  *------------------------------------------------------------------*/
413 l_ok
415  l_int32 xcen,
416  l_int32 ycen,
417  l_float32 angle,
418  l_int32 incolor)
419 {
420 l_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., incolor);
438  pixVShearIP(pixs, xcen, hangle, incolor);
439  pixHShearIP(pixs, ycen, angle / 2., incolor);
440  return 0;
441 }
442 
443 
444 /*------------------------------------------------------------------*
445  * Rotations about the image center *
446  *------------------------------------------------------------------*/
455 PIX *
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 
476 l_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 }
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2464
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2521
@ L_ALPHA_CHANNEL
Definition: pix.h:331
@ L_BRING_IN_BLACK
Definition: pix.h:663
@ L_BRING_IN_WHITE
Definition: pix.h:662
PIX * pixRotate2Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate2Shear()
Definition: rotateshear.c:260
l_ok pixRotateShearIP(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShearIP()
Definition: rotateshear.c:414
PIX * pixRotate3Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate3Shear()
Definition: rotateshear.c:335
PIX * pixRotateShear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShear()
Definition: rotateshear.c:208
l_ok pixRotateShearCenterIP(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateShearCenterIP()
Definition: rotateshear.c:477
PIX * pixRotateShearCenter(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateShearCenter()
Definition: rotateshear.c:456
PIX * pixVShear(PIX *pixd, PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor)
pixVShear()
Definition: shear.c:236
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
PIX * pixHShear(PIX *pixd, PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShear()
Definition: shear.c:117