Leptonica  1.77.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 
163 #include <math.h>
164 #include <string.h>
165 #include "allheaders.h"
166 
167 static const l_float32 MIN_ANGLE_TO_ROTATE = 0.001; /* radians; ~0.06 deg */
168 static const l_float32 MAX_2_SHEAR_ANGLE = 0.06; /* radians; ~3 deg */
169 static const l_float32 LIMIT_SHEAR_ANGLE = 0.35; /* radians; ~20 deg */
170 
171 /*------------------------------------------------------------------*
172  * Rotations about an arbitrary point *
173  *------------------------------------------------------------------*/
195 PIX *
197  l_int32 xcen,
198  l_int32 ycen,
199  l_float32 angle,
200  l_int32 incolor)
201 {
202  PROCNAME("pixRotateShear");
203 
204  if (!pixs)
205  return (PIX *)(PIX *)ERROR_PTR("pixs not defined", procName, NULL);
206  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
207  return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", procName, NULL);
208 
209  if (L_ABS(angle) < MIN_ANGLE_TO_ROTATE)
210  return pixClone(pixs);
211 
212  if (L_ABS(angle) <= MAX_2_SHEAR_ANGLE)
213  return pixRotate2Shear(pixs, xcen, ycen, angle, incolor);
214 
215  if (L_ABS(angle) > LIMIT_SHEAR_ANGLE)
216  L_WARNING("%6.2f radians; large angle for shear rotation\n",
217  procName, L_ABS(angle));
218  return pixRotate3Shear(pixs, xcen, ycen, angle, incolor);
219 }
220 
221 
247 PIX *
249  l_int32 xcen,
250  l_int32 ycen,
251  l_float32 angle,
252  l_int32 incolor)
253 {
254 PIX *pix1, *pix2, *pixd;
255 
256  PROCNAME("pixRotate2Shear");
257 
258  if (!pixs)
259  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
260  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
261  return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", procName, NULL);
262 
263  if (L_ABS(angle) < MIN_ANGLE_TO_ROTATE)
264  return pixClone(pixs);
265  if (L_ABS(angle) > MAX_2_SHEAR_ANGLE)
266  L_WARNING("%6.2f radians; large angle for 2-shear rotation\n",
267  procName, L_ABS(angle));
268 
269  if ((pix1 = pixHShear(NULL, pixs, ycen, angle, incolor)) == NULL)
270  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
271  pixd = pixVShear(NULL, pix1, xcen, angle, incolor);
272  pixDestroy(&pix1);
273  if (!pixd)
274  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
275 
276  if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4) {
277  pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
278  /* L_BRING_IN_WHITE brings in opaque for the alpha component */
279  pix2 = pixRotate2Shear(pix1, xcen, ycen, angle, L_BRING_IN_WHITE);
280  pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
281  pixDestroy(&pix1);
282  pixDestroy(&pix2);
283  }
284  return pixd;
285 }
286 
318 PIX *
320  l_int32 xcen,
321  l_int32 ycen,
322  l_float32 angle,
323  l_int32 incolor)
324 {
325 l_float32 hangle;
326 PIX *pix1, *pix2, *pixd;
327 
328  PROCNAME("pixRotate3Shear");
329 
330  if (!pixs)
331  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
332  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
333  return (PIX *)(PIX *)ERROR_PTR("invalid incolor value", procName, NULL);
334 
335  if (L_ABS(angle) < MIN_ANGLE_TO_ROTATE)
336  return pixClone(pixs);
337  if (L_ABS(angle) > LIMIT_SHEAR_ANGLE) {
338  L_WARNING("%6.2f radians; large angle for 3-shear rotation\n",
339  procName, L_ABS(angle));
340  }
341 
342  hangle = atan(sin(angle));
343  if ((pixd = pixVShear(NULL, pixs, xcen, angle / 2., incolor)) == NULL)
344  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
345  if ((pix1 = pixHShear(NULL, pixd, ycen, hangle, incolor)) == NULL) {
346  pixDestroy(&pixd);
347  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
348  }
349  pixVShear(pixd, pix1, xcen, angle / 2., incolor);
350  pixDestroy(&pix1);
351 
352  if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4) {
353  pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
354  /* L_BRING_IN_WHITE brings in opaque for the alpha component */
355  pix2 = pixRotate3Shear(pix1, xcen, ycen, angle, L_BRING_IN_WHITE);
356  pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
357  pixDestroy(&pix1);
358  pixDestroy(&pix2);
359  }
360  return pixd;
361 }
362 
363 
364 /*------------------------------------------------------------------*
365  * Rotations in-place about an arbitrary point *
366  *------------------------------------------------------------------*/
394 l_ok
396  l_int32 xcen,
397  l_int32 ycen,
398  l_float32 angle,
399  l_int32 incolor)
400 {
401 l_float32 hangle;
402 
403  PROCNAME("pixRotateShearIP");
404 
405  if (!pixs)
406  return ERROR_INT("pixs not defined", procName, 1);
407  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
408  return ERROR_INT("invalid value for incolor", procName, 1);
409  if (pixGetColormap(pixs) != NULL)
410  return ERROR_INT("pixs is colormapped", procName, 1);
411 
412  if (angle == 0.0)
413  return 0;
414  if (L_ABS(angle) > LIMIT_SHEAR_ANGLE) {
415  L_WARNING("%6.2f radians; large angle for in-place 3-shear rotation\n",
416  procName, L_ABS(angle));
417  }
418 
419  hangle = atan(sin(angle));
420  pixHShearIP(pixs, ycen, angle / 2., incolor);
421  pixVShearIP(pixs, xcen, hangle, incolor);
422  pixHShearIP(pixs, ycen, angle / 2., incolor);
423  return 0;
424 }
425 
426 
427 /*------------------------------------------------------------------*
428  * Rotations about the image center *
429  *------------------------------------------------------------------*/
438 PIX *
440  l_float32 angle,
441  l_int32 incolor)
442 {
443  PROCNAME("pixRotateShearCenter");
444 
445  if (!pixs)
446  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
447 
448  return pixRotateShear(pixs, pixGetWidth(pixs) / 2,
449  pixGetHeight(pixs) / 2, angle, incolor);
450 }
451 
452 
461 l_ok
463  l_float32 angle,
464  l_int32 incolor)
465 {
466  PROCNAME("pixRotateShearCenterIP");
467 
468  if (!pixs)
469  return ERROR_INT("pixs not defined", procName, 1);
470 
471  return pixRotateShearIP(pixs, pixGetWidth(pixs) / 2,
472  pixGetHeight(pixs) / 2, angle, incolor);
473 }
PIX * pixRotateShear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShear()
Definition: rotateshear.c:196
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2463
PIX * pixRotate2Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate2Shear()
Definition: rotateshear.c:248
PIX * pixRotate3Shear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotate3Shear()
Definition: rotateshear.c:319
l_ok pixRotateShearIP(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShearIP()
Definition: rotateshear.c:395
l_ok pixVShearIP(PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor)
pixVShearIP()
Definition: shear.c:534
PIX * pixVShear(PIX *pixd, PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor)
pixVShear()
Definition: shear.c:230
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2404
l_ok pixHShearIP(PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShearIP()
Definition: shear.c:459
PIX * pixRotateShearCenter(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateShearCenter()
Definition: rotateshear.c:439
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
PIX * pixHShear(PIX *pixd, PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor)
pixHShear()
Definition: shear.c:113
Definition: pix.h:134
l_ok pixRotateShearCenterIP(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateShearCenterIP()
Definition: rotateshear.c:462