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