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  */
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  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 
261 PIX *
263  l_int32 xcen,
264  l_int32 ycen,
265  l_float32 angle,
266  l_int32 incolor)
267 {
268 PIX *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) {
296  pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
297  /* L_BRING_IN_WHITE brings in opaque for the alpha component */
298  pix2 = pixRotate2Shear(pix1, xcen, ycen, angle, L_BRING_IN_WHITE);
299  pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
300  pixDestroy(&pix1);
301  pixDestroy(&pix2);
302  }
303  return pixd;
304 }
305 
306 
338 PIX *
340  l_int32 xcen,
341  l_int32 ycen,
342  l_float32 angle,
343  l_int32 incolor)
344 {
345 l_float32 hangle;
346 PIX *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) {
378  pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
379  /* L_BRING_IN_WHITE brings in opaque for the alpha component */
380  pix2 = pixRotate3Shear(pix1, xcen, ycen, angle, L_BRING_IN_WHITE);
381  pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
382  pixDestroy(&pix1);
383  pixDestroy(&pix2);
384  }
385  return pixd;
386 }
387 
388 
389 /*------------------------------------------------------------------*
390  * Rotations in-place about an arbitrary point *
391  *------------------------------------------------------------------*/
419 l_ok
421  l_int32 xcen,
422  l_int32 ycen,
423  l_float32 angle,
424  l_int32 incolor)
425 {
426 l_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  *------------------------------------------------------------------*/
463 PIX *
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 
486 l_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 * pixRotate2Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate2Shear()
Definition: rotateshear.c:262
l_ok pixRotateShearIP(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShearIP()
Definition: rotateshear.c:420
PIX * pixRotate3Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate3Shear()
Definition: rotateshear.c:339
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:487
PIX * pixRotateShearCenter(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateShearCenter()
Definition: rotateshear.c:464
PIX * pixVShear(PIX *pixd, PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor)
pixVShear()
Definition: shear.c:238
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
PIX * pixHShear(PIX *pixd, PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShear()
Definition: shear.c:117
Definition: pix.h:139