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 * rotateorthlow.c
19 *
20 * 90-degree rotation (cw)
21 * void rotate90Low()
22 *
23 * LR-flip
24 * void flipLRLow()
25 *
26 * TB-flip
27 * void flipTBLow()
28 *
29 * Byte reverse tables
30 * l_uint8 *makeReverseByteTab1()
31 * l_uint8 *makeReverseByteTab2()
32 * l_uint8 *makeReverseByteTab4()
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include "allheaders.h"
39
40
41
42 /*------------------------------------------------------------------*
43 * 90 degree rotation *
44 *------------------------------------------------------------------*/
45 /*!
46 * rotate90Low()
47 *
48 * direction: 1 for cw rotation
49 * -1 for ccw rotation
50 *
51 * Notes:
52 * (1) The dest must be cleared in advance because not
53 * all source pixels are written to the destination.
54 */
55 void
rotate90Low(l_uint32 * datad,l_int32 wd,l_int32 hd,l_int32 d,l_int32 wpld,l_uint32 * datas,l_int32 wpls,l_int32 direction)56 rotate90Low(l_uint32 *datad,
57 l_int32 wd,
58 l_int32 hd,
59 l_int32 d,
60 l_int32 wpld,
61 l_uint32 *datas,
62 l_int32 wpls,
63 l_int32 direction)
64 {
65 l_int32 i, j, k, m, iend, nswords;
66 l_uint32 val, word;
67 l_uint32 *lines, *lined;
68
69 PROCNAME("rotate90Low");
70
71 if (direction == 1) { /* clockwise */
72 switch (d)
73 {
74 case 32:
75 for (i = 0; i < hd; i++) {
76 lined = datad + i * wpld;
77 lines = datas + (wd - 1) * wpls;
78 for (j = 0; j < wd; j++) {
79 lined[j] = lines[i];
80 lines -= wpls;
81 }
82 }
83 break;
84 case 16:
85 for (i = 0; i < hd; i++) {
86 lined = datad + i * wpld;
87 lines = datas + (wd - 1) * wpls;
88 for (j = 0; j < wd; j++) {
89 if ((val = GET_DATA_TWO_BYTES(lines, i)))
90 SET_DATA_TWO_BYTES(lined, j, val);
91 lines -= wpls;
92 }
93 }
94 break;
95 case 8:
96 for (i = 0; i < hd; i++) {
97 lined = datad + i * wpld;
98 lines = datas + (wd - 1) * wpls;
99 for (j = 0; j < wd; j++) {
100 if ((val = GET_DATA_BYTE(lines, i)))
101 SET_DATA_BYTE(lined, j, val);
102 lines -= wpls;
103 }
104 }
105 break;
106 case 4:
107 for (i = 0; i < hd; i++) {
108 lined = datad + i * wpld;
109 lines = datas + (wd - 1) * wpls;
110 for (j = 0; j < wd; j++) {
111 if ((val = GET_DATA_QBIT(lines, i)))
112 SET_DATA_QBIT(lined, j, val);
113 lines -= wpls;
114 }
115 }
116 break;
117 case 2:
118 for (i = 0; i < hd; i++) {
119 lined = datad + i * wpld;
120 lines = datas + (wd - 1) * wpls;
121 for (j = 0; j < wd; j++) {
122 if ((val = GET_DATA_DIBIT(lines, i)))
123 SET_DATA_DIBIT(lined, j, val);
124 lines -= wpls;
125 }
126 }
127 break;
128 case 1:
129 nswords = hd / 32;
130 for (j = 0; j < wd; j++) {
131 lined = datad;
132 lines = datas + (wd - 1 - j) * wpls;
133 for (k = 0; k < nswords; k++) {
134 word = lines[k];
135 if (!word) {
136 lined += 32 * wpld;
137 continue;
138 }
139 else {
140 iend = 32 * (k + 1);
141 for (m = 0, i = 32 * k; i < iend; i++, m++) {
142 if ((word << m) & 0x80000000)
143 SET_DATA_BIT(lined, j);
144 lined += wpld;
145 }
146 }
147 }
148 for (i = 32 * nswords; i < hd; i++) {
149 if (GET_DATA_BIT(lines, i))
150 SET_DATA_BIT(lined, j);
151 lined += wpld;
152 }
153 }
154 break;
155 default:
156 ERROR_VOID("illegal depth", procName);
157 }
158 }
159 else { /* direction counter-clockwise */
160 switch (d)
161 {
162 case 32:
163 for (i = 0; i < hd; i++) {
164 lined = datad + i * wpld;
165 lines = datas;
166 for (j = 0; j < wd; j++) {
167 lined[j] = lines[hd - 1 - i];
168 lines += wpls;
169 }
170 }
171 break;
172 case 16:
173 for (i = 0; i < hd; i++) {
174 lined = datad + i * wpld;
175 lines = datas;
176 for (j = 0; j < wd; j++) {
177 if ((val = GET_DATA_TWO_BYTES(lines, hd - 1 - i)))
178 SET_DATA_TWO_BYTES(lined, j, val);
179 lines += wpls;
180 }
181 }
182 break;
183 case 8:
184 for (i = 0; i < hd; i++) {
185 lined = datad + i * wpld;
186 lines = datas;
187 for (j = 0; j < wd; j++) {
188 if ((val = GET_DATA_BYTE(lines, hd - 1 - i)))
189 SET_DATA_BYTE(lined, j, val);
190 lines += wpls;
191 }
192 }
193 break;
194 case 4:
195 for (i = 0; i < hd; i++) {
196 lined = datad + i * wpld;
197 lines = datas;
198 for (j = 0; j < wd; j++) {
199 if ((val = GET_DATA_QBIT(lines, hd - 1 - i)))
200 SET_DATA_QBIT(lined, j, val);
201 lines += wpls;
202 }
203 }
204 break;
205 case 2:
206 for (i = 0; i < hd; i++) {
207 lined = datad + i * wpld;
208 lines = datas;
209 for (j = 0; j < wd; j++) {
210 if ((val = GET_DATA_DIBIT(lines, hd - 1 - i)))
211 SET_DATA_DIBIT(lined, j, val);
212 lines += wpls;
213 }
214 }
215 break;
216 case 1:
217 nswords = hd / 32;
218 for (j = 0; j < wd; j++) {
219 lined = datad + (hd - 1) * wpld;
220 lines = datas + (wd - 1 - j) * wpls;
221 for (k = 0; k < nswords; k++) {
222 word = lines[k];
223 if (!word) {
224 lined -= 32 * wpld;
225 continue;
226 }
227 else {
228 iend = 32 * (k + 1);
229 for (m = 0, i = 32 * k; i < iend; i++, m++) {
230 if ((word << m) & 0x80000000)
231 SET_DATA_BIT(lined, wd - 1 - j);
232 lined -= wpld;
233 }
234 }
235 }
236 for (i = 32 * nswords; i < hd; i++) {
237 if (GET_DATA_BIT(lines, i))
238 SET_DATA_BIT(lined, wd - 1 - j);
239 lined -= wpld;
240 }
241 }
242 break;
243 default:
244 ERROR_VOID("illegal depth", procName);
245 }
246 }
247
248 return;
249 }
250
251
252 /*------------------------------------------------------------------*
253 * Left/right flip *
254 *------------------------------------------------------------------*/
255 /*!
256 * flipLRLow()
257 *
258 * Notes:
259 * (1) The pixel access routines allow a trivial implementation.
260 * However, for d < 8, it is more efficient to right-justify
261 * each line to a 32-bit boundary and then extract bytes and
262 * do pixel reversing. In those cases, as in the 180 degree
263 * rotation, we right-shift the data (if necessary) to
264 * right-justify on the 32 bit boundary, and then read the
265 * bytes off each raster line in reverse order, reversing
266 * the pixels in each byte using a table. These functions
267 * for 1, 2 and 4 bpp were tested against the "trivial"
268 * version (shown here for 4 bpp):
269 * for (i = 0; i < h; i++) {
270 * line = data + i * wpl;
271 * memcpy(buffer, line, bpl);
272 * for (j = 0; j < w; j++) {
273 * val = GET_DATA_QBIT(buffer, w - 1 - j);
274 * SET_DATA_QBIT(line, j, val);
275 * }
276 * }
277 * (2) This operation is in-place.
278 */
279 void
flipLRLow(l_uint32 * data,l_int32 w,l_int32 h,l_int32 d,l_int32 wpl,l_uint8 * tab,l_uint32 * buffer)280 flipLRLow(l_uint32 *data,
281 l_int32 w,
282 l_int32 h,
283 l_int32 d,
284 l_int32 wpl,
285 l_uint8 *tab,
286 l_uint32 *buffer)
287 {
288 l_int32 extra, shift, databpl, bpl, i, j;
289 l_uint32 val;
290 l_uint32 *line;
291
292 PROCNAME("flipLRLow");
293
294 bpl = 4 * wpl;
295 switch (d)
296 {
297 case 32:
298 for (i = 0; i < h; i++) {
299 line = data + i * wpl;
300 memcpy(buffer, line, bpl);
301 for (j = 0; j < w; j++)
302 line[j] = buffer[w - 1 - j];
303 }
304 break;
305 case 16:
306 for (i = 0; i < h; i++) {
307 line = data + i * wpl;
308 memcpy(buffer, line, bpl);
309 for (j = 0; j < w; j++) {
310 val = GET_DATA_TWO_BYTES(buffer, w - 1 - j);
311 SET_DATA_TWO_BYTES(line, j, val);
312 }
313 }
314 break;
315 case 8:
316 for (i = 0; i < h; i++) {
317 line = data + i * wpl;
318 memcpy(buffer, line, bpl);
319 for (j = 0; j < w; j++) {
320 val = GET_DATA_BYTE(buffer, w - 1 - j);
321 SET_DATA_BYTE(line, j, val);
322 }
323 }
324 break;
325 case 4:
326 extra = (w * d) & 31;
327 if (extra)
328 shift = 8 - extra / 4;
329 else
330 shift = 0;
331 if (shift)
332 rasteropHipLow(data, h, d, wpl, 0, h, shift);
333
334 databpl = (w + 1) / 2;
335 for (i = 0; i < h; i++) {
336 line = data + i * wpl;
337 memcpy(buffer, line, bpl);
338 for (j = 0; j < databpl; j++) {
339 val = GET_DATA_BYTE(buffer, bpl - 1 - j);
340 SET_DATA_BYTE(line, j, tab[val]);
341 }
342 }
343 break;
344 case 2:
345 extra = (w * d) & 31;
346 if (extra)
347 shift = 16 - extra / 2;
348 else
349 shift = 0;
350 if (shift)
351 rasteropHipLow(data, h, d, wpl, 0, h, shift);
352
353 databpl = (w + 3) / 4;
354 for (i = 0; i < h; i++) {
355 line = data + i * wpl;
356 memcpy(buffer, line, bpl);
357 for (j = 0; j < databpl; j++) {
358 val = GET_DATA_BYTE(buffer, bpl - 1 - j);
359 SET_DATA_BYTE(line, j, tab[val]);
360 }
361 }
362 break;
363 case 1:
364 extra = (w * d) & 31;
365 if (extra)
366 shift = 32 - extra;
367 else
368 shift = 0;
369 if (shift)
370 rasteropHipLow(data, h, d, wpl, 0, h, shift);
371
372 databpl = (w + 7) / 8;
373 for (i = 0; i < h; i++) {
374 line = data + i * wpl;
375 memcpy(buffer, line, bpl);
376 for (j = 0; j < databpl; j++) {
377 val = GET_DATA_BYTE(buffer, bpl - 1 - j);
378 SET_DATA_BYTE(line, j, tab[val]);
379 }
380 }
381 break;
382 default:
383 ERROR_VOID("depth not permitted for LR rot", procName);
384 return;
385 }
386
387 return;
388 }
389
390
391 /*------------------------------------------------------------------*
392 * Top/bottom flip *
393 *------------------------------------------------------------------*/
394 /*!
395 * flipTBLow()
396 *
397 * Notes:
398 * (1) This is simple and fast. We use the memcpy function
399 * to do all the work on aligned data, regardless of pixel
400 * depth.
401 * (2) This operation is in-place.
402 */
403 void
flipTBLow(l_uint32 * data,l_int32 h,l_int32 wpl,l_uint32 * buffer)404 flipTBLow(l_uint32 *data,
405 l_int32 h,
406 l_int32 wpl,
407 l_uint32 *buffer)
408 {
409 l_int32 i, k, h2, bpl;
410 l_uint32 *linet, *lineb;
411
412 h2 = h / 2;
413 bpl = 4 * wpl;
414 for (i = 0, k = h - 1; i < h2; i++, k--) {
415 linet = data + i * wpl;
416 lineb = data + k * wpl;
417 memcpy(buffer, linet, bpl);
418 memcpy(linet, lineb, bpl);
419 memcpy(lineb, buffer, bpl);
420 }
421
422 return;
423 }
424
425
426 /*------------------------------------------------------------------*
427 * Byte reverse tables *
428 *------------------------------------------------------------------*/
429 /*!
430 * makeReverseByteTab1()
431 *
432 * Notes:
433 * (1) This generates an 8 bit lookup table for reversing
434 * the order of eight 1-bit pixels.
435 */
436 l_uint8 *
makeReverseByteTab1(void)437 makeReverseByteTab1(void)
438 {
439 l_int32 i;
440 l_uint8 *tab;
441
442 PROCNAME("makeReverseByteTab1");
443
444 if ((tab = (l_uint8 *)CALLOC(256, sizeof(l_uint8))) == NULL)
445 return (l_uint8 *)ERROR_PTR("calloc fail for tab", procName, NULL);
446
447 for (i = 0; i < 256; i++)
448 tab[i] = ((0x80 & i) >> 7) |
449 ((0x40 & i) >> 5) |
450 ((0x20 & i) >> 3) |
451 ((0x10 & i) >> 1) |
452 ((0x08 & i) << 1) |
453 ((0x04 & i) << 3) |
454 ((0x02 & i) << 5) |
455 ((0x01 & i) << 7);
456
457 return tab;
458 }
459
460
461 /*!
462 * makeReverseByteTab2()
463 *
464 * Notes:
465 * (1) This generates an 8 bit lookup table for reversing
466 * the order of four 2-bit pixels.
467 */
468 l_uint8 *
makeReverseByteTab2(void)469 makeReverseByteTab2(void)
470 {
471 l_int32 i;
472 l_uint8 *tab;
473
474 PROCNAME("makeReverseByteTab2");
475
476 if ((tab = (l_uint8 *)CALLOC(256, sizeof(l_uint8))) == NULL)
477 return (l_uint8 *)ERROR_PTR("calloc fail for tab", procName, NULL);
478
479 for (i = 0; i < 256; i++)
480 tab[i] = ((0xc0 & i) >> 6) |
481 ((0x30 & i) >> 2) |
482 ((0x0c & i) << 2) |
483 ((0x03 & i) << 6);
484 return tab;
485 }
486
487
488 /*!
489 * makeReverseByteTab4()
490 *
491 * Notes:
492 * (1) This generates an 8 bit lookup table for reversing
493 * the order of two 4-bit pixels.
494 */
495 l_uint8 *
makeReverseByteTab4(void)496 makeReverseByteTab4(void)
497 {
498 l_int32 i;
499 l_uint8 *tab;
500
501 PROCNAME("makeReverseByteTab4");
502
503 if ((tab = (l_uint8 *)CALLOC(256, sizeof(l_uint8))) == NULL)
504 return (l_uint8 *)ERROR_PTR("calloc fail for tab", procName, NULL);
505
506 for (i = 0; i < 256; i++)
507 tab[i] = ((0xf0 & i) >> 4) | ((0x0f & i) << 4);
508 return tab;
509 }
510
511