Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

stretch.cpp

Go to the documentation of this file.
00001 /*
00002     parastretch - image stretching functions
00003     Copyright (C) 2000,2001,2002  Alexander Pipelka
00004  
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009  
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014  
00015     You should have received a copy of the GNU Library General Public
00016     License along with this library; if not, write to the Free
00017     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  
00019     Alexander Pipelka
00020     pipelka@teleweb.at
00021  
00022     Last Update:      $Author: mbickel $
00023     Update Date:      $Date: 2007-04-13 16:16:01 $
00024     Source File:      $Source: /home/cvspsrv/cvsroot/games/asc/source/libs/paragui/src/draw/stretch.cpp,v $
00025     CVS/RCS Revision: $Revision: 1.2 $
00026     Status:           $State: Exp $
00027 */
00028 
00029 #include "pgdraw.h"
00030 
00031 #include <cstdio>
00032 #include <cstring>
00033 #include <cstdlib>
00034 #include <cmath>
00035 
00036 #if ! defined( macintosh ) && ! defined( __MWERKS__ )
00037 // malloc.h should not be included on Mac with CodeWarrior (pro 4)
00038 // Masahiro Minami<elsur@aaa.letter.co.jp>
00039 // 01/05/05
00040 //#include <malloc.h>
00041 #endif // not defined macintosh nor __MWERKS__
00042 
00043 #define sign(x) ((x)>0 ? 1:-1)
00044 
00045 /*void SDL_FillRectEx(SDL_Surface *dst, Uint16 x0, Uint16 y0, Uint16 x1, Uint16 y1, Uint32 color) {
00046         SDL_Rect r;
00047         r.x = x0;
00048         r.y = y0;
00049         r.w = abs(x1 - x0) + 1;
00050         r.h = abs(y1 - y0) + 1;
00051  
00052         SDL_FillRect(dst, &r, color);
00053 }*/
00054 
00055 
00056 inline void LockSurface(SDL_Surface* s) {
00057         if ( SDL_MUSTLOCK(s) ) {
00058                 if ( SDL_LockSurface(s) < 0 )
00059                         return ;
00060         }
00061 }
00062 
00063 inline void UnlockSurface(SDL_Surface* s) {
00064         if ( SDL_MUSTLOCK(s) ) {
00065                 SDL_UnlockSurface(s);
00066                 return ;
00067         }
00068 }
00069 
00070 template < class ST, class DT >
00071 inline void StretchTemplateLUT(int x1, int x2, int y1, int y2, int yr, int yw, ST src_pixels, DT dst_pixels, Uint32* lut) {
00072         int dx, dy, e, d, dx2;
00073 
00074         register Uint32 p;
00075 
00076         dx = (x2 - x1);
00077         dy = (y2 - y1);
00078 
00079         dy <<= 1;
00080         e = dy - dx;
00081         dx2 = dx << 1;
00082 
00083         for (d = 0; d < dx; d++) {
00084                 p = lut[*src_pixels];
00085                 *dst_pixels++ = p;
00086 
00087                 while (e >= 0) {
00088                         src_pixels ++;
00089                         e -= dx2;
00090                 }
00091 
00092                 e += dy;
00093         }
00094 }
00095 
00096 template < class ST, class DT >
00097 inline void StretchTemplate(int x1, int x2, int y1, int y2, int yr, int yw, ST src_pixels, DT dst_pixels) {
00098         int dx, dy, e, d, dx2;
00099         /*int cx0 = 0;
00100         int cx1 = 0;
00101         DT dst_cx0 = (dst_pixels += cx0);
00102         DT dst_cx1 = (dst_pixels += cx1);*/
00103 
00104         dx = (x2 - x1);
00105         dy = (y2 - y1);
00106 
00107         dy <<= 1;
00108         e = dy - dx;
00109         dx2 = dx << 1;
00110 
00111         for (d = 0; d < dx; d++) {
00112                 // hmm, ...
00113                 // i know this is a bit tricky (and maybe ugly)
00114                 //if((dst_pixels >= dst_cx0) && (dst_pixels <= dst_cx1)) {
00115                 *dst_pixels++ = *((DT)src_pixels);
00116                 //}
00117                 //else {
00118                 //      dst_pixels++;
00119                 //}
00120 
00121                 while (e >= 0) {
00122                         src_pixels ++;
00123                         e -= dx2;
00124                 }
00125 
00126                 e += dy;
00127         }
00128 }
00129 
00130 template < class ST, class DT >
00131 inline void RectStretchTemplate(SDL_Surface* src_surface, ST src, int xs1, int ys1, int xs2, int ys2, SDL_Surface* dst_surface, DT dst, int xd1, int yd1, int xd2, int yd2, Uint32* lutVOI) {
00132         int dx, dy, e, d, dx2;
00133         int sx, sy;
00134         dx = abs((int)(yd2 - yd1));
00135         dy = abs((int)(ys2 - ys1));
00136         sx = sign(yd2 - yd1);
00137         sy = sign(ys2 - ys1);
00138         e = (dy << 1)-dx;
00139         dx2 = dx << 1;
00140         dy <<= 1;
00141 
00142         Uint16 src_pitch = src_surface->pitch;
00143         Uint16 dst_pitch = dst_surface->pitch;
00144 
00145         int src_bpp = src_surface->format->BytesPerPixel;
00146         int dst_bpp = dst_surface->format->BytesPerPixel;
00147 
00148         SDL_Rect clip;
00149         SDL_GetClipRect(dst_surface, &clip);
00150 
00151         register long src_pixels = ((long)src + ys1 * src_pitch + xs1 * src_bpp);
00152         register long dst_pixels = ((long)dst + yd1 * dst_pitch + xd1 * dst_bpp);
00153         register Uint32* lut = lutVOI;
00154 
00155         if (lut == NULL) {                                      // Stretch without lookup table
00156                 for (d = 0; (d <= dx) && (yd1 < dst_surface->h) && (ys1 < src_surface->h); d++) {
00157 
00158                         if(yd1 < clip.y || yd1 > clip.y+clip.h-1) {
00159                                 continue;
00160                         }
00161 
00162                         StretchTemplate(xd1, xd2, xs1, xs2, ys1, yd1, (ST)src_pixels, (DT)dst_pixels);
00163 
00164                         while (e >= 0) {
00165                                 src_pixels += src_pitch;
00166                                 ys1++;
00167                                 e -= dx2;
00168                         }
00169                         dst_pixels += dst_pitch;
00170                         yd1++;
00171                         e += dy;
00172                 }
00173         } else {                                                                        // Stretch with lookup table
00174                 for (d = 0; (d <= dx) && (yd1 < dst_surface->h) && (ys1 < src_surface->h); d++) {
00175                         StretchTemplateLUT(xd1, xd2, xs1, xs2, ys1, yd1, (ST)src_pixels, (DT)dst_pixels, lut);
00176 
00177                         while (e >= 0) {
00178                                 src_pixels += src_pitch;
00179                                 ys1++;
00180                                 e -= dx2;
00181                         }
00182                         dst_pixels += dst_pitch;
00183                         yd1++;
00184                         e += dy;
00185                 }
00186         }
00187 
00188 }
00189 
00190 inline void StretchTemplate24to32(int x1, int x2, int y1, int y2, int yr, int yw, Uint8* src_pixels, Uint32* dst_pixels, Uint32* lut) {
00191         int dx, dy, e, d, dx2;
00192 
00193         register Uint8 pr;
00194         register Uint8 pg;
00195         register Uint8 pb;
00196         register Uint32 r;
00197 
00198         dx = (x2 - x1);
00199         dy = (y2 - y1);
00200 
00201         dy <<= 1;
00202         e = dy - dx;
00203         dx2 = dx << 1;
00204 
00205         for (d = 0; d < dx; d++) {
00206                 pr = lut[*(src_pixels)];
00207                 pg = lut[*(src_pixels+1)];
00208                 pb = lut[*(src_pixels+2)];
00209 
00210                 r = pr << 16 | pg << 8 | pb;
00211                 *dst_pixels++ = r;
00212 
00213                 while (e >= 0) {
00214                         src_pixels+=3;
00215                         e -= dx2;
00216                 }
00217 
00218                 e += dy;
00219         }
00220 }
00221 
00222 inline void RectStretch24to32(SDL_Surface* src_surface, Uint8* src, int xs1, int ys1, int xs2, int ys2, SDL_Surface* dst_surface, Uint32* dst, int xd1, int yd1, int xd2, int yd2, Uint32* lutVOI) {
00223         int dx, dy, e, d, dx2;
00224         int sx, sy;
00225         dx = abs((int)(yd2 - yd1));
00226         dy = abs((int)(ys2 - ys1));
00227         sx = sign(yd2 - yd1);
00228         sy = sign(ys2 - ys1);
00229         e = (dy << 1)-dx;
00230         dx2 = dx << 1;
00231         dy <<= 1;
00232 
00233         Uint16 src_pitch = src_surface->pitch;
00234         Uint16 dst_pitch = dst_surface->pitch;
00235 
00236         int src_bpp = src_surface->format->BytesPerPixel;
00237         int dst_bpp = dst_surface->format->BytesPerPixel;
00238 
00239         SDL_Rect clip;
00240         SDL_GetClipRect(dst_surface, &clip);
00241 
00242         register long src_pixels = ((long)src + ys1 * src_pitch + xs1 * src_bpp);
00243         register long dst_pixels = ((long)dst + yd1 * dst_pitch + xd1 * dst_bpp);
00244         register Uint32* lut = lutVOI;
00245 
00246         for (d = 0; (d <= dx) && (yd1 < dst_surface->h) && (ys1 < src_surface->h); d++) {
00247                 StretchTemplate24to32(xd1, xd2, xs1, xs2, ys1, yd1, (Uint8*)src_pixels, (Uint32*)dst_pixels, lut);
00248 
00249                 while (e >= 0) {
00250                         src_pixels += src_pitch;
00251                         ys1++;
00252                         e -= dx2;
00253                 }
00254                 dst_pixels += dst_pitch;
00255                 yd1++;
00256                 e += dy;
00257         }
00258 
00259 }
00260 
00261 void PG_Draw::RectStretch(SDL_Surface* src_surface, int xs1, int ys1, int xs2, int ys2, SDL_Surface* dst_surface, int xd1, int yd1, int xd2, int yd2, Uint32* lutVOI) {
00262         int src_bpp = src_surface->format->BytesPerPixel;
00263         int dst_bpp = dst_surface->format->BytesPerPixel;
00264 
00265         switch (dst_bpp) {
00266 
00267                 case 1:
00268                         switch (src_bpp) {
00269 
00270                                 case 1:
00271                                         if(src_surface->format->palette != NULL) {
00272                                                 SDL_SetColors(dst_surface, src_surface->format->palette->colors, 0, 256);
00273                                         }
00274                                         RectStretchTemplate(src_surface, (Uint8*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint8*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00275                                         break;
00276 
00277                                 case 2:
00278                                         RectStretchTemplate(src_surface, (Uint16*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint8*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00279                                         break;
00280                         }
00281                         break;
00282 
00283                 case 2:
00284                         switch (src_bpp) {
00285 
00286                                 case 2:
00287                                         RectStretchTemplate(src_surface, (Uint16*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint16*)dst_surface->pixels, xd1, yd1, xd2, yd2, NULL);
00288                                         break;
00289                         }
00290                         break;
00291 
00292                 case 4:
00293                         switch (src_bpp) {
00294 
00295                                 case 1:
00296                                         RectStretchTemplate(src_surface, (Uint8*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint32*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00297                                         break;
00298 
00299                                 case 3:
00300                                         RectStretch24to32(src_surface, (Uint8*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint32*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00301                                         break;
00302 
00303                                 case 2:
00304                                         RectStretchTemplate(src_surface, (Uint16*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint32*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00305                                         break;
00306 
00307                                 case 4:
00308                                         RectStretchTemplate(src_surface, (Uint32*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint32*)dst_surface->pixels, xd1, yd1, xd2, yd2, NULL);
00309                                         break;
00310 
00311                         }
00312                         break;
00313         }
00314 
00315         // copy the colorkey
00316         //SDL_SetColorKey(dst_surface, SDL_SRCCOLORKEY, src_surface->format->colorkey);
00317 }
00318 
00319 
00320 typedef Uint8 Pixel;
00321 
00322 #define WHITE_PIXEL     (255)
00323 #define BLACK_PIXEL     (0)
00324 
00325 
00326 inline SDL_Surface* new_image(int xsize, int ysize)     /* create a blank image */
00327 {
00328         return SDL_CreateRGBSurface(
00329                    SDL_SWSURFACE,
00330                    xsize,
00331                    ysize,
00332                    8,
00333                    0, 0, 0, 0);
00334 }
00335 
00336 inline void free_image(SDL_Surface* image) {
00337         SDL_FreeSurface(image);
00338 }
00339 
00340 inline void get_row(Pixel* row, SDL_Surface* image, int y) {
00341         memcpy(row, (Uint8*)image->pixels + (y * image->pitch), (sizeof(Pixel) * image->w));
00342 }
00343 
00344 inline void get_column(Pixel* column, SDL_Surface* image, int x) {
00345         register int i, d;
00346         register Pixel *p;
00347         d = image->pitch;
00348 
00349         register Uint8* pixels = (Uint8*)image->pixels + x;
00350 
00351         for (i = image->h, p = pixels; i-- > 0; p += d) {
00352                 *column++ = *p;
00353         }
00354 }
00355 
00356 /*
00357  *      filter function definitions
00358  */
00359 
00360 #define filter_support          (1.0)
00361 
00362 inline double filter(double t) {
00363         /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
00364         if (t < 0.0)
00365                 t = -t;
00366         if (t < 1.0)
00367                 return ((2.0 * t - 3.0) * t * t + 1.0);
00368         return (0.0);
00369 }
00370 
00371 #define box_support             (0.5)
00372 
00373 inline double box_filter(double t) {
00374         if ((t > -0.5) && (t <= 0.5))
00375                 return (1.0);
00376         return (0.0);
00377 }
00378 
00379 #define triangle_support        (1.0)
00380 
00381 inline double triangle_filter(double t) {
00382         if (t < 0.0)
00383                 t = -t;
00384         if (t < 1.0)
00385                 return (1.0 - t);
00386         return (0.0);
00387 }
00388 
00389 #define bell_support            (1.5)
00390 
00391 inline double bell_filter(double t)             /* box (*) box (*) box */
00392 {
00393         if (t < 0)
00394                 t = -t;
00395         if (t < .5)
00396                 return (.75 - (t * t));
00397         if (t < 1.5) {
00398                 t = (t - 1.5);
00399                 return (.5 * (t * t));
00400         }
00401         return (0.0);
00402 }
00403 
00404 #define B_spline_support        (2.0)
00405 
00406 inline double B_spline_filter(double t) /* box (*) box (*) box (*) box */
00407 {
00408         static double tt;
00409 
00410         if (t < 0)
00411                 t = -t;
00412         if (t < 1) {
00413                 tt = t * t;
00414                 return ((.5 * tt * t) - tt + (2.0 / 3.0));
00415         } else if (t < 2) {
00416                 t = 2 - t;
00417                 return ((1.0 / 6.0) * (t * t * t));
00418         }
00419         return (0.0);
00420 }
00421 
00422 inline double sinc(double x) {
00423         x *= M_PI;
00424 
00425         if (x != 0)
00426                 return (sin(x) / x);
00427         return (1.0);
00428 }
00429 
00430 #define Lanczos3_support        (3.0)
00431 
00432 inline double Lanczos3_filter(double t) {
00433         if (t < 0)
00434                 t = -t;
00435         if (t < 3.0)
00436                 return (sinc(t) * sinc(t / 3.0));
00437         return (0.0);
00438 }
00439 
00440 #define Mitchell_support        (2.0)
00441 
00442 #define B       (1.0 / 3.0)
00443 #define C       (1.0 / 3.0)
00444 
00445 inline double Mitchell_filter(double t) {
00446         double tt;
00447 
00448         tt = t * t;
00449         if (t < 0)
00450                 t = -t;
00451         if (t < 1.0) {
00452                 t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt))
00453                      + (( -18.0 + 12.0 * B + 6.0 * C) * tt)
00454                      + (6.0 - 2 * B));
00455                 return (t / 6.0);
00456         } else if (t < 2.0) {
00457                 t = ((( -1.0 * B - 6.0 * C) * (t * tt))
00458                      + ((6.0 * B + 30.0 * C) * tt)
00459                      + (( -12.0 * B - 48.0 * C) * t)
00460                      + (8.0 * B + 24 * C));
00461                 return (t / 6.0);
00462         }
00463         return (0.0);
00464 }
00465 
00466 //      image rescaling routine
00467 
00468 typedef struct {
00469         int     pixel;
00470         double  weight;
00471 }
00472 CONTRIB;
00473 
00474 typedef struct {
00475         int     n;              /* number of contributors */
00476         CONTRIB *p;             /* pointer to list of contributions */
00477 }
00478 CLIST;
00479 
00480 CLIST   *contrib;               /* array of contribution lists */
00481 static double filterLUT[4001];
00482 
00483 void PG_Draw::CreateFilterLUT() {
00484         static bool bCreated = false;
00485         double v;
00486 
00487         if(bCreated) {
00488                 return;
00489         }
00490 
00491         for (int i = -2000; i < 2001; i++) {
00492                 v = (double)i / 1000.0;
00493                 filterLUT[i + 2000] = B_spline_filter(v);
00494         }
00495 
00496         bCreated = true;
00497 }
00498 
00499 typedef double (*filterfunc)(double);
00500 
00501 //#define CLAMP(v,l,h)    ((v)<(l) ? (l) : (v) > (h) ? (h) : v)
00502 #define CLAMP(v,l,h)    ((Uint32)v & 0xFF)
00503 #define FLTIDX(v)               (int)(v*1000 + 2000)
00504 
00505 void zoom(SDL_Surface* dst, SDL_Surface* src, double fwidth) {
00506         SDL_Surface *tmp;                       /* intermediate image */
00507         double xscale, yscale;          /* zoom scale factors */
00508         register int i, j, k;                   /* loop variables */
00509         double n;                               /* pixel number */
00510         double center, left, right;     /* filter calculation variables */
00511         double width, fscale, weight;   /* filter calculation variables */
00512         Pixel *raster;                  /* a row or column of pixels */
00513         register Uint8* tmp_pixels;
00514         int tmp_pitch;
00515         register double tmp_w, tmp_h, src_w;
00516 
00517         if (!src || !dst)
00518                 return;
00519 
00520         if (!src->w || !src->h || !dst->w || !dst->h)
00521                 return;
00522 
00523         LockSurface(src);
00524         LockSurface(dst);
00525 
00526         /* create intermediate image to hold horizontal zoom */
00527         tmp = new_image(dst->w, src->h);
00528         LockSurface(tmp);
00529 
00530         xscale = (double) dst->w / (double) src->w;
00531         yscale = (double) dst->h / (double) src->h;
00532 
00533         /* pre-calculate filter contributions for a row */
00534         contrib = (CLIST *)calloc(dst->w, sizeof(CLIST));
00535         src_w = (double)src->w;
00536         if (xscale < 1.0) {
00537                 width = (double)(fwidth / xscale);
00538                 fscale = (double)(1.0 / xscale);
00539                 tmp_w = (double)dst->w;
00540                 for (i = 0; i < tmp_w; ++i) {
00541                         contrib[i].n = 0;
00542                         contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),
00543                                                          sizeof(CONTRIB));
00544                         center = i / xscale;
00545                         left = ceil(center - width);
00546                         right = floor(center + width);
00547                         for (j = (int)left; j <= (int)right; ++j) {
00548                                 weight = center - j;
00549                                 //weight = B_spline_filter(weight / fscale) / fscale;
00550                                 weight = filterLUT[FLTIDX(weight / fscale)] / fscale;
00551                                 if (j < 0) {
00552                                         n = -j;
00553                                 } else if (j >= src_w) {
00554                                         n = (src_w - j) + src_w - 1;
00555                                 } else {
00556                                         n = j;
00557                                 }
00558                                 k = contrib[i].n++;
00559                                 contrib[i].p[k].pixel = (int)n;
00560                                 contrib[i].p[k].weight = weight;
00561                         }
00562                 }
00563         } else {
00564                 tmp_w = dst->w;
00565                 for (i = 0; i < tmp_w; ++i) {
00566                         contrib[i].n = 0;
00567                         contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
00568                                                          sizeof(CONTRIB));
00569                         center = i / xscale;
00570                         left = ceil(center - fwidth);
00571                         right = floor(center + fwidth);
00572                         for (j = (int)left; j <= (int)right; ++j) {
00573                                 weight = center - j;
00574                                 //weight = B_spline_filter(weight);
00575                                 weight = filterLUT[FLTIDX(weight)];
00576                                 if (j < 0) {
00577                                         n = -j;
00578                                 } else if (j >= src_w) {
00579                                         n = (src_w - j) + src_w - 1;
00580                                 } else {
00581                                         n = j;
00582                                 }
00583                                 k = contrib[i].n++;
00584                                 contrib[i].p[k].pixel = (int)n;
00585                                 contrib[i].p[k].weight = weight;
00586                         }
00587                 }
00588         }
00589 
00590         /* apply filter to zoom horizontally from src to tmp */
00591         tmp_pitch = tmp->pitch;
00592         tmp_pixels = (Uint8*)tmp->pixels;
00593 
00594         raster = (Pixel *)calloc(src->w, sizeof(Pixel));
00595         tmp_h = tmp->h;
00596         tmp_w = tmp->w;
00597 
00598         int offset = (int)(tmp_pitch - tmp_w);
00599 
00600         for (k = 0; k < tmp_h; ++k) {
00601                 //get_row(raster, src, k);
00602                 memcpy(raster, (Uint8*)src->pixels + (k * src->pitch), (sizeof(Pixel) * src->w));
00603                 for (i = 0; i < tmp_w; ++i) {
00604                         weight = 0.0;
00605                         for (j = 0; j < contrib[i].n; ++j) {
00606                                 weight += raster[contrib[i].p[j].pixel]
00607                                           * contrib[i].p[j].weight;
00608                         }
00609                         *((Uint8 *)tmp_pixels++) = (Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL);
00610                 }
00611                 // tmp_pixels -= i;
00612                 tmp_pixels += offset;
00613         }
00614 
00615         free(raster);
00616 
00617         /* free the memory allocated for horizontal filter weights */
00618         for (i = 0; i < tmp_w; ++i) {
00619                 free(contrib[i].p);
00620         }
00621         free(contrib);
00622 
00623         /* pre-calculate filter contributions for a column */
00624         contrib = (CLIST *)calloc(dst->h, sizeof(CLIST));
00625         if (yscale < 1.0) {
00626                 width = fwidth / yscale;
00627                 fscale = 1.0 / yscale;
00628                 tmp_h = dst->h;
00629                 for (i = 0; i < tmp_h; ++i) {
00630                         contrib[i].n = 0;
00631                         contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),
00632                                                          sizeof(CONTRIB));
00633                         center = i / yscale;
00634                         left = ceil(center - width);
00635                         right = floor(center + width);
00636                         for (j = (int)left; j <= (int)right; ++j) {
00637                                 weight = center - j;
00638                                 //weight = B_spline_filter(weight / fscale) / fscale;
00639                                 weight = filterLUT[FLTIDX(weight / fscale)] / fscale;
00640                                 if (j < 0) {
00641                                         n = -j;
00642                                 } else if (j >= tmp->h) {
00643                                         n = (tmp->h - j) + tmp->h - 1;
00644                                 } else {
00645                                         n = j;
00646                                 }
00647                                 k = contrib[i].n++;
00648                                 contrib[i].p[k].pixel = (int)n;
00649                                 contrib[i].p[k].weight = weight;
00650                         }
00651                 }
00652         } else {
00653                 tmp_h = dst->h;
00654                 for (i = 0; i < tmp_h; ++i) {
00655                         contrib[i].n = 0;
00656                         contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
00657                                                          sizeof(CONTRIB));
00658                         center = i / yscale;
00659                         left = ceil(center - fwidth);
00660                         right = floor(center + fwidth);
00661                         for (j = (int)left; j <= (int)right; ++j) {
00662                                 weight = center - j;
00663                                 //weight = B_spline_filter(weight);
00664                                 weight = filterLUT[FLTIDX(weight)];
00665                                 if (j < 0) {
00666                                         n = -j;
00667                                 } else if (j >= tmp->h) {
00668                                         n = (tmp->h - j) + tmp->h - 1;
00669                                 } else {
00670                                         n = j;
00671                                 }
00672                                 k = contrib[i].n++;
00673                                 contrib[i].p[k].pixel = (int)n;
00674                                 contrib[i].p[k].weight = weight;
00675                         }
00676                 }
00677         }
00678 
00679         /* apply filter to zoom vertically from tmp to dst */
00680         tmp_pitch = dst->pitch;
00681         tmp_pixels = (Uint8*)dst->pixels;
00682 
00683         raster = (Pixel *)calloc(tmp->h, sizeof(Pixel));
00684         tmp_w = dst->w;
00685         tmp_h = dst->h;
00686 
00687         offset = 1 - (int)(tmp_w * tmp_pitch);
00688 
00689         for (k = 0; k < tmp_w; ++k) {
00690                 get_column(raster, tmp, k);
00691                 for (i = 0; i < tmp_h; ++i) {
00692                         weight = 0.0;
00693                         for (j = 0; j < contrib[i].n; ++j) {
00694                                 weight += raster[contrib[i].p[j].pixel]
00695                                           * contrib[i].p[j].weight;
00696                         }
00697                         *(((Uint8 *)tmp_pixels) + i*tmp_pitch + k) = (Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL);
00698                 }
00699                 //tmp_pixels += offset;
00700         }
00701 
00702         free(raster);
00703 
00704         /* free the memory allocated for vertical filter weights */
00705         for (i = 0; i < tmp_h; ++i) {
00706                 free(contrib[i].p);
00707         }
00708         free(contrib);
00709 
00710         UnlockSurface(src);
00711         UnlockSurface(dst);
00712         UnlockSurface(tmp);
00713         free_image(tmp);
00714 }
00715 
00716 
00717 void PG_Draw::PG_SmoothFast(SDL_Surface* src, SDL_Surface* dst) {
00718         zoom(dst, src, B_spline_support);
00719 }
00720 
00721 SDL_Surface* PG_CopyRect(SDL_Surface* s, int x, int y, int w, int h) {
00722         SDL_Surface* image = new_image(w, h);
00723 
00724         for (int i = 0; i < h; i++) {
00725                 memcpy(
00726                     (Uint8*)image->pixels + i*image->pitch,
00727                     (Uint8*)s->pixels + (y + i)*s->pitch + x,
00728                     w);
00729         }
00730 
00731         return image;
00732 }
00733 
00734 
00735 #define SCALE 1024
00736 #define HALFSCALE 512
00737 
00738 /*
00739         based on scaling algorithm of "Extended Portable Bitmap Toolkit" (pbmplus10dec91)
00740 */
00741 
00742 void PG_Draw::InterpolatePixel(SDL_Surface* src, SDL_Surface* dest) {
00743 
00744         register Uint16 x;
00745         register Uint16 y;
00746         register const Uint8 *p;
00747         register Uint8 *q;
00748         Uint8 const *sp = NULL;                          // initialization avoids compiler warning
00749         Uint8 const *fp;
00750         Uint8 *sq;
00751 
00752         if (!src || !dest)
00753                 return;
00754 
00755         if (!src->w || !src->h || !dest->w || !dest->h)
00756                 return;
00757 
00758         int Dest_X = dest->w;
00759         int Dest_Y = dest->h;
00760         int Src_X = src->w;
00761         int Src_Y = src->h;
00762 
00763         const unsigned long sxscale = (unsigned long)(((double)Dest_X / (double)Src_X) * SCALE);
00764         const unsigned long syscale = (unsigned long)(((double)Dest_Y / (double)Src_Y) * SCALE);
00765 
00766         Uint8 *xtemp = new Uint8[Src_X];
00767         signed long *xvalue = new signed long[Src_X];
00768 
00769         fp = (Uint8*)src->pixels;
00770         sq = (Uint8*)dest->pixels;
00771         for (x = 0; x < Src_X; x++)
00772                 xvalue[x] = HALFSCALE;
00773 
00774         register unsigned long yfill = SCALE;
00775         register unsigned long yleft = syscale;
00776         register int yneed = 1;
00777         int ysrc = 0;
00778 
00779         for (y = 0; y < Dest_Y; y++) {
00780                 if (Src_Y == Dest_Y) {
00781                         sp = fp;
00782 
00783                         for (x = 0, p = sp, q = xtemp; x < Src_X; x++)
00784                                 *(q++) = *(p++);
00785 
00786                         fp += src->pitch;
00787                 } else {
00788                         while (yleft < yfill) {
00789                                 if (yneed && (ysrc < (int)Src_Y)) {
00790                                         sp = fp;
00791                                         fp += src->pitch;
00792                                         ysrc++;
00793                                 }
00794 
00795                                 for (x = 0, p = sp; x < Src_X; x++)
00796                                         xvalue[x] += yleft * (signed long)(*(p++));
00797 
00798                                 yfill -= yleft;
00799                                 yleft = syscale;
00800                                 yneed = 1;
00801                         }
00802 
00803                         if (yneed && (ysrc < (int)Src_Y)) {
00804                                 sp = fp;
00805                                 fp += src->pitch;
00806                                 ysrc++;
00807                                 yneed = 0;
00808                         }
00809 
00810                         for (x = 0, p = sp, q = xtemp; x < Src_X; x++) {
00811                                 register signed long v = xvalue[x] + yfill * (signed long)(*(p++));
00812                                 v /= SCALE;
00813                                 *(q++) = (unsigned char)v;  //& 0xFF; //(Uint8)((v > 255) ? 255 : v);
00814                                 xvalue[x] = HALFSCALE;
00815                         }
00816                         yleft -= yfill;
00817                         if (yleft == 0) {
00818                                 yleft = syscale;
00819                                 yneed = 1;
00820                         }
00821                         yfill = SCALE;
00822                 }
00823                 if (Src_X == Dest_X) {
00824 
00825                         for (x = 0, p = xtemp, q = sq; x < Dest_X; x++)
00826                                 *(q++) = *(p++);
00827 
00828                         sq += dest->pitch;
00829                 } else {
00830                         register signed long v = HALFSCALE;
00831                         register unsigned long xfill = SCALE;
00832                         register unsigned long xleft;
00833                         register int xneed = 0;
00834                         q = sq;
00835 
00836                         for (x = 0, p = xtemp; x < Src_X; x++, p++) {
00837                                 xleft = sxscale;
00838 
00839                                 while (xleft >= xfill) {
00840                                         if (xneed) {
00841                                                 q++;
00842                                                 v = HALFSCALE;
00843                                         }
00844                                         v += xfill * (signed long)(*p);
00845                                         v /= SCALE;
00846                                         *q = (unsigned char)v;  // & 0xFF; //(Uint8)((v > 255) ? 255 : v);
00847                                         xleft -= xfill;
00848                                         xfill = SCALE;
00849                                         xneed = 1;
00850                                 }
00851                                 if (xleft > 0) {
00852                                         if (xneed) {
00853                                                 q++;
00854                                                 v = HALFSCALE;
00855                                                 xneed = 0;
00856                                         }
00857                                         v += xleft * (signed long)(*p);
00858                                         xfill -= xleft;
00859                                 }
00860                         }
00861 
00862                         if (xfill > 0)
00863                                 v += xfill * (signed long)(*(--p));
00864 
00865                         if (!xneed) {
00866                                 v /= SCALE;
00867                                 *q = (unsigned char)v;  // & 0xFF; //(Uint8)((v > 255) ? 255 : v);
00868                         }
00869 
00870                         sq += dest->pitch;
00871                 }
00872         }
00873 
00874         delete[] xtemp;
00875         delete[] xvalue;
00876 }

Generated on Tue Jun 24 01:27:52 2008 for Advanced Strategic Command by  doxygen 1.4.2