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 
60 static l_uint8 *makeReverseByteTab1(void);
61 static l_uint8 *makeReverseByteTab2(void);
62 static l_uint8 *makeReverseByteTab4(void);
63 
64 /*------------------------------------------------------------------*
65  * Top-level rotation by multiples of 90 degrees *
66  *------------------------------------------------------------------*/
74 PIX *
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  *------------------------------------------------------------------*/
123 PIX *
125  PIX *pixs)
126 {
127 l_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  *------------------------------------------------------------------*/
165 PIX *
167  l_int32 direction)
168 {
169 l_int32 wd, hd, d, wpls, wpld;
170 l_int32 i, j, k, m, iend, nswords;
171 l_uint32 val, word;
172 l_uint32 *lines, *datas, *lined, *datad;
173 PIX *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  *------------------------------------------------------------------*/
426 PIX *
428  PIX *pixs)
429 {
430 l_uint8 *tab;
431 l_int32 w, h, d, wpl;
432 l_int32 extra, shift, databpl, bpl, i, j;
433 l_uint32 val;
434 l_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  *------------------------------------------------------------------*/
604 PIX *
606  PIX *pixs)
607 {
608 l_int32 h, d, wpl, i, k, h2, bpl;
609 l_uint32 *linet, *lineb;
610 l_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  *------------------------------------------------------------------*/
655 static l_uint8 *
657 {
658 l_int32 i;
659 l_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 
682 static l_uint8 *
684 {
685 l_int32 i;
686 l_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 
705 static l_uint8 *
707 {
708 l_int32 i;
709 l_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
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
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 * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition: pix1.c:816
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
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 * pixRotate180(PIX *pixd, PIX *pixs)
pixRotate180()
Definition: rotateorth.c:124
PIX * pixRotate90(PIX *pixs, l_int32 direction)
pixRotate90()
Definition: rotateorth.c:166
PIX * pixFlipLR(PIX *pixd, PIX *pixs)
pixFlipLR()
Definition: rotateorth.c:427
PIX * pixFlipTB(PIX *pixd, PIX *pixs)
pixFlipTB()
Definition: rotateorth.c:605
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
PIX * pixRotateOrth(PIX *pixs, l_int32 quads)
pixRotateOrth()
Definition: rotateorth.c:75
Definition: pix.h:139