Leptonica 1.68
C Image Processing Library

rotatefastalt.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  *  rotatefastalt.c
00019  *
00020  *      Alternative (slightly slower) method for rotating color images,
00021  *      with antialiasing.  This is here just for comparison with
00022  *      the better methods in the library.
00023  *
00024  *      Includes these functions:
00025  *          pixRotateAMColorFast2()
00026  *          pixShiftRGB258()
00027  *          rotateAMColorFastLow2()
00028  */
00029 
00030 #include <string.h>
00031 #include <math.h>   /* required for sin and tan */
00032 #include "allheaders.h"
00033 
00034 static const l_float32  VERY_SMALL_ANGLE = 0.001;  /* radians; ~0.06 degrees */
00035 
00036 static PIX *pixRotateAMColorFast2(PIX *pixs, l_float32 angle, l_uint8 grayval);
00037 static PIX *pixShiftRGB258(PIX  *pixs);
00038 static void rotateAMColorFastLow2(l_uint32  *datad, l_int32  w, l_int32  h,
00039                                   l_int32  wpld, l_uint32  *datas,
00040                                   l_int32  wpls, l_float32  angle,
00041                                   l_uint8  grayval);
00042 
00043 main(int    argc,
00044      char **argv)
00045 {
00046 char      *filein, *fileout;
00047 l_float32  angle, deg2rad;
00048 PIX       *pixs, *pixd;
00049 static char  mainName[] = "rotatefastalt";
00050 
00051     if (argc != 4)
00052         exit(ERROR_INT("Syntax:  rotatefastalt filein angle fileout",
00053                        mainName, 1));
00054     filein = argv[1];
00055     angle = atof(argv[2]);
00056     fileout = argv[3];
00057 
00058     deg2rad = 3.1415926535 / 180.;
00059 
00060     if ((pixs = pixRead(filein)) == NULL)
00061         exit(ERROR_INT("pixs not read", mainName, 1));
00062 
00063     startTimer();
00064     pixd = pixRotateAMColorFast2(pixs, deg2rad * angle, 255);
00065     fprintf(stderr, "Time for rotation: %7.3f sec\n", stopTimer());
00066     pixWrite(fileout, pixd, IFF_JFIF_JPEG);
00067 
00068     pixDestroy(&pixs);
00069     pixDestroy(&pixd);
00070     return 0;
00071 }
00072 
00073 
00074 /*!
00075  *  pixRotateAMColorFast2()
00076  *
00077  *      Input: pixs
00078  *             angle (radians; clockwise is positive)
00079  *             grayval (0 to bring in BLACK, 255 for WHITE)
00080  *      Return:  pixd, or null on error
00081  *
00082  *  Notes:
00083  *      - This rotates a color image about the image center.
00084  *        A positive angle gives a clockwise rotation.
00085  *      - It uses area mapping, dividing each pixel into
00086  *        16 subpixels.
00087  *      - It creates a temporary 32-bit color image.
00088  *      - It is slightly slower than pixRotateAMColorFast(),
00089  *        which uses less memory because it does not create
00090  *        a temporary image.
00091  *
00092  *  *** Warning: implicit assumption about RGB component ordering ***
00093  */
00094 PIX *
00095 pixRotateAMColorFast2(PIX       *pixs,
00096                       l_float32  angle,
00097                       l_uint8    grayval)
00098 {
00099 l_int32    w, h, wpls, wpld;
00100 l_uint32  *datas, *datad;
00101 PIX       *pixshft, *pixd;
00102 
00103     PROCNAME("pixRotateAMColorFast2");
00104 
00105     if (!pixs)
00106         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
00107     if (pixGetDepth(pixs) != 32)
00108         return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
00109 
00110     if (L_ABS(angle) < VERY_SMALL_ANGLE)
00111         return pixClone(pixs);
00112 
00113     if ((pixshft = pixShiftRGB258(pixs)) == NULL)
00114         return (PIX *)ERROR_PTR("pixshft not defined", procName, NULL);
00115 
00116     w = pixGetWidth(pixshft);
00117     h = pixGetHeight(pixshft);
00118     datas = pixGetData(pixshft);
00119     wpls = pixGetWpl(pixshft);
00120     pixd = pixCreateTemplate(pixshft);
00121     datad = pixGetData(pixd);
00122     wpld = pixGetWpl(pixd);
00123 
00124     rotateAMColorFastLow2(datad, w, h, wpld, datas, wpls, angle, grayval);
00125 
00126     pixDestroy(&pixshft);
00127     return pixd;
00128 }
00129 
00130 
00131 /*!
00132  *  pixShiftRGB258()
00133  *
00134  *      Makes a new 32 bpp image with the R, G and B components
00135  *      right-shifted by 2, 5 and 8 bits, respectively.
00136  */
00137 PIX *
00138 pixShiftRGB258(PIX  *pixs)
00139 {
00140 l_int32    w, h, wpls, wpld, i, j;
00141 l_uint32   word;
00142 l_uint32  *datas, *datad, *lines, *lined;
00143 PIX       *pixd;
00144 
00145     PROCNAME("pixShift258");
00146 
00147     if (!pixs)
00148         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
00149     if (pixGetDepth(pixs) != 32)
00150         return (PIX *)ERROR_PTR("depth not 32 bpp", procName, NULL);
00151     w = pixGetWidth(pixs);
00152     h = pixGetHeight(pixs);
00153     wpls = pixGetWpl(pixs);
00154     datas = pixGetData(pixs);
00155 
00156     if ((pixd = pixCreate(w, h, 32)) == NULL)
00157         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00158     wpld = pixGetWpl(pixd);
00159     datad = pixGetData(pixd);
00160       
00161     for (i = 0; i < h; i++) {
00162         lines = datas + i * wpls;
00163         lined = datad + i * wpld;
00164         for (j = 0; j < w; j++) {
00165             word = *(lines + j);
00166             *(lined + j) = ((word & 0xff000000) >> 2) |
00167                            ((word & 0x00ff0000) >> 5) |
00168                            ((word & 0x0000ff00) >> 8);
00169         }
00170     }
00171 
00172     return pixd;
00173 }
00174 
00175 
00176 /*!
00177  *  rotateAMColorFastLow2()
00178  *
00179  *  Alternative version for fast color rotation
00180  *
00181  *  *** Warning: explicit assumption about RGB component ordering ***
00182  */
00183 void
00184 rotateAMColorFastLow2(l_uint32  *datad,
00185                       l_int32    w,
00186                       l_int32    h,
00187                       l_int32    wpld,
00188                       l_uint32  *datas,
00189                       l_int32    wpls,
00190                       l_float32  angle,
00191                       l_uint8    grayval)
00192 {
00193 l_int32    i, j, xcen, ycen, wm2, hm2;
00194 l_int32    xdif, ydif, xpm, ypm, xp, yp, xf, yf;
00195 l_uint32   edgeval, word;
00196 l_uint32  *pword, *lines, *lined;
00197 l_float32  sina, cosa;
00198 
00199     xcen = w / 2;
00200     wm2 = w - 2;
00201     ycen = h / 2;
00202     hm2 = h - 2;
00203     sina = 4. * sin(angle);
00204     cosa = 4. * cos(angle);
00205 
00206     edgeval = (grayval << 24) | (grayval << 16) | (grayval << 8);
00207     for (i = 0; i < h; i++) {
00208         ydif = ycen - i;
00209         lined = datad + i * wpld;
00210         for (j = 0; j < w; j++) {
00211             xdif = xcen - j;
00212             xpm = (l_int32)(-xdif * cosa - ydif * sina + 0.5);
00213             ypm = (l_int32)(-ydif * cosa + xdif * sina + 0.5);
00214             xp = xcen + (xpm >> 2);
00215             yp = ycen + (ypm >> 2);
00216             xf = xpm & 0x03;
00217             yf = ypm & 0x03;
00218 
00219                 /* if off the edge, write the input grayval */
00220             if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
00221                 *(lined + j) = edgeval;
00222                 continue;
00223             }
00224 
00225             lines = datas + yp * wpls;
00226             pword = lines + xp;
00227 
00228             switch (xf + 4 * yf)
00229             {
00230             case 0:
00231                 word = *pword;
00232                 *(lined + j) = ((word & 0x3fc00000) << 2) |
00233                                ((word & 0x0007f800) << 5) |
00234                                ((word & 0x000000ff) << 8);
00235                 break;
00236             case 1:
00237                 word = 3 * (*pword) + *(pword + 1);
00238                 *(lined + j) = (word & 0xff000000) |
00239                                ((word & 0x001fe000) << 3) |
00240                                ((word & 0x000003fc) << 6);
00241                 break;
00242             case 2:
00243                 word = *pword + *(pword + 1);
00244                 *(lined + j) = ((word & 0x7f800000) << 1) |
00245                                ((word & 0x000ff000) << 4) |
00246                                ((word & 0x000001fe) << 7);
00247                 break;
00248             case 3:
00249                 word = *pword + 3 * (*(pword + 1));
00250                 *(lined + j) = (word & 0xff000000) |
00251                                ((word & 0x001fe000) << 3) |
00252                                ((word & 0x000003fc) << 6);
00253                 break;
00254             case 4:
00255                 word = 3 * (*pword) + *(pword + wpls);
00256                 *(lined + j) = (word & 0xff000000) |
00257                                ((word & 0x001fe000) << 3) |
00258                                ((word & 0x000003fc) << 6);
00259                 break;
00260             case 5:
00261                 word = 2 * (*pword) + *(pword + 1) + *(pword + wpls);
00262                 *(lined + j) = (word & 0xff000000) |
00263                                ((word & 0x001fe000) << 3) |
00264                                ((word & 0x000003fc) << 6);
00265                 break;
00266             case 6:
00267                 word = *pword + *(pword + 1);
00268                 *(lined + j) = ((word & 0x7f800000) << 1) |
00269                                ((word & 0x000ff000) << 4) |
00270                                ((word & 0x000001fe) << 7);
00271                 break;
00272             case 7:
00273                 word = *pword + 2 * (*(pword + 1)) + *(pword + wpls + 1);
00274                 *(lined + j) = (word & 0xff000000) |
00275                                ((word & 0x001fe000) << 3) |
00276                                ((word & 0x000003fc) << 6);
00277                 break;
00278             case 8:
00279                 word = *pword + *(pword + wpls);
00280                 *(lined + j) = ((word & 0x7f800000) << 1) |
00281                                ((word & 0x000ff000) << 4) |
00282                                ((word & 0x000001fe) << 7);
00283                 break;
00284             case 9:
00285                 word = *pword + *(pword + wpls);
00286                 *(lined + j) = ((word & 0x7f800000) << 1) |
00287                                ((word & 0x000ff000) << 4) |
00288                                ((word & 0x000001fe) << 7);
00289                 break;
00290             case 10:
00291                 word = *pword + *(pword + 1) + *(pword + wpls) +
00292                        *(pword + wpls + 1);
00293                 *(lined + j) = (word & 0xff000000) |
00294                                ((word & 0x001fe000) << 3) |
00295                                ((word & 0x000003fc) << 6);
00296                 break;
00297             case 11:
00298                 word = *(pword + 1) + *(pword + wpls + 1);
00299                 *(lined + j) = ((word & 0x7f800000) << 1) |
00300                                ((word & 0x000ff000) << 4) |
00301                                ((word & 0x000001fe) << 7);
00302                 break;
00303             case 12:
00304                 word = *pword + 3 * (*(pword + wpls));
00305                 *(lined + j) = (word & 0xff000000) |
00306                                ((word & 0x001fe000) << 3) |
00307                                ((word & 0x000003fc) << 6);
00308                 break;
00309             case 13:
00310                 word = *pword + 2 * (*(pword + wpls)) + *(pword + wpls + 1);
00311                 *(lined + j) = (word & 0xff000000) |
00312                                ((word & 0x001fe000) << 3) |
00313                                ((word & 0x000003fc) << 6);
00314                 break;
00315             case 14:
00316                 word = *(pword + wpls) + *(pword + wpls + 1);
00317                 *(lined + j) = ((word & 0x7f800000) << 1) |
00318                                ((word & 0x000ff000) << 4) |
00319                                ((word & 0x000001fe) << 7);
00320                 break;
00321             case 15:
00322                 word = *(pword + 1) + *(pword + wpls) +
00323                            2 * (*(pword + wpls + 1));
00324                 *(lined + j) = (word & 0xff000000) |
00325                                ((word & 0x001fe000) << 3) |
00326                                ((word & 0x000003fc) << 6);
00327                 break;
00328             default:  /* for testing only; no interpolation, no shift */
00329                 fprintf(stderr, "shouldn't get here\n");
00330                 *(lined + j) = *pword;
00331                 break;
00332             }
00333         }
00334     }
00335 
00336     return;
00337 }
00338 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines