SDL_rotozoom.cpp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. /*
  2. SDL_rotozoom.c - rotozoomer for 32bit or 8bit surfaces
  3. LGPL (c) A. Schiffler
  4. */
  5. #include "stdafx.h"
  6. #ifdef WIN32
  7. #include <windows.h>
  8. #endif
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "SDL_rotozoom.h"
  12. #define MAX(a,b) (((a) > (b)) ? (a) : (b))
  13. /*
  14. 32bit integer-factor averaging Shrinker
  15. Shrinks 32bit RGBA/ABGR 'src' surface to 'dst' surface.
  16. */
  17. int shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
  18. {
  19. int x, y, dx, dy, sgap, dgap, ra, ga, ba, aa;
  20. int n_average;
  21. tColorRGBA *sp, *osp, *oosp;
  22. tColorRGBA *dp;
  23. /*
  24. * Averaging integer shrink
  25. */
  26. /* Precalculate division factor */
  27. n_average = factorx*factory;
  28. /*
  29. * Scan destination
  30. */
  31. sp = (tColorRGBA *) src->pixels;
  32. sgap = src->pitch - src->w * 4;
  33. dp = (tColorRGBA *) dst->pixels;
  34. dgap = dst->pitch - dst->w * 4;
  35. for (y = 0; y < dst->h; y++) {
  36. osp=sp;
  37. for (x = 0; x < dst->w; x++) {
  38. /* Trace out source box and accumulate */
  39. oosp=sp;
  40. ra=ga=ba=aa=0;
  41. for (dy=0; dy < factory; dy++) {
  42. for (dx=0; dx < factorx; dx++) {
  43. ra += sp->r;
  44. ga += sp->g;
  45. ba += sp->b;
  46. aa += sp->a;
  47. sp++;
  48. } // src dx loop
  49. sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y
  50. } // src dy loop
  51. // next box-x
  52. sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx);
  53. /* Store result in destination */
  54. dp->r = ra/n_average;
  55. dp->g = ga/n_average;
  56. dp->b = ba/n_average;
  57. dp->a = aa/n_average;
  58. /*
  59. * Advance destination pointer
  60. */
  61. dp++;
  62. } // dst x loop
  63. // next box-y
  64. sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory);
  65. /*
  66. * Advance destination pointers
  67. */
  68. dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
  69. } // dst y loop
  70. return (0);
  71. }
  72. /*
  73. 8bit integer-factor averaging Shrinker
  74. Shrinks 8bit Y 'src' surface to 'dst' surface.
  75. */
  76. int shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
  77. {
  78. int x, y, dx, dy, sgap, dgap, a;
  79. int n_average;
  80. Uint8 *sp, *osp, *oosp;
  81. Uint8 *dp;
  82. /*
  83. * Averaging integer shrink
  84. */
  85. /* Precalculate division factor */
  86. n_average = factorx*factory;
  87. /*
  88. * Scan destination
  89. */
  90. sp = (Uint8 *) src->pixels;
  91. sgap = src->pitch - src->w;
  92. dp = (Uint8 *) dst->pixels;
  93. dgap = dst->pitch - dst->w;
  94. for (y = 0; y < dst->h; y++) {
  95. osp=sp;
  96. for (x = 0; x < dst->w; x++) {
  97. /* Trace out source box and accumulate */
  98. oosp=sp;
  99. a=0;
  100. for (dy=0; dy < factory; dy++) {
  101. for (dx=0; dx < factorx; dx++) {
  102. a += (*sp);
  103. sp++; // next x
  104. } // src dx loop
  105. sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx)); // next y
  106. } // src dy loop
  107. // next box-x
  108. sp = (Uint8 *)((Uint8*)oosp + factorx);
  109. /* Store result in destination */
  110. *dp = a/n_average;
  111. /*
  112. * Advance destination pointer
  113. */
  114. dp++;
  115. } // dst x loop
  116. // next box-y
  117. sp = (Uint8 *)((Uint8*)osp + src->pitch*factory);
  118. /*
  119. * Advance destination pointers
  120. */
  121. dp = (Uint8 *)((Uint8 *)dp + dgap);
  122. } // dst y loop
  123. return (0);
  124. }
  125. /*
  126. 32bit Zoomer with optional anti-aliasing by bilinear interpolation.
  127. Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
  128. */
  129. int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
  130. {
  131. int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep;
  132. tColorRGBA *c00, *c01, *c10, *c11;
  133. tColorRGBA *sp, *csp, *dp;
  134. int dgap;
  135. /*
  136. * Variable setup
  137. */
  138. if (smooth) {
  139. /*
  140. * For interpolation: assume source dimension is one pixel
  141. */
  142. /*
  143. * smaller to avoid overflow on right and bottom edge.
  144. */
  145. sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
  146. sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
  147. } else {
  148. sx = (int) (65536.0 * (float) src->w / (float) dst->w);
  149. sy = (int) (65536.0 * (float) src->h / (float) dst->h);
  150. }
  151. /*
  152. * Allocate memory for row increments
  153. */
  154. if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
  155. return (-1);
  156. }
  157. if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
  158. free(sax);
  159. return (-1);
  160. }
  161. /*
  162. * Precalculate row increments
  163. */
  164. sp = csp = (tColorRGBA *) src->pixels;
  165. dp = (tColorRGBA *) dst->pixels;
  166. if (flipx) csp += (src->w-1);
  167. if (flipy) csp = (tColorRGBA*)( (Uint8*)csp + src->pitch*(src->h-1) );
  168. csx = 0;
  169. csax = sax;
  170. for (x = 0; x <= dst->w; x++) {
  171. *csax = csx;
  172. csax++;
  173. csx &= 0xffff;
  174. csx += sx;
  175. }
  176. csy = 0;
  177. csay = say;
  178. for (y = 0; y <= dst->h; y++) {
  179. *csay = csy;
  180. csay++;
  181. csy &= 0xffff;
  182. csy += sy;
  183. }
  184. dgap = dst->pitch - dst->w * 4;
  185. /*
  186. * Switch between interpolating and non-interpolating code
  187. */
  188. if (smooth) {
  189. /*
  190. * Interpolating Zoom
  191. */
  192. /*
  193. * Scan destination
  194. */
  195. csay = say;
  196. for (y = 0; y < dst->h; y++) {
  197. /*
  198. * Setup color source pointers
  199. */
  200. c00 = csp;
  201. c01 = csp;
  202. c01++;
  203. c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch);
  204. c11 = c10;
  205. c11++;
  206. csax = sax;
  207. for (x = 0; x < dst->w; x++) {
  208. /*
  209. * Interpolate colors
  210. */
  211. ex = (*csax & 0xffff);
  212. ey = (*csay & 0xffff);
  213. t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
  214. t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
  215. dp->r = (((t2 - t1) * ey) >> 16) + t1;
  216. t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
  217. t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
  218. dp->g = (((t2 - t1) * ey) >> 16) + t1;
  219. t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
  220. t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
  221. dp->b = (((t2 - t1) * ey) >> 16) + t1;
  222. t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
  223. t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
  224. dp->a = (((t2 - t1) * ey) >> 16) + t1;
  225. /*
  226. * Advance source pointers
  227. */
  228. csax++;
  229. sstep = (*csax >> 16);
  230. c00 += sstep;
  231. c01 += sstep;
  232. c10 += sstep;
  233. c11 += sstep;
  234. /*
  235. * Advance destination pointer
  236. */
  237. dp++;
  238. }
  239. /*
  240. * Advance source pointer
  241. */
  242. csay++;
  243. csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
  244. /*
  245. * Advance destination pointers
  246. */
  247. dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
  248. }
  249. } else {
  250. /*
  251. * Non-Interpolating Zoom
  252. */
  253. csay = say;
  254. for (y = 0; y < dst->h; y++) {
  255. sp = csp;
  256. csax = sax;
  257. for (x = 0; x < dst->w; x++) {
  258. /*
  259. * Draw
  260. */
  261. *dp = *sp;
  262. /*
  263. * Advance source pointers
  264. */
  265. csax++;
  266. sstep = (*csax >> 16);
  267. if (flipx) sstep = -sstep;
  268. sp += sstep;
  269. /*
  270. * Advance destination pointer
  271. */
  272. dp++;
  273. }
  274. /*
  275. * Advance source pointer
  276. */
  277. csay++;
  278. sstep = (*csay >> 16) * src->pitch;
  279. if (flipy) sstep = -sstep;
  280. csp = (tColorRGBA *) ((Uint8 *) csp + sstep);
  281. /*
  282. * Advance destination pointers
  283. */
  284. dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
  285. }
  286. }
  287. /*
  288. * Remove temp arrays
  289. */
  290. free(sax);
  291. free(say);
  292. return (0);
  293. }
  294. /*
  295. 8bit Zoomer without smoothing.
  296. Zoomes 8bit palette/Y 'src' surface to 'dst' surface.
  297. */
  298. int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
  299. {
  300. Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
  301. Uint8 *sp, *dp, *csp;
  302. int dgap;
  303. /*
  304. * Variable setup
  305. */
  306. sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
  307. sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
  308. /*
  309. * Allocate memory for row increments
  310. */
  311. if ((sax = (Uint32 *) malloc(dst->w * sizeof(Uint32))) == NULL) {
  312. return (-1);
  313. }
  314. if ((say = (Uint32 *) malloc(dst->h * sizeof(Uint32))) == NULL) {
  315. if (sax != NULL) {
  316. free(sax);
  317. }
  318. return (-1);
  319. }
  320. /*
  321. * Precalculate row increments
  322. */
  323. csx = 0;
  324. csax = sax;
  325. for (x = 0; x < dst->w; x++) {
  326. csx += sx;
  327. *csax = (csx >> 16);
  328. csx &= 0xffff;
  329. csax++;
  330. }
  331. csy = 0;
  332. csay = say;
  333. for (y = 0; y < dst->h; y++) {
  334. csy += sy;
  335. *csay = (csy >> 16);
  336. csy &= 0xffff;
  337. csay++;
  338. }
  339. csx = 0;
  340. csax = sax;
  341. for (x = 0; x < dst->w; x++) {
  342. csx += (*csax);
  343. csax++;
  344. }
  345. csy = 0;
  346. csay = say;
  347. for (y = 0; y < dst->h; y++) {
  348. csy += (*csay);
  349. csay++;
  350. }
  351. /*
  352. * Pointer setup
  353. */
  354. sp = csp = (Uint8 *) src->pixels;
  355. dp = (Uint8 *) dst->pixels;
  356. dgap = dst->pitch - dst->w;
  357. /*
  358. * Draw
  359. */
  360. csay = say;
  361. for (y = 0; y < dst->h; y++) {
  362. csax = sax;
  363. sp = csp;
  364. for (x = 0; x < dst->w; x++) {
  365. /*
  366. * Draw
  367. */
  368. *dp = *sp;
  369. /*
  370. * Advance source pointers
  371. */
  372. sp += (*csax);
  373. csax++;
  374. /*
  375. * Advance destination pointer
  376. */
  377. dp++;
  378. }
  379. /*
  380. * Advance source pointer (for row)
  381. */
  382. csp += ((*csay) * src->pitch);
  383. csay++;
  384. /*
  385. * Advance destination pointers
  386. */
  387. dp += dgap;
  388. }
  389. /*
  390. * Remove temp arrays
  391. */
  392. free(sax);
  393. free(say);
  394. return (0);
  395. }
  396. /*
  397. 32bit Rotozoomer with optional anti-aliasing by bilinear interpolation.
  398. Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
  399. */
  400. void transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
  401. {
  402. int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
  403. tColorRGBA c00, c01, c10, c11;
  404. tColorRGBA *pc, *sp;
  405. int gap;
  406. /*
  407. * Variable setup
  408. */
  409. xd = ((src->w - dst->w) << 15);
  410. yd = ((src->h - dst->h) << 15);
  411. ax = (cx << 16) - (icos * cx);
  412. ay = (cy << 16) - (isin * cx);
  413. sw = src->w - 1;
  414. sh = src->h - 1;
  415. pc = (tColorRGBA*)dst->pixels;
  416. gap = dst->pitch - dst->w * 4;
  417. /*
  418. * Switch between interpolating and non-interpolating code
  419. */
  420. if (smooth) {
  421. for (y = 0; y < dst->h; y++) {
  422. dy = cy - y;
  423. sdx = (ax + (isin * dy)) + xd;
  424. sdy = (ay - (icos * dy)) + yd;
  425. for (x = 0; x < dst->w; x++) {
  426. dx = (sdx >> 16);
  427. dy = (sdy >> 16);
  428. if ((dx >= -1) && (dy >= -1) && (dx < src->w) && (dy < src->h)) {
  429. if ((dx >= 0) && (dy >= 0) && (dx < sw) && (dy < sh)) {
  430. sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
  431. sp += dx;
  432. c00 = *sp;
  433. sp += 1;
  434. c01 = *sp;
  435. sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
  436. sp -= 1;
  437. c10 = *sp;
  438. sp += 1;
  439. c11 = *sp;
  440. } else if ((dx == sw) && (dy == sh)) {
  441. sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
  442. sp += dx;
  443. c00 = *sp;
  444. c01 = *sp;
  445. c10 = *sp;
  446. c11 = *sp;
  447. } else if ((dx == -1) && (dy == -1)) {
  448. sp = (tColorRGBA *) (src->pixels);
  449. c00 = *sp;
  450. c01 = *sp;
  451. c10 = *sp;
  452. c11 = *sp;
  453. } else if ((dx == -1) && (dy == sh)) {
  454. sp = (tColorRGBA *) (src->pixels);
  455. sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
  456. c00 = *sp;
  457. c01 = *sp;
  458. c10 = *sp;
  459. c11 = *sp;
  460. } else if ((dx == sw) && (dy == -1)) {
  461. sp = (tColorRGBA *) (src->pixels);
  462. sp += dx;
  463. c00 = *sp;
  464. c01 = *sp;
  465. c10 = *sp;
  466. c11 = *sp;
  467. } else if (dx == -1) {
  468. sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
  469. c00 = *sp;
  470. c01 = *sp;
  471. c10 = *sp;
  472. sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
  473. c11 = *sp;
  474. } else if (dy == -1) {
  475. sp = (tColorRGBA *) (src->pixels);
  476. sp += dx;
  477. c00 = *sp;
  478. c01 = *sp;
  479. c10 = *sp;
  480. sp += 1;
  481. c11 = *sp;
  482. } else if (dx == sw) {
  483. sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
  484. sp += dx;
  485. c00 = *sp;
  486. c01 = *sp;
  487. sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
  488. c10 = *sp;
  489. c11 = *sp;
  490. } else if (dy == sh) {
  491. sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
  492. sp += dx;
  493. c00 = *sp;
  494. sp += 1;
  495. c01 = *sp;
  496. c10 = *sp;
  497. c11 = *sp;
  498. }
  499. /*
  500. * Interpolate colors
  501. */
  502. ex = (sdx & 0xffff);
  503. ey = (sdy & 0xffff);
  504. t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
  505. t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
  506. pc->r = (((t2 - t1) * ey) >> 16) + t1;
  507. t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
  508. t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
  509. pc->g = (((t2 - t1) * ey) >> 16) + t1;
  510. t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
  511. t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
  512. pc->b = (((t2 - t1) * ey) >> 16) + t1;
  513. t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
  514. t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
  515. pc->a = (((t2 - t1) * ey) >> 16) + t1;
  516. }
  517. sdx += icos;
  518. sdy += isin;
  519. pc++;
  520. }
  521. pc = (tColorRGBA *) ((Uint8 *) pc + gap);
  522. }
  523. } else {
  524. for (y = 0; y < dst->h; y++) {
  525. dy = cy - y;
  526. sdx = (ax + (isin * dy)) + xd;
  527. sdy = (ay - (icos * dy)) + yd;
  528. for (x = 0; x < dst->w; x++) {
  529. dx = (short) (sdx >> 16);
  530. dy = (short) (sdy >> 16);
  531. if (flipx) dx = (src->w-1)-dx;
  532. if (flipy) dy = (src->h-1)-dy;
  533. if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
  534. sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
  535. sp += dx;
  536. *pc = *sp;
  537. }
  538. sdx += icos;
  539. sdy += isin;
  540. pc++;
  541. }
  542. pc = (tColorRGBA *) ((Uint8 *) pc + gap);
  543. }
  544. }
  545. }
  546. /*
  547. 8bit Rotozoomer without smoothing
  548. Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface.
  549. */
  550. void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos)
  551. {
  552. int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh;
  553. tColorY *pc, *sp;
  554. int gap;
  555. /*
  556. * Variable setup
  557. */
  558. xd = ((src->w - dst->w) << 15);
  559. yd = ((src->h - dst->h) << 15);
  560. ax = (cx << 16) - (icos * cx);
  561. ay = (cy << 16) - (isin * cx);
  562. sw = src->w - 1;
  563. sh = src->h - 1;
  564. pc = (tColorY*)dst->pixels;
  565. gap = dst->pitch - dst->w;
  566. /*
  567. * Clear surface to colorkey
  568. */
  569. memset(pc, (unsigned char) (src->format->colorkey & 0xff), dst->pitch * dst->h);
  570. /*
  571. * Iterate through destination surface
  572. */
  573. for (y = 0; y < dst->h; y++) {
  574. dy = cy - y;
  575. sdx = (ax + (isin * dy)) + xd;
  576. sdy = (ay - (icos * dy)) + yd;
  577. for (x = 0; x < dst->w; x++) {
  578. dx = (short) (sdx >> 16);
  579. dy = (short) (sdy >> 16);
  580. if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
  581. sp = (tColorY *) (src->pixels);
  582. sp += (src->pitch * dy + dx);
  583. *pc = *sp;
  584. }
  585. sdx += icos;
  586. sdy += isin;
  587. pc++;
  588. }
  589. pc += gap;
  590. }
  591. }
  592. /*
  593. rotozoomSurface()
  594. Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
  595. 'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1
  596. then the destination 32bit surface is anti-aliased. If the surface is not 8bit
  597. or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
  598. */
  599. #define VALUE_LIMIT 0.001
  600. /* Local rotozoom-size function with trig result return */
  601. void rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight,
  602. double *canglezoom, double *sanglezoom)
  603. {
  604. double x, y, cx, cy, sx, sy;
  605. double radangle;
  606. int dstwidthhalf, dstheighthalf;
  607. /*
  608. * Determine destination width and height by rotating a centered source box
  609. */
  610. radangle = angle * (M_PI / 180.0);
  611. *sanglezoom = sin(radangle);
  612. *canglezoom = cos(radangle);
  613. *sanglezoom *= zoomx;
  614. *canglezoom *= zoomx;
  615. x = width / 2;
  616. y = height / 2;
  617. cx = *canglezoom * x;
  618. cy = *canglezoom * y;
  619. sx = *sanglezoom * x;
  620. sy = *sanglezoom * y;
  621. dstwidthhalf = MAX((int)
  622. ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
  623. dstheighthalf = MAX((int)
  624. ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
  625. *dstwidth = 2 * dstwidthhalf;
  626. *dstheight = 2 * dstheighthalf;
  627. }
  628. /* Publically available rotozoom-size function */
  629. void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
  630. {
  631. double dummy_sanglezoom, dummy_canglezoom;
  632. rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
  633. }
  634. /* Publically available rotozoom-size function */
  635. void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
  636. {
  637. double dummy_sanglezoom, dummy_canglezoom;
  638. rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
  639. }
  640. /* Publically available rotozoom function */
  641. SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
  642. {
  643. return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
  644. }
  645. /* Publically available rotozoom function */
  646. SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
  647. {
  648. SDL_Surface *rz_src;
  649. SDL_Surface *rz_dst;
  650. double zoominv;
  651. double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
  652. int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
  653. int is32bit;
  654. int i, src_converted;
  655. int flipx,flipy;
  656. /*
  657. * Sanity check
  658. */
  659. if (src == NULL)
  660. return (NULL);
  661. /*
  662. * Determine if source surface is 32bit or 8bit
  663. */
  664. is32bit = (src->format->BitsPerPixel == 32);
  665. if ((is32bit) || (src->format->BitsPerPixel == 8)) {
  666. /*
  667. * Use source surface 'as is'
  668. */
  669. rz_src = src;
  670. src_converted = 0;
  671. } else {
  672. /*
  673. * New source surface is 32bit with a defined RGBA ordering
  674. */
  675. rz_src =
  676. SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
  677. SDL_BlitSurface(src, NULL, rz_src, NULL);
  678. src_converted = 1;
  679. is32bit = 1;
  680. }
  681. /*
  682. * Sanity check zoom factor
  683. */
  684. flipx = (zoomx<0);
  685. if (flipx) zoomx=-zoomx;
  686. flipy = (zoomy<0);
  687. if (flipy) zoomy=-zoomy;
  688. if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
  689. if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
  690. zoominv = 65536.0 / (zoomx * zoomx);
  691. /*
  692. * Check if we have a rotozoom or just a zoom
  693. */
  694. if (fabs(angle) > VALUE_LIMIT) {
  695. /*
  696. * Angle!=0: full rotozoom
  697. */
  698. /*
  699. * -----------------------
  700. */
  701. /* Determine target size */
  702. rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
  703. /*
  704. * Calculate target factors from sin/cos and zoom
  705. */
  706. sanglezoominv = sanglezoom;
  707. canglezoominv = canglezoom;
  708. sanglezoominv *= zoominv;
  709. canglezoominv *= zoominv;
  710. /* Calculate half size */
  711. dstwidthhalf = dstwidth / 2;
  712. dstheighthalf = dstheight / 2;
  713. /*
  714. * Alloc space to completely contain the rotated surface
  715. */
  716. rz_dst = NULL;
  717. if (is32bit) {
  718. /*
  719. * Target surface is 32bit with source RGBA/ABGR ordering
  720. */
  721. rz_dst =
  722. SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32,
  723. rz_src->format->Rmask, rz_src->format->Gmask,
  724. rz_src->format->Bmask, rz_src->format->Amask);
  725. } else {
  726. /*
  727. * Target surface is 8bit
  728. */
  729. rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
  730. }
  731. /*
  732. * Lock source surface
  733. */
  734. SDL_LockSurface(rz_src);
  735. /*
  736. * Check which kind of surface we have
  737. */
  738. if (is32bit) {
  739. /*
  740. * Call the 32bit transformation routine to do the rotation (using alpha)
  741. */
  742. transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
  743. (int) (sanglezoominv), (int) (canglezoominv),
  744. flipx, flipy,
  745. smooth);
  746. /*
  747. * Turn on source-alpha support
  748. */
  749. SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
  750. } else {
  751. /*
  752. * Copy palette and colorkey info
  753. */
  754. for (i = 0; i < rz_src->format->palette->ncolors; i++) {
  755. rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
  756. }
  757. rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
  758. /*
  759. * Call the 8bit transformation routine to do the rotation
  760. */
  761. transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
  762. (int) (sanglezoominv), (int) (canglezoominv));
  763. SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
  764. }
  765. /*
  766. * Unlock source surface
  767. */
  768. SDL_UnlockSurface(rz_src);
  769. } else {
  770. /*
  771. * Angle=0: Just a zoom
  772. */
  773. /*
  774. * --------------------
  775. */
  776. /*
  777. * Calculate target size
  778. */
  779. zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
  780. /*
  781. * Alloc space to completely contain the zoomed surface
  782. */
  783. rz_dst = NULL;
  784. if (is32bit) {
  785. /*
  786. * Target surface is 32bit with source RGBA/ABGR ordering
  787. */
  788. rz_dst =
  789. SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32,
  790. rz_src->format->Rmask, rz_src->format->Gmask,
  791. rz_src->format->Bmask, rz_src->format->Amask);
  792. } else {
  793. /*
  794. * Target surface is 8bit
  795. */
  796. rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
  797. }
  798. /*
  799. * Lock source surface
  800. */
  801. SDL_LockSurface(rz_src);
  802. /*
  803. * Check which kind of surface we have
  804. */
  805. if (is32bit) {
  806. /*
  807. * Call the 32bit transformation routine to do the zooming (using alpha)
  808. */
  809. zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
  810. /*
  811. * Turn on source-alpha support
  812. */
  813. SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
  814. } else {
  815. /*
  816. * Copy palette and colorkey info
  817. */
  818. for (i = 0; i < rz_src->format->palette->ncolors; i++) {
  819. rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
  820. }
  821. rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
  822. /*
  823. * Call the 8bit transformation routine to do the zooming
  824. */
  825. zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
  826. SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
  827. }
  828. /*
  829. * Unlock source surface
  830. */
  831. SDL_UnlockSurface(rz_src);
  832. }
  833. /*
  834. * Cleanup temp surface
  835. */
  836. if (src_converted) {
  837. SDL_FreeSurface(rz_src);
  838. }
  839. /*
  840. * Return destination surface
  841. */
  842. return (rz_dst);
  843. }
  844. /*
  845. zoomSurface()
  846. Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
  847. 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1
  848. then the destination 32bit surface is anti-aliased. If the surface is not 8bit
  849. or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
  850. */
  851. #define VALUE_LIMIT 0.001
  852. void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
  853. {
  854. /*
  855. * Sanity check zoom factors
  856. */
  857. if (zoomx < VALUE_LIMIT) {
  858. zoomx = VALUE_LIMIT;
  859. }
  860. if (zoomy < VALUE_LIMIT) {
  861. zoomy = VALUE_LIMIT;
  862. }
  863. /*
  864. * Calculate target size
  865. */
  866. *dstwidth = (int) ((double) width * zoomx);
  867. *dstheight = (int) ((double) height * zoomy);
  868. if (*dstwidth < 1) {
  869. *dstwidth = 1;
  870. }
  871. if (*dstheight < 1) {
  872. *dstheight = 1;
  873. }
  874. }
  875. SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
  876. {
  877. SDL_Surface *rz_src;
  878. SDL_Surface *rz_dst;
  879. int dstwidth, dstheight;
  880. int is32bit;
  881. int i, src_converted;
  882. int flipx, flipy;
  883. /*
  884. * Sanity check
  885. */
  886. if (src == NULL)
  887. return (NULL);
  888. /*
  889. * Determine if source surface is 32bit or 8bit
  890. */
  891. is32bit = (src->format->BitsPerPixel == 32);
  892. if ((is32bit) || (src->format->BitsPerPixel == 8)) {
  893. /*
  894. * Use source surface 'as is'
  895. */
  896. rz_src = src;
  897. src_converted = 0;
  898. } else {
  899. /*
  900. * New source surface is 32bit with a defined RGBA ordering
  901. */
  902. rz_src =
  903. SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
  904. SDL_BlitSurface(src, NULL, rz_src, NULL);
  905. src_converted = 1;
  906. is32bit = 1;
  907. }
  908. flipx = (zoomx<0);
  909. if (flipx) zoomx = -zoomx;
  910. flipy = (zoomy<0);
  911. if (flipy) zoomy = -zoomy;
  912. /* Get size if target */
  913. zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
  914. /*
  915. * Alloc space to completely contain the zoomed surface
  916. */
  917. rz_dst = NULL;
  918. if (is32bit) {
  919. /*
  920. * Target surface is 32bit with source RGBA/ABGR ordering
  921. */
  922. rz_dst =
  923. SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32,
  924. rz_src->format->Rmask, rz_src->format->Gmask,
  925. rz_src->format->Bmask, rz_src->format->Amask);
  926. } else {
  927. /*
  928. * Target surface is 8bit
  929. */
  930. rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
  931. }
  932. /*
  933. * Lock source surface
  934. */
  935. SDL_LockSurface(rz_src);
  936. /*
  937. * Check which kind of surface we have
  938. */
  939. if (is32bit) {
  940. /*
  941. * Call the 32bit transformation routine to do the zooming (using alpha)
  942. */
  943. zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
  944. /*
  945. * Turn on source-alpha support
  946. */
  947. SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
  948. } else {
  949. /*
  950. * Copy palette and colorkey info
  951. */
  952. for (i = 0; i < rz_src->format->palette->ncolors; i++) {
  953. rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
  954. }
  955. rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
  956. /*
  957. * Call the 8bit transformation routine to do the zooming
  958. */
  959. zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
  960. SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
  961. }
  962. /*
  963. * Unlock source surface
  964. */
  965. SDL_UnlockSurface(rz_src);
  966. /*
  967. * Cleanup temp surface
  968. */
  969. if (src_converted) {
  970. SDL_FreeSurface(rz_src);
  971. }
  972. /*
  973. * Return destination surface
  974. */
  975. return (rz_dst);
  976. }
  977. SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory)
  978. {
  979. SDL_Surface *rz_src;
  980. SDL_Surface *rz_dst;
  981. int dstwidth, dstheight;
  982. int is32bit;
  983. int i, src_converted;
  984. /*
  985. * Sanity check
  986. */
  987. if (src == NULL)
  988. return (NULL);
  989. /*
  990. * Determine if source surface is 32bit or 8bit
  991. */
  992. is32bit = (src->format->BitsPerPixel == 32);
  993. if ((is32bit) || (src->format->BitsPerPixel == 8)) {
  994. /*
  995. * Use source surface 'as is'
  996. */
  997. rz_src = src;
  998. src_converted = 0;
  999. } else {
  1000. /*
  1001. * New source surface is 32bit with a defined RGBA ordering
  1002. */
  1003. rz_src =
  1004. SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
  1005. SDL_BlitSurface(src, NULL, rz_src, NULL);
  1006. src_converted = 1;
  1007. is32bit = 1;
  1008. }
  1009. /* Get size for target */
  1010. dstwidth=rz_src->w/factorx;
  1011. while (dstwidth*factorx>rz_src->w) { dstwidth--; }
  1012. dstheight=rz_src->h/factory;
  1013. while (dstheight*factory>rz_src->h) { dstheight--; }
  1014. /*
  1015. * Alloc space to completely contain the shrunken surface
  1016. */
  1017. rz_dst = NULL;
  1018. if (is32bit) {
  1019. /*
  1020. * Target surface is 32bit with source RGBA/ABGR ordering
  1021. */
  1022. rz_dst =
  1023. SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32,
  1024. rz_src->format->Rmask, rz_src->format->Gmask,
  1025. rz_src->format->Bmask, rz_src->format->Amask);
  1026. } else {
  1027. /*
  1028. * Target surface is 8bit
  1029. */
  1030. rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
  1031. }
  1032. /*
  1033. * Lock source surface
  1034. */
  1035. SDL_LockSurface(rz_src);
  1036. /*
  1037. * Check which kind of surface we have
  1038. */
  1039. if (is32bit) {
  1040. /*
  1041. * Call the 32bit transformation routine to do the shrinking (using alpha)
  1042. */
  1043. shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
  1044. /*
  1045. * Turn on source-alpha support
  1046. */
  1047. SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
  1048. } else {
  1049. /*
  1050. * Copy palette and colorkey info
  1051. */
  1052. for (i = 0; i < rz_src->format->palette->ncolors; i++) {
  1053. rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
  1054. }
  1055. rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
  1056. /*
  1057. * Call the 8bit transformation routine to do the shrinking
  1058. */
  1059. shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
  1060. SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
  1061. }
  1062. /*
  1063. * Unlock source surface
  1064. */
  1065. SDL_UnlockSurface(rz_src);
  1066. /*
  1067. * Cleanup temp surface
  1068. */
  1069. if (src_converted) {
  1070. SDL_FreeSurface(rz_src);
  1071. }
  1072. /*
  1073. * Return destination surface
  1074. */
  1075. return (rz_dst);
  1076. }