• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*====================================================================*
2  -  Copyright (C) 2001 Leptonica.  All rights reserved.
3  -  This software is distributed in the hope that it will be
4  -  useful, but with NO WARRANTY OF ANY KIND.
5  -  No author or distributor accepts responsibility to anyone for the
6  -  consequences of using this software, or for whether it serves any
7  -  particular purpose or works at all, unless he or she says so in
8  -  writing.  Everyone is granted permission to copy, modify and
9  -  redistribute this source code, for commercial or non-commercial
10  -  purposes, with the following restrictions: (1) the origin of this
11  -  source code must not be misrepresented; (2) modified versions must
12  -  be plainly marked as such; and (3) this notice may not be removed
13  -  or altered from any source or modified source distribution.
14  *====================================================================*/
15 
16 
17 /*
18  *  rotateorth.c
19  *
20  *      Top-level rotation by multiples of 90 degrees
21  *            PIX     *pixRotateOrth()
22  *
23  *      180-degree rotation
24  *            PIX     *pixRotate180()
25  *
26  *      90-degree rotation (both directions)
27  *            PIX     *pixRotate90()
28  *
29  *      Left-right flip
30  *            PIX     *pixFlipLR()
31  *
32  *      Top-bottom flip
33  *            PIX     *pixFlipTB()
34  */
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include "allheaders.h"
39 
40 
41 /*!
42  *  pixRotateOrth()
43  *
44  *      Input:  pixs (all depths)
45  *              quads (0-3; number of 90 degree cw rotations)
46  *      Return: pixd, or null on error
47  */
48 PIX *
pixRotateOrth(PIX * pixs,l_int32 quads)49 pixRotateOrth(PIX     *pixs,
50               l_int32  quads)
51 {
52     PROCNAME("pixRotateOrth");
53 
54     if (!pixs)
55         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
56     if (quads < 0 || quads > 4)
57         return (PIX *)ERROR_PTR("quads not in {0,1,2,3,4}", procName, NULL);
58 
59     if (quads == 0 || quads == 4)
60         return pixCopy(NULL, pixs);
61     else if (quads == 1)
62         return pixRotate90(pixs, 1);
63     else if (quads == 2)
64         return pixRotate180(NULL, pixs);
65     else /* quads == 3 */
66         return pixRotate90(pixs, -1);
67 }
68 
69 
70 /*!
71  *  pixRotate180()
72  *
73  *      Input:  pixd  (<optional>; can be null, equal to pixs,
74  *                     or different from pixs)
75  *              pixs (all depths)
76  *      Return: pixd, or null on error
77  *
78  *  Notes:
79  *      (1) This does a 180 rotation of the image about the center,
80  *          which is equivalent to a left-right flip about a vertical
81  *          line through the image center, followed by a top-bottom
82  *          flip about a horizontal line through the image center.
83  *      (2) There are 3 cases for input:
84  *          (a) pixd == null (creates a new pixd)
85  *          (b) pixd == pixs (in-place operation)
86  *          (c) pixd != pixs (existing pixd)
87  *      (3) For clarity, use these three patterns, respectively:
88  *          (a) pixd = pixRotate180(NULL, pixs);
89  *          (b) pixRotate180(pixs, pixs);
90  *          (c) pixRotate180(pixd, pixs);
91  */
92 PIX *
pixRotate180(PIX * pixd,PIX * pixs)93 pixRotate180(PIX  *pixd,
94              PIX  *pixs)
95 {
96 l_int32  d;
97 
98     PROCNAME("pixRotate180");
99 
100     if (!pixs)
101         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
102     d = pixGetDepth(pixs);
103     if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
104         return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
105                                 procName, NULL);
106 
107         /* Prepare pixd for in-place operation */
108     if ((pixd = pixCopy(pixd, pixs)) == NULL)
109 	return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
110 
111     pixFlipLR(pixd, pixd);
112     pixFlipTB(pixd, pixd);
113     return pixd;
114 }
115 
116 
117 /*!
118  *  pixRotate90()
119  *
120  *      Input:  pixs (all depths)
121  *              direction (1 = clockwise,  -1 = counter-clockwise)
122  *      Return: pixd, or null on error
123  *
124  *  Notes:
125  *      (1) This does a 90 degree rotation of the image about the center,
126  *          either cw or ccw, returning a new pix.
127  *      (2) The direction must be either 1 (cw) or -1 (ccw).
128  */
129 PIX *
pixRotate90(PIX * pixs,l_int32 direction)130 pixRotate90(PIX     *pixs,
131             l_int32  direction)
132 {
133 l_int32    wd, hd, d, wpls, wpld;
134 l_uint32  *datas, *datad;
135 PIX       *pixd;
136 
137     PROCNAME("pixRotate90");
138 
139     if (!pixs)
140         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
141     d = pixGetDepth(pixs);
142     if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
143         return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
144                                 procName, NULL);
145     if (direction != 1 && direction != -1)
146         return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
147 
148     hd = pixGetWidth(pixs);
149     wd = pixGetHeight(pixs);
150     if ((pixd = pixCreate(wd, hd, d)) == NULL)
151         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
152     pixCopyColormap(pixd, pixs);
153     pixCopyResolution(pixd, pixs);
154     pixCopyInputFormat(pixd, pixs);
155 
156     datas = pixGetData(pixs);
157     wpls = pixGetWpl(pixs);
158     datad = pixGetData(pixd);
159     wpld = pixGetWpl(pixd);
160 
161     rotate90Low(datad, wd, hd, d, wpld, datas, wpls, direction);
162 
163     return pixd;
164 }
165 
166 
167 /*!
168  *  pixFlipLR()
169  *
170  *      Input:  pixd  (<optional>; can be null, equal to pixs,
171  *                     or different from pixs)
172  *              pixs (all depths)
173  *      Return: pixd, or null on error
174  *
175  *  Notes:
176  *      (1) This does a left-right flip of the image, which is
177  *          equivalent to a rotation out of the plane about a
178  *          vertical line through the image center.
179  *      (2) There are 3 cases for input:
180  *          (a) pixd == null (creates a new pixd)
181  *          (b) pixd == pixs (in-place operation)
182  *          (c) pixd != pixs (existing pixd)
183  *      (3) For clarity, use these three patterns, respectively:
184  *          (a) pixd = pixFlipLR(NULL, pixs);
185  *          (b) pixFlipLR(pixs, pixs);
186  *          (c) pixFlipLR(pixd, pixs);
187  *      (4) If an existing pixd is not the same size as pixs, the
188  *          image data will be reallocated.
189  */
190 PIX *
pixFlipLR(PIX * pixd,PIX * pixs)191 pixFlipLR(PIX  *pixd,
192           PIX  *pixs)
193 {
194 l_uint8   *tab;
195 l_int32    w, h, d, wpld;
196 l_uint32  *datad, *buffer;
197 
198     PROCNAME("pixFlipLR");
199 
200     if (!pixs)
201         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
202     pixGetDimensions(pixs, &w, &h, &d);
203     if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
204         return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
205                                 procName, NULL);
206 
207         /* Prepare pixd for in-place operation */
208     if ((pixd = pixCopy(pixd, pixs)) == NULL)
209 	return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
210 
211     datad = pixGetData(pixd);
212     wpld = pixGetWpl(pixd);
213     switch (d)
214     {
215     case 1:
216         tab = makeReverseByteTab1();
217         break;
218     case 2:
219         tab = makeReverseByteTab2();
220         break;
221     case 4:
222         tab = makeReverseByteTab4();
223         break;
224     default:
225         tab = NULL;
226         break;
227     }
228 
229     if ((buffer = (l_uint32 *)CALLOC(wpld, sizeof(l_uint32))) == NULL)
230         return (PIX *)ERROR_PTR("buffer not made", procName, NULL);
231 
232     flipLRLow(datad, w, h, d, wpld, tab, buffer);
233 
234     FREE(buffer);
235     if (tab) FREE(tab);
236     return pixd;
237 }
238 
239 
240 /*!
241  *  pixFlipTB()
242  *
243  *      Input:  pixd  (<optional>; can be null, equal to pixs,
244  *                     or different from pixs)
245  *              pixs (all depths)
246  *      Return: pixd, or null on error
247  *
248  *  Notes:
249  *      (1) This does a top-bottom flip of the image, which is
250  *          equivalent to a rotation out of the plane about a
251  *          horizontal line through the image center.
252  *      (2) There are 3 cases for input:
253  *          (a) pixd == null (creates a new pixd)
254  *          (b) pixd == pixs (in-place operation)
255  *          (c) pixd != pixs (existing pixd)
256  *      (3) For clarity, use these three patterns, respectively:
257  *          (a) pixd = pixFlipTB(NULL, pixs);
258  *          (b) pixFlipTB(pixs, pixs);
259  *          (c) pixFlipTB(pixd, pixs);
260  *      (4) If an existing pixd is not the same size as pixs, the
261  *          image data will be reallocated.
262  */
263 PIX *
pixFlipTB(PIX * pixd,PIX * pixs)264 pixFlipTB(PIX  *pixd,
265           PIX  *pixs)
266 {
267 l_int32    h, d, wpld;
268 l_uint32  *datad, *buffer;
269 
270     PROCNAME("pixFlipTB");
271 
272     if (!pixs)
273         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
274     pixGetDimensions(pixs, NULL, &h, &d);
275     if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
276         return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
277                                 procName, NULL);
278 
279         /* Prepare pixd for in-place operation */
280     if ((pixd = pixCopy(pixd, pixs)) == NULL)
281 	return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
282 
283     datad = pixGetData(pixd);
284     wpld = pixGetWpl(pixd);
285     if ((buffer = (l_uint32 *)CALLOC(wpld, sizeof(l_uint32))) == NULL)
286         return (PIX *)ERROR_PTR("buffer not made", procName, NULL);
287 
288     flipTBLow(datad, h, wpld, buffer);
289 
290     FREE(buffer);
291     return pixd;
292 }
293 
294