comparison window/SDL_rotozoom.cc @ 0:223b71206888

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