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