psycho-skin-resize.C

00001 /*!@file AppPsycho/psycho-skin-indexing.C Psychophysics support for psycho-skin-indexing.C */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/psycho-skin-resize.C $
00035 // $Id: psycho-skin-resize.C 10794 2009-02-08 06:21:09Z itti $
00036 //
00037 
00038 /*
00039  *                Filtered filter_Image Rescaling
00040  *
00041  *                  by Dale Schumacher
00042  *
00043  */
00044 
00045 /*
00046         Additional changes by Ray Gardener, Daylon Graphics Ltd.
00047         December 4, 1999
00048 
00049         Extreme modification to this to make it usable with SDL_Surfaces -Dave Olsen 1/2006
00050         and compatible with c++ compilers.... namely VC++2005 Express edition.
00051     It's a major hack-job. If anyone cleans this up, please let me know!
00052     I'm sure it can be made more efficient. (It's lots faster in release than in debug)
00053 
00054         Summary:
00055 
00056                 - Horizontal filter contributions are calculated on the fly,
00057                   as each column is mapped from src to dst image. This lets
00058                   us omit having to allocate a temporary full horizontal stretch
00059                   of the src image.
00060 
00061                 - If none of the src pixels within a sampling region differ,
00062                   then the output pixel is forced to equal (any of) the source pixel.
00063                   This ensures that filters do not corrupt areas of constant color.
00064 
00065                 - Filter weight contribution results, after summing, are
00066                   rounded to the nearest pixel color value instead of
00067                   being casted to Pixel (usually an int or char). Otherwise,
00068                   artifacting occurs.
00069 
00070                 - All memory allocations checked for failure; zoom() returns
00071                   error code. filter_new_image() returns NULL if unable to allocate
00072                   pixel storage, even if filter_Image struct can be allocated.
00073                   Some assertions added.
00074 */
00075 
00076 
00077 // "Public Domain 1991 by Dale Schumacher. Mods by Ray Gardener";
00078 // further mods by ME! (David Olsen)
00079 // and even more by Kevin Baragona, to make it valid C
00080 // and a few more to make it valid C89, and return NULL when needed (David Olsen)
00081 
00082 
00083 //It would be fantastic if someone would eventually modify these routines to make use
00084 //of native SDL image and pixel formats during the resize process... but, whatever.
00085 
00086 //Modified by Nader Noori, nnoori@usc.edu . The modification is in a way that the source image will not be discarded
00087 
00088 #include <stdlib.h>
00089 #include <math.h>
00090 #include <SDL/SDL.h>
00091 
00092 /* clamp the input to the specified range */
00093 #define CLAMP(v,l,h)    ((v)<(l) ? (l) : (v) > (h) ? (h) : v)
00094 #ifndef M_PI
00095 #define M_PI    3.14159265359
00096 #endif
00097 
00098 typedef        Uint8 Pixel;
00099 typedef struct
00100 {
00101         int        xsize;                /* horizontal size of the image in Pixels */
00102         int        ysize;                /* vertical size of the image in Pixels */
00103         Pixel *        data;        /* pointer to first scanline of image */
00104         int        span;                /* byte offset between two scanlines */
00105 } filter_Image;
00106 typedef struct
00107 {
00108         int        pixel;
00109         double        weight;
00110 } CONTRIB;
00111 typedef struct
00112 {
00113         int        n;                /* number of contributors */
00114         CONTRIB        *p;                /* pointer to list of contributions */
00115 } CLIST;
00116 
00117 SDL_Surface* SDL_ResizeFactor(SDL_Surface *image, float scalefactor,    int filter);
00118 SDL_Surface* SDL_ResizeXY(SDL_Surface *image, int new_w, int new_h, int filter);
00119 
00120 static SDL_Surface *filter_resizexy(SDL_Surface* source,int new_w, int new_h, int filter);
00121 
00122 static Uint32 filter_GetPixel(SDL_Surface *surface, int x, int y)
00123 {
00124     int bpp = surface->format->BytesPerPixel;
00125     /* Here p is the address to the pixel we want to retrieve */
00126     Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
00127 
00128     switch(bpp)
00129     {
00130         case 1: return *p;
00131         case 2: return *(Uint16 *)p;
00132         case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
00133                     return p[0] << 16 | p[1] << 8 | p[2];
00134                 else
00135                     return p[0] | p[1] << 8 | p[2] << 16;
00136         case 4: return *(Uint32 *)p;
00137         default: return 0;       /* shouldn't happen, but avoids warnings */
00138     }
00139 }
00140 
00141 static void filter_PutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
00142 {
00143     int bpp = surface->format->BytesPerPixel;
00144     /* Here p is the address to the pixel we want to set */
00145     Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
00146 
00147     switch(bpp)
00148     {
00149     case 1: *p = pixel;
00150             break;
00151     case 2: *(Uint16 *)p = pixel;
00152             break;
00153     case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
00154             {
00155                 p[0] = (pixel >> 16) & 0xff;
00156                 p[1] = (pixel >> 8) & 0xff;
00157                 p[2] = pixel & 0xff;
00158             }
00159             else
00160             {
00161                 p[0] = pixel & 0xff;
00162                 p[1] = (pixel >> 8) & 0xff;
00163                 p[2] = (pixel >> 16) & 0xff;
00164             }
00165             break;
00166     case 4: *(Uint32 *)p = pixel;
00167             break;
00168     }
00169 }
00170 
00171 #ifdef __cplusplus
00172 SDL_Surface* SDL_Resize(SDL_Surface *image, float scalefactor, int filter)
00173 {
00174     return SDL_ResizeFactor(image, scalefactor, filter);
00175 }
00176 #endif
00177 SDL_Surface* SDL_ResizeFactor(SDL_Surface *image, float scalefactor, int filter)
00178 {
00179     int neww, newh;
00180     SDL_Surface * r;
00181     if (!image) return NULL; //invalid image passed in.
00182     if (scalefactor > 100.0f) scalefactor = 100.0f; //let's be reasonable...
00183     neww = (int)((float)image->w*scalefactor);
00184     newh = (int)((float)image->h*scalefactor);
00185     if (neww<1) neww = 1;
00186     if (newh<1) newh = 1;
00187     r = SDL_ResizeXY(image, neww, newh, filter);
00188     return r;
00189 }
00190 
00191 #ifdef __cplusplus
00192 SDL_Surface* SDL_Resize(SDL_Surface *image, int new_w, int new_h, int filter)
00193 {
00194     return SDL_ResizeXY(image, new_w, new_h, filter);
00195 }
00196 #endif
00197 SDL_Surface* SDL_ResizeXY(SDL_Surface *image, int new_w, int new_h, int filter)
00198 {
00199     SDL_Surface *dest = NULL;
00200     Uint8 alpha, r, g, b;
00201     char usealpha;
00202     int cx;
00203     if (!image) return NULL; //invalid image passed in
00204 
00205     if ((new_w != image->w) || (new_h != image->h))
00206         dest = filter_resizexy(image, new_w, new_h, filter);
00207         else
00208     {
00209         SDL_FreeSurface(dest);
00210         dest = image;
00211     }
00212 
00213     //check for alpha content of the image... like for buttons...
00214 
00215     if (SDL_MUSTLOCK(dest)) SDL_LockSurface(dest);
00216     alpha = 0; r = 0; g = 0; b = 0;
00217     usealpha = 0;
00218     cx = 0;
00219     for (; cx < dest->w; cx++)
00220     { //check the whole image for any occurance of alpha
00221         int cy = 0;
00222         for (; cy < dest->h; cy++)
00223         {
00224             SDL_GetRGBA(filter_GetPixel(dest, cx, cy), dest->format, &r, &g, &b, &alpha);
00225             if (alpha != SDL_ALPHA_OPAQUE) {usealpha = 1; cx=dest->w; break;}
00226         }
00227     }
00228     if (SDL_MUSTLOCK(dest)) SDL_UnlockSurface(dest);
00229 
00230     if (!usealpha) // no alpha component
00231     {
00232         image = SDL_DisplayFormat(dest);
00233         SDL_SetAlpha(image, SDL_RLEACCEL, 0);
00234     }
00235     else // it does have alpha
00236     {
00237         image = SDL_DisplayFormatAlpha(dest);
00238         SDL_SetAlpha(image, SDL_RLEACCEL | SDL_SRCALPHA, 0);
00239     }
00240     SDL_FreeSurface(dest);
00241     return image;
00242 }
00243 
00244 static Pixel filter_get_pixel2(SDL_Surface *image, int x, int y, int which)
00245 {
00246     static Uint8 r=0, g=0, b=0, a=0;
00247     static int xx=-1, yy=-1;
00248     Pixel p = 0;
00249 
00250     if((x < 0) || (x >= image->w) || (y < 0) || (y >= image->h))
00251         return(0);
00252 
00253     if ((xx!=x) || (yy!=y))
00254     {
00255         Uint32 fullpixel;
00256         xx = x; yy = y; //this way it only calls the Getpixel,RGBA once per pixel...
00257         fullpixel = filter_GetPixel(image,x,y);
00258         SDL_GetRGBA(fullpixel,image->format,&r,&g,&b,&a);
00259     }
00260 
00261     switch (which)
00262     {
00263         case 0 : p = r; break;
00264         case 1 : p = g; break;
00265         case 2 : p = b; break;
00266         case 3 : p = a; break;
00267         default: p = r; break; //not really needed...
00268     }
00269     return(p);
00270 }
00271 
00272 static char filter_put_pixel2(SDL_Surface *image, int x, int y, Uint8 c[4])
00273 {
00274     if((x < 0) || (x >= image->w) || (y < 0) || (y >= image->h))
00275         return 0;
00276     filter_PutPixel(image,x,y,SDL_MapRGBA(image->format,c[0],c[1],c[2],c[3]));
00277     return 1;
00278 }
00279 
00280 static double filter_hermite_interp(double t)
00281 {
00282         /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
00283         if(t < 0.0) t = -t;
00284         if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0);
00285         return(0.0);
00286 }
00287 
00288 static double filter_box_interp(double t)
00289 {
00290         if((t > -0.5) && (t <= 0.5)) return(1.0);
00291         return(0.0);
00292 }
00293 
00294 static double filter_triangle_interp(double t)
00295 {
00296         if(t < 0.0) t = -t;
00297         if(t < 1.0) return(1.0 - t);
00298         return(0.0);
00299 }
00300 
00301 static double filter_bell_interp(double t)                /* box (*) box (*) box */
00302 {
00303         if(t < 0) t = -t;
00304         if(t < .5) return(.75 - (t * t));
00305         if(t < 1.5) {
00306                 t = (t - 1.5);
00307                 return(.5 * (t * t));
00308         }
00309         return(0.0);
00310 }
00311 
00312 static double filter_B_spline_interp(double t)        /* box (*) box (*) box (*) box */
00313 {
00314         double tt;
00315 
00316         if(t < 0) t = -t;
00317         if(t < 1) {
00318                 tt = t * t;
00319                 return((.5 * tt * t) - tt + (2.0 / 3.0));
00320         } else if(t < 2) {
00321                 t = 2 - t;
00322                 return((1.0 / 6.0) * (t * t * t));
00323         }
00324         return(0.0);
00325 }
00326 
00327 static double filter_sinc(double x)
00328 {
00329         x *= M_PI;
00330         if(x != 0) return(sin(x) / x);
00331         return(1.0);
00332 }
00333 
00334 static double filter_Lanczos3_interp(double t)
00335 {
00336         if(t < 0) t = -t;
00337         if(t < 3.0) return(filter_sinc(t) * filter_sinc(t/3.0));
00338         return(0.0);
00339 }
00340 
00341 static double filter_Mitchell_interp(double t)
00342 {
00343         static double B = (1.0 / 3.0);
00344         static double C = (1.0 / 3.0);
00345         double tt;
00346 
00347         tt = t * t;
00348         if(t < 0) t = -t;
00349         if(t < 1.0) {
00350                 t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt))
00351                    + ((-18.0 + 12.0 * B + 6.0 * C) * tt)
00352                    + (6.0 - 2 * B));
00353                 return(t / 6.0);
00354         } else if(t < 2.0) {
00355                 t = (((-1.0 * B - 6.0 * C) * (t * tt))
00356                    + ((6.0 * B + 30.0 * C) * tt)
00357                    + ((-12.0 * B - 48.0 * C) * t)
00358                    + (8.0 * B + 24 * C));
00359                 return(t / 6.0);
00360         }
00361         return(0.0);
00362 }
00363 
00364 static int filter_roundcloser(double d)
00365 {
00366         /* Untested potential one-liner, but smacks of call overhead */
00367         /* return fabs(ceil(d)-d) <= 0.5 ? ceil(d) : floor(d); */
00368 
00369         /* Untested potential optimized ceil() usage */
00370 /*        double cd = ceil(d);
00371         int ncd = (int)cd;
00372         if(fabs(cd - d) > 0.5)
00373                 ncd--;
00374         return ncd;
00375 */
00376 
00377         /* Version that uses no function calls at all. */
00378         int n = (int) d;
00379         double diff = d - (double)n;
00380         if(diff < 0)
00381                 diff = -diff;
00382         if(diff >= 0.5)
00383         {
00384                 if(d < 0)
00385                         n--;
00386                 else
00387                         n++;
00388         }
00389         return n;
00390 } /* filter_roundcloser */
00391 
00392 static int filter_calc_x_contrib(CLIST *contribX, double xscale, double fwidth,
00393                                         int dstwidth, int srcwidth, double (*filterf)(double), int i)
00394 {
00395         double width;
00396         double fscale;
00397         double center, left, right;
00398         double weight;
00399         int j, k, n;
00400 
00401         if(xscale < 1.0)
00402         {
00403                 /* Shrinking image */
00404                 width = fwidth / xscale;
00405                 fscale = 1.0 / xscale;
00406 
00407                 contribX->n = 0;
00408                 contribX->p = (CONTRIB *)calloc((int) (width * 2 + 1),
00409                                 sizeof(CONTRIB));
00410                 if(contribX->p == NULL)
00411                         return -1;
00412 
00413                 center = (double) i / xscale;
00414                 left = ceil(center - width);
00415                 right = floor(center + width);
00416                 for(j = (int)left; j <= right; ++j)
00417                 {
00418                         weight = center - (double) j;
00419                         weight = ((*filterf)(weight / fscale)) / fscale;
00420                         if(j < 0)
00421                                 n = -j;
00422                         else if(j >= srcwidth)
00423                                 n = (srcwidth - j) + srcwidth - 1;
00424                         else
00425                                 n = j;
00426 
00427                         k = contribX->n++;
00428                         contribX->p[k].pixel = n;
00429                         contribX->p[k].weight = weight;
00430                 }
00431 
00432         }
00433         else
00434         {
00435                 /* Expanding image */
00436                 contribX->n = 0;
00437                 contribX->p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
00438                                 sizeof(CONTRIB));
00439                 if(contribX->p == NULL)
00440                         return -1;
00441                 center = (double) i / xscale;
00442                 left = ceil(center - fwidth);
00443                 right = floor(center + fwidth);
00444 
00445                 for(j = (int)left; j <= right; ++j)
00446                 {
00447                         weight = center - (double) j;
00448                         weight = (*filterf)(weight);
00449                         if(j < 0) {
00450                                 n = -j;
00451                         } else if(j >= srcwidth) {
00452                                 n = (srcwidth - j) + srcwidth - 1;
00453                         } else {
00454                                 n = j;
00455                         }
00456                         k = contribX->n++;
00457                         contribX->p[k].pixel = n;
00458                         contribX->p[k].weight = weight;
00459                 }
00460         }
00461         return 0;
00462 } /* filter_calc_x_contrib */
00463 
00464 static int filter_zoom2(SDL_Surface *dst, SDL_Surface *src, double (*filterf)(double), double fwidth)
00465 {
00466         Pixel* tmp;
00467         double xscale, yscale;                /* zoom scale factors */
00468         int xx;
00469         int i, j, k;                        /* loop variables */
00470         int n;                                /* pixel number */
00471         double center, left, right;        /* filter calculation variables */
00472         double width, fscale, weight;        /* filter calculation variables */
00473         Uint8 weightedcolor[4]; //reconstruct the pixel out of these!
00474         Pixel pel, pel2;
00475         int bPelDelta;
00476         CLIST        *contribY;                /* array of contribution lists */
00477         CLIST        contribX;
00478         int                nRet = -1;
00479 
00480         /* create intermediate column to hold horizontal dst column zoom */
00481         tmp = (Pixel*)malloc(src->h * sizeof(Pixel) * 4);
00482         if(tmp == NULL)
00483                 return 0;
00484 
00485         xscale = (double) dst->w / (double) src->w;
00486 
00487         /* Build y weights */
00488         /* pre-calculate filter contributions for a column */
00489         contribY = (CLIST *)calloc(dst->h, sizeof(CLIST));
00490         if(contribY == NULL)
00491         {
00492                 free(tmp);
00493                 return -1;
00494         }
00495 
00496         yscale = (double) dst->h / (double) src->h;
00497 
00498         if(yscale < 1.0)
00499         {
00500                 width = fwidth / yscale;
00501                 fscale = 1.0 / yscale;
00502                 for(i = 0; i < dst->h; ++i)
00503                 {
00504                         contribY[i].n = 0;
00505                         contribY[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),
00506                                         sizeof(CONTRIB));
00507                         if(contribY[i].p == NULL)
00508                         {
00509                                 free(tmp);
00510                                 free(contribY);
00511                                 return -1;
00512                         }
00513                         center = (double) i / yscale;
00514                         left = ceil(center - width);
00515                         right = floor(center + width);
00516                         for(j = (int)left; j <= right; ++j) {
00517                                 weight = center - (double) j;
00518                                 weight = (*filterf)(weight / fscale) / fscale;
00519                                 if(j < 0) {
00520                                         n = -j;
00521                                 } else if(j >= src->h) {
00522                                         n = (src->h - j) + src->h - 1;
00523                                 } else {
00524                                         n = j;
00525                                 }
00526                                 k = contribY[i].n++;
00527                                 contribY[i].p[k].pixel = n;
00528                                 contribY[i].p[k].weight = weight;
00529                         }
00530                 }
00531         } else {
00532                 for(i = 0; i < dst->h; ++i) {
00533                         contribY[i].n = 0;
00534                         contribY[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
00535                                         sizeof(CONTRIB));
00536                         if(contribY[i].p == NULL)
00537                         {
00538                                 free(tmp);
00539                                 free(contribY);
00540                                 return -1;
00541                         }
00542                         center = (double) i / yscale;
00543                         left = ceil(center - fwidth);
00544                         right = floor(center + fwidth);
00545                         for(j = (int)left; j <= right; ++j) {
00546                                 weight = center - (double) j;
00547                                 weight = (*filterf)(weight);
00548                                 if(j < 0) {
00549                                         n = -j;
00550                                 } else if(j >= src->h) {
00551                                         n = (src->h - j) + src->h - 1;
00552                                 } else {
00553                                         n = j;
00554                                 }
00555                                 k = contribY[i].n++;
00556                                 contribY[i].p[k].pixel = n;
00557                                 contribY[i].p[k].weight = weight;
00558                         }
00559                 }
00560         }
00561 
00562 
00563 
00564         for(xx = 0; xx < dst->w; xx++)
00565         {
00566                 if(0 != filter_calc_x_contrib(&contribX, xscale, fwidth,
00567                                                                 dst->w, src->w, filterf, xx))
00568                 {
00569                         goto __zoom_cleanup;
00570                 }
00571                 /* Apply horz filter to make dst column in tmp. */
00572                 for(k = 0; k < src->h; ++k)
00573                 {
00574                   //mine!!!!
00575                   int w=0;
00576                   for (; w<4; w++) {
00577                         weight = 0.0;
00578                         bPelDelta = 0;
00579                         pel = filter_get_pixel2(src, contribX.p[0].pixel, k, w);
00580                         for(j = 0; j < contribX.n; ++j)
00581                         {
00582                                 pel2 = filter_get_pixel2(src, contribX.p[j].pixel, k, w);
00583                                 if(pel2 != pel)
00584                                         bPelDelta = 1;
00585                                 weight += pel2 * contribX.p[j].weight;
00586                         }
00587                         weight = bPelDelta ? filter_roundcloser(weight) : pel;
00588 
00589                         tmp[k+w*src->h] = (Pixel)CLAMP(weight, 0, 255); // keep it Uint8
00590                   } //cycle through each color...
00591                 } /* next row in temp column */
00592 
00593                 free(contribX.p);
00594 
00595 
00596                 /* The temp column has been built. Now stretch it
00597                  vertically into dst column. */
00598                 for(i = 0; i < dst->h; ++i)
00599                 {
00600                   int w=0;
00601                   for (; w<4; w++) {
00602                         weight = 0.0;
00603                         bPelDelta = 0;
00604                         pel = tmp[contribY[i].p[0].pixel+w*src->h];
00605 
00606                         for(j = 0; j < contribY[i].n; ++j)
00607                         {
00608                                 pel2 = tmp[contribY[i].p[j].pixel+w*src->h];
00609                                 if(pel2 != pel)
00610                                         bPelDelta = 1;
00611                                 weight += pel2 * contribY[i].p[j].weight;
00612                         }
00613                         weight = bPelDelta ? filter_roundcloser(weight) : pel;
00614                         weightedcolor[w] = (Uint8)CLAMP(weight, 0, 255); //get all 4 "colors" this way
00615               }
00616                   filter_put_pixel2(dst, xx, i, weightedcolor ); //keep it Uint8
00617                 } /* next dst row */
00618 
00619         } /* next dst column */
00620         nRet = 0; /* success */
00621 
00622 __zoom_cleanup:
00623         free(tmp);
00624 
00625         /* free the memory allocated for vertical filter weights */
00626         for(i = 0; i < dst->h; ++i)
00627                 free(contribY[i].p);
00628         free(contribY);
00629 
00630         return nRet;
00631 } /* zoom */
00632 
00633 static SDL_Surface *filter_resizexy(SDL_Surface* source,int new_w, int new_h, int filter)
00634 {
00635     //f and s need to be complementary... one as filter, one as support.
00636         double (*f)(double) ; //function pointer
00637         double s; //support
00638     SDL_Surface *temp, *dest;
00639 
00640         const double box_support = 0.5,
00641                         triangle_support = 1.0,
00642                         bell_support     = 1.5,
00643                         B_spline_support = 2.0,
00644                         hermite_support  = 1.0,
00645                         Mitchell_support = 2.0,
00646             Lanczos3_support = 3.0;
00647 
00648         switch (filter)
00649     {
00650         case 1 : f=filter_box_interp;       s=box_support;      break;
00651         case 2 : f=filter_triangle_interp;  s=triangle_support; break;
00652         case 3 : f=filter_bell_interp;      s=bell_support;     break;
00653                 case 4 : f=filter_hermite_interp;        s=hermite_support;        break;
00654                 case 5 : f=filter_B_spline_interp;        s=B_spline_support;        break;
00655                 case 6 : f=filter_Mitchell_interp;        s=Mitchell_support;        break;
00656         case 7 : f=filter_Lanczos3_interp;        s=Lanczos3_support;        break;
00657                 default: f=filter_Lanczos3_interp;        s=Lanczos3_support;        break;
00658         }
00659 
00660     //Make new surface and send it in to the real filter
00661         temp = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA,
00662                                 new_w, new_h, 32,0,0,0,0) ,
00663         dest = SDL_DisplayFormatAlpha(temp);
00664 
00665         SDL_FreeSurface(temp);
00666 
00667         if (SDL_MUSTLOCK(source)) SDL_LockSurface(source);
00668         if (SDL_MUSTLOCK(dest))   SDL_LockSurface(dest);
00669 
00670         filter_zoom2(dest, source, f, s );
00671 
00672         if (SDL_MUSTLOCK(dest))   SDL_UnlockSurface(dest);
00673         if (SDL_MUSTLOCK(source)) SDL_UnlockSurface(source);
00674 
00675         //SDL_FreeSurface(source);
00676         //should be all cleaned up!
00677         *source=*dest ;
00678 
00679         dest = NULL;
00680         SDL_FreeSurface(dest);
00681         return source;
00682 }
00683 
Generated on Sun May 8 08:04:13 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3