00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #ifdef WIN32
00010 #include <windows.h>
00011 #endif
00012 
00013 #include <stdlib.h>
00014 #include <string.h>
00015 
00016 #include "SDL_rotozoom.h"
00017 
00018 
00019 
00023 typedef struct tColorRGBA {
00024         Uint8 r;
00025         Uint8 g;
00026         Uint8 b;
00027         Uint8 a;
00028 } tColorRGBA;
00029 
00033 typedef struct tColorY {
00034         Uint8 y;
00035 } tColorY;
00036 
00040 #define MAX(a,b)    (((a) > (b)) ? (a) : (b))
00041 
00052 #define GUARD_ROWS (2)
00053 
00057 #define VALUE_LIMIT     0.001
00058 
00062 Uint32 _colorkey(SDL_Surface *src)
00063 {
00064         Uint32 key = 0; 
00065 #if (SDL_MINOR_VERSION == 3)
00066         SDL_GetColorKey(src, &key);
00067 #else
00068         if (src) 
00069         {
00070                 key = src->format->colorkey;
00071         }
00072 #endif
00073         return key;
00074 }
00075 
00076 
00092 int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
00093 {
00094         int x, y, dx, dy, sgap, dgap, ra, ga, ba, aa;
00095         int n_average;
00096         tColorRGBA *sp, *osp, *oosp;
00097         tColorRGBA *dp;
00098 
00099         
00100 
00101 
00102 
00103         
00104         n_average = factorx*factory;
00105 
00106         
00107 
00108 
00109         sp = (tColorRGBA *) src->pixels;
00110         sgap = src->pitch - src->w * 4;
00111 
00112         dp = (tColorRGBA *) dst->pixels;
00113         dgap = dst->pitch - dst->w * 4;
00114 
00115         for (y = 0; y < dst->h; y++) {
00116 
00117                 osp=sp;
00118                 for (x = 0; x < dst->w; x++) {
00119 
00120                         
00121                         oosp=sp;
00122                         ra=ga=ba=aa=0;
00123                         for (dy=0; dy < factory; dy++) {
00124                                 for (dx=0; dx < factorx; dx++) {
00125                                         ra += sp->r;
00126                                         ga += sp->g;
00127                                         ba += sp->b;
00128                                         aa += sp->a;
00129 
00130                                         sp++;
00131                                 } 
00132                                 
00133                                 sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); 
00134                         }
00135                         
00136 
00137                         
00138                         sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx);
00139 
00140                         
00141                         dp->r = ra/n_average;
00142                         dp->g = ga/n_average;
00143                         dp->b = ba/n_average;
00144                         dp->a = aa/n_average;
00145 
00146                         
00147 
00148 
00149                         dp++;
00150                 } 
00151                 
00152 
00153                 
00154                 sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory);
00155 
00156                 
00157 
00158 
00159                 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00160         } 
00161         
00162 
00163         return (0);
00164 }
00165 
00181 int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
00182 {
00183         int x, y, dx, dy, sgap, dgap, a;
00184         int n_average;
00185         Uint8 *sp, *osp, *oosp;
00186         Uint8 *dp;
00187 
00188         
00189 
00190 
00191 
00192         
00193         n_average = factorx*factory;
00194 
00195         
00196 
00197 
00198         sp = (Uint8 *) src->pixels;
00199         sgap = src->pitch - src->w;
00200 
00201         dp = (Uint8 *) dst->pixels;
00202         dgap = dst->pitch - dst->w;
00203 
00204         for (y = 0; y < dst->h; y++) {    
00205 
00206                 osp=sp;
00207                 for (x = 0; x < dst->w; x++) {
00208 
00209                         
00210                         oosp=sp;
00211                         a=0;
00212                         for (dy=0; dy < factory; dy++) {
00213                                 for (dx=0; dx < factorx; dx++) {
00214                                         a += (*sp);
00215                                                    
00216                                         sp++;
00217                                 } 
00218                                          
00219                                 
00220                                 sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx)); 
00221                         } 
00222                         
00223 
00224                         
00225                         sp = (Uint8 *)((Uint8*)oosp + factorx);
00226 
00227                         
00228                         *dp = a/n_average;
00229 
00230                         
00231 
00232 
00233                         dp++;
00234                 } 
00235                 
00236 
00237                 
00238                 sp = (Uint8 *)((Uint8*)osp + src->pitch*factory);
00239 
00240                 
00241 
00242 
00243                 dp = (Uint8 *)((Uint8 *)dp + dgap);
00244         } 
00245         
00246 
00247         return (0);
00248 }
00249 
00265 int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
00266 {
00267         int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, lx, ly;
00268         tColorRGBA *c00, *c01, *c10, *c11, *cswap;
00269         tColorRGBA *sp, *csp, *dp;
00270         int dgap;
00271 
00272         
00273 
00274 
00275         if (smooth) {
00276                 
00277 
00278 
00279 
00280                 sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
00281                 sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
00282         } else {
00283                 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
00284                 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
00285         }
00286 
00287         
00288 
00289 
00290         if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
00291                 return (-1);
00292         }
00293         if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
00294                 free(sax);
00295                 return (-1);
00296         }
00297 
00298         
00299 
00300 
00301         sp = csp = (tColorRGBA *) src->pixels;
00302         dp = (tColorRGBA *) dst->pixels;
00303 
00304         if (flipx) csp += (src->w-1);
00305         if (flipy) csp += ((src->pitch/4)*(src->h-1));
00306 
00307         csx = 0;
00308         csax = sax;
00309         for (x = 0; x <= dst->w; x++) {
00310                 *csax = csx;
00311                 csax++;
00312                 csx &= 0xffff;
00313                 csx += sx;
00314         }
00315         csy = 0;
00316         csay = say;
00317         for (y = 0; y <= dst->h; y++) {
00318                 *csay = csy;
00319                 csay++;
00320                 csy &= 0xffff;
00321                 csy += sy;
00322         }
00323 
00324         dgap = dst->pitch - dst->w * 4;
00325 
00326         
00327 
00328 
00329         if (smooth) {
00330 
00331                 
00332 
00333 
00334 
00335                 
00336 
00337 
00338                 csay = say;
00339                 ly = 0;
00340                 for (y = 0; y < dst->h; y++) {
00341                         
00342 
00343 
00344                         c00 = csp;
00345                         c01 = csp;
00346                         c01++;      
00347                         c10 = csp;
00348                         c10 += src->pitch/4;
00349                         c11 = c10;
00350                         c11++;
00351                         if (flipx) {
00352                                 cswap = c00; c00=c01; c01=cswap;
00353                                 cswap = c10; c10=c11; c11=cswap;
00354                         }
00355                         if (flipy) {
00356                                 cswap = c00; c00=c10; c10=cswap;
00357                                 cswap = c01; c01=c11; c11=cswap;
00358                         }
00359 
00360                         csax = sax;
00361                         lx = 0;
00362                         for (x = 0; x < dst->w; x++) {
00363                                 
00364 
00365 
00366                                 ex = (*csax & 0xffff);
00367                                 ey = (*csay & 0xffff);
00368                                 t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
00369                                 t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
00370                                 dp->r = (((t2 - t1) * ey) >> 16) + t1;
00371                                 t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
00372                                 t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
00373                                 dp->g = (((t2 - t1) * ey) >> 16) + t1;
00374                                 t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
00375                                 t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
00376                                 dp->b = (((t2 - t1) * ey) >> 16) + t1;
00377                                 t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
00378                                 t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
00379                                 dp->a = (((t2 - t1) * ey) >> 16) + t1;
00380 
00381                                 
00382 
00383 
00384                                 csax++;
00385                                 if (*csax > 0)
00386                                 {
00387                                         sstep = (*csax >> 16);
00388                                         lx += sstep;
00389                                         if (flipx) sstep = -sstep;
00390                                         if (lx <= src->w)
00391                                         {
00392                                                 c00 += sstep;
00393                                                 c01 += sstep;
00394                                                 c10 += sstep;
00395                                                 c11 += sstep;
00396                                         }
00397                                 }
00398 
00399                                 
00400 
00401 
00402                                 dp++;
00403                         }
00404 
00405                         
00406 
00407 
00408                         csay++;
00409                         if (*csay > 0)
00410                         {
00411                                 sstep = (*csay >> 16);
00412                                 ly += sstep;                            
00413                                 if (flipy) sstep = -sstep;
00414                                 if (ly < src->h)
00415                                 {
00416                                         csp += (sstep * (src->pitch/4));
00417                                 }
00418                         }
00419 
00420                         
00421 
00422 
00423                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00424                 }
00425         } else {
00426 
00427                 
00428 
00429 
00430                 csay = say;
00431                 for (y = 0; y < dst->h; y++) {
00432                         sp = csp;
00433                         csax = sax;
00434                         for (x = 0; x < dst->w; x++) {
00435                                 
00436 
00437 
00438                                 *dp = *sp;
00439                                 
00440 
00441 
00442                                 csax++;
00443                                 if (*csax > 0)
00444                                 {
00445                                         sstep = (*csax >> 16);
00446                                         if (flipx) sstep = -sstep;
00447                                         sp += sstep;
00448                                 }
00449                                 
00450 
00451 
00452                                 dp++;
00453                         }
00454                         
00455 
00456 
00457                         csay++;
00458                         if (*csay > 0)
00459                         {
00460                                 sstep = (*csay >> 16) * (src->pitch/4);
00461                                 if (flipy) sstep = -sstep;
00462                                 csp += sstep;
00463                         }
00464 
00465                         
00466 
00467 
00468                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00469                 }
00470         }
00471 
00472         
00473 
00474 
00475         free(sax);
00476         free(say);
00477 
00478         return (0);
00479 }
00480 
00496 int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
00497 {
00498         int x, y;
00499         Uint32 *sax, *say, *csax, *csay;
00500         int csx, csy;
00501         Uint8 *sp, *dp, *csp;
00502         int dgap;
00503 
00504         
00505 
00506 
00507         if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
00508                 return (-1);
00509         }
00510         if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
00511                 free(sax);
00512                 return (-1);
00513         }
00514 
00515         
00516 
00517 
00518         sp = csp = (Uint8 *) src->pixels;
00519         dp = (Uint8 *) dst->pixels;
00520         dgap = dst->pitch - dst->w;
00521 
00522         if (flipx) csp += (src->w-1);
00523         if (flipy) csp  = ( (Uint8*)csp + src->pitch*(src->h-1) );
00524 
00525         
00526 
00527 
00528         csx = 0;
00529         csax = sax;
00530         for (x = 0; x < dst->w; x++) {
00531                 csx += src->w;
00532                 *csax = 0;
00533                 while (csx >= dst->w) {
00534                         csx -= dst->w;
00535                         (*csax)++;
00536                 }
00537                 csax++;
00538         }
00539         csy = 0;
00540         csay = say;
00541         for (y = 0; y < dst->h; y++) {
00542                 csy += src->h;
00543                 *csay = 0;
00544                 while (csy >= dst->h) {
00545                         csy -= dst->h;
00546                         (*csay)++;
00547                 }
00548                 csay++;
00549         }
00550 
00551         
00552 
00553 
00554         csay = say;
00555         for (y = 0; y < dst->h; y++) {
00556                 csax = sax;
00557                 sp = csp;
00558                 for (x = 0; x < dst->w; x++) {
00559                         
00560 
00561 
00562                         *dp = *sp;
00563                         
00564 
00565 
00566                         sp += (*csax) * (flipx ? -1 : 1);
00567                         csax++;
00568                         
00569 
00570 
00571                         dp++;
00572                 }
00573                 
00574 
00575 
00576                 csp += ((*csay) * src->pitch) * (flipy ? -1 : 1);
00577                 csay++;
00578 
00579                 
00580 
00581 
00582                 dp += dgap;
00583         }
00584 
00585         
00586 
00587 
00588         free(sax);
00589         free(say);
00590 
00591         return (0);
00592 }
00593 
00613 void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
00614 {
00615         int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
00616         tColorRGBA c00, c01, c10, c11, cswap;
00617         tColorRGBA *pc, *sp;
00618         int gap;
00619 
00620         
00621 
00622 
00623         xd = ((src->w - dst->w) << 15);
00624         yd = ((src->h - dst->h) << 15);
00625         ax = (cx << 16) - (icos * cx);
00626         ay = (cy << 16) - (isin * cx);
00627         sw = src->w - 1;
00628         sh = src->h - 1;
00629         pc = (tColorRGBA*) dst->pixels;
00630         gap = dst->pitch - dst->w * 4;
00631 
00632         
00633 
00634 
00635         if (smooth) {
00636                 for (y = 0; y < dst->h; y++) {
00637                         dy = cy - y;
00638                         sdx = (ax + (isin * dy)) + xd;
00639                         sdy = (ay - (icos * dy)) + yd;
00640                         for (x = 0; x < dst->w; x++) {
00641                                 dx = (sdx >> 16);
00642                                 dy = (sdy >> 16);
00643                                 if (flipx) dx = sw - dx;
00644                                 if (flipy) dy = sh - dy;
00645                                 if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
00646                                         sp = (tColorRGBA *)src->pixels;;
00647                                         sp += ((src->pitch/4) * dy);
00648                                         sp += dx;
00649                                         c00 = *sp;
00650                                         sp += 1;
00651                                         c01 = *sp;
00652                                         sp += (src->pitch/4);
00653                                         c11 = *sp;
00654                                         sp -= 1;
00655                                         c10 = *sp;
00656                                         if (flipx) {
00657                                                 cswap = c00; c00=c01; c01=cswap;
00658                                                 cswap = c10; c10=c11; c11=cswap;
00659                                         }
00660                                         if (flipy) {
00661                                                 cswap = c00; c00=c10; c10=cswap;
00662                                                 cswap = c01; c01=c11; c11=cswap;
00663                                         }
00664                                         
00665 
00666 
00667                                         ex = (sdx & 0xffff);
00668                                         ey = (sdy & 0xffff);
00669                                         t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
00670                                         t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
00671                                         pc->r = (((t2 - t1) * ey) >> 16) + t1;
00672                                         t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
00673                                         t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
00674                                         pc->g = (((t2 - t1) * ey) >> 16) + t1;
00675                                         t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
00676                                         t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
00677                                         pc->b = (((t2 - t1) * ey) >> 16) + t1;
00678                                         t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
00679                                         t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
00680                                         pc->a = (((t2 - t1) * ey) >> 16) + t1;
00681                                 }
00682                                 sdx += icos;
00683                                 sdy += isin;
00684                                 pc++;
00685                         }
00686                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
00687                 }
00688         } else {
00689                 for (y = 0; y < dst->h; y++) {
00690                         dy = cy - y;
00691                         sdx = (ax + (isin * dy)) + xd;
00692                         sdy = (ay - (icos * dy)) + yd;
00693                         for (x = 0; x < dst->w; x++) {
00694                                 dx = (short) (sdx >> 16);
00695                                 dy = (short) (sdy >> 16);
00696                                 if (flipx) dx = (src->w-1)-dx;
00697                                 if (flipy) dy = (src->h-1)-dy;
00698                                 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
00699                                         sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
00700                                         sp += dx;
00701                                         *pc = *sp;
00702                                 }
00703                                 sdx += icos;
00704                                 sdy += isin;
00705                                 pc++;
00706                         }
00707                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
00708                 }
00709         }
00710 }
00711 
00730 void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
00731 {
00732         int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh;
00733         tColorY *pc, *sp;
00734         int gap;
00735 
00736         
00737 
00738 
00739         xd = ((src->w - dst->w) << 15);
00740         yd = ((src->h - dst->h) << 15);
00741         ax = (cx << 16) - (icos * cx);
00742         ay = (cy << 16) - (isin * cx);
00743         sw = src->w - 1;
00744         sh = src->h - 1;
00745         pc = (tColorY*) dst->pixels;
00746         gap = dst->pitch - dst->w;
00747         
00748 
00749       
00750         memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h);
00751         
00752 
00753 
00754         for (y = 0; y < dst->h; y++) {
00755                 dy = cy - y;
00756                 sdx = (ax + (isin * dy)) + xd;
00757                 sdy = (ay - (icos * dy)) + yd;
00758                 for (x = 0; x < dst->w; x++) {
00759                         dx = (short) (sdx >> 16);
00760                         dy = (short) (sdy >> 16);
00761                         if (flipx) dx = (src->w-1)-dx;
00762                         if (flipy) dy = (src->h-1)-dy;
00763                         if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
00764                                 sp = (tColorY *) (src->pixels);
00765                                 sp += (src->pitch * dy + dx);
00766                                 *pc = *sp;
00767                         }
00768                         sdx += icos;
00769                         sdy += isin;
00770                         pc++;
00771                 }
00772                 pc += gap;
00773         }
00774 }
00775 
00789 SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns) 
00790 {
00791         int row, col, newWidth, newHeight;
00792         int bpp, src_ipr, dst_ipr;
00793         SDL_Surface* dst;
00794         Uint32* srcBuf;
00795         Uint32* dstBuf;
00796 
00797         
00798         if (!src || src->format->BitsPerPixel != 32) { return NULL; }
00799 
00800         
00801         while(numClockwiseTurns < 0) { numClockwiseTurns += 4; }
00802         numClockwiseTurns = (numClockwiseTurns % 4);
00803 
00804         
00805         newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w);
00806         newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h);
00807         dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel,
00808                 src->format->Rmask,
00809                 src->format->Gmask, 
00810                 src->format->Bmask, 
00811                 src->format->Amask);
00812         if(!dst) {
00813                 return NULL;
00814         }
00815 
00816         if (SDL_MUSTLOCK(dst)) {
00817                 SDL_LockSurface(dst);
00818         }
00819         if (SDL_MUSTLOCK(dst)) {
00820                 SDL_LockSurface(dst);
00821         }
00822 
00823         
00824         bpp = src->format->BitsPerPixel / 8;
00825         src_ipr = src->pitch / bpp;
00826         dst_ipr = dst->pitch / bpp;
00827 
00828         switch(numClockwiseTurns) {
00829                 case 0: 
00830                         {
00831                                 
00832 
00833 
00834                                 if (src->pitch == dst->pitch) {
00835                                         
00836                                         memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
00837                                 }
00838                                 else
00839                                 {
00840                                         
00841                                         srcBuf = (Uint32*)(src->pixels); 
00842                                         dstBuf = (Uint32*)(dst->pixels);
00843                                         for (row = 0; row < src->h; row++) {
00844                                                 memcpy(dstBuf, srcBuf, dst->w * bpp);
00845                                                 srcBuf += src_ipr;
00846                                                 dstBuf += dst_ipr;
00847                                         } 
00848                                 } 
00849                         }
00850                         break;
00851 
00852                         
00853                 case 1: 
00854                  {
00855                          for (row = 0; row < src->h; ++row) {
00856                                  srcBuf = (Uint32*)(src->pixels) + (row * src_ipr);
00857                                  dstBuf = (Uint32*)(dst->pixels) + (dst->w - row - 1);
00858                                  for (col = 0; col < src->w; ++col) {
00859                                          *dstBuf = *srcBuf;
00860                                          ++srcBuf;
00861                                          dstBuf += dst_ipr;
00862                                  } 
00863                                  
00864                          } 
00865                          
00866                  }
00867                  break;
00868 
00869                 case 2: 
00870                  {
00871                          for (row = 0; row < src->h; ++row) {
00872                                  srcBuf = (Uint32*)(src->pixels) + (row * src_ipr);
00873                                  dstBuf = (Uint32*)(dst->pixels) + ((dst->h - row - 1) * dst_ipr) + (dst->w - 1);
00874                                  for (col = 0; col < src->w; ++col) {
00875                                          *dstBuf = *srcBuf;
00876                                          ++srcBuf;
00877                                          --dstBuf;
00878                                  } 
00879                          } 
00880                  }
00881                  break;
00882 
00883                 case 3:
00884                  {
00885                          for (row = 0; row < src->h; ++row) {
00886                                  srcBuf = (Uint32*)(src->pixels) + (row * src_ipr);
00887                                  dstBuf = (Uint32*)(dst->pixels) + row + ((dst->h - 1) * dst_ipr);
00888                                  for (col = 0; col < src->w; ++col) {
00889                                          *dstBuf = *srcBuf;
00890                                          ++srcBuf;
00891                                          dstBuf -= dst_ipr;
00892                                  } 
00893                          } 
00894                  }
00895                  break;
00896         } 
00897         
00898 
00899         if (SDL_MUSTLOCK(src)) {
00900                 SDL_UnlockSurface(src);
00901         }
00902         if (SDL_MUSTLOCK(dst)) {
00903                 SDL_UnlockSurface(dst);
00904         }
00905 
00906         return dst;
00907 }
00908 
00909 
00924 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, 
00925                                                           int *dstwidth, int *dstheight, 
00926                                                           double *canglezoom, double *sanglezoom)
00927 {
00928         double x, y, cx, cy, sx, sy;
00929         double radangle;
00930         int dstwidthhalf, dstheighthalf;
00931 
00932         
00933 
00934 
00935         radangle = angle * (M_PI / 180.0);
00936         *sanglezoom = sin(radangle);
00937         *canglezoom = cos(radangle);
00938         *sanglezoom *= zoomx;
00939         *canglezoom *= zoomx;
00940         x = (double)(width / 2);
00941         y = (double)(height / 2);
00942         cx = *canglezoom * x;
00943         cy = *canglezoom * y;
00944         sx = *sanglezoom * x;
00945         sy = *sanglezoom * y;
00946 
00947         dstwidthhalf = MAX((int)
00948                 ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
00949         dstheighthalf = MAX((int)
00950                 ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
00951         *dstwidth = 2 * dstwidthhalf;
00952         *dstheight = 2 * dstheighthalf;
00953 }
00954 
00966 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
00967 {
00968         double dummy_sanglezoom, dummy_canglezoom;
00969 
00970         _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
00971 }
00972 
00983 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
00984 {
00985         double dummy_sanglezoom, dummy_canglezoom;
00986 
00987         _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
00988 }
00989 
01005 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
01006 {
01007         return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
01008 }
01009 
01026 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
01027 {
01028         SDL_Surface *rz_src;
01029         SDL_Surface *rz_dst;
01030         double zoominv;
01031         double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
01032         int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
01033         int is32bit;
01034         int i, src_converted;
01035         int flipx,flipy;
01036         Uint8 r,g,b;
01037         Uint32 colorkey = 0;
01038         int colorKeyAvailable = 0;
01039 
01040         
01041 
01042 
01043         if (src == NULL)
01044                 return (NULL);
01045 
01046         if (src->flags & SDL_SRCCOLORKEY)
01047         {
01048                 colorkey = _colorkey(src);
01049                 SDL_GetRGB(colorkey, src->format, &r, &g, &b);
01050                 colorKeyAvailable = 1;
01051         }
01052         
01053 
01054 
01055         is32bit = (src->format->BitsPerPixel == 32);
01056         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01057                 
01058 
01059 
01060                 rz_src = src;
01061                 src_converted = 0;
01062         } else {
01063                 
01064 
01065 
01066                 rz_src =
01067                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 
01068 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01069                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01070 #else
01071                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
01072 #endif
01073                         );
01074                 if(colorKeyAvailable)
01075                         SDL_SetColorKey(src, 0, 0);
01076 
01077                 SDL_BlitSurface(src, NULL, rz_src, NULL);
01078 
01079                 if(colorKeyAvailable)
01080                         SDL_SetColorKey(src, SDL_SRCCOLORKEY, colorkey);
01081                 src_converted = 1;
01082                 is32bit = 1;
01083         }
01084 
01085         
01086 
01087 
01088         flipx = (zoomx<0.0);
01089         if (flipx) zoomx=-zoomx;
01090         flipy = (zoomy<0.0);
01091         if (flipy) zoomy=-zoomy;
01092         if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
01093         if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
01094         zoominv = 65536.0 / (zoomx * zoomx);
01095 
01096         
01097 
01098 
01099         if (fabs(angle) > VALUE_LIMIT) {
01100 
01101                 
01102 
01103 
01104                 
01105 
01106 
01107 
01108                 
01109                 _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
01110 
01111                 
01112 
01113 
01114                 sanglezoominv = sanglezoom;
01115                 canglezoominv = canglezoom;
01116                 sanglezoominv *= zoominv;
01117                 canglezoominv *= zoominv;
01118 
01119                 
01120                 dstwidthhalf = dstwidth / 2;
01121                 dstheighthalf = dstheight / 2;
01122 
01123                 
01124 
01125 
01126                 rz_dst = NULL;
01127                 if (is32bit) {
01128                         
01129 
01130 
01131                         rz_dst =
01132                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01133                                 rz_src->format->Rmask, rz_src->format->Gmask,
01134                                 rz_src->format->Bmask, rz_src->format->Amask);
01135                 } else {
01136                         
01137 
01138 
01139                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01140                 }
01141 
01142                 
01143                 if (rz_dst == NULL)
01144                         return NULL;
01145 
01146                 
01147                 rz_dst->h = dstheight;
01148 
01149                 if (colorKeyAvailable == 1){
01150                         colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
01151 
01152                         SDL_FillRect(rz_dst, NULL, colorkey );
01153                 }
01154 
01155                 
01156 
01157 
01158                 if (SDL_MUSTLOCK(rz_src)) {
01159                         SDL_LockSurface(rz_src);
01160                 }
01161 
01162                 
01163 
01164 
01165                 if (is32bit) {
01166                         
01167 
01168 
01169                         _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
01170                                 (int) (sanglezoominv), (int) (canglezoominv), 
01171                                 flipx, flipy,
01172                                 smooth);
01173                         
01174 
01175 
01176                         SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
01177                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01178                 } else {
01179                         
01180 
01181 
01182                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01183                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01184                         }
01185                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01186                         
01187 
01188 
01189                         transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
01190                                 (int) (sanglezoominv), (int) (canglezoominv),
01191                                 flipx, flipy);
01192                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01193                 }
01194                 
01195 
01196 
01197                 if (SDL_MUSTLOCK(rz_src)) {
01198                         SDL_UnlockSurface(rz_src);
01199                 }
01200 
01201         } else {
01202 
01203                 
01204 
01205 
01206                 
01207 
01208 
01209 
01210                 
01211 
01212 
01213                 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
01214 
01215                 
01216 
01217 
01218                 rz_dst = NULL;
01219                 if (is32bit) {
01220                         
01221 
01222 
01223                         rz_dst =
01224                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01225                                 rz_src->format->Rmask, rz_src->format->Gmask,
01226                                 rz_src->format->Bmask, rz_src->format->Amask);
01227                 } else {
01228                         
01229 
01230 
01231                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01232                 }
01233 
01234                 
01235                 if (rz_dst == NULL)
01236                         return NULL;
01237 
01238                 
01239                 rz_dst->h = dstheight;
01240 
01241                 if (colorKeyAvailable == 1){
01242                         colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
01243 
01244                         SDL_FillRect(rz_dst, NULL, colorkey );
01245                 }
01246 
01247                 
01248 
01249 
01250                 if (SDL_MUSTLOCK(rz_src)) {
01251                         SDL_LockSurface(rz_src);
01252                 }
01253 
01254                 
01255 
01256 
01257                 if (is32bit) {
01258                         
01259 
01260 
01261                         _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
01262 
01263                         
01264 
01265 
01266                         SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
01267                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01268                 } else {
01269                         
01270 
01271 
01272                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01273                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01274                         }
01275                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01276 
01277                         
01278 
01279 
01280                         _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
01281                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01282                 }
01283 
01284                 
01285 
01286 
01287                 if (SDL_MUSTLOCK(rz_src)) {
01288                         SDL_UnlockSurface(rz_src);
01289                 }
01290         }
01291 
01292         
01293 
01294 
01295         if (src_converted) {
01296                 SDL_FreeSurface(rz_src);
01297         }
01298 
01299         
01300 
01301 
01302         return (rz_dst);
01303 }
01304 
01317 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
01318 {
01319         
01320 
01321 
01322         int flipx, flipy;
01323         flipx = (zoomx<0.0);
01324         if (flipx) zoomx = -zoomx;
01325         flipy = (zoomy<0.0);
01326         if (flipy) zoomy = -zoomy;
01327 
01328         
01329 
01330 
01331         if (zoomx < VALUE_LIMIT) {
01332                 zoomx = VALUE_LIMIT;
01333         }
01334         if (zoomy < VALUE_LIMIT) {
01335                 zoomy = VALUE_LIMIT;
01336         }
01337 
01338         
01339 
01340 
01341         *dstwidth = (int) ((double) width * zoomx);
01342         *dstheight = (int) ((double) height * zoomy);
01343         if (*dstwidth < 1) {
01344                 *dstwidth = 1;
01345         }
01346         if (*dstheight < 1) {
01347                 *dstheight = 1;
01348         }
01349 }
01350 
01367 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
01368 {
01369         SDL_Surface *rz_src;
01370         SDL_Surface *rz_dst;
01371         int dstwidth, dstheight;
01372         int is32bit;
01373         int i, src_converted;
01374         int flipx, flipy;
01375 
01376         
01377 
01378 
01379         if (src == NULL)
01380                 return (NULL);
01381 
01382         
01383 
01384 
01385         is32bit = (src->format->BitsPerPixel == 32);
01386         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01387                 
01388 
01389 
01390                 rz_src = src;
01391                 src_converted = 0;
01392         } else {
01393                 
01394 
01395 
01396                 rz_src =
01397                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 
01398 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01399                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01400 #else
01401                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
01402 #endif
01403                         );
01404                 SDL_BlitSurface(src, NULL, rz_src, NULL);
01405                 src_converted = 1;
01406                 is32bit = 1;
01407         }
01408 
01409         flipx = (zoomx<0.0);
01410         if (flipx) zoomx = -zoomx;
01411         flipy = (zoomy<0.0);
01412         if (flipy) zoomy = -zoomy;
01413 
01414         
01415         zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
01416 
01417         
01418 
01419 
01420         rz_dst = NULL;
01421         if (is32bit) {
01422                 
01423 
01424 
01425                 rz_dst =
01426                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01427                         rz_src->format->Rmask, rz_src->format->Gmask,
01428                         rz_src->format->Bmask, rz_src->format->Amask);
01429         } else {
01430                 
01431 
01432 
01433                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01434         }
01435 
01436         
01437         if (rz_dst == NULL)
01438                 return NULL;
01439 
01440         
01441         rz_dst->h = dstheight;
01442 
01443         
01444 
01445 
01446         if (SDL_MUSTLOCK(rz_src)) {
01447                 SDL_LockSurface(rz_src);
01448         }
01449 
01450         
01451 
01452 
01453         if (is32bit) {
01454                 
01455 
01456 
01457                 _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
01458                 
01459 
01460 
01461                 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
01462         } else {
01463                 
01464 
01465 
01466                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01467                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01468                 }
01469                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01470                 
01471 
01472 
01473                 _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
01474                 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01475         }
01476         
01477 
01478 
01479         if (SDL_MUSTLOCK(rz_src)) {
01480                 SDL_UnlockSurface(rz_src);
01481         }
01482 
01483         
01484 
01485 
01486         if (src_converted) {
01487                 SDL_FreeSurface(rz_src);
01488         }
01489 
01490         
01491 
01492 
01493         return (rz_dst);
01494 }
01495 
01512  
01513 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
01514 {
01515         int result;
01516         SDL_Surface *rz_src;
01517         SDL_Surface *rz_dst = NULL;
01518         int dstwidth, dstheight;
01519         int is32bit;
01520         int i, src_converted;
01521         int haveError = 0;
01522 
01523         
01524 
01525 
01526         if (src == NULL) {
01527                 return (NULL);
01528         }
01529 
01530         
01531 
01532 
01533         is32bit = (src->format->BitsPerPixel == 32);
01534         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01535                 
01536 
01537 
01538                 rz_src = src;
01539                 src_converted = 0;
01540         } else {
01541                 
01542 
01543 
01544                 rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 
01545 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01546                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01547 #else
01548                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
01549 #endif
01550                         );
01551                 if (rz_src==NULL) {
01552                         haveError = 1;
01553                         goto exitShrinkSurface;
01554                 }
01555                 
01556                 SDL_BlitSurface(src, NULL, rz_src, NULL);
01557                 src_converted = 1;
01558                 is32bit = 1;
01559         }
01560 
01561         
01562 
01563 
01564         if (SDL_MUSTLOCK(rz_src)) {
01565                 if (SDL_LockSurface(rz_src) < 0) {
01566                         haveError = 1;
01567                         goto exitShrinkSurface;
01568                 }
01569         }
01570 
01571         
01572         dstwidth=rz_src->w/factorx;
01573         while (dstwidth*factorx>rz_src->w) { dstwidth--; }
01574         dstheight=rz_src->h/factory;
01575         while (dstheight*factory>rz_src->h) { dstheight--; }
01576 
01577         
01578 
01579 
01580 
01581         if (is32bit==1) {
01582                 
01583 
01584 
01585                 rz_dst =
01586                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01587                         rz_src->format->Rmask, rz_src->format->Gmask,
01588                         rz_src->format->Bmask, rz_src->format->Amask);
01589         } else {
01590                 
01591 
01592 
01593                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01594         }
01595         
01596         
01597         if (rz_dst == NULL) {
01598                 haveError = 1;
01599                 goto exitShrinkSurface;
01600         }
01601 
01602         
01603         rz_dst->h = dstheight;
01604 
01605         
01606 
01607 
01608         if (is32bit==1) {
01609                 
01610 
01611 
01612                 result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);          
01613                 if ((result!=0) || (rz_dst==NULL)) {
01614                         haveError = 1;
01615                         goto exitShrinkSurface;
01616                 }
01617                 
01618                 
01619 
01620 
01621                 result = SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
01622                 if (result!=0) {
01623                         haveError = 1;
01624                         goto exitShrinkSurface;
01625                 }
01626         } else {
01627                 
01628 
01629 
01630                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01631                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01632                 }
01633                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01634                 
01635 
01636 
01637                 result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
01638                 if (result!=0) {
01639                         haveError = 1;
01640                         goto exitShrinkSurface;
01641                 }
01642                 
01643                 
01644 
01645 
01646                 result = SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01647                 if (result!=0) {
01648                         haveError = 1;
01649                         goto exitShrinkSurface;
01650                 }               
01651         }
01652 
01653 exitShrinkSurface:
01654         if (rz_src!=NULL) {
01655                 
01656 
01657 
01658                 if (SDL_MUSTLOCK(rz_src)) {
01659                         SDL_UnlockSurface(rz_src);
01660                 }
01661 
01662                 
01663 
01664 
01665                 if (src_converted==1) {
01666                         SDL_FreeSurface(rz_src);
01667                 }
01668         }
01669         
01670         
01671         if (haveError==1) {
01672                 if (rz_dst!=NULL) {
01673                         SDL_FreeSurface(rz_dst);
01674                 }
01675                 rz_dst=NULL;
01676         } 
01677         
01678         
01679 
01680 
01681         return (rz_dst);
01682 }