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