IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 1250


Ignore:
Timestamp:
Jul 21, 2004, 1:39:10 PM (22 years ago)
Author:
desonia
Message:

Added psImageRotate, psImageShift

Location:
trunk/psLib/src/image
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/image/psImageManip.c

    r1226 r1250  
    1010 *  @author Ross Harman, MHPCC
    1111 *
    12  *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2004-07-15 19:58:37 $
     12 *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2004-07-21 23:39:10 $
    1414 *
    1515 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2424#include "psStats.h"
    2525#include "psMemory.h"
     26#include "psImageStats.h"
    2627
    2728bool getSpecifiedStatValue(const psStats* stats, double* value);
     
    527528    return out;
    528529}
     530
     531psImage* psImageRotate(psImage* out, const psImage* in, float angle, float unexposedValue, psImageInterpolateMode mode)
     532{
     533    if (in == NULL) {
     534        psError(__func__,"The input image was NULL.");
     535        psFree(out);
     536        return NULL;
     537    }
     538
     539    // put the angle in the range of 0...360.
     540    angle = angle - 360.0f*floor(angle/360.0f);
     541
     542    if (fabsf(angle-90.0f) < FLT_EPSILON) {
     543        // perform 1/4 rotate counter-clockwise
     544        int numRows = in->numCols;
     545        int numCols = in->numRows;
     546        int lastCol = numCols - 1;
     547        psElemType type = in->type.type;
     548        out = psImageRecycle(out,numCols,numRows,type);
     549
     550        #define PSIMAGE_ROTATE_LEFT_90(TYPE) \
     551    case PS_TYPE_##TYPE: { \
     552            ps##TYPE** inData = in->data.TYPE; \
     553            for (int row=0;row<numRows;row++) { \
     554                ps##TYPE* outRow = out->data.TYPE[row]; \
     555                for (int col=0;col<numCols;col++) { \
     556                    outRow[col] = inData[lastCol-col][row]; \
     557                } \
     558            } \
     559        } \
     560        break;
     561
     562        switch (type) {
     563            PSIMAGE_ROTATE_LEFT_90(U8);
     564            PSIMAGE_ROTATE_LEFT_90(U16);
     565            PSIMAGE_ROTATE_LEFT_90(U32);
     566            PSIMAGE_ROTATE_LEFT_90(U64);
     567            PSIMAGE_ROTATE_LEFT_90(S8);
     568            PSIMAGE_ROTATE_LEFT_90(S16);
     569            PSIMAGE_ROTATE_LEFT_90(S32);
     570            PSIMAGE_ROTATE_LEFT_90(S64);
     571            PSIMAGE_ROTATE_LEFT_90(F32);
     572            PSIMAGE_ROTATE_LEFT_90(F64);
     573            PSIMAGE_ROTATE_LEFT_90(C32);
     574            PSIMAGE_ROTATE_LEFT_90(C64);
     575        default:
     576            psError(__func__,"Unsupported type (%d)",type);
     577            psFree(out);
     578            return NULL;
     579        }
     580    } else if (fabsf(angle-180.0f) < FLT_EPSILON) {
     581        // perform 1/2 rotate
     582        int numRows = in->numRows;
     583        int lastRow = numRows - 1;
     584        int numCols = in->numCols;
     585        int lastCol = numCols - 1;
     586        psElemType type = in->type.type;
     587        out = psImageRecycle(out,numCols,numRows,type);
     588
     589        #define PSIMAGE_ROTATE_180_CASE(TYPE) \
     590    case PS_TYPE_##TYPE: { \
     591            for (int row=0;row<numRows;row++) { \
     592                ps##TYPE* outRow = out->data.TYPE[row]; \
     593                ps##TYPE* inRow = in->data.TYPE[lastRow-row]; \
     594                for (int col=0;col<numCols;col++) { \
     595                    outRow[col] = inRow[lastCol - col]; \
     596                } \
     597            } \
     598        } \
     599        break;
     600
     601        switch (type) {
     602            PSIMAGE_ROTATE_180_CASE(U8);
     603            PSIMAGE_ROTATE_180_CASE(U16);
     604            PSIMAGE_ROTATE_180_CASE(U32);
     605            PSIMAGE_ROTATE_180_CASE(U64);
     606            PSIMAGE_ROTATE_180_CASE(S8);
     607            PSIMAGE_ROTATE_180_CASE(S16);
     608            PSIMAGE_ROTATE_180_CASE(S32);
     609            PSIMAGE_ROTATE_180_CASE(S64);
     610            PSIMAGE_ROTATE_180_CASE(F32);
     611            PSIMAGE_ROTATE_180_CASE(F64);
     612            PSIMAGE_ROTATE_180_CASE(C32);
     613            PSIMAGE_ROTATE_180_CASE(C64);
     614        default:
     615            psError(__func__,"Unsupported type (%d)",type);
     616            psFree(out);
     617            return NULL;
     618        }
     619    } else if (fabsf(angle-270.0f) < FLT_EPSILON) {
     620        // perform 1/4 rotate clockwise
     621        int numRows = in->numCols;
     622        int lastRow = numRows - 1;
     623        int numCols = in->numRows;
     624        psElemType type = in->type.type;
     625        out = psImageRecycle(out,numCols,numRows,type);
     626
     627        #define PSIMAGE_ROTATE_RIGHT_90(TYPE) \
     628    case PS_TYPE_##TYPE: { \
     629            ps##TYPE** inData = in->data.TYPE; \
     630            for (int row=0;row<numRows;row++) { \
     631                ps##TYPE* outRow = out->data.TYPE[row]; \
     632                for (int col=0;col<numCols;col++) { \
     633                    outRow[col] = inData[col][lastRow-row]; \
     634                } \
     635            } \
     636        } \
     637        break;
     638
     639        switch (type) {
     640            PSIMAGE_ROTATE_RIGHT_90(U8);
     641            PSIMAGE_ROTATE_RIGHT_90(U16);
     642            PSIMAGE_ROTATE_RIGHT_90(U32);
     643            PSIMAGE_ROTATE_RIGHT_90(U64);
     644            PSIMAGE_ROTATE_RIGHT_90(S8);
     645            PSIMAGE_ROTATE_RIGHT_90(S16);
     646            PSIMAGE_ROTATE_RIGHT_90(S32);
     647            PSIMAGE_ROTATE_RIGHT_90(S64);
     648            PSIMAGE_ROTATE_RIGHT_90(F32);
     649            PSIMAGE_ROTATE_RIGHT_90(F64);
     650            PSIMAGE_ROTATE_RIGHT_90(C32);
     651            PSIMAGE_ROTATE_RIGHT_90(C64);
     652        default:
     653            psError(__func__,"Unsupported type (%d)",type);
     654            psFree(out);
     655            return NULL;
     656        }
     657    } else if (fabsf(angle) < FLT_EPSILON) {
     658        out = psImageCopy(out,in,in->type.type);
     659    } else {
     660        psElemType type = in->type.type;
     661        int numRows = in->numRows;
     662        int numCols = in->numCols;
     663        double centerX = (float)(numCols) / 2.0f;
     664        float centerY = (float)(numRows) / 2.0f;
     665        float t = angle*(3.14159265358f/180.0f);
     666        float cosT = cosf(t);
     667        float sinT = sinf(t);
     668        float cosNegT = cosf(-t);
     669        float sinNegT = sinf(-t);
     670
     671        // calculate the corners of the rotated image so we know the proper output image size.
     672        //    x' = x cos(t) + y sin(t);  i.e, x' = (x-centerX)*cosT + (y-centerY)*sinT;
     673        //    y' = y cos(t) - x sin(t);  i.e. y' = (y-centerY)*cosT - (x-centerX)*sinT;
     674
     675        #define rotateProjectX(x,y) (x-centerX)*cosNegT + (y-centerY)*sinNegT
     676        #define rotateProjectY(x,y) (y-centerY)*cosNegT - (x-centerX)*sinNegT
     677
     678        // bottom-left, i.e., (0,0)
     679        float xbl = rotateProjectX(0,0);
     680        float ybl = rotateProjectY(0,0);
     681        // bottom-right, i.e., (numCols,0)
     682        float xbr = rotateProjectX(numCols,0);
     683        float ybr = rotateProjectY(numCols,0);
     684        // top-left, i.e., (0,numRows)
     685        float xtl = rotateProjectX(0,numRows);
     686        float ytl = rotateProjectY(0,numRows);
     687        // top-right, i.e., (numCols,numRows)
     688        float xtr = rotateProjectX(numCols,numRows);
     689        float ytr = rotateProjectY(numCols,numRows);
     690
     691        float minX = xbl;
     692        minX = (minX > xbr) ? xbr : minX;
     693        minX = (minX > xtl) ? xtl : minX;
     694        minX = (minX > xtr) ? xtr : minX;
     695
     696        float minY = ybl;
     697        minY = (minY > ybr) ? ybr : minY;
     698        minY = (minY > ytl) ? ytl : minY;
     699        minY = (minY > ytr) ? ytr : minY;
     700
     701        float maxX = xbl;
     702        maxX = (maxX < xbr) ? xbr : maxX;
     703        maxX = (maxX < xtl) ? xtl : maxX;
     704        maxX = (maxX < xtr) ? xtr : maxX;
     705
     706        float maxY = ybl;
     707        maxY = (maxY < ybr) ? ybr : maxY;
     708        maxY = (maxY < ytl) ? ytl : maxY;
     709        maxY = (maxY < ytr) ? ytr : maxY;
     710
     711        int intMinY = minY;
     712        int outRows = ceil(maxY-minY)+1;
     713        int outCols = ceil(maxX-minX)+1;
     714
     715        out = psImageRecycle(out,outCols,outRows,type);
     716
     717        /* optimized public domain rotation routine by Karl Lager
     718        float cosT,sinT;
     719        cosT = cos(t);
     720        sinT = sin(t);
     721        for (y = min_y; y <= max_y; y++)
     722         { x' = min_x * cosT + y * sinT + x1';
     723           y' = y * cosT - min_x * sinT + y1';
     724           for (x = min_x; x <= max_x; x++)
     725            { if (x', y') is in the bounds of the bitmap,
     726                 get pixel(x', y') and plot the pixel to
     727                 (x, y) on screen.
     728              x' += cosT;
     729              y' -= sinT;
     730            }
     731         }
     732        */
     733
     734        // precalculate some figures that are used within loop
     735        float minXTimesCosTPlusCenterX = minX*cosT+centerX;
     736        float CenterYMinusminXTimesSinT = centerY-minX*sinT;
     737
     738        #define PSIMAGE_ROTATE_ARBITRARY_LOOP(TYPE,MODE) { \
     739            if (unexposedValue < PS_MIN_##TYPE || unexposedValue > PS_MAX_##TYPE) { \
     740                psError(__func__,"The given unexposedValue (%g) is outside of the " \
     741                        "image type's range (%g->%g).", \
     742                        unexposedValue, (double)PS_MIN_##TYPE,(double)PS_MAX_##TYPE); \
     743                psFree(out); \
     744                out = NULL; \
     745                break; \
     746            } \
     747            float inX; \
     748            float inY; \
     749            ps##TYPE* outRow; \
     750            for (int y = 0; y < outRows; y++) { \
     751                inX = minXTimesCosTPlusCenterX + (y+intMinY) * sinT; \
     752                inY = CenterYMinusminXTimesSinT + (y+intMinY) * cosT; \
     753                outRow = out->data.TYPE[y]; \
     754                for (int x = 0; x < outCols; x++) { \
     755                    outRow[x] = p_psImagePixelInterpolate##MODE##_##TYPE(in,inX,inY,unexposedValue); \
     756                    inX += cosT; \
     757                    inY -= sinT; \
     758                } \
     759            } \
     760        }
     761
     762        #define PSIMAGE_ROTATE_ARBITRARY_CASE(MODE) \
     763    case PS_INTERPOLATE_##MODE: \
     764        switch (type) { \
     765        case PS_TYPE_U8: \
     766            PSIMAGE_ROTATE_ARBITRARY_LOOP(U8,MODE); \
     767            break; \
     768        case PS_TYPE_U16: \
     769            PSIMAGE_ROTATE_ARBITRARY_LOOP(U16,MODE); \
     770            break; \
     771        case PS_TYPE_U32: \
     772            PSIMAGE_ROTATE_ARBITRARY_LOOP(U32,MODE); \
     773            break; \
     774        case PS_TYPE_U64: \
     775            PSIMAGE_ROTATE_ARBITRARY_LOOP(U64,MODE); \
     776            break; \
     777        case PS_TYPE_S8: \
     778            PSIMAGE_ROTATE_ARBITRARY_LOOP(S8,MODE); \
     779            break; \
     780        case PS_TYPE_S16: \
     781            PSIMAGE_ROTATE_ARBITRARY_LOOP(S16,MODE); \
     782            break; \
     783        case PS_TYPE_S32: \
     784            PSIMAGE_ROTATE_ARBITRARY_LOOP(S32,MODE); \
     785            break; \
     786        case PS_TYPE_S64: \
     787            PSIMAGE_ROTATE_ARBITRARY_LOOP(S64,MODE); \
     788            break; \
     789        case PS_TYPE_F32: \
     790            PSIMAGE_ROTATE_ARBITRARY_LOOP(F32,MODE); \
     791            break; \
     792        case PS_TYPE_F64: \
     793            PSIMAGE_ROTATE_ARBITRARY_LOOP(F64,MODE); \
     794            break; \
     795        default: \
     796            psError(__func__,"Image type (%d) not supported",type); \
     797            psFree(out); \
     798            out = NULL; \
     799        } \
     800        break;
     801
     802        switch (mode) {
     803            PSIMAGE_ROTATE_ARBITRARY_CASE(FLAT);
     804            PSIMAGE_ROTATE_ARBITRARY_CASE(BILINEAR);
     805        default:
     806            psError(__func__,"Unsupported interpolation mode (%d)",mode);
     807            psFree(out);
     808            out = NULL;
     809        }
     810    }
     811
     812    return out;
     813}
     814
     815psImage* psImageShift(psImage* out, const psImage* in, float dx, float dy, psF64 unexposedValue, psImageInterpolateMode mode)
     816{
     817    int outRows;
     818    int outCols;
     819    int elementSize;
     820    psElemType type;
     821
     822    if (in == NULL) {
     823        psError(__func__,"Input image can not be NULL.");
     824        return NULL;
     825    }
     826
     827    // create an output image of the same size and type
     828    outRows = in->numRows;
     829    outCols = in->numCols;
     830    type = in->type.type;
     831    elementSize = PSELEMTYPE_SIZEOF(type);
     832    out = psImageRecycle(out,outCols, outRows, type);
     833
     834    #define PSIMAGE_SHIFT_CASE(TYPE) \
     835case PS_TYPE_##TYPE: \
     836    if (unexposedValue < PS_MIN_##TYPE || unexposedValue > PS_MAX_##TYPE) { \
     837        psError(__func__,"The given unexposedValue (%g) is outside of the " \
     838                "image type's range (%g->%g).", \
     839                unexposedValue, (double)PS_MIN_##TYPE,(double)PS_MAX_##TYPE); \
     840        psFree(out); \
     841        out = NULL; \
     842        break; \
     843    } \
     844    for (int row=0;row<outRows;row++) { \
     845        ps##TYPE* outRow = out->data.TYPE[row]; \
     846        float y = dy+(float)row; \
     847        for (int col=0;col<outCols;col++) { \
     848            outRow[col] = psImagePixelInterpolate(in,dx+(float)col,y,unexposedValue,mode); \
     849        } \
     850    } \
     851    break;
     852
     853    switch (in->type.type) {
     854        PSIMAGE_SHIFT_CASE(U8);
     855        PSIMAGE_SHIFT_CASE(U16);
     856        PSIMAGE_SHIFT_CASE(U32);
     857        PSIMAGE_SHIFT_CASE(U64);
     858        PSIMAGE_SHIFT_CASE(S8);
     859        PSIMAGE_SHIFT_CASE(S16);
     860        PSIMAGE_SHIFT_CASE(S32);
     861        PSIMAGE_SHIFT_CASE(S64);
     862        PSIMAGE_SHIFT_CASE(F32);
     863        PSIMAGE_SHIFT_CASE(F64);
     864        PSIMAGE_SHIFT_CASE(C32);
     865        PSIMAGE_SHIFT_CASE(C64);
     866    default:
     867        psError(__func__,"Image type (%d) not supported.",type);
     868        psFree(out);
     869        out = NULL;
     870    }
     871    return out;
     872}
  • trunk/psLib/src/image/psImageManip.h

    r1226 r1250  
    1010 *  @author Ross Harman, MHPCC
    1111 *
    12  *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2004-07-15 19:58:37 $
     12 *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2004-07-21 23:39:10 $
    1414 *
    1515 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1919
    2020#include "psImage.h"
     21#include "psImageStats.h"
    2122
    2223/// @addtogroup Image
     
    104105);
    105106
     107psImage* psImageRotate(
     108    psImage* out,                   ///< an psImage to recycle.  If NULL, a new image is created
     109    const psImage* in,              ///< input image
     110    float angle,
     111    float unexposedValue,
     112    psImageInterpolateMode mode
     113);
     114
     115psImage* psImageShift(
     116    psImage* out,                   ///< an psImage to recycle.  If NULL, a new image is created
     117    const psImage* in,              ///< input image
     118    float dx,
     119    float dy,
     120    float unexposedValue,
     121    psImageInterpolateMode mode
     122);
     123
    106124/** Roll image by an integer number of pixels in either direction.
    107125 *
Note: See TracChangeset for help on using the changeset viewer.