Logo Search packages:      
Sourcecode: leptonlib version File versions  Download package

rotatefastalt.c

/*====================================================================*
 -  Copyright (C) 2001 Leptonica.  All rights reserved.
 -  This software is distributed in the hope that it will be
 -  useful, but with NO WARRANTY OF ANY KIND.
 -  No author or distributor accepts responsibility to anyone for the
 -  consequences of using this software, or for whether it serves any
 -  particular purpose or works at all, unless he or she says so in
 -  writing.  Everyone is granted permission to copy, modify and
 -  redistribute this source code, for commercial or non-commercial
 -  purposes, with the following restrictions: (1) the origin of this
 -  source code must not be misrepresented; (2) modified versions must
 -  be plainly marked as such; and (3) this notice may not be removed
 -  or altered from any source or modified source distribution.
 *====================================================================*/


/*
 *  rotatefastalt.c
 *
 *      Alternative (slightly slower) method for rotating color images,
 *      with antialiasing.  This is here just for comparison with
 *      the better methods in the library.
 *
 *      Includes these functions:
 *          pixRotateAMColorFast2()
 *          pixShiftRGB258()
 *          rotateAMColorFastLow2()
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>   /* required for sin and tan */
#include "allheaders.h"

static const l_float32  VERY_SMALL_ANGLE = 0.001;  /* radians; ~0.06 degrees */

static PIX *pixRotateAMColorFast2(PIX *pixs, l_float32 angle, l_uint8 grayval);
static PIX *pixShiftRGB258(PIX  *pixs);
static void rotateAMColorFastLow2(l_uint32  *datad, l_int32  w, l_int32  h,
                                l_int32  wpld, l_uint32  *datas,
                          l_int32  wpls, l_float32  angle,
                          l_uint8  grayval);

main(int    argc,
     char **argv)
{
char      *filein, *fileout;
l_float32  angle, deg2rad;
PIX       *pixs, *pixd;
static char  mainName[] = "rotatefastalt";

    if (argc != 4)
      exit(ERROR_INT("Syntax:  rotatefastalt filein angle fileout",
                     mainName, 1));
    filein = argv[1];
    angle = atof(argv[2]);
    fileout = argv[3];

    deg2rad = 3.1415926535 / 180.;

    if ((pixs = pixRead(filein)) == NULL)
      exit(ERROR_INT("pixs not read", mainName, 1));

    startTimer();
    pixd = pixRotateAMColorFast2(pixs, deg2rad * angle, 255);
    fprintf(stderr, "Time for rotation: %7.3f sec\n", stopTimer());
    pixWrite(fileout, pixd, IFF_JFIF_JPEG);

    pixDestroy(&pixs);
    pixDestroy(&pixd);
}


/*!
 *  pixRotateAMColorFast2()
 *
 *      Input: pixs
 *             angle (radians; clockwise is positive)
 *             grayval (0 to bring in BLACK, 255 for WHITE)
 *      Return:  pixd, or null on error
 *
 *  Notes:
 *      - This rotates a color image about the image center.
 *        A positive angle gives a clockwise rotation.
 *      - It uses area mapping, dividing each pixel into
 *        16 subpixels.
 *      - It creates a temporary 32-bit color image.
 *      - It is slightly slower than pixRotateAMColorFast(),
 *        which uses less memory because it does not create
 *        a temporary image.
 *
 *  *** Warning: implicit assumption about RGB component ordering ***
 */
PIX *
pixRotateAMColorFast2(PIX       *pixs,
                    l_float32  angle,
                  l_uint8    grayval)
{
l_int32    w, h, wpls, wpld;
l_uint32  *datas, *datad;
PIX           *pixshft, *pixd;

    PROCNAME("pixRotateAMColorFast2");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 32)
        return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);

    if (L_ABS(angle) < VERY_SMALL_ANGLE)
      return pixClone(pixs);

    if ((pixshft = pixShiftRGB258(pixs)) == NULL)
        return (PIX *)ERROR_PTR("pixshft not defined", procName, NULL);

    w = pixGetWidth(pixshft);
    h = pixGetHeight(pixshft);
    datas = pixGetData(pixshft);
    wpls = pixGetWpl(pixshft);
    pixd = pixCreateTemplate(pixshft);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);

    rotateAMColorFastLow2(datad, w, h, wpld, datas, wpls, angle, grayval);

    pixDestroy(&pixshft);
    return pixd;
}


/*!
 *  pixShiftRGB256()
 *
 *      Makes a new 32 bpp image with the R, G and B components
 *      right-shifted by 2, 5 and 8 bits, respectively.
 */
PIX *
pixShiftRGB258(PIX  *pixs)
{
l_int32    w, h, wpls, wpld, i, j;
l_uint32   word;
l_uint32  *datas, *datad, *lines, *lined;
PIX       *pixd;

    PROCNAME("pixShift258");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 32)
        return (PIX *)ERROR_PTR("depth not 32 bpp", procName, NULL);
    w = pixGetWidth(pixs);
    h = pixGetHeight(pixs);
    wpls = pixGetWpl(pixs);
    datas = pixGetData(pixs);

    if ((pixd = pixCreate(w, h, 32)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    wpld = pixGetWpl(pixd);
    datad = pixGetData(pixd);
      
    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        lined = datad + i * wpld;
      for (j = 0; j < w; j++) {
          word = *(lines + j);
          *(lined + j) = ((word & 0xff000000) >> 2) |
                       ((word & 0x00ff0000) >> 5) |
                       ((word & 0x0000ff00) >> 8);
        }
    }

    return pixd;
}


/*!
 *  rotateAMColorFastLow2()
 *
 *  Alternative version for fast color rotation
 *
 *  *** Warning: explicit assumption about RGB component ordering ***
 */
void
rotateAMColorFastLow2(l_uint32  *datad,
                      l_int32    w,
                    l_int32    h,
                    l_int32    wpld,
                    l_uint32  *datas,
                    l_int32    wpls,
                    l_float32  angle,
                  l_uint8    grayval)
{
l_int32    i, j, xcen, ycen, wm2, hm2;
l_int32    xdif, ydif, xpm, ypm, xp, yp, xf, yf;
l_uint32   edgeval, word;
l_uint32  *pword, *lines, *lined;
l_float32  sina, cosa;

    xcen = w / 2;
    wm2 = w - 2;
    ycen = h / 2;
    hm2 = h - 2;
    sina = 4. * sin(angle);
    cosa = 4. * cos(angle);

    edgeval = (grayval << 24) | (grayval << 16) | (grayval << 8);
    for (i = 0; i < h; i++) {
      ydif = ycen - i;
      lined = datad + i * wpld;
      for (j = 0; j < w; j++) {
          xdif = xcen - j;
          xpm = (l_int32)(-xdif * cosa - ydif * sina + 0.5);
          ypm = (l_int32)(-ydif * cosa + xdif * sina + 0.5);
          xp = xcen + (xpm >> 2);
          yp = ycen + (ypm >> 2);
          xf = xpm & 0x03;
          yf = ypm & 0x03;

            /* if off the edge, write the input grayval */
          if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
              *(lined + j) = edgeval;
            continue;
          }

          lines = datas + yp * wpls;
          pword = lines + xp;

          switch (xf + 4 * yf)
          {
            case 0:
              word = *pword;
              *(lined + j) = ((word & 0x3fc00000) << 2) |
                           ((word & 0x0007f800) << 5) |
                         ((word & 0x000000ff) << 8);
              break;
            case 1:
              word = 3 * (*pword) + *(pword + 1);
              *(lined + j) = (word & 0xff000000) |
                           ((word & 0x001fe000) << 3) |
                           ((word & 0x000003fc) << 6);
                break;
            case 2:
              word = *pword + *(pword + 1);
              *(lined + j) = ((word & 0x7f800000) << 1) |
                           ((word & 0x000ff000) << 4) |
                           ((word & 0x000001fe) << 7);
                break;
            case 3:
              word = *pword + 3 * (*(pword + 1));
              *(lined + j) = (word & 0xff000000) |
                           ((word & 0x001fe000) << 3) |
                           ((word & 0x000003fc) << 6);
                break;
            case 4:
              word = 3 * (*pword) + *(pword + wpls);
              *(lined + j) = (word & 0xff000000) |
                           ((word & 0x001fe000) << 3) |
                           ((word & 0x000003fc) << 6);
                break;
            case 5:
              word = 2 * (*pword) + *(pword + 1) + *(pword + wpls);
              *(lined + j) = (word & 0xff000000) |
                           ((word & 0x001fe000) << 3) |
                           ((word & 0x000003fc) << 6);
                break;
            case 6:
              word = *pword + *(pword + 1);
              *(lined + j) = ((word & 0x7f800000) << 1) |
                           ((word & 0x000ff000) << 4) |
                           ((word & 0x000001fe) << 7);
                break;
            case 7:
              word = *pword + 2 * (*(pword + 1)) + *(pword + wpls + 1);
              *(lined + j) = (word & 0xff000000) |
                           ((word & 0x001fe000) << 3) |
                           ((word & 0x000003fc) << 6);
                break;
            case 8:
              word = *pword + *(pword + wpls);
              *(lined + j) = ((word & 0x7f800000) << 1) |
                           ((word & 0x000ff000) << 4) |
                           ((word & 0x000001fe) << 7);
                break;
            case 9:
              word = *pword + *(pword + wpls);
              *(lined + j) = ((word & 0x7f800000) << 1) |
                           ((word & 0x000ff000) << 4) |
                           ((word & 0x000001fe) << 7);
                break;
            case 10:
              word = *pword + *(pword + 1) + *(pword + wpls) +
                   *(pword + wpls + 1);
              *(lined + j) = (word & 0xff000000) |
                           ((word & 0x001fe000) << 3) |
                           ((word & 0x000003fc) << 6);
                break;
            case 11:
              word = *(pword + 1) + *(pword + wpls + 1);
              *(lined + j) = ((word & 0x7f800000) << 1) |
                           ((word & 0x000ff000) << 4) |
                           ((word & 0x000001fe) << 7);
                break;
            case 12:
              word = *pword + 3 * (*(pword + wpls));
              *(lined + j) = (word & 0xff000000) |
                           ((word & 0x001fe000) << 3) |
                           ((word & 0x000003fc) << 6);
                break;
            case 13:
              word = *pword + 2 * (*(pword + wpls)) + *(pword + wpls + 1);
              *(lined + j) = (word & 0xff000000) |
                           ((word & 0x001fe000) << 3) |
                           ((word & 0x000003fc) << 6);
                break;
            case 14:
              word = *(pword + wpls) + *(pword + wpls + 1);
              *(lined + j) = ((word & 0x7f800000) << 1) |
                           ((word & 0x000ff000) << 4) |
                           ((word & 0x000001fe) << 7);
                break;
            case 15:
              word = *(pword + 1) + *(pword + wpls) +
                       2 * (*(pword + wpls + 1));
              *(lined + j) = (word & 0xff000000) |
                           ((word & 0x001fe000) << 3) |
                           ((word & 0x000003fc) << 6);
                break;
            default:  /* for testing only; no interpolation, no shift */
              fprintf(stderr, "shouldn't get here\n");
                *(lined + j) = *pword;
            break;
            }
      }
    }

    return;
}


Generated by  Doxygen 1.6.0   Back to index