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
00281
00282 sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
00283 sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
00284 } else {
00285 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
00286 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
00287 }
00288
00289
00290
00291
00292 if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
00293 return (-1);
00294 }
00295 if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
00296 free(sax);
00297 return (-1);
00298 }
00299
00300
00301
00302
00303 sp = csp = (tColorRGBA *) src->pixels;
00304 dp = (tColorRGBA *) dst->pixels;
00305
00306 if (flipx) csp += (src->w-1);
00307 if (flipy) csp += (src->pitch*(src->h-1));
00308
00309 csx = 0;
00310 csax = sax;
00311 for (x = 0; x <= dst->w; x++) {
00312 *csax = csx;
00313 csax++;
00314 csx &= 0xffff;
00315 csx += sx;
00316 }
00317 csy = 0;
00318 csay = say;
00319 for (y = 0; y <= dst->h; y++) {
00320 *csay = csy;
00321 csay++;
00322 csy &= 0xffff;
00323 csy += sy;
00324 }
00325
00326 dgap = dst->pitch - dst->w * 4;
00327
00328
00329
00330
00331 if (smooth) {
00332
00333
00334
00335
00336
00337
00338
00339
00340 ly = 0;
00341 csay = say;
00342 for (y = 0; y < dst->h; y++) {
00343
00344
00345
00346 c00 = csp;
00347 c01 = csp;
00348 c01++;
00349 c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch);
00350 c11 = c10;
00351 c11++;
00352 csax = sax;
00353 if (flipx) {
00354 cswap = c00; c00=c01; c01=cswap;
00355 cswap = c10; c10=c11; c11=cswap;
00356 }
00357 if (flipy) {
00358 cswap = c00; c00=c10; c10=cswap;
00359 cswap = c01; c01=c11; c11=cswap;
00360 }
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 sstep = (*csax >> 16);
00386 lx += sstep;
00387 if (lx >= src->w) sstep = 0;
00388 if (flipx) sstep = -sstep;
00389 c00 += sstep;
00390 c01 += sstep;
00391 c10 += sstep;
00392 c11 += sstep;
00393
00394
00395
00396 dp++;
00397 }
00398
00399
00400
00401 csay++;
00402 sstep = (*csay >> 16);
00403 ly += sstep;
00404 if (ly >= src->h) sstep = 0;
00405 sstep *= src->pitch;
00406 if (flipy) sstep = -sstep;
00407 csp = (tColorRGBA *) ((Uint8 *) csp + sstep);
00408
00409
00410
00411
00412 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00413 }
00414 } else {
00415
00416
00417
00418
00419
00420 csay = say;
00421 for (y = 0; y < dst->h; y++) {
00422 sp = csp;
00423 csax = sax;
00424 for (x = 0; x < dst->w; x++) {
00425
00426
00427
00428 *dp = *sp;
00429
00430
00431
00432 csax++;
00433 sstep = (*csax >> 16);
00434 if (flipx) sstep = -sstep;
00435 sp += sstep;
00436
00437
00438
00439 dp++;
00440 }
00441
00442
00443
00444 csay++;
00445 sstep = (*csay >> 16) * src->pitch;
00446 if (flipy) sstep = -sstep;
00447 csp = (tColorRGBA *) ((Uint8 *) csp + sstep);
00448
00449
00450
00451
00452 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00453 }
00454 }
00455
00456
00457
00458
00459 free(sax);
00460 free(say);
00461
00462 return (0);
00463 }
00464
00480 int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
00481 {
00482 int x, y;
00483 Uint32 *sax, *say, *csax, *csay;
00484 int csx, csy;
00485 Uint8 *sp, *dp, *csp;
00486 int dgap;
00487
00488
00489
00490
00491 if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
00492 return (-1);
00493 }
00494 if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
00495 free(sax);
00496 return (-1);
00497 }
00498
00499
00500
00501
00502 sp = csp = (Uint8 *) src->pixels;
00503 dp = (Uint8 *) dst->pixels;
00504 dgap = dst->pitch - dst->w;
00505
00506 if (flipx) csp += (src->w-1);
00507 if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) );
00508
00509
00510
00511
00512 csx = 0;
00513 csax = sax;
00514 for (x = 0; x < dst->w; x++) {
00515 csx += src->w;
00516 *csax = 0;
00517 while (csx >= dst->w) {
00518 csx -= dst->w;
00519 (*csax)++;
00520 }
00521 csax++;
00522 }
00523 csy = 0;
00524 csay = say;
00525 for (y = 0; y < dst->h; y++) {
00526 csy += src->h;
00527 *csay = 0;
00528 while (csy >= dst->h) {
00529 csy -= dst->h;
00530 (*csay)++;
00531 }
00532 csay++;
00533 }
00534
00535
00536
00537
00538 csay = say;
00539 for (y = 0; y < dst->h; y++) {
00540 csax = sax;
00541 sp = csp;
00542 for (x = 0; x < dst->w; x++) {
00543
00544
00545
00546 *dp = *sp;
00547
00548
00549
00550 sp += (*csax) * (flipx ? -1 : 1);
00551 csax++;
00552
00553
00554
00555 dp++;
00556 }
00557
00558
00559
00560 csp += ((*csay) * src->pitch) * (flipy ? -1 : 1);
00561 csay++;
00562
00563
00564
00565
00566 dp += dgap;
00567 }
00568
00569
00570
00571
00572 free(sax);
00573 free(say);
00574
00575 return (0);
00576 }
00577
00597 void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
00598 {
00599 int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
00600 tColorRGBA c00, c01, c10, c11, cswap;
00601 tColorRGBA *pc, *sp;
00602 int gap;
00603
00604
00605
00606
00607 xd = ((src->w - dst->w) << 15);
00608 yd = ((src->h - dst->h) << 15);
00609 ax = (cx << 16) - (icos * cx);
00610 ay = (cy << 16) - (isin * cx);
00611 sw = src->w - 1;
00612 sh = src->h - 1;
00613 pc = (tColorRGBA*) dst->pixels;
00614 gap = dst->pitch - dst->w * 4;
00615
00616
00617
00618
00619 if (smooth) {
00620 for (y = 0; y < dst->h; y++) {
00621 dy = cy - y;
00622 sdx = (ax + (isin * dy)) + xd;
00623 sdy = (ay - (icos * dy)) + yd;
00624 for (x = 0; x < dst->w; x++) {
00625 dx = (sdx >> 16);
00626 dy = (sdy >> 16);
00627 if ((dx > -1) && (dy > -1) && (dx < src->w) && (dy < src->h)) {
00628 if (flipx) dx = sw - dx;
00629 if (flipy) dy = sh - dy;
00630 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
00631 sp += dx;
00632 c00 = *sp;
00633 sp += 1;
00634 c01 = *sp;
00635 sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
00636 c11 = *sp;
00637 sp -= 1;
00638 c10 = *sp;
00639 if (flipx) {
00640 cswap = c00; c00=c01; c01=cswap;
00641 cswap = c10; c10=c11; c11=cswap;
00642 }
00643 if (flipy) {
00644 cswap = c00; c00=c10; c10=cswap;
00645 cswap = c01; c01=c11; c11=cswap;
00646 }
00647
00648
00649
00650 ex = (sdx & 0xffff);
00651 ey = (sdy & 0xffff);
00652 t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
00653 t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
00654 pc->r = (((t2 - t1) * ey) >> 16) + t1;
00655 t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
00656 t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
00657 pc->g = (((t2 - t1) * ey) >> 16) + t1;
00658 t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
00659 t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
00660 pc->b = (((t2 - t1) * ey) >> 16) + t1;
00661 t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
00662 t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
00663 pc->a = (((t2 - t1) * ey) >> 16) + t1;
00664 }
00665 sdx += icos;
00666 sdy += isin;
00667 pc++;
00668 }
00669 pc = (tColorRGBA *) ((Uint8 *) pc + gap);
00670 }
00671 } else {
00672 for (y = 0; y < dst->h; y++) {
00673 dy = cy - y;
00674 sdx = (ax + (isin * dy)) + xd;
00675 sdy = (ay - (icos * dy)) + yd;
00676 for (x = 0; x < dst->w; x++) {
00677 dx = (short) (sdx >> 16);
00678 dy = (short) (sdy >> 16);
00679 if (flipx) dx = (src->w-1)-dx;
00680 if (flipy) dy = (src->h-1)-dy;
00681 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
00682 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
00683 sp += dx;
00684 *pc = *sp;
00685 }
00686 sdx += icos;
00687 sdy += isin;
00688 pc++;
00689 }
00690 pc = (tColorRGBA *) ((Uint8 *) pc + gap);
00691 }
00692 }
00693 }
00694
00713 void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
00714 {
00715 int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh;
00716 tColorY *pc, *sp;
00717 int gap;
00718
00719
00720
00721
00722 xd = ((src->w - dst->w) << 15);
00723 yd = ((src->h - dst->h) << 15);
00724 ax = (cx << 16) - (icos * cx);
00725 ay = (cy << 16) - (isin * cx);
00726 sw = src->w - 1;
00727 sh = src->h - 1;
00728 pc = (tColorY*) dst->pixels;
00729 gap = dst->pitch - dst->w;
00730
00731
00732
00733 memset(pc, (unsigned char) (_colorkey(src) & 0xff), dst->pitch * dst->h);
00734
00735
00736
00737 for (y = 0; y < dst->h; y++) {
00738 dy = cy - y;
00739 sdx = (ax + (isin * dy)) + xd;
00740 sdy = (ay - (icos * dy)) + yd;
00741 for (x = 0; x < dst->w; x++) {
00742 dx = (short) (sdx >> 16);
00743 dy = (short) (sdy >> 16);
00744 if (flipx) dx = (src->w-1)-dx;
00745 if (flipy) dy = (src->h-1)-dy;
00746 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
00747 sp = (tColorY *) (src->pixels);
00748 sp += (src->pitch * dy + dx);
00749 *pc = *sp;
00750 }
00751 sdx += icos;
00752 sdy += isin;
00753 pc++;
00754 }
00755 pc += gap;
00756 }
00757 }
00758
00772 SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns)
00773 {
00774 int row, col, newWidth, newHeight;
00775 int bpp, src_ipr, dst_ipr;
00776 SDL_Surface* dst;
00777 Uint32* srcBuf;
00778 Uint32* dstBuf;
00779
00780
00781 if (!src || src->format->BitsPerPixel != 32) { return NULL; }
00782
00783
00784 while(numClockwiseTurns < 0) { numClockwiseTurns += 4; }
00785 numClockwiseTurns = (numClockwiseTurns % 4);
00786
00787
00788 newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w);
00789 newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h);
00790 dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel,
00791 src->format->Rmask,
00792 src->format->Gmask,
00793 src->format->Bmask,
00794 src->format->Amask);
00795 if(!dst) {
00796 return NULL;
00797 }
00798
00799 if (SDL_MUSTLOCK(dst)) {
00800 SDL_LockSurface(dst);
00801 }
00802 if (SDL_MUSTLOCK(dst)) {
00803 SDL_LockSurface(dst);
00804 }
00805
00806
00807 bpp = src->format->BitsPerPixel / 8;
00808 src_ipr = src->pitch / bpp;
00809 dst_ipr = dst->pitch / bpp;
00810
00811 switch(numClockwiseTurns) {
00812 case 0:
00813 {
00814
00815
00816
00817 if (src->pitch == dst->pitch) {
00818
00819 memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
00820 }
00821 else
00822 {
00823
00824 srcBuf = (Uint32*)(src->pixels);
00825 dstBuf = (Uint32*)(dst->pixels);
00826 for (row = 0; row < src->h; row++) {
00827 memcpy(dstBuf, srcBuf, dst->w * bpp);
00828 srcBuf += src_ipr;
00829 dstBuf += dst_ipr;
00830 }
00831 }
00832 }
00833 break;
00834
00835
00836 case 1:
00837 {
00838 for (row = 0; row < src->h; ++row) {
00839 srcBuf = (Uint32*)(src->pixels) + (row * src_ipr);
00840 dstBuf = (Uint32*)(dst->pixels) + (dst->w - row - 1);
00841 for (col = 0; col < src->w; ++col) {
00842 *dstBuf = *srcBuf;
00843 ++srcBuf;
00844 dstBuf += dst_ipr;
00845 }
00846
00847 }
00848
00849 }
00850 break;
00851
00852 case 2:
00853 {
00854 for (row = 0; row < src->h; ++row) {
00855 srcBuf = (Uint32*)(src->pixels) + (row * src_ipr);
00856 dstBuf = (Uint32*)(dst->pixels) + ((dst->h - row - 1) * dst_ipr) + (dst->w - 1);
00857 for (col = 0; col < src->w; ++col) {
00858 *dstBuf = *srcBuf;
00859 ++srcBuf;
00860 --dstBuf;
00861 }
00862 }
00863 }
00864 break;
00865
00866 case 3:
00867 {
00868 for (row = 0; row < src->h; ++row) {
00869 srcBuf = (Uint32*)(src->pixels) + (row * src_ipr);
00870 dstBuf = (Uint32*)(dst->pixels) + row + ((dst->h - 1) * dst_ipr);
00871 for (col = 0; col < src->w; ++col) {
00872 *dstBuf = *srcBuf;
00873 ++srcBuf;
00874 dstBuf -= dst_ipr;
00875 }
00876 }
00877 }
00878 break;
00879 }
00880
00881
00882 if (SDL_MUSTLOCK(src)) {
00883 SDL_UnlockSurface(src);
00884 }
00885 if (SDL_MUSTLOCK(dst)) {
00886 SDL_UnlockSurface(dst);
00887 }
00888
00889 return dst;
00890 }
00891
00892
00907 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy,
00908 int *dstwidth, int *dstheight,
00909 double *canglezoom, double *sanglezoom)
00910 {
00911 double x, y, cx, cy, sx, sy;
00912 double radangle;
00913 int dstwidthhalf, dstheighthalf;
00914
00915
00916
00917
00918 radangle = angle * (M_PI / 180.0);
00919 *sanglezoom = sin(radangle);
00920 *canglezoom = cos(radangle);
00921 *sanglezoom *= zoomx;
00922 *canglezoom *= zoomx;
00923 x = width / 2;
00924 y = height / 2;
00925 cx = *canglezoom * x;
00926 cy = *canglezoom * y;
00927 sx = *sanglezoom * x;
00928 sy = *sanglezoom * y;
00929
00930 dstwidthhalf = MAX((int)
00931 ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
00932 dstheighthalf = MAX((int)
00933 ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
00934 *dstwidth = 2 * dstwidthhalf;
00935 *dstheight = 2 * dstheighthalf;
00936 }
00937
00949 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
00950 {
00951 double dummy_sanglezoom, dummy_canglezoom;
00952
00953 _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
00954 }
00955
00966 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
00967 {
00968 double dummy_sanglezoom, dummy_canglezoom;
00969
00970 _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
00971 }
00972
00988 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
00989 {
00990 return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
00991 }
00992
01009 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
01010 {
01011 SDL_Surface *rz_src;
01012 SDL_Surface *rz_dst;
01013 double zoominv;
01014 double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
01015 int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
01016 int is32bit;
01017 int i, src_converted;
01018 int flipx,flipy;
01019 Uint8 r,g,b;
01020 Uint32 colorkey = 0;
01021 int colorKeyAvailable = 0;
01022
01023
01024
01025
01026 if (src == NULL)
01027 return (NULL);
01028
01029 if (src->flags & SDL_SRCCOLORKEY)
01030 {
01031 colorkey = _colorkey(src);
01032 SDL_GetRGB(colorkey, src->format, &r, &g, &b);
01033 colorKeyAvailable = 1;
01034 }
01035
01036
01037
01038 is32bit = (src->format->BitsPerPixel == 32);
01039 if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01040
01041
01042
01043 rz_src = src;
01044 src_converted = 0;
01045 } else {
01046
01047
01048
01049 rz_src =
01050 SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
01051 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01052 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01053 #else
01054 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
01055 #endif
01056 );
01057 if(colorKeyAvailable)
01058 SDL_SetColorKey(src, 0, 0);
01059
01060 SDL_BlitSurface(src, NULL, rz_src, NULL);
01061
01062 if(colorKeyAvailable)
01063 SDL_SetColorKey(src, SDL_SRCCOLORKEY, colorkey);
01064 src_converted = 1;
01065 is32bit = 1;
01066 }
01067
01068
01069
01070
01071 flipx = (zoomx<0.0);
01072 if (flipx) zoomx=-zoomx;
01073 flipy = (zoomy<0.0);
01074 if (flipy) zoomy=-zoomy;
01075 if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
01076 if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
01077 zoominv = 65536.0 / (zoomx * zoomx);
01078
01079
01080
01081
01082 if (fabs(angle) > VALUE_LIMIT) {
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
01093
01094
01095
01096
01097 sanglezoominv = sanglezoom;
01098 canglezoominv = canglezoom;
01099 sanglezoominv *= zoominv;
01100 canglezoominv *= zoominv;
01101
01102
01103 dstwidthhalf = dstwidth / 2;
01104 dstheighthalf = dstheight / 2;
01105
01106
01107
01108
01109 rz_dst = NULL;
01110 if (is32bit) {
01111
01112
01113
01114 rz_dst =
01115 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01116 rz_src->format->Rmask, rz_src->format->Gmask,
01117 rz_src->format->Bmask, rz_src->format->Amask);
01118 } else {
01119
01120
01121
01122 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01123 }
01124
01125 if (colorKeyAvailable == 1){
01126 colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
01127
01128 SDL_FillRect(rz_dst, NULL, colorkey );
01129 }
01130
01131
01132
01133
01134 if (SDL_MUSTLOCK(rz_src)) {
01135 SDL_LockSurface(rz_src);
01136 }
01137
01138
01139
01140
01141 if (is32bit) {
01142
01143
01144
01145 _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
01146 (int) (sanglezoominv), (int) (canglezoominv),
01147 flipx, flipy,
01148 smooth);
01149
01150
01151
01152 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
01153 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01154 } else {
01155
01156
01157
01158 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01159 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01160 }
01161 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01162
01163
01164
01165 transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
01166 (int) (sanglezoominv), (int) (canglezoominv),
01167 flipx, flipy);
01168 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01169 }
01170
01171
01172
01173 if (SDL_MUSTLOCK(rz_src)) {
01174 SDL_UnlockSurface(rz_src);
01175 }
01176
01177 } else {
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
01190
01191
01192
01193
01194 rz_dst = NULL;
01195 if (is32bit) {
01196
01197
01198
01199 rz_dst =
01200 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01201 rz_src->format->Rmask, rz_src->format->Gmask,
01202 rz_src->format->Bmask, rz_src->format->Amask);
01203 } else {
01204
01205
01206
01207 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01208 }
01209
01210 if (colorKeyAvailable == 1){
01211 colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
01212
01213 SDL_FillRect(rz_dst, NULL, colorkey );
01214 }
01215
01216
01217
01218
01219 if (SDL_MUSTLOCK(rz_src)) {
01220 SDL_LockSurface(rz_src);
01221 }
01222
01223
01224
01225
01226 if (is32bit) {
01227
01228
01229
01230 _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
01231
01232
01233
01234 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
01235 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01236 } else {
01237
01238
01239
01240 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01241 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01242 }
01243 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01244
01245
01246
01247 _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
01248 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01249 }
01250
01251
01252
01253 if (SDL_MUSTLOCK(rz_src)) {
01254 SDL_UnlockSurface(rz_src);
01255 }
01256 }
01257
01258
01259
01260
01261 if (src_converted) {
01262 SDL_FreeSurface(rz_src);
01263 }
01264
01265
01266
01267
01268 rz_dst->h -= GUARD_ROWS;
01269 return (rz_dst);
01270 }
01271
01284 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
01285 {
01286
01287
01288
01289 int flipx, flipy;
01290 flipx = (zoomx<0.0);
01291 if (flipx) zoomx = -zoomx;
01292 flipy = (zoomy<0.0);
01293 if (flipy) zoomy = -zoomy;
01294
01295
01296
01297
01298 if (zoomx < VALUE_LIMIT) {
01299 zoomx = VALUE_LIMIT;
01300 }
01301 if (zoomy < VALUE_LIMIT) {
01302 zoomy = VALUE_LIMIT;
01303 }
01304
01305
01306
01307
01308 *dstwidth = (int) ((double) width * zoomx);
01309 *dstheight = (int) ((double) height * zoomy);
01310 if (*dstwidth < 1) {
01311 *dstwidth = 1;
01312 }
01313 if (*dstheight < 1) {
01314 *dstheight = 1;
01315 }
01316 }
01317
01334 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
01335 {
01336 SDL_Surface *rz_src;
01337 SDL_Surface *rz_dst;
01338 int dstwidth, dstheight;
01339 int is32bit;
01340 int i, src_converted;
01341 int flipx, flipy;
01342
01343
01344
01345
01346 if (src == NULL)
01347 return (NULL);
01348
01349
01350
01351
01352 is32bit = (src->format->BitsPerPixel == 32);
01353 if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01354
01355
01356
01357 rz_src = src;
01358 src_converted = 0;
01359 } else {
01360
01361
01362
01363 rz_src =
01364 SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
01365 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01366 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01367 #else
01368 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
01369 #endif
01370 );
01371 SDL_BlitSurface(src, NULL, rz_src, NULL);
01372 src_converted = 1;
01373 is32bit = 1;
01374 }
01375
01376 flipx = (zoomx<0.0);
01377 if (flipx) zoomx = -zoomx;
01378 flipy = (zoomy<0.0);
01379 if (flipy) zoomy = -zoomy;
01380
01381
01382 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
01383
01384
01385
01386
01387 rz_dst = NULL;
01388 if (is32bit) {
01389
01390
01391
01392 rz_dst =
01393 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01394 rz_src->format->Rmask, rz_src->format->Gmask,
01395 rz_src->format->Bmask, rz_src->format->Amask);
01396 } else {
01397
01398
01399
01400 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01401 }
01402
01403
01404
01405
01406 if (SDL_MUSTLOCK(rz_src)) {
01407 SDL_LockSurface(rz_src);
01408 }
01409
01410
01411
01412
01413 if (is32bit) {
01414
01415
01416
01417 _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
01418
01419
01420
01421 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
01422 } else {
01423
01424
01425
01426 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01427 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01428 }
01429 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01430
01431
01432
01433 _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
01434 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01435 }
01436
01437
01438
01439 if (SDL_MUSTLOCK(rz_src)) {
01440 SDL_UnlockSurface(rz_src);
01441 }
01442
01443
01444
01445
01446 if (src_converted) {
01447 SDL_FreeSurface(rz_src);
01448 }
01449
01450
01451
01452
01453 rz_dst->h -= GUARD_ROWS;
01454 return (rz_dst);
01455 }
01456
01473 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
01474 {
01475 SDL_Surface *rz_src;
01476 SDL_Surface *rz_dst;
01477 int dstwidth, dstheight;
01478 int is32bit;
01479 int i, src_converted;
01480
01481
01482
01483
01484 if (src == NULL)
01485 return (NULL);
01486
01487
01488
01489
01490 is32bit = (src->format->BitsPerPixel == 32);
01491 if ((is32bit) || (src->format->BitsPerPixel == 8)) {
01492
01493
01494
01495 rz_src = src;
01496 src_converted = 0;
01497 } else {
01498
01499
01500
01501 rz_src =
01502 SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
01503 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
01504 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
01505 #else
01506 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
01507 #endif
01508 );
01509 SDL_BlitSurface(src, NULL, rz_src, NULL);
01510 src_converted = 1;
01511 is32bit = 1;
01512 }
01513
01514
01515 dstwidth=rz_src->w/factorx;
01516 while (dstwidth*factorx>rz_src->w) { dstwidth--; }
01517 dstheight=rz_src->h/factory;
01518 while (dstheight*factory>rz_src->h) { dstheight--; }
01519
01520
01521
01522
01523
01524 rz_dst = NULL;
01525 if (is32bit) {
01526
01527
01528
01529 rz_dst =
01530 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
01531 rz_src->format->Rmask, rz_src->format->Gmask,
01532 rz_src->format->Bmask, rz_src->format->Amask);
01533 } else {
01534
01535
01536
01537 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
01538 }
01539
01540
01541
01542
01543 if (SDL_MUSTLOCK(rz_src)) {
01544 SDL_LockSurface(rz_src);
01545 }
01546
01547
01548
01549
01550 if (is32bit) {
01551
01552
01553
01554 _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
01555
01556
01557
01558 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
01559 } else {
01560
01561
01562
01563 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
01564 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
01565 }
01566 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
01567
01568
01569
01570 _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
01571 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
01572 }
01573
01574
01575
01576
01577 if (SDL_MUSTLOCK(rz_src)) {
01578 SDL_UnlockSurface(rz_src);
01579 }
01580
01581
01582
01583
01584 if (src_converted) {
01585 SDL_FreeSurface(rz_src);
01586 }
01587
01588
01589
01590
01591 rz_dst->h -= GUARD_ROWS;
01592 return (rz_dst);
01593 }