|
Atrinik Client 2.5
|
00001 /* 00002 00003 SDL_rotozoom.c - rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces 00004 00005 LGPL (c) A. Schiffler 00006 00007 */ 00008 00009 #include <global.h> 00010 00011 /* ---- Internally used structures */ 00012 00016 typedef struct tColorRGBA { 00017 Uint8 r; 00018 Uint8 g; 00019 Uint8 b; 00020 Uint8 a; 00021 } tColorRGBA; 00022 00026 typedef struct tColorY { 00027 Uint8 y; 00028 } tColorY; 00029 00040 #define GUARD_ROWS (2) 00041 00045 #define VALUE_LIMIT 0.001 00046 00050 Uint32 _colorkey(SDL_Surface *src) 00051 { 00052 Uint32 key = 0; 00053 #if (SDL_MINOR_VERSION == 3) 00054 SDL_GetColorKey(src, &key); 00055 #else 00056 if (src) 00057 { 00058 key = src->format->colorkey; 00059 } 00060 #endif 00061 return key; 00062 } 00063 00064 00080 int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) 00081 { 00082 int x, y, dx, dy, dgap, ra, ga, ba, aa; 00083 int n_average; 00084 tColorRGBA *sp, *osp, *oosp; 00085 tColorRGBA *dp; 00086 00087 /* 00088 * Averaging integer shrink 00089 */ 00090 00091 /* Precalculate division factor */ 00092 n_average = factorx*factory; 00093 00094 /* 00095 * Scan destination 00096 */ 00097 sp = (tColorRGBA *) src->pixels; 00098 00099 dp = (tColorRGBA *) dst->pixels; 00100 dgap = dst->pitch - dst->w * 4; 00101 00102 for (y = 0; y < dst->h; y++) { 00103 00104 osp=sp; 00105 for (x = 0; x < dst->w; x++) { 00106 00107 /* Trace out source box and accumulate */ 00108 oosp=sp; 00109 ra=ga=ba=aa=0; 00110 for (dy=0; dy < factory; dy++) { 00111 for (dx=0; dx < factorx; dx++) { 00112 ra += sp->r; 00113 ga += sp->g; 00114 ba += sp->b; 00115 aa += sp->a; 00116 00117 sp++; 00118 } 00119 /* src dx loop */ 00120 sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); /* next y */ 00121 } 00122 /* src dy loop */ 00123 00124 /* next box-x */ 00125 sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx); 00126 00127 /* Store result in destination */ 00128 dp->r = ra/n_average; 00129 dp->g = ga/n_average; 00130 dp->b = ba/n_average; 00131 dp->a = aa/n_average; 00132 00133 /* 00134 * Advance destination pointer 00135 */ 00136 dp++; 00137 } 00138 /* dst x loop */ 00139 00140 /* next box-y */ 00141 sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory); 00142 00143 /* 00144 * Advance destination pointers 00145 */ 00146 dp = (tColorRGBA *) ((Uint8 *) dp + dgap); 00147 } 00148 /* dst y loop */ 00149 00150 return (0); 00151 } 00152 00168 int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) 00169 { 00170 int x, y, dx, dy, dgap, a; 00171 int n_average; 00172 Uint8 *sp, *osp, *oosp; 00173 Uint8 *dp; 00174 00175 /* 00176 * Averaging integer shrink 00177 */ 00178 00179 /* Precalculate division factor */ 00180 n_average = factorx*factory; 00181 00182 /* 00183 * Scan destination 00184 */ 00185 sp = (Uint8 *) src->pixels; 00186 00187 dp = (Uint8 *) dst->pixels; 00188 dgap = dst->pitch - dst->w; 00189 00190 for (y = 0; y < dst->h; y++) { 00191 00192 osp=sp; 00193 for (x = 0; x < dst->w; x++) { 00194 00195 /* Trace out source box and accumulate */ 00196 oosp=sp; 00197 a=0; 00198 for (dy=0; dy < factory; dy++) { 00199 for (dx=0; dx < factorx; dx++) { 00200 a += (*sp); 00201 /* next x */ 00202 sp++; 00203 } 00204 /* end src dx loop */ 00205 /* next y */ 00206 sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx)); 00207 } 00208 /* end src dy loop */ 00209 00210 /* next box-x */ 00211 sp = (Uint8 *)((Uint8*)oosp + factorx); 00212 00213 /* Store result in destination */ 00214 *dp = a/n_average; 00215 00216 /* 00217 * Advance destination pointer 00218 */ 00219 dp++; 00220 } 00221 /* end dst x loop */ 00222 00223 /* next box-y */ 00224 sp = (Uint8 *)((Uint8*)osp + src->pitch*factory); 00225 00226 /* 00227 * Advance destination pointers 00228 */ 00229 dp = (Uint8 *)((Uint8 *)dp + dgap); 00230 } 00231 /* end dst y loop */ 00232 00233 return (0); 00234 } 00235 00251 int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth) 00252 { 00253 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, lx, ly; 00254 tColorRGBA *c00, *c01, *c10, *c11, *cswap; 00255 tColorRGBA *sp, *csp, *dp; 00256 int dgap; 00257 00258 /* 00259 * Variable setup 00260 */ 00261 if (smooth) { 00262 /* 00263 * For interpolation: assume source dimension is one pixel 00264 * smaller to avoid overflow on right and bottom edge. 00265 */ 00266 sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); 00267 sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); 00268 } else { 00269 sx = (int) (65536.0 * (float) src->w / (float) dst->w); 00270 sy = (int) (65536.0 * (float) src->h / (float) dst->h); 00271 } 00272 00273 /* 00274 * Allocate memory for row increments 00275 */ 00276 if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { 00277 return (-1); 00278 } 00279 if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { 00280 free(sax); 00281 return (-1); 00282 } 00283 00284 /* 00285 * Precalculate row increments 00286 */ 00287 sp = csp = (tColorRGBA *) src->pixels; 00288 dp = (tColorRGBA *) dst->pixels; 00289 00290 if (flipx) csp += (src->w-1); 00291 if (flipy) csp += ((src->pitch/4)*(src->h-1)); 00292 00293 csx = 0; 00294 csax = sax; 00295 for (x = 0; x <= dst->w; x++) { 00296 *csax = csx; 00297 csax++; 00298 csx &= 0xffff; 00299 csx += sx; 00300 } 00301 csy = 0; 00302 csay = say; 00303 for (y = 0; y <= dst->h; y++) { 00304 *csay = csy; 00305 csay++; 00306 csy &= 0xffff; 00307 csy += sy; 00308 } 00309 00310 dgap = dst->pitch - dst->w * 4; 00311 00312 /* 00313 * Switch between interpolating and non-interpolating code 00314 */ 00315 if (smooth) { 00316 00317 /* 00318 * Interpolating Zoom 00319 */ 00320 00321 /* 00322 * Scan destination 00323 */ 00324 csay = say; 00325 ly = 0; 00326 for (y = 0; y < dst->h; y++) { 00327 /* 00328 * Setup color source pointers 00329 */ 00330 c00 = csp; 00331 c01 = csp; 00332 c01++; 00333 c10 = csp; 00334 c10 += src->pitch/4; 00335 c11 = c10; 00336 c11++; 00337 if (flipx) { 00338 cswap = c00; c00=c01; c01=cswap; 00339 cswap = c10; c10=c11; c11=cswap; 00340 } 00341 if (flipy) { 00342 cswap = c00; c00=c10; c10=cswap; 00343 cswap = c01; c01=c11; c11=cswap; 00344 } 00345 00346 csax = sax; 00347 lx = 0; 00348 for (x = 0; x < dst->w; x++) { 00349 /* 00350 * Draw and interpolate colors 00351 */ 00352 ex = (*csax & 0xffff); 00353 ey = (*csay & 0xffff); 00354 t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; 00355 t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; 00356 dp->r = (((t2 - t1) * ey) >> 16) + t1; 00357 t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; 00358 t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; 00359 dp->g = (((t2 - t1) * ey) >> 16) + t1; 00360 t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; 00361 t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; 00362 dp->b = (((t2 - t1) * ey) >> 16) + t1; 00363 t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; 00364 t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; 00365 dp->a = (((t2 - t1) * ey) >> 16) + t1; 00366 00367 /* 00368 * Advance source pointers 00369 */ 00370 csax++; 00371 if (*csax > 0) 00372 { 00373 sstep = (*csax >> 16); 00374 lx += sstep; 00375 if (flipx) sstep = -sstep; 00376 if (lx <= src->w) 00377 { 00378 c00 += sstep; 00379 c01 += sstep; 00380 c10 += sstep; 00381 c11 += sstep; 00382 } 00383 } 00384 00385 /* 00386 * Advance destination pointer 00387 */ 00388 dp++; 00389 } 00390 00391 /* 00392 * Advance source pointer 00393 */ 00394 csay++; 00395 if (*csay > 0) 00396 { 00397 sstep = (*csay >> 16); 00398 ly += sstep; 00399 if (flipy) sstep = -sstep; 00400 if (ly < src->h) 00401 { 00402 csp += (sstep * (src->pitch/4)); 00403 } 00404 } 00405 00406 /* 00407 * Advance destination pointers 00408 */ 00409 dp = (tColorRGBA *) ((Uint8 *) dp + dgap); 00410 } 00411 } else { 00412 00413 /* 00414 * Non-Interpolating Zoom 00415 */ 00416 csay = say; 00417 for (y = 0; y < dst->h; y++) { 00418 sp = csp; 00419 csax = sax; 00420 for (x = 0; x < dst->w; x++) { 00421 /* 00422 * Draw 00423 */ 00424 *dp = *sp; 00425 /* 00426 * Advance source pointers 00427 */ 00428 csax++; 00429 if (*csax > 0) 00430 { 00431 sstep = (*csax >> 16); 00432 if (flipx) sstep = -sstep; 00433 sp += sstep; 00434 } 00435 /* 00436 * Advance destination pointer 00437 */ 00438 dp++; 00439 } 00440 /* 00441 * Advance source pointer 00442 */ 00443 csay++; 00444 if (*csay > 0) 00445 { 00446 sstep = (*csay >> 16) * (src->pitch/4); 00447 if (flipy) sstep = -sstep; 00448 csp += sstep; 00449 } 00450 00451 /* 00452 * Advance destination pointers 00453 */ 00454 dp = (tColorRGBA *) ((Uint8 *) dp + dgap); 00455 } 00456 } 00457 00458 /* 00459 * Remove temp arrays 00460 */ 00461 free(sax); 00462 free(say); 00463 00464 return (0); 00465 } 00466 00482 int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy) 00483 { 00484 int x, y; 00485 Uint32 *sax, *say, *csax, *csay; 00486 int csx, csy; 00487 Uint8 *sp, *dp, *csp; 00488 int dgap; 00489 00490 /* 00491 * Allocate memory for row increments 00492 */ 00493 if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { 00494 return (-1); 00495 } 00496 if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { 00497 free(sax); 00498 return (-1); 00499 } 00500 00501 /* 00502 * Pointer setup 00503 */ 00504 sp = csp = (Uint8 *) src->pixels; 00505 dp = (Uint8 *) dst->pixels; 00506 dgap = dst->pitch - dst->w; 00507 00508 if (flipx) csp += (src->w-1); 00509 if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) ); 00510 00511 /* 00512 * Precalculate row increments 00513 */ 00514 csx = 0; 00515 csax = sax; 00516 for (x = 0; x < dst->w; x++) { 00517 csx += src->w; 00518 *csax = 0; 00519 while (csx >= dst->w) { 00520 csx -= dst->w; 00521 (*csax)++; 00522 } 00523 csax++; 00524 } 00525 csy = 0; 00526 csay = say; 00527 for (y = 0; y < dst->h; y++) { 00528 csy += src->h; 00529 *csay = 0; 00530 while (csy >= dst->h) { 00531 csy -= dst->h; 00532 (*csay)++; 00533 } 00534 csay++; 00535 } 00536 00537 /* 00538 * Draw 00539 */ 00540 csay = say; 00541 for (y = 0; y < dst->h; y++) { 00542 csax = sax; 00543 sp = csp; 00544 for (x = 0; x < dst->w; x++) { 00545 /* 00546 * Draw 00547 */ 00548 *dp = *sp; 00549 /* 00550 * Advance source pointers 00551 */ 00552 sp += (*csax) * (flipx ? -1 : 1); 00553 csax++; 00554 /* 00555 * Advance destination pointer 00556 */ 00557 dp++; 00558 } 00559 /* 00560 * Advance source pointer (for row) 00561 */ 00562 csp += ((*csay) * src->pitch) * (flipy ? -1 : 1); 00563 csay++; 00564 00565 /* 00566 * Advance destination pointers 00567 */ 00568 dp += dgap; 00569 } 00570 00571 /* 00572 * Remove temp arrays 00573 */ 00574 free(sax); 00575 free(say); 00576 00577 return (0); 00578 } 00579 00599 void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth) 00600 { 00601 int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh; 00602 tColorRGBA c00, c01, c10, c11, cswap; 00603 tColorRGBA *pc, *sp; 00604 int gap; 00605 00606 /* 00607 * Variable setup 00608 */ 00609 xd = ((src->w - dst->w) << 15); 00610 yd = ((src->h - dst->h) << 15); 00611 ax = (cx << 16) - (icos * cx); 00612 ay = (cy << 16) - (isin * cx); 00613 sw = src->w - 1; 00614 sh = src->h - 1; 00615 pc = (tColorRGBA*) dst->pixels; 00616 gap = dst->pitch - dst->w * 4; 00617 00618 /* 00619 * Switch between interpolating and non-interpolating code 00620 */ 00621 if (smooth) { 00622 for (y = 0; y < dst->h; y++) { 00623 dy = cy - y; 00624 sdx = (ax + (isin * dy)) + xd; 00625 sdy = (ay - (icos * dy)) + yd; 00626 for (x = 0; x < dst->w; x++) { 00627 dx = (sdx >> 16); 00628 dy = (sdy >> 16); 00629 if (flipx) dx = sw - dx; 00630 if (flipy) dy = sh - dy; 00631 if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) { 00632 sp = (tColorRGBA *)src->pixels;; 00633 sp += ((src->pitch/4) * dy); 00634 sp += dx; 00635 c00 = *sp; 00636 sp += 1; 00637 c01 = *sp; 00638 sp += (src->pitch/4); 00639 c11 = *sp; 00640 sp -= 1; 00641 c10 = *sp; 00642 if (flipx) { 00643 cswap = c00; c00=c01; c01=cswap; 00644 cswap = c10; c10=c11; c11=cswap; 00645 } 00646 if (flipy) { 00647 cswap = c00; c00=c10; c10=cswap; 00648 cswap = c01; c01=c11; c11=cswap; 00649 } 00650 /* 00651 * Interpolate colors 00652 */ 00653 ex = (sdx & 0xffff); 00654 ey = (sdy & 0xffff); 00655 t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; 00656 t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; 00657 pc->r = (((t2 - t1) * ey) >> 16) + t1; 00658 t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; 00659 t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; 00660 pc->g = (((t2 - t1) * ey) >> 16) + t1; 00661 t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; 00662 t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; 00663 pc->b = (((t2 - t1) * ey) >> 16) + t1; 00664 t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; 00665 t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; 00666 pc->a = (((t2 - t1) * ey) >> 16) + t1; 00667 } 00668 sdx += icos; 00669 sdy += isin; 00670 pc++; 00671 } 00672 pc = (tColorRGBA *) ((Uint8 *) pc + gap); 00673 } 00674 } else { 00675 for (y = 0; y < dst->h; y++) { 00676 dy = cy - y; 00677 sdx = (ax + (isin * dy)) + xd; 00678 sdy = (ay - (icos * dy)) + yd; 00679 for (x = 0; x < dst->w; x++) { 00680 dx = (short) (sdx >> 16); 00681 dy = (short) (sdy >> 16); 00682 if (flipx) dx = (src->w-1)-dx; 00683 if (flipy) dy = (src->h-1)-dy; 00684 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { 00685 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); 00686 sp += dx; 00687 *pc = *sp; 00688 } 00689 sdx += icos; 00690 sdy += isin; 00691 pc++; 00692 } 00693 pc = (tColorRGBA *) ((Uint8 *) pc + gap); 00694 } 00695 } 00696 } 00697 00716 void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy) 00717 { 00718 int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay; 00719 tColorY *pc, *sp; 00720 int gap; 00721 00722 /* 00723 * Variable setup 00724 */ 00725 xd = ((src->w - dst->w) << 15); 00726 yd = ((src->h - dst->h) << 15); 00727 ax = (cx << 16) - (icos * cx); 00728 ay = (cy << 16) - (isin * cx); 00729 pc = (tColorY*) dst->pixels; 00730 gap = dst->pitch - dst->w; 00731 /* 00732 * Clear surface to colorkey 00733 */ 00734 memset(pc, (unsigned char) (_colorkey(src) & 0xff), dst->pitch * dst->h); 00735 /* 00736 * Iterate through destination surface 00737 */ 00738 for (y = 0; y < dst->h; y++) { 00739 dy = cy - y; 00740 sdx = (ax + (isin * dy)) + xd; 00741 sdy = (ay - (icos * dy)) + yd; 00742 for (x = 0; x < dst->w; x++) { 00743 dx = (short) (sdx >> 16); 00744 dy = (short) (sdy >> 16); 00745 if (flipx) dx = (src->w-1)-dx; 00746 if (flipy) dy = (src->h-1)-dy; 00747 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { 00748 sp = (tColorY *) (src->pixels); 00749 sp += (src->pitch * dy + dx); 00750 *pc = *sp; 00751 } 00752 sdx += icos; 00753 sdy += isin; 00754 pc++; 00755 } 00756 pc += gap; 00757 } 00758 } 00759 00773 SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns) 00774 { 00775 int row, col, newWidth, newHeight; 00776 int bpp, src_ipr, dst_ipr; 00777 SDL_Surface* dst; 00778 Uint32* srcBuf; 00779 Uint32* dstBuf; 00780 00781 /* Has to be a valid surface pointer and only 32-bit surfaces (for now) */ 00782 if (!src || src->format->BitsPerPixel != 32) { return NULL; } 00783 00784 /* normalize numClockwiseTurns */ 00785 while(numClockwiseTurns < 0) { numClockwiseTurns += 4; } 00786 numClockwiseTurns = (numClockwiseTurns % 4); 00787 00788 /* if it's even, our new width will be the same as the source surface */ 00789 newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w); 00790 newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h); 00791 dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel, 00792 src->format->Rmask, 00793 src->format->Gmask, 00794 src->format->Bmask, 00795 src->format->Amask); 00796 if(!dst) { 00797 return NULL; 00798 } 00799 00800 if (SDL_MUSTLOCK(dst)) { 00801 SDL_LockSurface(dst); 00802 } 00803 if (SDL_MUSTLOCK(dst)) { 00804 SDL_LockSurface(dst); 00805 } 00806 00807 /* Calculate int-per-row */ 00808 bpp = src->format->BitsPerPixel / 8; 00809 src_ipr = src->pitch / bpp; 00810 dst_ipr = dst->pitch / bpp; 00811 00812 switch(numClockwiseTurns) { 00813 case 0: /* Make a copy of the surface */ 00814 { 00815 /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface 00816 since it does not preserve alpha. */ 00817 00818 if (src->pitch == dst->pitch) { 00819 /* If the pitch is the same for both surfaces, the memory can be copied all at once. */ 00820 memcpy(dst->pixels, src->pixels, (src->h * src->pitch)); 00821 } 00822 else 00823 { 00824 /* If the pitch differs, copy each row separately */ 00825 srcBuf = (Uint32*)(src->pixels); 00826 dstBuf = (Uint32*)(dst->pixels); 00827 for (row = 0; row < src->h; row++) { 00828 memcpy(dstBuf, srcBuf, dst->w * bpp); 00829 srcBuf += src_ipr; 00830 dstBuf += dst_ipr; 00831 } /* end for(col) */ 00832 } /* end for(row) */ 00833 } 00834 break; 00835 00836 /* rotate clockwise */ 00837 case 1: /* rotated 90 degrees clockwise */ 00838 { 00839 for (row = 0; row < src->h; ++row) { 00840 srcBuf = (Uint32*)(src->pixels) + (row * src_ipr); 00841 dstBuf = (Uint32*)(dst->pixels) + (dst->w - row - 1); 00842 for (col = 0; col < src->w; ++col) { 00843 *dstBuf = *srcBuf; 00844 ++srcBuf; 00845 dstBuf += dst_ipr; 00846 } 00847 /* end for(col) */ 00848 } 00849 /* end for(row) */ 00850 } 00851 break; 00852 00853 case 2: /* rotated 180 degrees clockwise */ 00854 { 00855 for (row = 0; row < src->h; ++row) { 00856 srcBuf = (Uint32*)(src->pixels) + (row * src_ipr); 00857 dstBuf = (Uint32*)(dst->pixels) + ((dst->h - row - 1) * dst_ipr) + (dst->w - 1); 00858 for (col = 0; col < src->w; ++col) { 00859 *dstBuf = *srcBuf; 00860 ++srcBuf; 00861 --dstBuf; 00862 } 00863 } 00864 } 00865 break; 00866 00867 case 3: 00868 { 00869 for (row = 0; row < src->h; ++row) { 00870 srcBuf = (Uint32*)(src->pixels) + (row * src_ipr); 00871 dstBuf = (Uint32*)(dst->pixels) + row + ((dst->h - 1) * dst_ipr); 00872 for (col = 0; col < src->w; ++col) { 00873 *dstBuf = *srcBuf; 00874 ++srcBuf; 00875 dstBuf -= dst_ipr; 00876 } 00877 } 00878 } 00879 break; 00880 } 00881 /* end switch */ 00882 00883 if (SDL_MUSTLOCK(src)) { 00884 SDL_UnlockSurface(src); 00885 } 00886 if (SDL_MUSTLOCK(dst)) { 00887 SDL_UnlockSurface(dst); 00888 } 00889 00890 return dst; 00891 } 00892 00893 00908 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, 00909 int *dstwidth, int *dstheight, 00910 double *canglezoom, double *sanglezoom) 00911 { 00912 double x, y, cx, cy, sx, sy; 00913 double radangle; 00914 double dstwidthhalf, dstheighthalf; 00915 00916 (void) zoomy; 00917 00918 /* 00919 * Determine destination width and height by rotating a centered source box 00920 */ 00921 radangle = angle * (M_PI / 180.0); 00922 *sanglezoom = sin(radangle); 00923 *canglezoom = cos(radangle); 00924 *sanglezoom *= zoomx; 00925 *canglezoom *= zoomx; 00926 x = width / 2; 00927 y = height / 2; 00928 cx = *canglezoom * x; 00929 cy = *canglezoom * y; 00930 sx = *sanglezoom * x; 00931 sy = *sanglezoom * y; 00932 00933 dstwidthhalf = MAX(ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1); 00934 dstheighthalf = MAX(ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1); 00935 *dstwidth = (int) (dstwidthhalf * 2.0); 00936 *dstheight = (int) (dstheighthalf * 2.0); 00937 } 00938 00950 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight) 00951 { 00952 double dummy_sanglezoom, dummy_canglezoom; 00953 00954 _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); 00955 } 00956 00967 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight) 00968 { 00969 double dummy_sanglezoom, dummy_canglezoom; 00970 00971 _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); 00972 } 00973 00989 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth) 00990 { 00991 return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth); 00992 } 00993 01010 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth) 01011 { 01012 SDL_Surface *rz_src; 01013 SDL_Surface *rz_dst; 01014 double zoominv; 01015 double sanglezoom, canglezoom, sanglezoominv, canglezoominv; 01016 int dstwidthhalf, dstwidth, dstheighthalf, dstheight; 01017 int is32bit; 01018 int i, src_converted; 01019 int flipx,flipy; 01020 Uint8 r,g,b; 01021 Uint32 colorkey = 0; 01022 int colorKeyAvailable = 0; 01023 01024 /* 01025 * Sanity check 01026 */ 01027 if (src == NULL) 01028 return (NULL); 01029 01030 if (src->flags & SDL_SRCCOLORKEY) 01031 { 01032 colorkey = _colorkey(src); 01033 SDL_GetRGB(colorkey, src->format, &r, &g, &b); 01034 colorKeyAvailable = 1; 01035 } 01036 /* 01037 * Determine if source surface is 32bit or 8bit 01038 */ 01039 is32bit = (src->format->BitsPerPixel == 32); 01040 if ((is32bit) || (src->format->BitsPerPixel == 8)) { 01041 /* 01042 * Use source surface 'as is' 01043 */ 01044 rz_src = src; 01045 src_converted = 0; 01046 } else { 01047 /* 01048 * New source surface is 32bit with a defined RGBA ordering 01049 */ 01050 rz_src = 01051 SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 01052 #if SDL_BYTEORDER == SDL_LIL_ENDIAN 01053 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 01054 #else 01055 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff 01056 #endif 01057 ); 01058 if(colorKeyAvailable) 01059 SDL_SetColorKey(src, 0, 0); 01060 01061 SDL_BlitSurface(src, NULL, rz_src, NULL); 01062 01063 if(colorKeyAvailable) 01064 SDL_SetColorKey(src, SDL_SRCCOLORKEY, colorkey); 01065 src_converted = 1; 01066 is32bit = 1; 01067 } 01068 01069 /* 01070 * Sanity check zoom factor 01071 */ 01072 flipx = (zoomx<0.0); 01073 if (flipx) zoomx=-zoomx; 01074 flipy = (zoomy<0.0); 01075 if (flipy) zoomy=-zoomy; 01076 if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT; 01077 if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT; 01078 zoominv = 65536.0 / (zoomx * zoomx); 01079 01080 /* 01081 * Check if we have a rotozoom or just a zoom 01082 */ 01083 if (fabs(angle) > VALUE_LIMIT) { 01084 01085 /* 01086 * Angle!=0: full rotozoom 01087 */ 01088 /* 01089 * ----------------------- 01090 */ 01091 01092 /* Determine target size */ 01093 _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom); 01094 01095 /* 01096 * Calculate target factors from sin/cos and zoom 01097 */ 01098 sanglezoominv = sanglezoom; 01099 canglezoominv = canglezoom; 01100 sanglezoominv *= zoominv; 01101 canglezoominv *= zoominv; 01102 01103 /* Calculate half size */ 01104 dstwidthhalf = dstwidth / 2; 01105 dstheighthalf = dstheight / 2; 01106 01107 /* 01108 * Alloc space to completely contain the rotated surface 01109 */ 01110 rz_dst = NULL; 01111 if (is32bit) { 01112 /* 01113 * Target surface is 32bit with source RGBA/ABGR ordering 01114 */ 01115 rz_dst = 01116 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, 01117 rz_src->format->Rmask, rz_src->format->Gmask, 01118 rz_src->format->Bmask, rz_src->format->Amask); 01119 } else { 01120 /* 01121 * Target surface is 8bit 01122 */ 01123 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); 01124 } 01125 01126 /* Check target */ 01127 if (rz_dst == NULL) 01128 return NULL; 01129 01130 /* Adjust for guard rows */ 01131 rz_dst->h = dstheight; 01132 01133 if (colorKeyAvailable == 1){ 01134 colorkey = SDL_MapRGB(rz_dst->format, r, g, b); 01135 01136 SDL_FillRect(rz_dst, NULL, colorkey ); 01137 } 01138 01139 /* 01140 * Lock source surface 01141 */ 01142 if (SDL_MUSTLOCK(rz_src)) { 01143 SDL_LockSurface(rz_src); 01144 } 01145 01146 /* 01147 * Check which kind of surface we have 01148 */ 01149 if (is32bit) { 01150 /* 01151 * Call the 32bit transformation routine to do the rotation (using alpha) 01152 */ 01153 _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf, 01154 (int) (sanglezoominv), (int) (canglezoominv), 01155 flipx, flipy, 01156 smooth); 01157 /* 01158 * Turn on source-alpha support 01159 */ 01160 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); 01161 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); 01162 } else { 01163 /* 01164 * Copy palette and colorkey info 01165 */ 01166 for (i = 0; i < rz_src->format->palette->ncolors; i++) { 01167 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; 01168 } 01169 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; 01170 /* 01171 * Call the 8bit transformation routine to do the rotation 01172 */ 01173 transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf, 01174 (int) (sanglezoominv), (int) (canglezoominv), 01175 flipx, flipy); 01176 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); 01177 } 01178 /* 01179 * Unlock source surface 01180 */ 01181 if (SDL_MUSTLOCK(rz_src)) { 01182 SDL_UnlockSurface(rz_src); 01183 } 01184 01185 } else { 01186 01187 /* 01188 * Angle=0: Just a zoom 01189 */ 01190 /* 01191 * -------------------- 01192 */ 01193 01194 /* 01195 * Calculate target size 01196 */ 01197 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); 01198 01199 /* 01200 * Alloc space to completely contain the zoomed surface 01201 */ 01202 rz_dst = NULL; 01203 if (is32bit) { 01204 /* 01205 * Target surface is 32bit with source RGBA/ABGR ordering 01206 */ 01207 rz_dst = 01208 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, 01209 rz_src->format->Rmask, rz_src->format->Gmask, 01210 rz_src->format->Bmask, rz_src->format->Amask); 01211 } else { 01212 /* 01213 * Target surface is 8bit 01214 */ 01215 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); 01216 } 01217 01218 /* Check target */ 01219 if (rz_dst == NULL) 01220 return NULL; 01221 01222 /* Adjust for guard rows */ 01223 rz_dst->h = dstheight; 01224 01225 if (colorKeyAvailable == 1){ 01226 colorkey = SDL_MapRGB(rz_dst->format, r, g, b); 01227 01228 SDL_FillRect(rz_dst, NULL, colorkey ); 01229 } 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 /* 01248 * Turn on source-alpha support 01249 */ 01250 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); 01251 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); 01252 } else { 01253 /* 01254 * Copy palette and colorkey info 01255 */ 01256 for (i = 0; i < rz_src->format->palette->ncolors; i++) { 01257 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; 01258 } 01259 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; 01260 01261 /* 01262 * Call the 8bit transformation routine to do the zooming 01263 */ 01264 _zoomSurfaceY(rz_src, rz_dst, flipx, flipy); 01265 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); 01266 } 01267 01268 /* 01269 * Unlock source surface 01270 */ 01271 if (SDL_MUSTLOCK(rz_src)) { 01272 SDL_UnlockSurface(rz_src); 01273 } 01274 } 01275 01276 /* 01277 * Cleanup temp surface 01278 */ 01279 if (src_converted) { 01280 SDL_FreeSurface(rz_src); 01281 } 01282 01283 /* 01284 * Return destination surface 01285 */ 01286 return (rz_dst); 01287 } 01288 01301 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) 01302 { 01303 /* 01304 * Make zoom factors positive 01305 */ 01306 int flipx, flipy; 01307 flipx = (zoomx<0.0); 01308 if (flipx) zoomx = -zoomx; 01309 flipy = (zoomy<0.0); 01310 if (flipy) zoomy = -zoomy; 01311 01312 /* 01313 * Sanity check zoom factors 01314 */ 01315 if (zoomx < VALUE_LIMIT) { 01316 zoomx = VALUE_LIMIT; 01317 } 01318 if (zoomy < VALUE_LIMIT) { 01319 zoomy = VALUE_LIMIT; 01320 } 01321 01322 /* 01323 * Calculate target size 01324 */ 01325 *dstwidth = (int) ((double) width * zoomx); 01326 *dstheight = (int) ((double) height * zoomy); 01327 if (*dstwidth < 1) { 01328 *dstwidth = 1; 01329 } 01330 if (*dstheight < 1) { 01331 *dstheight = 1; 01332 } 01333 } 01334 01351 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth) 01352 { 01353 SDL_Surface *rz_src; 01354 SDL_Surface *rz_dst; 01355 int dstwidth, dstheight; 01356 int is32bit; 01357 int i, src_converted; 01358 int flipx, flipy; 01359 01360 /* 01361 * Sanity check 01362 */ 01363 if (src == NULL) 01364 return (NULL); 01365 01366 /* 01367 * Determine if source surface is 32bit or 8bit 01368 */ 01369 is32bit = (src->format->BitsPerPixel == 32); 01370 if ((is32bit) || (src->format->BitsPerPixel == 8)) { 01371 /* 01372 * Use source surface 'as is' 01373 */ 01374 rz_src = src; 01375 src_converted = 0; 01376 } else { 01377 /* 01378 * New source surface is 32bit with a defined RGBA ordering 01379 */ 01380 rz_src = 01381 SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 01382 #if SDL_BYTEORDER == SDL_LIL_ENDIAN 01383 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 01384 #else 01385 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff 01386 #endif 01387 ); 01388 SDL_BlitSurface(src, NULL, rz_src, NULL); 01389 src_converted = 1; 01390 is32bit = 1; 01391 } 01392 01393 flipx = (zoomx<0.0); 01394 if (flipx) zoomx = -zoomx; 01395 flipy = (zoomy<0.0); 01396 if (flipy) zoomy = -zoomy; 01397 01398 /* Get size if target */ 01399 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); 01400 01401 /* 01402 * Alloc space to completely contain the zoomed surface 01403 */ 01404 rz_dst = NULL; 01405 if (is32bit) { 01406 /* 01407 * Target surface is 32bit with source RGBA/ABGR ordering 01408 */ 01409 rz_dst = 01410 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, 01411 rz_src->format->Rmask, rz_src->format->Gmask, 01412 rz_src->format->Bmask, rz_src->format->Amask); 01413 } else { 01414 /* 01415 * Target surface is 8bit 01416 */ 01417 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); 01418 } 01419 01420 /* Check target */ 01421 if (rz_dst == NULL) 01422 return NULL; 01423 01424 /* Adjust for guard rows */ 01425 rz_dst->h = dstheight; 01426 01427 /* 01428 * Lock source surface 01429 */ 01430 if (SDL_MUSTLOCK(rz_src)) { 01431 SDL_LockSurface(rz_src); 01432 } 01433 01434 /* 01435 * Check which kind of surface we have 01436 */ 01437 if (is32bit) { 01438 /* 01439 * Call the 32bit transformation routine to do the zooming (using alpha) 01440 */ 01441 _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); 01442 /* 01443 * Turn on source-alpha support 01444 */ 01445 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); 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 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); 01459 } 01460 /* 01461 * Unlock source surface 01462 */ 01463 if (SDL_MUSTLOCK(rz_src)) { 01464 SDL_UnlockSurface(rz_src); 01465 } 01466 01467 /* 01468 * Cleanup temp surface 01469 */ 01470 if (src_converted) { 01471 SDL_FreeSurface(rz_src); 01472 } 01473 01474 /* 01475 * Return destination surface 01476 */ 01477 return (rz_dst); 01478 } 01479 01496 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory) 01497 { 01498 SDL_Surface *rz_src; 01499 SDL_Surface *rz_dst; 01500 int dstwidth, dstheight; 01501 int is32bit; 01502 int i, src_converted; 01503 01504 /* 01505 * Sanity check 01506 */ 01507 if (src == NULL) 01508 return (NULL); 01509 01510 /* 01511 * Determine if source surface is 32bit or 8bit 01512 */ 01513 is32bit = (src->format->BitsPerPixel == 32); 01514 if ((is32bit) || (src->format->BitsPerPixel == 8)) { 01515 /* 01516 * Use source surface 'as is' 01517 */ 01518 rz_src = src; 01519 src_converted = 0; 01520 } else { 01521 /* 01522 * New source surface is 32bit with a defined RGBA ordering 01523 */ 01524 rz_src = 01525 SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 01526 #if SDL_BYTEORDER == SDL_LIL_ENDIAN 01527 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 01528 #else 01529 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff 01530 #endif 01531 ); 01532 SDL_BlitSurface(src, NULL, rz_src, NULL); 01533 src_converted = 1; 01534 is32bit = 1; 01535 } 01536 01537 /* Get size for target */ 01538 dstwidth=rz_src->w/factorx; 01539 while (dstwidth*factorx>rz_src->w) { dstwidth--; } 01540 dstheight=rz_src->h/factory; 01541 while (dstheight*factory>rz_src->h) { dstheight--; } 01542 01543 /* 01544 * Alloc space to completely contain the shrunken surface 01545 * (with added guard rows) 01546 */ 01547 rz_dst = NULL; 01548 if (is32bit) { 01549 /* 01550 * Target surface is 32bit with source RGBA/ABGR ordering 01551 */ 01552 rz_dst = 01553 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, 01554 rz_src->format->Rmask, rz_src->format->Gmask, 01555 rz_src->format->Bmask, rz_src->format->Amask); 01556 } else { 01557 /* 01558 * Target surface is 8bit 01559 */ 01560 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); 01561 } 01562 01563 /* Check target */ 01564 if (rz_dst == NULL) 01565 return NULL; 01566 01567 /* Adjust for guard rows */ 01568 rz_dst->h = dstheight; 01569 01570 /* 01571 * Lock source surface 01572 */ 01573 if (SDL_MUSTLOCK(rz_src)) { 01574 SDL_LockSurface(rz_src); 01575 } 01576 01577 /* 01578 * Check which kind of surface we have 01579 */ 01580 if (is32bit) { 01581 /* 01582 * Call the 32bit transformation routine to do the shrinking (using alpha) 01583 */ 01584 _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory); 01585 /* 01586 * Turn on source-alpha support 01587 */ 01588 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); 01589 } else { 01590 /* 01591 * Copy palette and colorkey info 01592 */ 01593 for (i = 0; i < rz_src->format->palette->ncolors; i++) { 01594 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; 01595 } 01596 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; 01597 /* 01598 * Call the 8bit transformation routine to do the shrinking 01599 */ 01600 _shrinkSurfaceY(rz_src, rz_dst, factorx, factory); 01601 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); 01602 } 01603 01604 /* 01605 * Unlock source surface 01606 */ 01607 if (SDL_MUSTLOCK(rz_src)) { 01608 SDL_UnlockSurface(rz_src); 01609 } 01610 01611 /* 01612 * Cleanup temp surface 01613 */ 01614 if (src_converted) { 01615 SDL_FreeSurface(rz_src); 01616 } 01617 01618 /* 01619 * Return destination surface 01620 */ 01621 return (rz_dst); 01622 }
1.7.4