home *** CD-ROM | disk | FTP | other *** search
- /*
- * imrotate.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* IMROTATE: funtion rotates image by given angle using
- * bilinear interpolation (slower method) or nearest pixel
- * (quicker method)
- * usage: imrotate(imgIn, imgOut, angle, x0, y0, quickFlag)
- *
- */
-
- #include <math.h>
- #include <tiffimage.h> /* tiff info on images */
- #include <images.h> /* for sun images */
-
- #ifndef M_PI
- #define M_PI 3.141592654
- #endif
-
- int
- imrotate (imgI, imgO, angle, x0, y0, quickFlag)
- Image *imgI, *imgO; /* I/O image structures */
- double angle; /* angle to be rotated */
- long x0, y0; /* top left of output img in input img */
- short quickFlag; /* bilinear interp if 0; nearest pix if 1 */
- {
- unsigned char **imgIn, /* image array */
- **imgOut; /* output image */
- long widthI, heightI; /* input image size */
- int gray; /* flag = 1 if image is gray; 0 otherwise */
- double cosA, sinA; /* cos and sin of rotation angle */
- long widthIM1, heightIM1; /* width, height minus 1 */
- double startX, startY; /* start of rows/columns in rot. img. */
- double x, y;
- register long intX, intY; /* integer truncation of x,y */
- unsigned char *pImg, *pImgP1; /* pointers to image locations */
- unsigned char *pImgOut; /* pointer to output image */
- register double fractX, fractY; /* roundoff minus truncation of x,y */
- register double fXfY; /* fractX times fractY */
- long temp;
- long iX, iY;
-
- /* input and output images */
- imgIn = imgI->img;
- heightI = ImageGetHeight (imgI);
- widthI = ImageGetWidth (imgI);
- gray = (ImageIsGray (imgI)) ? 1 : 0;
- imgOut = imgO->img; /* ImageGetPtr (imgO); */
-
- /* rotate image */
- angle = angle * M_PI / 180.0;
- cosA = cos (angle);
- sinA = sin (angle);
- startX = -(double) x0 *cosA + (double) y0 *sinA + (double) x0;
- startY = -(double) x0 *sinA - (double) y0 *cosA + (double) y0;
-
-
- widthIM1 = widthI - 1;
- heightIM1 = heightI - 1;
-
- /* rotate image by bilinear interpolation (slower method) */
- if (quickFlag == 0) {
- for (iY = 0, y = startY; iY < heightI; iY++) {
- pImgOut = imgOut[iY];
- for (iX = 0, x = startX; iX < widthI; iX++) {
- intX = (long) x;
- intY = (long) y;
- if ((intX >= 1 && intX < widthIM1)
- && (intY >= 1 && intY < heightIM1)) {
- fractX = x - (double) intX;
- fractY = y - (double) intY;
- pImg = &(imgIn[intY][intX]);
- pImgP1 = &(imgIn[intY + 1][intX]);
- fXfY = fractX * fractY;
- temp = (long) ((1.0 - fractX - fractY + fXfY) * *pImg
- + (fractX - fXfY) * *(pImg + 1)
- + (fractY - fXfY) * *pImgP1
- + fXfY * *(pImgP1 + 1) + 0.5);
- if (!gray) {
- if (temp >= 128)
- temp = 255;
- else
- temp = 0;
- }
- else {
- if (temp > 255)
- temp = 255;
- else if (temp < 0)
- temp = 0;
- }
- }
- else
- temp = 0;
- *pImgOut = (unsigned char) temp;
- pImgOut++;
- x += cosA;
- y += sinA;
- }
- startY += cosA;
- y = startY;
- startX -= sinA;
- }
- }
- /* rotate image by nearest pixel (quicker method) */
- else {
- for (iY = 0, y = startY; iY < heightI; iY++) {
- pImgOut = imgOut[iY];
- for (iX = 0, x = startX; iX < widthI; iX++) {
- intX = (long) x;
- intY = (long) y;
- if ((intX >= 1 && intX < widthIM1)
- && (intY >= 1 && intY < heightIM1)) {
- fractX = x - (double) intX;
- fractY = y - (double) intY;
- pImg = &(imgIn[intY][intX]);
- pImgP1 = &(imgIn[intY + 1][intX]);
- if (fractX < 0.5)
- *pImgOut = (fractY < 0.5) ?
- imgIn[intY][intX] : imgIn[intY + 1][intX];
- else
- *pImgOut = (fractY < 0.5) ?
- imgIn[intY][intX + 1] : imgIn[intY + 1][intX + 1];
- }
- else
- *pImgOut = 0;
- pImgOut++;
- x += cosA;
- y += sinA;
- }
- startY += cosA;
- y = startY;
- startX -= sinA;
- }
- }
-
- return (1);
- }
-