InterpolatingImage::InterpolatingImage(const ImageFeature& image, uint splinedegree) : sourceImage_(image), splinedegree_(splinedegree) { #ifdef HAVE_INTERPOL_LIBRARY coeff_=new float*[image.zsize()]; for(uint i=0; i<image.zsize(); ++i) { coeff_[i]=new float[image.xsize()*image.ysize()]; for(uint x=0; x<image.xsize(); ++x) { for(uint y=0; y<image.ysize(); ++y) { coeff_[i][y*image.xsize()+x]=float(image(x,y,i)); } } SamplesToCoefficients(coeff_[i],image.xsize(),image.ysize(),splinedegree); } #endif }
/* Actually no need to modify this function, since I will only use the float * type here, so the roundoff I added will never take effect. * What I need to modify is the MRIchangeType function! */ MRI *MRIlinearTransformInterpBSpline(MRI *mri_src, MRI *mri_dst, MATRIX *mA, int splinedegree) { int y1, y2, y3, width, height, depth ; VECTOR *v_X, *v_Y ; /* original and transformed coordinate systems */ MATRIX *mAinv ; /* inverse of mA */ double val, x1, x2, x3 ; MRI *mri_Bcoeff; mAinv = MatrixInverse(mA, NULL) ; /* will sample from dst back to src */ if (!mAinv) ErrorReturn(NULL, (ERROR_BADPARM, "MRIlinearTransformBSpline: xform is singular")) ; if (!mri_dst) mri_dst = MRIclone(mri_src, NULL) ; else MRIclear(mri_dst) ; /* set all values to zero */ if (mri_src->type != MRI_FLOAT) mri_Bcoeff = MRIchangeType(mri_src, MRI_FLOAT, 0, 1.0, 1); else mri_Bcoeff = MRIcopy(mri_src, NULL); /* convert between a representation based on image samples */ /* and a representation based on image B-spline coefficients */ if (SamplesToCoefficients(mri_Bcoeff, splinedegree)) { ErrorReturn(NULL, (ERROR_BADPARM, "Change of basis failed\n")); } printf("Direct B-spline Transform Finished. \n"); width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ; v_X = VectorAlloc(4, MATRIX_REAL) ; /* input (src) coordinates */ v_Y = VectorAlloc(4, MATRIX_REAL) ; /* transformed (dst) coordinates */ v_Y->rptr[4][1] = 1.0f ; for (y3 = 0 ; y3 < mri_dst->depth ; y3++) { V3_Z(v_Y) = y3 ; for (y2 = 0 ; y2 < mri_dst->height ; y2++) { V3_Y(v_Y) = y2 ; for (y1 = 0 ; y1 < mri_dst->width ; y1++) { V3_X(v_Y) = y1 ; MatrixMultiply(mAinv, v_Y, v_X) ; x1 = V3_X(v_X) ; x2 = V3_Y(v_X) ; x3 = V3_Z(v_X) ; if (x1 <= -0.5 || x1 >= (width - 0.5) || x2 <= -0.5 || x2 >= (height - 0.5) || x3 <= -0.5 || x3 >= (depth-0.5)) val = 0.0; else val = InterpolatedValue(mri_Bcoeff, x1, x2, x3, splinedegree); switch (mri_dst->type) { case MRI_UCHAR: if (val <-0.5) val = -0.5; if (val > 254.5) val = 254.5; MRIvox(mri_dst,y1,y2,y3) = (BUFTYPE)nint(val+0.5) ; break ; case MRI_SHORT: MRISvox(mri_dst,y1,y2,y3) = (short)nint(val+0.5) ; break ; case MRI_FLOAT: MRIFvox(mri_dst,y1,y2,y3) = (float)(val) ; break ; case MRI_INT: MRIIvox(mri_dst,y1,y2,y3) = nint(val+0.5) ; break ; default: ErrorReturn(NULL, (ERROR_UNSUPPORTED, "MRIlinearTransformBSpline: unsupported dst type %d", mri_dst->type)) ; break ; } } } } MatrixFree(&v_X) ; MatrixFree(&mAinv) ; MatrixFree(&v_Y) ; MRIfree(&mri_Bcoeff); return(mri_dst) ; }
/** Image translation and rotation using B-Splines. @param dib Input 8-bit greyscale image @param angle Output image rotation in degree @param x_shift Output image horizontal shift @param y_shift Output image vertical shift @param x_origin Output origin of the x-axis @param y_origin Output origin of the y-axis @param spline_degree Output degree of the B-spline model @param use_mask Whether or not to mask the image @return Returns the translated & rotated dib if successful, returns NULL otherwise */ static FIBITMAP * Rotate8Bit(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, long spline_degree, BOOL use_mask) { double *ImageRasterArray; double p; double a11, a12, a21, a22; double x0, y0, x1, y1; long x, y; long spline; bool bResult; int bpp = FreeImage_GetBPP(dib); if(bpp != 8) { return NULL; } int width = FreeImage_GetWidth(dib); int height = FreeImage_GetHeight(dib); switch(spline_degree) { case ROTATE_QUADRATIC: spline = 2L; // Use splines of degree 2 (quadratic interpolation) break; case ROTATE_CUBIC: spline = 3L; // Use splines of degree 3 (cubic interpolation) break; case ROTATE_QUARTIC: spline = 4L; // Use splines of degree 4 (quartic interpolation) break; case ROTATE_QUINTIC: spline = 5L; // Use splines of degree 5 (quintic interpolation) break; default: spline = 3L; } // allocate output image FIBITMAP *dst = FreeImage_Allocate(width, height, bpp); if(!dst) return NULL; // buid a grey scale palette RGBQUAD *pal = FreeImage_GetPalette(dst); for(int i = 0; i < 256; i++) { pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)i; } // allocate a temporary array ImageRasterArray = (double*)malloc(width * height * sizeof(double)); if(!ImageRasterArray) { FreeImage_Unload(dst); return NULL; } // copy data samples for(y = 0; y < height; y++) { double *pImage = &ImageRasterArray[y*width]; BYTE *src_bits = FreeImage_GetScanLine(dib, height-1-y); for(x = 0; x < width; x++) { pImage[x] = (double)src_bits[x]; } } // convert between a representation based on image samples // and a representation based on image B-spline coefficients bResult = SamplesToCoefficients(ImageRasterArray, width, height, spline); if(!bResult) { FreeImage_Unload(dst); free(ImageRasterArray); return NULL; } // prepare the geometry angle *= PI / 180.0; a11 = cos(angle); a12 = -sin(angle); a21 = sin(angle); a22 = cos(angle); x0 = a11 * (x_shift + x_origin) + a12 * (y_shift + y_origin); y0 = a21 * (x_shift + x_origin) + a22 * (y_shift + y_origin); x_shift = x_origin - x0; y_shift = y_origin - y0; // visit all pixels of the output image and assign their value for(y = 0; y < height; y++) { BYTE *dst_bits = FreeImage_GetScanLine(dst, height-1-y); x0 = a12 * (double)y + x_shift; y0 = a22 * (double)y + y_shift; for(x = 0; x < width; x++) { x1 = x0 + a11 * (double)x; y1 = y0 + a21 * (double)x; if(use_mask) { if((x1 <= -0.5) || (((double)width - 0.5) <= x1) || (y1 <= -0.5) || (((double)height - 0.5) <= y1)) { p = 0; } else { p = (double)InterpolatedValue(ImageRasterArray, width, height, x1, y1, spline); } } else { p = (double)InterpolatedValue(ImageRasterArray, width, height, x1, y1, spline); } // clamp and convert to BYTE dst_bits[x] = (BYTE)MIN(MAX((int)0, (int)(p + 0.5)), (int)255); } } // free working array and return free(ImageRasterArray); return dst; }
/*--------------------------------------------------------------------------*/ extern int main ( int argc, const char *argv[] ) { /* begin main */ float *ImageRasterArray, *OutputImage; float *p; double a11, a12, a21, a22; double x0, y0, x1, y1; double xOrigin, yOrigin; double Angle, xShift, yShift; long Width, Height; long SplineDegree; long x, y; int Masking; int Error; /* access data samples */ Error = ReadByteImageRawData(&ImageRasterArray, &Width, &Height); if (Error) { printf("Failure to import image data\n"); return(1); } /* ask for transformation parameters */ RigidBody(&Angle, &xShift, &yShift, &xOrigin, &yOrigin, &SplineDegree, &Masking); /* allocate output image */ OutputImage = (float *)malloc((size_t)(Width * Height * (long)sizeof(float))); if (OutputImage == (float *)NULL) { free(ImageRasterArray); printf("Allocation of output image failed\n"); return(1); } /* convert between a representation based on image samples */ /* and a representation based on image B-spline coefficients */ Error = SamplesToCoefficients(ImageRasterArray, Width, Height, SplineDegree); if (Error) { free(OutputImage); free(ImageRasterArray); printf("Change of basis failed\n"); return(1); } /* prepare the geometry */ Angle *= PI / 180.0; a11 = cos(Angle); a12 = -sin(Angle); a21 = sin(Angle); a22 = cos(Angle); x0 = a11 * (xShift + xOrigin) + a12 * (yShift + yOrigin); y0 = a21 * (xShift + xOrigin) + a22 * (yShift + yOrigin); xShift = xOrigin - x0; yShift = yOrigin - y0; /* visit all pixels of the output image and assign their value */ p = OutputImage; for (y = 0L; y < Height; y++) { x0 = a12 * (double)y + xShift; y0 = a22 * (double)y + yShift; for (x = 0L; x < Width; x++) { x1 = x0 + a11 * (double)x; y1 = y0 + a21 * (double)x; if (Masking) { if ((x1 <= -0.5) || (((double)Width - 0.5) <= x1) || (y1 <= -0.5) || (((double)Height - 0.5) <= y1)) { *p++ = 0.0F; } else { *p++ = (float)InterpolatedValue(ImageRasterArray, Width, Height, x1, y1, SplineDegree); } } else { *p++ = (float)InterpolatedValue(ImageRasterArray, Width, Height, x1, y1, SplineDegree); } } } /* save output */ Error = WriteByteImageRawData(OutputImage, Width, Height); if (Error) { free(OutputImage); free(ImageRasterArray); printf("Failure to export image data\n"); return(1); } free(OutputImage); free(ImageRasterArray); printf("Done\n"); return(0); } /* end main */