Leptonica 1.68
C Image Processing Library

rotateorthlow.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 
00017 /*
00018  *  rotateorthlow.c
00019  *
00020  *      90-degree rotation (cw)
00021  *            void      rotate90Low()
00022  *
00023  *      LR-flip
00024  *            void      flipLRLow()
00025  *
00026  *      TB-flip
00027  *            void      flipTBLow()
00028  *
00029  *      Byte reverse tables
00030  *            l_uint8  *makeReverseByteTab1()
00031  *            l_uint8  *makeReverseByteTab2()
00032  *            l_uint8  *makeReverseByteTab4()
00033  */
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include "allheaders.h"
00039 
00040 
00041 
00042 /*------------------------------------------------------------------*
00043  *                           90 degree rotation                     *
00044  *------------------------------------------------------------------*/
00045 /*!
00046  *  rotate90Low()
00047  *
00048  *      direction:  1 for cw rotation
00049  *                 -1 for ccw rotation
00050  *
00051  *  Notes:
00052  *      (1) The dest must be cleared in advance because not
00053  *          all source pixels are written to the destination.
00054  */
00055 void
00056 rotate90Low(l_uint32  *datad,
00057             l_int32    wd,
00058             l_int32    hd,
00059             l_int32    d,
00060             l_int32    wpld,
00061             l_uint32  *datas, 
00062             l_int32    wpls,
00063             l_int32    direction)
00064 {
00065 l_int32    i, j, k, m, iend, nswords;
00066 l_uint32   val, word;
00067 l_uint32  *lines, *lined;
00068 
00069     PROCNAME("rotate90Low");
00070 
00071     if (direction == 1) {  /* clockwise */
00072         switch (d)
00073         {
00074             case 32: 
00075                 for (i = 0; i < hd; i++) {
00076                     lined = datad + i * wpld;
00077                     lines = datas + (wd - 1) * wpls;
00078                     for (j = 0; j < wd; j++) {
00079                         lined[j] = lines[i];
00080                         lines -= wpls;
00081                     }
00082                 }
00083                 break;
00084             case 16:
00085                 for (i = 0; i < hd; i++) {
00086                     lined = datad + i * wpld;
00087                     lines = datas + (wd - 1) * wpls;
00088                     for (j = 0; j < wd; j++) {
00089                         if ((val = GET_DATA_TWO_BYTES(lines, i)))
00090                             SET_DATA_TWO_BYTES(lined, j, val);
00091                         lines -= wpls;
00092                     }
00093                 }
00094                 break;
00095             case 8:
00096                 for (i = 0; i < hd; i++) {
00097                     lined = datad + i * wpld;
00098                     lines = datas + (wd - 1) * wpls;
00099                     for (j = 0; j < wd; j++) {
00100                         if ((val = GET_DATA_BYTE(lines, i)))
00101                             SET_DATA_BYTE(lined, j, val);
00102                         lines -= wpls;
00103                     }
00104                 }
00105                 break;
00106             case 4:
00107                 for (i = 0; i < hd; i++) {
00108                     lined = datad + i * wpld;
00109                     lines = datas + (wd - 1) * wpls;
00110                     for (j = 0; j < wd; j++) {
00111                         if ((val = GET_DATA_QBIT(lines, i)))
00112                             SET_DATA_QBIT(lined, j, val);
00113                         lines -= wpls;
00114                     }
00115                 }
00116                 break;
00117             case 2:
00118                 for (i = 0; i < hd; i++) {
00119                     lined = datad + i * wpld;
00120                     lines = datas + (wd - 1) * wpls;
00121                     for (j = 0; j < wd; j++) {
00122                         if ((val = GET_DATA_DIBIT(lines, i)))
00123                             SET_DATA_DIBIT(lined, j, val);
00124                         lines -= wpls;
00125                     }
00126                 }
00127                 break;
00128             case 1:
00129                 nswords = hd / 32;
00130                 for (j = 0; j < wd; j++) {
00131                     lined = datad;
00132                     lines = datas + (wd - 1 - j) * wpls;
00133                     for (k = 0; k < nswords; k++) {
00134                         word = lines[k];
00135                         if (!word) {
00136                             lined += 32 * wpld;
00137                             continue;
00138                         }
00139                         else {
00140                             iend = 32 * (k + 1);
00141                             for (m = 0, i = 32 * k; i < iend; i++, m++) {
00142                                 if ((word << m) & 0x80000000)
00143                                     SET_DATA_BIT(lined, j);
00144                                 lined += wpld;
00145                             }
00146                         }
00147                     }
00148                     for (i = 32 * nswords; i < hd; i++) {
00149                         if (GET_DATA_BIT(lines, i))
00150                             SET_DATA_BIT(lined, j);
00151                         lined += wpld;
00152                     }
00153                 }
00154                 break;
00155             default:
00156                 L_ERROR("illegal depth", procName);
00157         }
00158     }
00159     else  {     /* direction counter-clockwise */
00160         switch (d)
00161         {
00162             case 32: 
00163                 for (i = 0; i < hd; i++) {
00164                     lined = datad + i * wpld;
00165                     lines = datas;
00166                     for (j = 0; j < wd; j++) {
00167                         lined[j] = lines[hd - 1 - i];
00168                         lines += wpls;
00169                     }
00170                 }
00171                 break;
00172             case 16:
00173                 for (i = 0; i < hd; i++) {
00174                     lined = datad + i * wpld;
00175                     lines = datas;
00176                     for (j = 0; j < wd; j++) {
00177                         if ((val = GET_DATA_TWO_BYTES(lines, hd - 1 - i)))
00178                             SET_DATA_TWO_BYTES(lined, j, val);
00179                         lines += wpls;
00180                     }
00181                 }
00182                 break;
00183             case 8:
00184                 for (i = 0; i < hd; i++) {
00185                     lined = datad + i * wpld;
00186                     lines = datas;
00187                     for (j = 0; j < wd; j++) {
00188                         if ((val = GET_DATA_BYTE(lines, hd - 1 - i)))
00189                             SET_DATA_BYTE(lined, j, val);
00190                         lines += wpls;
00191                     }
00192                 }
00193                 break;
00194             case 4:
00195                 for (i = 0; i < hd; i++) {
00196                     lined = datad + i * wpld;
00197                     lines = datas;
00198                     for (j = 0; j < wd; j++) {
00199                         if ((val = GET_DATA_QBIT(lines, hd - 1 - i)))
00200                             SET_DATA_QBIT(lined, j, val);
00201                         lines += wpls;
00202                     }
00203                 }
00204                 break;
00205             case 2:
00206                 for (i = 0; i < hd; i++) {
00207                     lined = datad + i * wpld;
00208                     lines = datas;
00209                     for (j = 0; j < wd; j++) {
00210                         if ((val = GET_DATA_DIBIT(lines, hd - 1 - i)))
00211                             SET_DATA_DIBIT(lined, j, val);
00212                         lines += wpls;
00213                     }
00214                 }
00215                 break;
00216             case 1:
00217                 nswords = hd / 32;
00218                 for (j = 0; j < wd; j++) {
00219                     lined = datad + (hd - 1) * wpld;
00220                     lines = datas + (wd - 1 - j) * wpls;
00221                     for (k = 0; k < nswords; k++) {
00222                         word = lines[k];
00223                         if (!word) {
00224                             lined -= 32 * wpld;
00225                             continue;
00226                         }
00227                         else {
00228                             iend = 32 * (k + 1);
00229                             for (m = 0, i = 32 * k; i < iend; i++, m++) {
00230                                 if ((word << m) & 0x80000000)
00231                                     SET_DATA_BIT(lined, wd - 1 - j);
00232                                 lined -= wpld;
00233                             }
00234                         }
00235                     }
00236                     for (i = 32 * nswords; i < hd; i++) {
00237                         if (GET_DATA_BIT(lines, i))
00238                             SET_DATA_BIT(lined, wd - 1 - j);
00239                         lined -= wpld;
00240                     }
00241                 }
00242                 break;
00243             default:
00244                 L_ERROR("illegal depth", procName);
00245         }
00246     }
00247 
00248     return;
00249 }
00250 
00251 
00252 /*------------------------------------------------------------------*
00253  *                           Left/right flip                        *
00254  *------------------------------------------------------------------*/
00255 /*!
00256  *  flipLRLow()
00257  *
00258  *  Notes:
00259  *      (1) The pixel access routines allow a trivial implementation.
00260  *          However, for d < 8, it is more efficient to right-justify
00261  *          each line to a 32-bit boundary and then extract bytes and
00262  *          do pixel reversing.   In those cases, as in the 180 degree
00263  *          rotation, we right-shift the data (if necessary) to
00264  *          right-justify on the 32 bit boundary, and then read the
00265  *          bytes off each raster line in reverse order, reversing
00266  *          the pixels in each byte using a table.  These functions
00267  *          for 1, 2 and 4 bpp were tested against the "trivial"
00268  *          version (shown here for 4 bpp):
00269  *              for (i = 0; i < h; i++) {
00270  *                  line = data + i * wpl;
00271  *                  memcpy(buffer, line, bpl);
00272  *                    for (j = 0; j < w; j++) {
00273  *                      val = GET_DATA_QBIT(buffer, w - 1 - j);
00274  *                        SET_DATA_QBIT(line, j, val);
00275  *                  }
00276  *              }
00277  *      (2) This operation is in-place.
00278  */
00279 void
00280 flipLRLow(l_uint32  *data,
00281           l_int32    w,
00282           l_int32    h,
00283           l_int32    d,
00284           l_int32    wpl,
00285           l_uint8   *tab,
00286           l_uint32  *buffer)
00287 {
00288 l_int32    extra, shift, databpl, bpl, i, j;
00289 l_uint32   val;
00290 l_uint32  *line;
00291 
00292     PROCNAME("flipLRLow");
00293 
00294     bpl = 4 * wpl;
00295     switch (d)
00296     {
00297         case 32: 
00298             for (i = 0; i < h; i++) {
00299                 line = data + i * wpl;
00300                 memcpy(buffer, line, bpl);
00301                 for (j = 0; j < w; j++)
00302                     line[j] = buffer[w - 1 - j];
00303             }
00304             break;
00305         case 16:
00306             for (i = 0; i < h; i++) {
00307                 line = data + i * wpl;
00308                 memcpy(buffer, line, bpl);
00309                 for (j = 0; j < w; j++) {
00310                     val = GET_DATA_TWO_BYTES(buffer, w - 1 - j);
00311                     SET_DATA_TWO_BYTES(line, j, val);
00312                 }
00313             }
00314             break;
00315         case 8:
00316             for (i = 0; i < h; i++) {
00317                 line = data + i * wpl;
00318                 memcpy(buffer, line, bpl);
00319                 for (j = 0; j < w; j++) {
00320                     val = GET_DATA_BYTE(buffer, w - 1 - j);
00321                     SET_DATA_BYTE(line, j, val);
00322                 }
00323             }
00324             break;
00325         case 4:
00326             extra = (w * d) & 31;
00327             if (extra)
00328                 shift = 8 - extra / 4;
00329             else
00330                 shift = 0;
00331             if (shift)
00332                 rasteropHipLow(data, h, d, wpl, 0, h, shift);
00333 
00334             databpl = (w + 1) / 2;
00335             for (i = 0; i < h; i++) {
00336                 line = data + i * wpl;
00337                 memcpy(buffer, line, bpl);
00338                 for (j = 0; j < databpl; j++) {
00339                     val = GET_DATA_BYTE(buffer, bpl - 1 - j);
00340                     SET_DATA_BYTE(line, j, tab[val]);
00341                 }
00342             }
00343             break;
00344         case 2:
00345             extra = (w * d) & 31;
00346             if (extra)
00347                 shift = 16 - extra / 2;
00348             else
00349                 shift = 0;
00350             if (shift)
00351                 rasteropHipLow(data, h, d, wpl, 0, h, shift);
00352 
00353             databpl = (w + 3) / 4;
00354             for (i = 0; i < h; i++) {
00355                 line = data + i * wpl;
00356                 memcpy(buffer, line, bpl);
00357                 for (j = 0; j < databpl; j++) {
00358                     val = GET_DATA_BYTE(buffer, bpl - 1 - j);
00359                     SET_DATA_BYTE(line, j, tab[val]);
00360                 }
00361             }
00362             break;
00363         case 1:
00364             extra = (w * d) & 31;
00365             if (extra)
00366                 shift = 32 - extra;
00367             else
00368                 shift = 0;
00369             if (shift)
00370                 rasteropHipLow(data, h, d, wpl, 0, h, shift);
00371 
00372             databpl = (w + 7) / 8;
00373             for (i = 0; i < h; i++) {
00374                 line = data + i * wpl;
00375                 memcpy(buffer, line, bpl);
00376                 for (j = 0; j < databpl; j++) {
00377                     val = GET_DATA_BYTE(buffer, bpl - 1 - j);
00378                     SET_DATA_BYTE(line, j, tab[val]);
00379                 }
00380             }
00381             break;
00382         default:
00383             L_ERROR("depth not permitted for LR rot", procName);
00384             return;
00385     }
00386 
00387     return;
00388 }
00389 
00390 
00391 /*------------------------------------------------------------------*
00392  *                            Top/bottom flip                       *
00393  *------------------------------------------------------------------*/
00394 /*!
00395  *  flipTBLow()
00396  *
00397  *  Notes:
00398  *      (1) This is simple and fast.  We use the memcpy function
00399  *          to do all the work on aligned data, regardless of pixel
00400  *          depth.
00401  *      (2) This operation is in-place.
00402  */
00403 void
00404 flipTBLow(l_uint32  *data,
00405           l_int32    h,
00406           l_int32    wpl,
00407           l_uint32  *buffer)
00408 {
00409 l_int32    i, k, h2, bpl;
00410 l_uint32  *linet, *lineb;
00411 
00412     h2 = h / 2;
00413     bpl = 4 * wpl;
00414     for (i = 0, k = h - 1; i < h2; i++, k--) {
00415         linet = data + i * wpl;
00416         lineb = data + k * wpl;
00417         memcpy(buffer, linet, bpl);
00418         memcpy(linet, lineb, bpl);
00419         memcpy(lineb, buffer, bpl);
00420     }
00421 
00422     return;
00423 }
00424 
00425 
00426 /*------------------------------------------------------------------*
00427  *                          Byte reverse tables                     *
00428  *------------------------------------------------------------------*/
00429 /*!
00430  *  makeReverseByteTab1()
00431  *
00432  *  Notes:
00433  *      (1) This generates an 8 bit lookup table for reversing
00434  *          the order of eight 1-bit pixels.
00435  */
00436 l_uint8 *
00437 makeReverseByteTab1(void)
00438 {
00439 l_int32   i;
00440 l_uint8  *tab;
00441 
00442     PROCNAME("makeReverseByteTab1");
00443 
00444     if ((tab = (l_uint8 *)CALLOC(256, sizeof(l_uint8))) == NULL)
00445         return (l_uint8 *)ERROR_PTR("calloc fail for tab", procName, NULL);
00446 
00447     for (i = 0; i < 256; i++)
00448         tab[i] = ((0x80 & i) >> 7) |
00449                  ((0x40 & i) >> 5) |
00450                  ((0x20 & i) >> 3) |
00451                  ((0x10 & i) >> 1) |
00452                  ((0x08 & i) << 1) |
00453                  ((0x04 & i) << 3) |
00454                  ((0x02 & i) << 5) |
00455                  ((0x01 & i) << 7);
00456 
00457     return tab;
00458 }
00459 
00460 
00461 /*!
00462  *  makeReverseByteTab2()
00463  *
00464  *  Notes:
00465  *      (1) This generates an 8 bit lookup table for reversing
00466  *          the order of four 2-bit pixels.
00467  */
00468 l_uint8 *
00469 makeReverseByteTab2(void)
00470 {
00471 l_int32   i;
00472 l_uint8  *tab;
00473 
00474     PROCNAME("makeReverseByteTab2");
00475 
00476     if ((tab = (l_uint8 *)CALLOC(256, sizeof(l_uint8))) == NULL)
00477         return (l_uint8 *)ERROR_PTR("calloc fail for tab", procName, NULL);
00478 
00479     for (i = 0; i < 256; i++)
00480         tab[i] = ((0xc0 & i) >> 6) |
00481                  ((0x30 & i) >> 2) |
00482                  ((0x0c & i) << 2) |
00483                  ((0x03 & i) << 6);
00484     return tab;
00485 }
00486 
00487 
00488 /*!
00489  *  makeReverseByteTab4()
00490  *
00491  *  Notes:
00492  *      (1) This generates an 8 bit lookup table for reversing
00493  *          the order of two 4-bit pixels.
00494  */
00495 l_uint8 *
00496 makeReverseByteTab4(void)
00497 {
00498 l_int32   i;
00499 l_uint8  *tab;
00500 
00501     PROCNAME("makeReverseByteTab4");
00502 
00503     if ((tab = (l_uint8 *)CALLOC(256, sizeof(l_uint8))) == NULL)
00504         return (l_uint8 *)ERROR_PTR("calloc fail for tab", procName, NULL);
00505 
00506     for (i = 0; i < 256; i++)
00507         tab[i] = ((0xf0 & i) >> 4) | ((0x0f & i) << 4);
00508     return tab;
00509 }
00510 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines