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, (unsigned char) (_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 = width / 2;
00941 y = 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 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
01513 {
01514 SDL_Surface *rz_src;
01515 SDL_Surface *rz_dst;
01516 int dstwidth, dstheight;
01517 int is32bit;
01518 int i, src_converted;
01519
01520
01521
01522
01523 if (src == NULL)
01524 return (NULL);
01525
01526
01527
01528
01529 is32bit = (src->format->BitsPerPixel == 32);
01530 if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01531
01532
01533
01534 rz_src = src;
01535 src_converted = 0;
01536 } else {
01537
01538
01539
01540 rz_src =
01541 SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
01542 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01543 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01544 #else
01545 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
01546 #endif
01547 );
01548 SDL_BlitSurface(src, NULL, rz_src, NULL);
01549 src_converted = 1;
01550 is32bit = 1;
01551 }
01552
01553
01554 dstwidth=rz_src->w/factorx;
01555 while (dstwidth*factorx>rz_src->w) { dstwidth--; }
01556 dstheight=rz_src->h/factory;
01557 while (dstheight*factory>rz_src->h) { dstheight--; }
01558
01559
01560
01561
01562
01563 rz_dst = NULL;
01564 if (is32bit) {
01565
01566
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
01575
01576 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01577 }
01578
01579
01580 if (rz_dst == NULL)
01581 return NULL;
01582
01583
01584 rz_dst->h = dstheight;
01585
01586
01587
01588
01589 if (SDL_MUSTLOCK(rz_src)) {
01590 SDL_LockSurface(rz_src);
01591 }
01592
01593
01594
01595
01596 if (is32bit) {
01597
01598
01599
01600 _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
01601
01602
01603
01604 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
01605 } else {
01606
01607
01608
01609 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01610 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01611 }
01612 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01613
01614
01615
01616 _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
01617 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01618 }
01619
01620
01621
01622
01623 if (SDL_MUSTLOCK(rz_src)) {
01624 SDL_UnlockSurface(rz_src);
01625 }
01626
01627
01628
01629
01630 if (src_converted) {
01631 SDL_FreeSurface(rz_src);
01632 }
01633
01634
01635
01636
01637 return (rz_dst);
01638 }