Leptonica 1.82.0
Image processing and image analysis suite
rotateorth.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
53#ifdef HAVE_CONFIG_H
54#include <config_auto.h>
55#endif /* HAVE_CONFIG_H */
56
57#include <string.h>
58#include "allheaders.h"
59
60static l_uint8 *makeReverseByteTab1(void);
61static l_uint8 *makeReverseByteTab2(void);
62static l_uint8 *makeReverseByteTab4(void);
63
64/*------------------------------------------------------------------*
65 * Top-level rotation by multiples of 90 degrees *
66 *------------------------------------------------------------------*/
74PIX *
76 l_int32 quads)
77{
78 PROCNAME("pixRotateOrth");
79
80 if (!pixs)
81 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
82 if (quads < 0 || quads > 3)
83 return (PIX *)ERROR_PTR("quads not in {0,1,2,3}", procName, NULL);
84
85 if (quads == 0)
86 return pixCopy(NULL, pixs);
87 else if (quads == 1)
88 return pixRotate90(pixs, 1);
89 else if (quads == 2)
90 return pixRotate180(NULL, pixs);
91 else /* quads == 3 */
92 return pixRotate90(pixs, -1);
93}
94
95
96/*------------------------------------------------------------------*
97 * 180 degree rotation *
98 *------------------------------------------------------------------*/
123PIX *
125 PIX *pixs)
126{
127l_int32 d;
128
129 PROCNAME("pixRotate180");
130
131 if (!pixs)
132 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
133 d = pixGetDepth(pixs);
134 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
135 return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
136 procName, NULL);
137
138 /* Prepare pixd for in-place operation */
139 if ((pixd = pixCopy(pixd, pixs)) == NULL)
140 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
141
142 pixFlipLR(pixd, pixd);
143 pixFlipTB(pixd, pixd);
144 return pixd;
145}
146
147
148/*------------------------------------------------------------------*
149 * 90 degree rotation *
150 *------------------------------------------------------------------*/
165PIX *
167 l_int32 direction)
168{
169l_int32 wd, hd, d, wpls, wpld;
170l_int32 i, j, k, m, iend, nswords;
171l_uint32 val, word;
172l_uint32 *lines, *datas, *lined, *datad;
173PIX *pixd;
174
175 PROCNAME("pixRotate90");
176
177 if (!pixs)
178 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
179 pixGetDimensions(pixs, &hd, &wd, &d); /* note: reversed */
180 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
181 return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
182 procName, NULL);
183 if (direction != 1 && direction != -1)
184 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
185
186 if ((pixd = pixCreate(wd, hd, d)) == NULL)
187 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
188 pixCopyColormap(pixd, pixs);
189 pixCopyResolution(pixd, pixs);
190 pixCopyInputFormat(pixd, pixs);
191 pixCopySpp(pixd, pixs);
192
193 datas = pixGetData(pixs);
194 wpls = pixGetWpl(pixs);
195 datad = pixGetData(pixd);
196 wpld = pixGetWpl(pixd);
197
198 if (direction == 1) { /* clockwise */
199 switch (d)
200 {
201 case 32:
202 for (i = 0; i < hd; i++) {
203 lined = datad + i * wpld;
204 lines = datas + (wd - 1) * wpls;
205 for (j = 0; j < wd; j++) {
206 lined[j] = lines[i];
207 lines -= wpls;
208 }
209 }
210 break;
211 case 16:
212 for (i = 0; i < hd; i++) {
213 lined = datad + i * wpld;
214 lines = datas + (wd - 1) * wpls;
215 for (j = 0; j < wd; j++) {
216 if ((val = GET_DATA_TWO_BYTES(lines, i)))
217 SET_DATA_TWO_BYTES(lined, j, val);
218 lines -= wpls;
219 }
220 }
221 break;
222 case 8:
223 for (i = 0; i < hd; i++) {
224 lined = datad + i * wpld;
225 lines = datas + (wd - 1) * wpls;
226 for (j = 0; j < wd; j++) {
227 if ((val = GET_DATA_BYTE(lines, i)))
228 SET_DATA_BYTE(lined, j, val);
229 lines -= wpls;
230 }
231 }
232 break;
233 case 4:
234 for (i = 0; i < hd; i++) {
235 lined = datad + i * wpld;
236 lines = datas + (wd - 1) * wpls;
237 for (j = 0; j < wd; j++) {
238 if ((val = GET_DATA_QBIT(lines, i)))
239 SET_DATA_QBIT(lined, j, val);
240 lines -= wpls;
241 }
242 }
243 break;
244 case 2:
245 for (i = 0; i < hd; i++) {
246 lined = datad + i * wpld;
247 lines = datas + (wd - 1) * wpls;
248 for (j = 0; j < wd; j++) {
249 if ((val = GET_DATA_DIBIT(lines, i)))
250 SET_DATA_DIBIT(lined, j, val);
251 lines -= wpls;
252 }
253 }
254 break;
255 case 1:
256 nswords = hd / 32;
257 for (j = 0; j < wd; j++) {
258 lined = datad;
259 lines = datas + (wd - 1 - j) * wpls;
260 for (k = 0; k < nswords; k++) {
261 word = lines[k];
262 if (!word) {
263 lined += 32 * wpld;
264 continue;
265 } else {
266 iend = 32 * (k + 1);
267 for (m = 0, i = 32 * k; i < iend; i++, m++) {
268 if ((word << m) & 0x80000000)
269 SET_DATA_BIT(lined, j);
270 lined += wpld;
271 }
272 }
273 }
274 for (i = 32 * nswords; i < hd; i++) {
275 if (GET_DATA_BIT(lines, i))
276 SET_DATA_BIT(lined, j);
277 lined += wpld;
278 }
279 }
280 break;
281 default:
282 pixDestroy(&pixd);
283 L_ERROR("illegal depth: %d\n", procName, d);
284 break;
285 }
286 } else { /* direction counter-clockwise */
287 switch (d)
288 {
289 case 32:
290 for (i = 0; i < hd; i++) {
291 lined = datad + i * wpld;
292 lines = datas;
293 for (j = 0; j < wd; j++) {
294 lined[j] = lines[hd - 1 - i];
295 lines += wpls;
296 }
297 }
298 break;
299 case 16:
300 for (i = 0; i < hd; i++) {
301 lined = datad + i * wpld;
302 lines = datas;
303 for (j = 0; j < wd; j++) {
304 if ((val = GET_DATA_TWO_BYTES(lines, hd - 1 - i)))
305 SET_DATA_TWO_BYTES(lined, j, val);
306 lines += wpls;
307 }
308 }
309 break;
310 case 8:
311 for (i = 0; i < hd; i++) {
312 lined = datad + i * wpld;
313 lines = datas;
314 for (j = 0; j < wd; j++) {
315 if ((val = GET_DATA_BYTE(lines, hd - 1 - i)))
316 SET_DATA_BYTE(lined, j, val);
317 lines += wpls;
318 }
319 }
320 break;
321 case 4:
322 for (i = 0; i < hd; i++) {
323 lined = datad + i * wpld;
324 lines = datas;
325 for (j = 0; j < wd; j++) {
326 if ((val = GET_DATA_QBIT(lines, hd - 1 - i)))
327 SET_DATA_QBIT(lined, j, val);
328 lines += wpls;
329 }
330 }
331 break;
332 case 2:
333 for (i = 0; i < hd; i++) {
334 lined = datad + i * wpld;
335 lines = datas;
336 for (j = 0; j < wd; j++) {
337 if ((val = GET_DATA_DIBIT(lines, hd - 1 - i)))
338 SET_DATA_DIBIT(lined, j, val);
339 lines += wpls;
340 }
341 }
342 break;
343 case 1:
344 nswords = hd / 32;
345 for (j = 0; j < wd; j++) {
346 lined = datad + (hd - 1) * wpld;
347 lines = datas + (wd - 1 - j) * wpls;
348 for (k = 0; k < nswords; k++) {
349 word = lines[k];
350 if (!word) {
351 lined -= 32 * wpld;
352 continue;
353 } else {
354 iend = 32 * (k + 1);
355 for (m = 0, i = 32 * k; i < iend; i++, m++) {
356 if ((word << m) & 0x80000000)
357 SET_DATA_BIT(lined, wd - 1 - j);
358 lined -= wpld;
359 }
360 }
361 }
362 for (i = 32 * nswords; i < hd; i++) {
363 if (GET_DATA_BIT(lines, i))
364 SET_DATA_BIT(lined, wd - 1 - j);
365 lined -= wpld;
366 }
367 }
368 break;
369 default:
370 pixDestroy(&pixd);
371 L_ERROR("illegal depth: %d\n", procName, d);
372 break;
373 }
374 }
375
376 return pixd;
377}
378
379
380/*------------------------------------------------------------------*
381 * Left-right flip *
382 *------------------------------------------------------------------*/
426PIX *
428 PIX *pixs)
429{
430l_uint8 *tab;
431l_int32 w, h, d, wpl;
432l_int32 extra, shift, databpl, bpl, i, j;
433l_uint32 val;
434l_uint32 *line, *data, *buffer;
435
436 PROCNAME("pixFlipLR");
437
438 if (!pixs)
439 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
440 pixGetDimensions(pixs, &w, &h, &d);
441 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
442 return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
443 procName, NULL);
444
445 /* Prepare pixd for in-place operation */
446 if ((pixd = pixCopy(pixd, pixs)) == NULL)
447 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
448
449 data = pixGetData(pixd);
450 wpl = pixGetWpl(pixd);
451 switch (d)
452 {
453 case 1:
454 tab = makeReverseByteTab1();
455 break;
456 case 2:
457 tab = makeReverseByteTab2();
458 break;
459 case 4:
460 tab = makeReverseByteTab4();
461 break;
462 default:
463 tab = NULL;
464 break;
465 }
466
467 /* Possibly inplace assigning return val, so on failure return pixd */
468 if ((buffer = (l_uint32 *)LEPT_CALLOC(wpl, sizeof(l_uint32))) == NULL) {
469 if (tab) LEPT_FREE(tab);
470 return (PIX *)ERROR_PTR("buffer not made", procName, pixd);
471 }
472
473 bpl = 4 * wpl;
474 switch (d)
475 {
476 case 32:
477 for (i = 0; i < h; i++) {
478 line = data + i * wpl;
479 memcpy(buffer, line, bpl);
480 for (j = 0; j < w; j++)
481 line[j] = buffer[w - 1 - j];
482 }
483 break;
484 case 16:
485 for (i = 0; i < h; i++) {
486 line = data + i * wpl;
487 memcpy(buffer, line, bpl);
488 for (j = 0; j < w; j++) {
489 val = GET_DATA_TWO_BYTES(buffer, w - 1 - j);
490 SET_DATA_TWO_BYTES(line, j, val);
491 }
492 }
493 break;
494 case 8:
495 for (i = 0; i < h; i++) {
496 line = data + i * wpl;
497 memcpy(buffer, line, bpl);
498 for (j = 0; j < w; j++) {
499 val = GET_DATA_BYTE(buffer, w - 1 - j);
500 SET_DATA_BYTE(line, j, val);
501 }
502 }
503 break;
504 case 4:
505 extra = (w * d) & 31;
506 if (extra)
507 shift = 8 - extra / 4;
508 else
509 shift = 0;
510 if (shift)
511 rasteropHipLow(data, h, d, wpl, 0, h, shift);
512
513 databpl = (w + 1) / 2;
514 for (i = 0; i < h; i++) {
515 line = data + i * wpl;
516 memcpy(buffer, line, bpl);
517 for (j = 0; j < databpl; j++) {
518 val = GET_DATA_BYTE(buffer, bpl - 1 - j);
519 SET_DATA_BYTE(line, j, tab[val]);
520 }
521 }
522 break;
523 case 2:
524 extra = (w * d) & 31;
525 if (extra)
526 shift = 16 - extra / 2;
527 else
528 shift = 0;
529 if (shift)
530 rasteropHipLow(data, h, d, wpl, 0, h, shift);
531
532 databpl = (w + 3) / 4;
533 for (i = 0; i < h; i++) {
534 line = data + i * wpl;
535 memcpy(buffer, line, bpl);
536 for (j = 0; j < databpl; j++) {
537 val = GET_DATA_BYTE(buffer, bpl - 1 - j);
538 SET_DATA_BYTE(line, j, tab[val]);
539 }
540 }
541 break;
542 case 1:
543 extra = (w * d) & 31;
544 if (extra)
545 shift = 32 - extra;
546 else
547 shift = 0;
548 if (shift)
549 rasteropHipLow(data, h, d, wpl, 0, h, shift);
550
551 databpl = (w + 7) / 8;
552 for (i = 0; i < h; i++) {
553 line = data + i * wpl;
554 memcpy(buffer, line, bpl);
555 for (j = 0; j < databpl; j++) {
556 val = GET_DATA_BYTE(buffer, bpl - 1 - j);
557 SET_DATA_BYTE(line, j, tab[val]);
558 }
559 }
560 break;
561 default:
562 pixDestroy(&pixd);
563 L_ERROR("illegal depth: %d\n", procName, d);
564 break;
565 }
566
567 LEPT_FREE(buffer);
568 if (tab) LEPT_FREE(tab);
569 return pixd;
570}
571
572
573/*------------------------------------------------------------------*
574 * Top-bottom flip *
575 *------------------------------------------------------------------*/
604PIX *
606 PIX *pixs)
607{
608l_int32 h, d, wpl, i, k, h2, bpl;
609l_uint32 *linet, *lineb;
610l_uint32 *data, *buffer;
611
612 PROCNAME("pixFlipTB");
613
614 if (!pixs)
615 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
616 pixGetDimensions(pixs, NULL, &h, &d);
617 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
618 return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
619 procName, NULL);
620
621 /* Prepare pixd for in-place operation */
622 if ((pixd = pixCopy(pixd, pixs)) == NULL)
623 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
624
625 data = pixGetData(pixd);
626 wpl = pixGetWpl(pixd);
627 if ((buffer = (l_uint32 *)LEPT_CALLOC(wpl, sizeof(l_uint32))) == NULL)
628 return (PIX *)ERROR_PTR("buffer not made", procName, pixd);
629
630 h2 = h / 2;
631 bpl = 4 * wpl;
632 for (i = 0, k = h - 1; i < h2; i++, k--) {
633 linet = data + i * wpl;
634 lineb = data + k * wpl;
635 memcpy(buffer, linet, bpl);
636 memcpy(linet, lineb, bpl);
637 memcpy(lineb, buffer, bpl);
638 }
639
640 LEPT_FREE(buffer);
641 return pixd;
642}
643
644
645/*------------------------------------------------------------------*
646 * Static byte reverse tables *
647 *------------------------------------------------------------------*/
655static l_uint8 *
657{
658l_int32 i;
659l_uint8 *tab;
660
661 tab = (l_uint8 *)LEPT_CALLOC(256, sizeof(l_uint8));
662 for (i = 0; i < 256; i++)
663 tab[i] = ((0x80 & i) >> 7) |
664 ((0x40 & i) >> 5) |
665 ((0x20 & i) >> 3) |
666 ((0x10 & i) >> 1) |
667 ((0x08 & i) << 1) |
668 ((0x04 & i) << 3) |
669 ((0x02 & i) << 5) |
670 ((0x01 & i) << 7);
671 return tab;
672}
673
674
682static l_uint8 *
684{
685l_int32 i;
686l_uint8 *tab;
687
688 tab = (l_uint8 *)LEPT_CALLOC(256, sizeof(l_uint8));
689 for (i = 0; i < 256; i++)
690 tab[i] = ((0xc0 & i) >> 6) |
691 ((0x30 & i) >> 2) |
692 ((0x0c & i) << 2) |
693 ((0x03 & i) << 6);
694 return tab;
695}
696
697
705static l_uint8 *
707{
708l_int32 i;
709l_uint8 *tab;
710
711 tab = (l_uint8 *)LEPT_CALLOC(256, sizeof(l_uint8));
712 for (i = 0; i < 256; i++)
713 tab[i] = ((0xf0 & i) >> 4) | ((0x0f & i) << 4);
714 return tab;
715}
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
l_ok pixCopySpp(PIX *pixd, const PIX *pixs)
pixCopySpp()
Definition: pix1.c:1236
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition: pix1.c:816
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
void rasteropHipLow(l_uint32 *data, l_int32 pixh, l_int32 depth, l_int32 wpl, l_int32 y, l_int32 h, l_int32 shift)
rasteropHipLow()
Definition: roplow.c:2386
PIX * pixRotate90(PIX *pixs, l_int32 direction)
pixRotate90()
Definition: rotateorth.c:166
PIX * pixFlipTB(PIX *pixd, PIX *pixs)
pixFlipTB()
Definition: rotateorth.c:605
PIX * pixRotate180(PIX *pixd, PIX *pixs)
pixRotate180()
Definition: rotateorth.c:124
PIX * pixFlipLR(PIX *pixd, PIX *pixs)
pixFlipLR()
Definition: rotateorth.c:427
PIX * pixRotateOrth(PIX *pixs, l_int32 quads)
pixRotateOrth()
Definition: rotateorth.c:75
static l_uint8 * makeReverseByteTab1(void)
makeReverseByteTab1()
Definition: rotateorth.c:656
static l_uint8 * makeReverseByteTab2(void)
makeReverseByteTab2()
Definition: rotateorth.c:683
static l_uint8 * makeReverseByteTab4(void)
makeReverseByteTab4()
Definition: rotateorth.c:706
Definition: pix.h:139