SDL2_gfx  1.0.0
GraphicsprimitivesandsurfacefunctionsforSDL2
I:/Sources/sdl2gfx/SDL2_rotozoom.c
Go to the documentation of this file.
00001 /*  
00002 
00003 SDL2_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
00004 
00005 Copyright (C) 2012  Andreas Schiffler
00006 
00007 This software is provided 'as-is', without any express or implied
00008 warranty. In no event will the authors be held liable for any damages
00009 arising from the use of this software.
00010 
00011 Permission is granted to anyone to use this software for any purpose,
00012 including commercial applications, and to alter it and redistribute it
00013 freely, subject to the following restrictions:
00014 
00015 1. The origin of this software must not be misrepresented; you must not
00016 claim that you wrote the original software. If you use this software
00017 in a product, an acknowledgment in the product documentation would be
00018 appreciated but is not required.
00019 
00020 2. Altered source versions must be plainly marked as such, and must not be
00021 misrepresented as being the original software.
00022 
00023 3. This notice may not be removed or altered from any source
00024 distribution.
00025 
00026 Andreas Schiffler -- aschiffler at ferzkopp dot net
00027 
00028 */
00029 
00030 #ifdef WIN32
00031 #include <windows.h>
00032 #endif
00033 
00034 #include <stdlib.h>
00035 #include <string.h>
00036 
00037 #include "SDL2_rotozoom.h"
00038 
00039 /* ---- Internally used structures */
00040 
00044 typedef struct tColorRGBA {
00045         Uint8 r;
00046         Uint8 g;
00047         Uint8 b;
00048         Uint8 a;
00049 } tColorRGBA;
00050 
00054 typedef struct tColorY {
00055         Uint8 y;
00056 } tColorY;
00057 
00061 #define MAX(a,b)    (((a) > (b)) ? (a) : (b))
00062 
00073 #define GUARD_ROWS (2)
00074 
00078 #define VALUE_LIMIT     0.001
00079 
00083 Uint32 _colorkey(SDL_Surface *src)
00084 {
00085         Uint32 key = 0; 
00086         SDL_GetColorKey(src, &key);
00087         return key;
00088 }
00089 
00090 
00106 int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
00107 {
00108         int x, y, dx, dy, dgap, ra, ga, ba, aa;
00109         int n_average;
00110         tColorRGBA *sp, *osp, *oosp;
00111         tColorRGBA *dp;
00112 
00113         /*
00114         * Averaging integer shrink
00115         */
00116 
00117         /* Precalculate division factor */
00118         n_average = factorx*factory;
00119 
00120         /*
00121         * Scan destination
00122         */
00123         sp = (tColorRGBA *) src->pixels;
00124         
00125         dp = (tColorRGBA *) dst->pixels;
00126         dgap = dst->pitch - dst->w * 4;
00127 
00128         for (y = 0; y < dst->h; y++) {
00129 
00130                 osp=sp;
00131                 for (x = 0; x < dst->w; x++) {
00132 
00133                         /* Trace out source box and accumulate */
00134                         oosp=sp;
00135                         ra=ga=ba=aa=0;
00136                         for (dy=0; dy < factory; dy++) {
00137                                 for (dx=0; dx < factorx; dx++) {
00138                                         ra += sp->r;
00139                                         ga += sp->g;
00140                                         ba += sp->b;
00141                                         aa += sp->a;
00142 
00143                                         sp++;
00144                                 } 
00145                                 /* src dx loop */
00146                                 sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y
00147                         }
00148                         /* src dy loop */
00149 
00150                         /* next box-x */
00151                         sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx);
00152 
00153                         /* Store result in destination */
00154                         dp->r = ra/n_average;
00155                         dp->g = ga/n_average;
00156                         dp->b = ba/n_average;
00157                         dp->a = aa/n_average;
00158 
00159                         /*
00160                         * Advance destination pointer 
00161                         */
00162                         dp++;
00163                 } 
00164                 /* dst x loop */
00165 
00166                 /* next box-y */
00167                 sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory);
00168 
00169                 /*
00170                 * Advance destination pointers 
00171                 */
00172                 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00173         } 
00174         /* dst y loop */
00175 
00176         return (0);
00177 }
00178 
00194 int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
00195 {
00196         int x, y, dx, dy, dgap, a;
00197         int n_average;
00198         Uint8 *sp, *osp, *oosp;
00199         Uint8 *dp;
00200 
00201         /*
00202         * Averaging integer shrink
00203         */
00204 
00205         /* Precalculate division factor */
00206         n_average = factorx*factory;
00207 
00208         /*
00209         * Scan destination
00210         */
00211         sp = (Uint8 *) src->pixels;
00212 
00213         dp = (Uint8 *) dst->pixels;
00214         dgap = dst->pitch - dst->w;
00215 
00216         for (y = 0; y < dst->h; y++) {    
00217 
00218                 osp=sp;
00219                 for (x = 0; x < dst->w; x++) {
00220 
00221                         /* Trace out source box and accumulate */
00222                         oosp=sp;
00223                         a=0;
00224                         for (dy=0; dy < factory; dy++) {
00225                                 for (dx=0; dx < factorx; dx++) {
00226                                         a += (*sp);
00227                                         /* next x */           
00228                                         sp++;
00229                                 } 
00230                                 /* end src dx loop */         
00231                                 /* next y */
00232                                 sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx)); 
00233                         } 
00234                         /* end src dy loop */
00235 
00236                         /* next box-x */
00237                         sp = (Uint8 *)((Uint8*)oosp + factorx);
00238 
00239                         /* Store result in destination */
00240                         *dp = a/n_average;
00241 
00242                         /*
00243                         * Advance destination pointer 
00244                         */
00245                         dp++;
00246                 } 
00247                 /* end dst x loop */
00248 
00249                 /* next box-y */
00250                 sp = (Uint8 *)((Uint8*)osp + src->pitch*factory);
00251 
00252                 /*
00253                 * Advance destination pointers 
00254                 */
00255                 dp = (Uint8 *)((Uint8 *)dp + dgap);
00256         } 
00257         /* end dst y loop */
00258 
00259         return (0);
00260 }
00261 
00277 int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
00278 {
00279         int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy;
00280         tColorRGBA *c00, *c01, *c10, *c11;
00281         tColorRGBA *sp, *csp, *dp;
00282         int spixelgap, spixelw, spixelh, dgap, t1, t2;
00283 
00284         /*
00285         * Allocate memory for row/column increments 
00286         */
00287         if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
00288                 return (-1);
00289         }
00290         if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
00291                 free(sax);
00292                 return (-1);
00293         }
00294 
00295         /*
00296         * Precalculate row increments 
00297         */
00298         spixelw = (src->w - 1);
00299         spixelh = (src->h - 1);
00300         if (smooth) {
00301                 sx = (int) (65536.0 * (float) spixelw / (float) (dst->w - 1));
00302                 sy = (int) (65536.0 * (float) spixelh / (float) (dst->h - 1));
00303         } else {
00304                 sx = (int) (65536.0 * (float) (src->w) / (float) (dst->w));
00305                 sy = (int) (65536.0 * (float) (src->h) / (float) (dst->h));
00306         }
00307 
00308         /* Maximum scaled source size */
00309         ssx = (src->w << 16) - 1;
00310         ssy = (src->h << 16) - 1;
00311 
00312         /* Precalculate horizontal row increments */
00313         csx = 0;
00314         csax = sax;
00315         for (x = 0; x <= dst->w; x++) {
00316                 *csax = csx;
00317                 csax++;
00318                 csx += sx;
00319 
00320                 /* Guard from overflows */
00321                 if (csx > ssx) { 
00322                         csx = ssx; 
00323                 }
00324         }
00325 
00326         /* Precalculate vertical row increments */
00327         csy = 0;
00328         csay = say;
00329         for (y = 0; y <= dst->h; y++) {
00330                 *csay = csy;
00331                 csay++;
00332                 csy += sy;
00333 
00334                 /* Guard from overflows */
00335                 if (csy > ssy) {
00336                         csy = ssy;
00337                 }
00338         }
00339 
00340         sp = (tColorRGBA *) src->pixels;
00341         dp = (tColorRGBA *) dst->pixels;
00342         dgap = dst->pitch - dst->w * 4;
00343         spixelgap = src->pitch/4;
00344 
00345         if (flipx) sp += spixelw;
00346         if (flipy) sp += (spixelgap * spixelh);
00347 
00348         /*
00349         * Switch between interpolating and non-interpolating code 
00350         */
00351         if (smooth) {
00352 
00353                 /*
00354                 * Interpolating Zoom 
00355                 */
00356                 csay = say;
00357                 for (y = 0; y < dst->h; y++) {
00358                         csp = sp;
00359                         csax = sax;
00360                         for (x = 0; x < dst->w; x++) {
00361                                 /*
00362                                 * Setup color source pointers 
00363                                 */
00364                                 ex = (*csax & 0xffff);
00365                                 ey = (*csay & 0xffff);
00366                                 cx = (*csax >> 16);
00367                                 cy = (*csay >> 16);
00368                                 sstepx = cx < spixelw;
00369                                 sstepy = cy < spixelh;
00370                                 c00 = sp;
00371                                 c01 = sp;
00372                                 c10 = sp;
00373                                 if (sstepy) {
00374                                         if (flipy) {
00375                                                 c10 -= spixelgap;
00376                                         } else {
00377                                                 c10 += spixelgap;
00378                                         }
00379                                 }
00380                                 c11 = c10;
00381                                 if (sstepx) {
00382                                         if (flipx) {
00383                                                 c01--;
00384                                                 c11--;
00385                                         } else {
00386                                                 c01++;
00387                                                 c11++;
00388                                         }
00389                                 }
00390 
00391                                 /*
00392                                 * Draw and interpolate colors 
00393                                 */
00394                                 t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
00395                                 t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
00396                                 dp->r = (((t2 - t1) * ey) >> 16) + t1;
00397                                 t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
00398                                 t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
00399                                 dp->g = (((t2 - t1) * ey) >> 16) + t1;
00400                                 t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
00401                                 t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
00402                                 dp->b = (((t2 - t1) * ey) >> 16) + t1;
00403                                 t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
00404                                 t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
00405                                 dp->a = (((t2 - t1) * ey) >> 16) + t1;                          
00406                                 /*
00407                                 * Advance source pointer x
00408                                 */
00409                                 salast = csax;
00410                                 csax++;                         
00411                                 sstep = (*csax >> 16) - (*salast >> 16);
00412                                 if (flipx) {
00413                                         sp -= sstep;
00414                                 } else {
00415                                         sp += sstep;
00416                                 }
00417 
00418                                 /*
00419                                 * Advance destination pointer x
00420                                 */
00421                                 dp++;
00422                         }
00423                         /*
00424                         * Advance source pointer y
00425                         */
00426                         salast = csay;
00427                         csay++;
00428                         sstep = (*csay >> 16) - (*salast >> 16);
00429                         sstep *= spixelgap;
00430                         if (flipy) { 
00431                                 sp = csp - sstep;
00432                         } else {
00433                                 sp = csp + sstep;
00434                         }
00435 
00436                         /*
00437                         * Advance destination pointer y
00438                         */
00439                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00440                 }
00441         } else {
00442                 /*
00443                 * Non-Interpolating Zoom 
00444                 */              
00445                 csay = say;
00446                 for (y = 0; y < dst->h; y++) {
00447                         csp = sp;
00448                         csax = sax;
00449                         for (x = 0; x < dst->w; x++) {
00450                                 /*
00451                                 * Draw 
00452                                 */
00453                                 *dp = *sp;
00454 
00455                                 /*
00456                                 * Advance source pointer x
00457                                 */
00458                                 salast = csax;
00459                                 csax++;                         
00460                                 sstep = (*csax >> 16) - (*salast >> 16);
00461                                 if (flipx) sstep = -sstep;
00462                                 sp += sstep;
00463 
00464                                 /*
00465                                 * Advance destination pointer x
00466                                 */
00467                                 dp++;
00468                         }
00469                         /*
00470                         * Advance source pointer y
00471                         */
00472                         salast = csay;
00473                         csay++;
00474                         sstep = (*csay >> 16) - (*salast >> 16);
00475                         sstep *= spixelgap;
00476                         if (flipy) sstep = -sstep;                      
00477                         sp = csp + sstep;
00478 
00479                         /*
00480                         * Advance destination pointer y
00481                         */
00482                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00483                 }
00484         }
00485 
00486         /*
00487         * Remove temp arrays 
00488         */
00489         free(sax);
00490         free(say);
00491 
00492         return (0);
00493 }
00494 
00510 int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
00511 {
00512         int x, y;
00513         Uint32 *sax, *say, *csax, *csay;
00514         int csx, csy;
00515         Uint8 *sp, *dp, *csp;
00516         int dgap;
00517 
00518         /*
00519         * Allocate memory for row increments 
00520         */
00521         if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
00522                 return (-1);
00523         }
00524         if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
00525                 free(sax);
00526                 return (-1);
00527         }
00528 
00529         /*
00530         * Pointer setup 
00531         */
00532         sp = csp = (Uint8 *) src->pixels;
00533         dp = (Uint8 *) dst->pixels;
00534         dgap = dst->pitch - dst->w;
00535 
00536         if (flipx) csp += (src->w-1);
00537         if (flipy) csp  = ( (Uint8*)csp + src->pitch*(src->h-1) );
00538 
00539         /*
00540         * Precalculate row increments 
00541         */
00542         csx = 0;
00543         csax = sax;
00544         for (x = 0; x < dst->w; x++) {
00545                 csx += src->w;
00546                 *csax = 0;
00547                 while (csx >= dst->w) {
00548                         csx -= dst->w;
00549                         (*csax)++;
00550                 }
00551                 (*csax) = (*csax) * (flipx ? -1 : 1);
00552                 csax++;
00553         }
00554         csy = 0;
00555         csay = say;
00556         for (y = 0; y < dst->h; y++) {
00557                 csy += src->h;
00558                 *csay = 0;
00559                 while (csy >= dst->h) {
00560                         csy -= dst->h;
00561                         (*csay)++;
00562                 }
00563                 (*csay) = (*csay) * (flipy ? -1 : 1);
00564                 csay++;
00565         }
00566 
00567         /*
00568         * Draw 
00569         */
00570         csay = say;
00571         for (y = 0; y < dst->h; y++) {
00572                 csax = sax;
00573                 sp = csp;
00574                 for (x = 0; x < dst->w; x++) {
00575                         /*
00576                         * Draw 
00577                         */
00578                         *dp = *sp;
00579                         /*
00580                         * Advance source pointers 
00581                         */
00582                         sp += (*csax);
00583                         csax++;
00584                         /*
00585                         * Advance destination pointer 
00586                         */
00587                         dp++;
00588                 }
00589                 /*
00590                 * Advance source pointer (for row) 
00591                 */
00592                 csp += ((*csay) * src->pitch);
00593                 csay++;
00594 
00595                 /*
00596                 * Advance destination pointers 
00597                 */
00598                 dp += dgap;
00599         }
00600 
00601         /*
00602         * Remove temp arrays 
00603         */
00604         free(sax);
00605         free(say);
00606 
00607         return (0);
00608 }
00609 
00629 void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
00630 {
00631         int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
00632         tColorRGBA c00, c01, c10, c11, cswap;
00633         tColorRGBA *pc, *sp;
00634         int gap;
00635 
00636         /*
00637         * Variable setup 
00638         */
00639         xd = ((src->w - dst->w) << 15);
00640         yd = ((src->h - dst->h) << 15);
00641         ax = (cx << 16) - (icos * cx);
00642         ay = (cy << 16) - (isin * cx);
00643         sw = src->w - 1;
00644         sh = src->h - 1;
00645         pc = (tColorRGBA*) dst->pixels;
00646         gap = dst->pitch - dst->w * 4;
00647 
00648         /*
00649         * Switch between interpolating and non-interpolating code 
00650         */
00651         if (smooth) {
00652                 for (y = 0; y < dst->h; y++) {
00653                         dy = cy - y;
00654                         sdx = (ax + (isin * dy)) + xd;
00655                         sdy = (ay - (icos * dy)) + yd;
00656                         for (x = 0; x < dst->w; x++) {
00657                                 dx = (sdx >> 16);
00658                                 dy = (sdy >> 16);
00659                                 if (flipx) dx = sw - dx;
00660                                 if (flipy) dy = sh - dy;
00661                                 if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
00662                                         sp = (tColorRGBA *)src->pixels;;
00663                                         sp += ((src->pitch/4) * dy);
00664                                         sp += dx;
00665                                         c00 = *sp;
00666                                         sp += 1;
00667                                         c01 = *sp;
00668                                         sp += (src->pitch/4);
00669                                         c11 = *sp;
00670                                         sp -= 1;
00671                                         c10 = *sp;
00672                                         if (flipx) {
00673                                                 cswap = c00; c00=c01; c01=cswap;
00674                                                 cswap = c10; c10=c11; c11=cswap;
00675                                         }
00676                                         if (flipy) {
00677                                                 cswap = c00; c00=c10; c10=cswap;
00678                                                 cswap = c01; c01=c11; c11=cswap;
00679                                         }
00680                                         /*
00681                                         * Interpolate colors 
00682                                         */
00683                                         ex = (sdx & 0xffff);
00684                                         ey = (sdy & 0xffff);
00685                                         t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
00686                                         t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
00687                                         pc->r = (((t2 - t1) * ey) >> 16) + t1;
00688                                         t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
00689                                         t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
00690                                         pc->g = (((t2 - t1) * ey) >> 16) + t1;
00691                                         t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
00692                                         t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
00693                                         pc->b = (((t2 - t1) * ey) >> 16) + t1;
00694                                         t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
00695                                         t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
00696                                         pc->a = (((t2 - t1) * ey) >> 16) + t1;
00697                                 }
00698                                 sdx += icos;
00699                                 sdy += isin;
00700                                 pc++;
00701                         }
00702                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
00703                 }
00704         } else {
00705                 for (y = 0; y < dst->h; y++) {
00706                         dy = cy - y;
00707                         sdx = (ax + (isin * dy)) + xd;
00708                         sdy = (ay - (icos * dy)) + yd;
00709                         for (x = 0; x < dst->w; x++) {
00710                                 dx = (short) (sdx >> 16);
00711                                 dy = (short) (sdy >> 16);
00712                                 if (flipx) dx = (src->w-1)-dx;
00713                                 if (flipy) dy = (src->h-1)-dy;
00714                                 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
00715                                         sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
00716                                         sp += dx;
00717                                         *pc = *sp;
00718                                 }
00719                                 sdx += icos;
00720                                 sdy += isin;
00721                                 pc++;
00722                         }
00723                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
00724                 }
00725         }
00726 }
00727 
00746 void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
00747 {
00748         int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay;
00749         tColorY *pc, *sp;
00750         int gap;
00751 
00752         /*
00753         * Variable setup 
00754         */
00755         xd = ((src->w - dst->w) << 15);
00756         yd = ((src->h - dst->h) << 15);
00757         ax = (cx << 16) - (icos * cx);
00758         ay = (cy << 16) - (isin * cx);
00759         pc = (tColorY*) dst->pixels;
00760         gap = dst->pitch - dst->w;
00761         /*
00762         * Clear surface to colorkey 
00763         */      
00764         memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h);
00765         /*
00766         * Iterate through destination surface 
00767         */
00768         for (y = 0; y < dst->h; y++) {
00769                 dy = cy - y;
00770                 sdx = (ax + (isin * dy)) + xd;
00771                 sdy = (ay - (icos * dy)) + yd;
00772                 for (x = 0; x < dst->w; x++) {
00773                         dx = (short) (sdx >> 16);
00774                         dy = (short) (sdy >> 16);
00775                         if (flipx) dx = (src->w-1)-dx;
00776                         if (flipy) dy = (src->h-1)-dy;
00777                         if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
00778                                 sp = (tColorY *) (src->pixels);
00779                                 sp += (src->pitch * dy + dx);
00780                                 *pc = *sp;
00781                         }
00782                         sdx += icos;
00783                         sdy += isin;
00784                         pc++;
00785                 }
00786                 pc += gap;
00787         }
00788 }
00789 
00803 SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns) 
00804 {
00805         int row, col, newWidth, newHeight;
00806         int bpp;
00807         SDL_Surface* dst;
00808         Uint8* srcBuf;
00809         Uint8* dstBuf;
00810 
00811         /* Has to be a valid surface pointer and be a 8/16/24/32-bit surface */
00812         if (!src || !src->format ||
00813                  !(src->format->BitsPerPixel == 8) || 
00814                   (src->format->BitsPerPixel == 16) ||
00815                   (src->format->BitsPerPixel == 24) ||
00816                   (src->format->BitsPerPixel == 32)) { return NULL; }
00817 
00818         /* normalize numClockwiseTurns */
00819         while(numClockwiseTurns < 0) { numClockwiseTurns += 4; }
00820         numClockwiseTurns = (numClockwiseTurns % 4);
00821 
00822         /* if it's even, our new width will be the same as the source surface */
00823         newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w);
00824         newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h);
00825         dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel,
00826                 src->format->Rmask,
00827                 src->format->Gmask, 
00828                 src->format->Bmask, 
00829                 src->format->Amask);
00830         if(!dst) {
00831                 return NULL;
00832         }
00833 
00834         if (SDL_MUSTLOCK(src)) {
00835                 SDL_LockSurface(src);
00836         }
00837         if (SDL_MUSTLOCK(dst)) {
00838                 SDL_LockSurface(dst);
00839         }
00840 
00841         /* Calculate byte-per-pixel */
00842         bpp = src->format->BitsPerPixel / 8;
00843 
00844         switch(numClockwiseTurns) {
00845         case 0: /* Make a copy of the surface */
00846                 {
00847                         /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface
00848                         since it does not preserve alpha. */
00849 
00850                         if (src->pitch == dst->pitch) {
00851                                 /* If the pitch is the same for both surfaces, the memory can be copied all at once. */
00852                                 memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
00853                         }
00854                         else
00855                         {
00856                                 /* If the pitch differs, copy each row separately */
00857                                 srcBuf = (Uint8*)(src->pixels);
00858                                 dstBuf = (Uint8*)(dst->pixels);
00859                                 for (row = 0; row < src->h; row++) {
00860                                         memcpy(dstBuf, srcBuf, dst->w * bpp);
00861                                         srcBuf += src->pitch;
00862                                         dstBuf += dst->pitch;
00863                                 } /* end for(col) */
00864                         } /* end for(row) */
00865                 }
00866                 break;
00867 
00868                 /* rotate clockwise */
00869         case 1: /* rotated 90 degrees clockwise */
00870                 {
00871                         for (row = 0; row < src->h; ++row) {
00872                                 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
00873                                 dstBuf = (Uint8*)(dst->pixels) + (dst->w - row - 1) * bpp;
00874                                 for (col = 0; col < src->w; ++col) {
00875                                         memcpy (dstBuf, srcBuf, bpp);
00876                                         srcBuf += bpp;
00877                                         dstBuf += dst->pitch;
00878                                 } 
00879                         } 
00880                 }
00881                 break;
00882 
00883         case 2: /* rotated 180 degrees clockwise */
00884                 {
00885                         for (row = 0; row < src->h; ++row) {
00886                                 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
00887                                 dstBuf = (Uint8*)(dst->pixels) + ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp;
00888                                 for (col = 0; col < src->w; ++col) {
00889                                         memcpy (dstBuf, srcBuf, bpp);
00890                                         srcBuf += bpp;
00891                                         dstBuf -= bpp;
00892                                 } 
00893                         } 
00894                 }
00895                 break;
00896 
00897         case 3: /* rotated 270 degrees clockwise */
00898                 {
00899                         for (row = 0; row < src->h; ++row) {
00900                                 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
00901                                 dstBuf = (Uint8*)(dst->pixels) + row + ((dst->h - 1) * dst->pitch);
00902                                 for (col = 0; col < src->w; ++col) {
00903                                         *dstBuf = *srcBuf;
00904                                         srcBuf += bpp;
00905                                         dstBuf -= dst->pitch;
00906                                 } 
00907                         } 
00908                 }
00909                 break;
00910         } 
00911         /* end switch */
00912 
00913         if (SDL_MUSTLOCK(src)) {
00914                 SDL_UnlockSurface(src);
00915         }
00916         if (SDL_MUSTLOCK(dst)) {
00917                 SDL_UnlockSurface(dst);
00918         }
00919 
00920         return dst;
00921 }
00922 
00923 
00938 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, 
00939         int *dstwidth, int *dstheight, 
00940         double *canglezoom, double *sanglezoom)
00941 {
00942         double x, y, cx, cy, sx, sy;
00943         double radangle;
00944         int dstwidthhalf, dstheighthalf;
00945 
00946         /*
00947         * Determine destination width and height by rotating a centered source box 
00948         */
00949         radangle = angle * (M_PI / 180.0);
00950         *sanglezoom = sin(radangle);
00951         *canglezoom = cos(radangle);
00952         *sanglezoom *= zoomx;
00953         *canglezoom *= zoomx;
00954         x = (double)(width / 2);
00955         y = (double)(height / 2);
00956         cx = *canglezoom * x;
00957         cy = *canglezoom * y;
00958         sx = *sanglezoom * x;
00959         sy = *sanglezoom * y;
00960 
00961         dstwidthhalf = MAX((int)
00962                 ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
00963         dstheighthalf = MAX((int)
00964                 ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
00965         *dstwidth = 2 * dstwidthhalf;
00966         *dstheight = 2 * dstheighthalf;
00967 }
00968 
00980 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
00981 {
00982         double dummy_sanglezoom, dummy_canglezoom;
00983 
00984         _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
00985 }
00986 
00997 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
00998 {
00999         double dummy_sanglezoom, dummy_canglezoom;
01000 
01001         _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
01002 }
01003 
01019 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
01020 {
01021         return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
01022 }
01023 
01040 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
01041 {
01042         SDL_Surface *rz_src;
01043         SDL_Surface *rz_dst;
01044         double zoominv;
01045         double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
01046         int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
01047         int is32bit;
01048         int i, src_converted;
01049         int flipx,flipy;
01050 
01051         /*
01052         * Sanity check 
01053         */
01054         if (src == NULL) {
01055                 return (NULL);
01056         }
01057 
01058         /*
01059         * Determine if source surface is 32bit or 8bit 
01060         */
01061         is32bit = (src->format->BitsPerPixel == 32);
01062         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01063                 /*
01064                 * Use source surface 'as is' 
01065                 */
01066                 rz_src = src;
01067                 src_converted = 0;
01068         } else {
01069                 /*
01070                 * New source surface is 32bit with a defined RGBA ordering 
01071                 */
01072                 rz_src =
01073                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 
01074 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01075                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01076 #else
01077                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
01078 #endif
01079                         );
01080 
01081                 SDL_BlitSurface(src, NULL, rz_src, NULL);
01082 
01083                 src_converted = 1;
01084                 is32bit = 1;
01085         }
01086 
01087         /*
01088         * Sanity check zoom factor 
01089         */
01090         flipx = (zoomx<0.0);
01091         if (flipx) zoomx=-zoomx;
01092         flipy = (zoomy<0.0);
01093         if (flipy) zoomy=-zoomy;
01094         if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
01095         if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
01096         zoominv = 65536.0 / (zoomx * zoomx);
01097 
01098         /*
01099         * Check if we have a rotozoom or just a zoom 
01100         */
01101         if (fabs(angle) > VALUE_LIMIT) {
01102 
01103                 /*
01104                 * Angle!=0: full rotozoom 
01105                 */
01106                 /*
01107                 * ----------------------- 
01108                 */
01109 
01110                 /* Determine target size */
01111                 _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
01112 
01113                 /*
01114                 * Calculate target factors from sin/cos and zoom 
01115                 */
01116                 sanglezoominv = sanglezoom;
01117                 canglezoominv = canglezoom;
01118                 sanglezoominv *= zoominv;
01119                 canglezoominv *= zoominv;
01120 
01121                 /* Calculate half size */
01122                 dstwidthhalf = dstwidth / 2;
01123                 dstheighthalf = dstheight / 2;
01124 
01125                 /*
01126                 * Alloc space to completely contain the rotated surface 
01127                 */
01128                 rz_dst = NULL;
01129                 if (is32bit) {
01130                         /*
01131                         * Target surface is 32bit with source RGBA/ABGR ordering 
01132                         */
01133                         rz_dst =
01134                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01135                                 rz_src->format->Rmask, rz_src->format->Gmask,
01136                                 rz_src->format->Bmask, rz_src->format->Amask);
01137                 } else {
01138                         /*
01139                         * Target surface is 8bit 
01140                         */
01141                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01142                 }
01143 
01144                 /* Check target */
01145                 if (rz_dst == NULL)
01146                         return NULL;
01147 
01148                 /* Adjust for guard rows */
01149                 rz_dst->h = dstheight;
01150 
01151                 /*
01152                 * Lock source surface 
01153                 */
01154                 if (SDL_MUSTLOCK(rz_src)) {
01155                         SDL_LockSurface(rz_src);
01156                 }
01157 
01158                 /*
01159                 * Check which kind of surface we have 
01160                 */
01161                 if (is32bit) {
01162                         /*
01163                         * Call the 32bit transformation routine to do the rotation (using alpha) 
01164                         */
01165                         _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
01166                                 (int) (sanglezoominv), (int) (canglezoominv), 
01167                                 flipx, flipy,
01168                                 smooth);
01169                 } else {
01170                         /*
01171                         * Copy palette and colorkey info 
01172                         */
01173                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01174                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01175                         }
01176                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01177                         /*
01178                         * Call the 8bit transformation routine to do the rotation 
01179                         */
01180                         transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
01181                                 (int) (sanglezoominv), (int) (canglezoominv),
01182                                 flipx, flipy);
01183                 }
01184                 /*
01185                 * Unlock source surface 
01186                 */
01187                 if (SDL_MUSTLOCK(rz_src)) {
01188                         SDL_UnlockSurface(rz_src);
01189                 }
01190 
01191         } else {
01192 
01193                 /*
01194                 * Angle=0: Just a zoom 
01195                 */
01196                 /*
01197                 * -------------------- 
01198                 */
01199 
01200                 /*
01201                 * Calculate target size
01202                 */
01203                 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
01204 
01205                 /*
01206                 * Alloc space to completely contain the zoomed surface 
01207                 */
01208                 rz_dst = NULL;
01209                 if (is32bit) {
01210                         /*
01211                         * Target surface is 32bit with source RGBA/ABGR ordering 
01212                         */
01213                         rz_dst =
01214                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01215                                 rz_src->format->Rmask, rz_src->format->Gmask,
01216                                 rz_src->format->Bmask, rz_src->format->Amask);
01217                 } else {
01218                         /*
01219                         * Target surface is 8bit 
01220                         */
01221                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01222                 }
01223 
01224                 /* Check target */
01225                 if (rz_dst == NULL)
01226                         return NULL;
01227 
01228                 /* Adjust for guard rows */
01229                 rz_dst->h = dstheight;
01230 
01231                 /*
01232                 * Lock source surface 
01233                 */
01234                 if (SDL_MUSTLOCK(rz_src)) {
01235                         SDL_LockSurface(rz_src);
01236                 }
01237 
01238                 /*
01239                 * Check which kind of surface we have 
01240                 */
01241                 if (is32bit) {
01242                         /*
01243                         * Call the 32bit transformation routine to do the zooming (using alpha) 
01244                         */
01245                         _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
01246 
01247                 } else {
01248                         /*
01249                         * Copy palette and colorkey info 
01250                         */
01251                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01252                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01253                         }
01254                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01255 
01256                         /*
01257                         * Call the 8bit transformation routine to do the zooming 
01258                         */
01259                         _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
01260                 }
01261 
01262                 /*
01263                 * Unlock source surface 
01264                 */
01265                 if (SDL_MUSTLOCK(rz_src)) {
01266                         SDL_UnlockSurface(rz_src);
01267                 }
01268         }
01269 
01270         /*
01271         * Cleanup temp surface 
01272         */
01273         if (src_converted) {
01274                 SDL_FreeSurface(rz_src);
01275         }
01276 
01277         /*
01278         * Return destination surface 
01279         */
01280         return (rz_dst);
01281 }
01282 
01295 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
01296 {
01297         /*
01298         * Make zoom factors positive 
01299         */
01300         int flipx, flipy;
01301         flipx = (zoomx<0.0);
01302         if (flipx) zoomx = -zoomx;
01303         flipy = (zoomy<0.0);
01304         if (flipy) zoomy = -zoomy;
01305 
01306         /*
01307         * Sanity check zoom factors 
01308         */
01309         if (zoomx < VALUE_LIMIT) {
01310                 zoomx = VALUE_LIMIT;
01311         }
01312         if (zoomy < VALUE_LIMIT) {
01313                 zoomy = VALUE_LIMIT;
01314         }
01315 
01316         /*
01317         * Calculate target size 
01318         */
01319         *dstwidth = (int) floor(((double) width * zoomx) + 0.5);
01320         *dstheight = (int) floor(((double) height * zoomy) + 0.5);
01321         if (*dstwidth < 1) {
01322                 *dstwidth = 1;
01323         }
01324         if (*dstheight < 1) {
01325                 *dstheight = 1;
01326         }
01327 }
01328 
01345 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
01346 {
01347         SDL_Surface *rz_src;
01348         SDL_Surface *rz_dst;
01349         int dstwidth, dstheight;
01350         int is32bit;
01351         int i, src_converted;
01352         int flipx, flipy;
01353 
01354         /*
01355         * Sanity check 
01356         */
01357         if (src == NULL)
01358                 return (NULL);
01359 
01360         /*
01361         * Determine if source surface is 32bit or 8bit 
01362         */
01363         is32bit = (src->format->BitsPerPixel == 32);
01364         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01365                 /*
01366                 * Use source surface 'as is' 
01367                 */
01368                 rz_src = src;
01369                 src_converted = 0;
01370         } else {
01371                 /*
01372                 * New source surface is 32bit with a defined RGBA ordering 
01373                 */
01374                 rz_src =
01375                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 
01376 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01377                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01378 #else
01379                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
01380 #endif
01381                         );
01382                 if (rz_src == NULL) {
01383                         return NULL;
01384                 }
01385                 SDL_BlitSurface(src, NULL, rz_src, NULL);
01386                 src_converted = 1;
01387                 is32bit = 1;
01388         }
01389 
01390         flipx = (zoomx<0.0);
01391         if (flipx) zoomx = -zoomx;
01392         flipy = (zoomy<0.0);
01393         if (flipy) zoomy = -zoomy;
01394 
01395         /* Get size if target */
01396         zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
01397 
01398         /*
01399         * Alloc space to completely contain the zoomed surface 
01400         */
01401         rz_dst = NULL;
01402         if (is32bit) {
01403                 /*
01404                 * Target surface is 32bit with source RGBA/ABGR ordering 
01405                 */
01406                 rz_dst =
01407                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01408                         rz_src->format->Rmask, rz_src->format->Gmask,
01409                         rz_src->format->Bmask, rz_src->format->Amask);
01410         } else {
01411                 /*
01412                 * Target surface is 8bit 
01413                 */
01414                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01415         }
01416 
01417         /* Check target */
01418         if (rz_dst == NULL) {
01419                 /*
01420                 * Cleanup temp surface 
01421                 */
01422                 if (src_converted) {
01423                         SDL_FreeSurface(rz_src);
01424                 }               
01425                 return NULL;
01426         }
01427 
01428         /* Adjust for guard rows */
01429         rz_dst->h = dstheight;
01430 
01431         /*
01432         * Lock source surface 
01433         */
01434         if (SDL_MUSTLOCK(rz_src)) {
01435                 SDL_LockSurface(rz_src);
01436         }
01437 
01438         /*
01439         * Check which kind of surface we have 
01440         */
01441         if (is32bit) {
01442                 /*
01443                 * Call the 32bit transformation routine to do the zooming (using alpha) 
01444                 */
01445                 _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
01446         } else {
01447                 /*
01448                 * Copy palette and colorkey info 
01449                 */
01450                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01451                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01452                 }
01453                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01454                 /*
01455                 * Call the 8bit transformation routine to do the zooming 
01456                 */
01457                 _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
01458         }
01459         /*
01460         * Unlock source surface 
01461         */
01462         if (SDL_MUSTLOCK(rz_src)) {
01463                 SDL_UnlockSurface(rz_src);
01464         }
01465 
01466         /*
01467         * Cleanup temp surface 
01468         */
01469         if (src_converted) {
01470                 SDL_FreeSurface(rz_src);
01471         }
01472 
01473         /*
01474         * Return destination surface 
01475         */
01476         return (rz_dst);
01477 }
01478 
01495 /*@null@*/ 
01496 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
01497 {
01498         int result;
01499         SDL_Surface *rz_src;
01500         SDL_Surface *rz_dst = NULL;
01501         int dstwidth, dstheight;
01502         int is32bit;
01503         int i, src_converted;
01504         int haveError = 0;
01505 
01506         /*
01507         * Sanity check 
01508         */
01509         if (src == NULL) {
01510                 return (NULL);
01511         }
01512 
01513         /*
01514         * Determine if source surface is 32bit or 8bit 
01515         */
01516         is32bit = (src->format->BitsPerPixel == 32);
01517         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01518                 /*
01519                 * Use source surface 'as is' 
01520                 */
01521                 rz_src = src;
01522                 src_converted = 0;
01523         } else {
01524                 /*
01525                 * New source surface is 32bit with a defined RGBA ordering 
01526                 */
01527                 rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 
01528 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01529                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01530 #else
01531                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
01532 #endif
01533                         );
01534                 if (rz_src==NULL) {
01535                         haveError = 1;
01536                         goto exitShrinkSurface;
01537                 }
01538 
01539                 SDL_BlitSurface(src, NULL, rz_src, NULL);
01540                 src_converted = 1;
01541                 is32bit = 1;
01542         }
01543 
01544         /*
01545         * Lock the surface 
01546         */
01547         if (SDL_MUSTLOCK(rz_src)) {
01548                 if (SDL_LockSurface(rz_src) < 0) {
01549                         haveError = 1;
01550                         goto exitShrinkSurface;
01551                 }
01552         }
01553 
01554         /* Get size for target */
01555         dstwidth=rz_src->w/factorx;
01556         while (dstwidth*factorx>rz_src->w) { dstwidth--; }
01557         dstheight=rz_src->h/factory;
01558         while (dstheight*factory>rz_src->h) { dstheight--; }
01559 
01560         /*
01561         * Alloc space to completely contain the shrunken surface
01562         * (with added guard rows)
01563         */
01564         if (is32bit==1) {
01565                 /*
01566                 * Target surface is 32bit with source RGBA/ABGR ordering 
01567                 */
01568                 rz_dst =
01569                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01570                         rz_src->format->Rmask, rz_src->format->Gmask,
01571                         rz_src->format->Bmask, rz_src->format->Amask);
01572         } else {
01573                 /*
01574                 * Target surface is 8bit 
01575                 */
01576                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01577         }
01578 
01579         /* Check target */
01580         if (rz_dst == NULL) {
01581                 haveError = 1;
01582                 goto exitShrinkSurface;
01583         }
01584 
01585         /* Adjust for guard rows */
01586         rz_dst->h = dstheight;
01587 
01588         /*
01589         * Check which kind of surface we have 
01590         */
01591         if (is32bit==1) {
01592                 /*
01593                 * Call the 32bit transformation routine to do the shrinking (using alpha) 
01594                 */
01595                 result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);          
01596                 if ((result!=0) || (rz_dst==NULL)) {
01597                         haveError = 1;
01598                         goto exitShrinkSurface;
01599                 }
01600         } else {
01601                 /*
01602                 * Copy palette and colorkey info 
01603                 */
01604                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01605                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01606                 }
01607                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01608                 /*
01609                 * Call the 8bit transformation routine to do the shrinking 
01610                 */
01611                 result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
01612                 if (result!=0) {
01613                         haveError = 1;
01614                         goto exitShrinkSurface;
01615                 }
01616         }
01617 
01618 exitShrinkSurface:
01619         if (rz_src!=NULL) {
01620                 /*
01621                 * Unlock source surface 
01622                 */
01623                 if (SDL_MUSTLOCK(rz_src)) {
01624                         SDL_UnlockSurface(rz_src);
01625                 }
01626 
01627                 /*
01628                 * Cleanup temp surface 
01629                 */
01630                 if (src_converted==1) {
01631                         SDL_FreeSurface(rz_src);
01632                 }
01633         }
01634 
01635         /* Check error state; maybe need to cleanup destination */
01636         if (haveError==1) {
01637                 if (rz_dst!=NULL) {
01638                         SDL_FreeSurface(rz_dst);
01639                 }
01640                 rz_dst=NULL;
01641         } 
01642 
01643         /*
01644         * Return destination surface 
01645         */
01646         return (rz_dst);
01647 }