1 |
/* |
/* |
2 |
|
|
3 |
SDL_rotozoom.c - rotozoomer for 32bit or 8bit surfaces |
SDL_rotozoom.c - rotozoomer for 32bit or 8bit surfaces |
4 |
|
|
12 |
|
|
13 |
#include <stdlib.h> |
#include <stdlib.h> |
14 |
#include <string.h> |
#include <string.h> |
15 |
|
#include <assert.h> |
16 |
|
|
17 |
#include "SDL_rotozoom.h" |
#include "SDL_rotozoom.h" |
18 |
|
|
19 |
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) |
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) |
20 |
|
|
21 |
/* |
/* |
22 |
|
|
23 |
32bit Zoomer with optional anti-aliasing by bilinear interpolation. |
32bit Zoomer with optional anti-aliasing by bilinear interpolation. |
24 |
|
|
25 |
Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. |
Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. |
26 |
|
|
27 |
*/ |
*/ |
28 |
|
|
29 |
int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int smooth) |
int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int smooth) |
30 |
{ |
{ |
31 |
int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep; |
int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep; |
|
tColorRGBA *c00, *c01, *c10, *c11; |
|
32 |
tColorRGBA *sp, *csp, *dp; |
tColorRGBA *sp, *csp, *dp; |
33 |
int sgap, dgap; |
int sgap, dgap; |
34 |
|
|
35 |
/* |
/* |
36 |
* Variable setup |
* Variable setup |
37 |
*/ |
*/ |
38 |
if (smooth) { |
if (smooth) { |
39 |
/* |
/* |
40 |
* For interpolation: assume source dimension is one pixel |
* For interpolation: assume source dimension is one pixel |
41 |
*/ |
*/ |
42 |
/* |
/* |
43 |
* smaller to avoid overflow on right and bottom edge. |
* 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); |
if (src->w > dst->w) { |
47 |
|
// if the image gets shrinked -> use stronger blur : |
48 |
|
smooth = (int)((double)(src->w)/dst->w-0.5); |
49 |
|
sx = (int) (65536.0 * (float) (src->w - smooth) / (float) dst->w); |
50 |
|
sy = (int) (65536.0 * (float) (src->h - smooth) / (float) dst->h); |
51 |
|
} |
52 |
|
else { |
53 |
|
smooth = 1; |
54 |
|
sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); |
55 |
|
sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); |
56 |
|
} |
57 |
} else { |
} else { |
58 |
sx = (int) (65536.0 * (float) src->w / (float) dst->w); |
sx = (int) (65536.0 * (float) src->w / (float) dst->w); |
59 |
sy = (int) (65536.0 * (float) src->h / (float) dst->h); |
sy = (int) (65536.0 * (float) src->h / (float) dst->h); |
60 |
} |
} |
61 |
|
|
62 |
/* |
/* |
63 |
* Allocate memory for row increments |
* Allocate memory for row increments |
64 |
*/ |
*/ |
65 |
if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { |
if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { |
66 |
return (-1); |
return (-1); |
71 |
} |
} |
72 |
|
|
73 |
/* |
/* |
74 |
* Precalculate row increments |
* Precalculate row increments |
75 |
*/ |
*/ |
76 |
csx = 0; |
csx = 0; |
77 |
csax = sax; |
csax = sax; |
91 |
} |
} |
92 |
|
|
93 |
/* |
/* |
94 |
* Pointer setup |
* Pointer setup |
95 |
*/ |
*/ |
96 |
sp = csp = (tColorRGBA *) src->pixels; |
sp = csp = (tColorRGBA *) src->pixels; |
97 |
dp = (tColorRGBA *) dst->pixels; |
dp = (tColorRGBA *) dst->pixels; |
99 |
dgap = dst->pitch - dst->w * 4; |
dgap = dst->pitch - dst->w * 4; |
100 |
|
|
101 |
/* |
/* |
102 |
* Switch between interpolating and non-interpolating code |
* Switch between interpolating and non-interpolating code |
103 |
*/ |
*/ |
104 |
if (smooth) { |
if (smooth) { |
105 |
|
|
106 |
/* |
/* |
107 |
* Interpolating Zoom |
* Interpolating Zoom |
108 |
*/ |
*/ |
109 |
|
|
110 |
/* |
/* |
111 |
* Scan destination |
* Scan destination |
112 |
*/ |
*/ |
113 |
csay = say; |
csay = say; |
|
for (y = 0; y < dst->h; y++) { |
|
|
/* |
|
|
* Setup color source pointers |
|
|
*/ |
|
|
c00 = csp; |
|
|
c01 = csp; |
|
|
c01++; |
|
|
c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch); |
|
|
c11 = c10; |
|
|
c11++; |
|
|
csax = sax; |
|
|
for (x = 0; x < dst->w; x++) { |
|
|
|
|
|
/* |
|
|
* Interpolate colors |
|
|
*/ |
|
|
ex = (*csax & 0xffff); |
|
|
ey = (*csay & 0xffff); |
|
|
t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; |
|
|
t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; |
|
|
dp->r = (((t2 - t1) * ey) >> 16) + t1; |
|
|
t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; |
|
|
t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; |
|
|
dp->g = (((t2 - t1) * ey) >> 16) + t1; |
|
|
t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; |
|
|
t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; |
|
|
dp->b = (((t2 - t1) * ey) >> 16) + t1; |
|
|
t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; |
|
|
t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; |
|
|
dp->a = (((t2 - t1) * ey) >> 16) + t1; |
|
114 |
|
|
115 |
/* |
for (y = 0; y < dst->h; y++) { |
116 |
* Advance source pointers |
if (smooth == 1) { |
117 |
*/ |
/* |
118 |
csax++; |
* Setup color source pointers |
119 |
sstep = (*csax >> 16); |
*/ |
120 |
c00 += sstep; |
tColorRGBA *c00, *c01, *c10, *c11; |
121 |
c01 += sstep; |
|
122 |
c10 += sstep; |
c00 = csp; |
123 |
c11 += sstep; |
c01 = csp; |
124 |
/* |
c01++; |
125 |
* Advance destination pointer |
c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch); |
126 |
*/ |
c11 = c10; |
127 |
dp++; |
c11++; |
128 |
} |
csax = sax; |
129 |
|
for (x = 0; x < dst->w; x++) { |
130 |
|
|
131 |
|
/* |
132 |
|
* Interpolate colors |
133 |
|
*/ |
134 |
|
ex = (*csax & 0xffff); |
135 |
|
ey = (*csay & 0xffff); |
136 |
|
t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; |
137 |
|
t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; |
138 |
|
dp->r = (((t2 - t1) * ey) >> 16) + t1; |
139 |
|
t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; |
140 |
|
t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; |
141 |
|
dp->g = (((t2 - t1) * ey) >> 16) + t1; |
142 |
|
t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; |
143 |
|
t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; |
144 |
|
dp->b = (((t2 - t1) * ey) >> 16) + t1; |
145 |
|
t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; |
146 |
|
t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; |
147 |
|
dp->a = (((t2 - t1) * ey) >> 16) + t1; |
148 |
|
|
149 |
|
/* |
150 |
|
* Advance source pointers |
151 |
|
*/ |
152 |
|
csax++; |
153 |
|
sstep = (*csax >> 16); |
154 |
|
c00 += sstep; |
155 |
|
c01 += sstep; |
156 |
|
c10 += sstep; |
157 |
|
c11 += sstep; |
158 |
|
/* |
159 |
|
* Advance destination pointer |
160 |
|
*/ |
161 |
|
dp++; |
162 |
|
} |
163 |
|
} |
164 |
|
else { // stronger blur for image shrinking |
165 |
|
/* |
166 |
|
* Setup color source pointers |
167 |
|
*/ |
168 |
|
|
169 |
|
tColorRGBA *c = csp; |
170 |
|
int smooth2 = smooth*smooth; |
171 |
|
csax = sax; |
172 |
|
|
173 |
|
for (x = 0; x < dst->w; x++) { |
174 |
|
/* |
175 |
|
* Interpolate colors |
176 |
|
*/ |
177 |
|
|
178 |
|
int xo, yo; |
179 |
|
tColorRGBA *co = c; |
180 |
|
int r = 0, g = 0, b = 0, a = 0; |
181 |
|
|
182 |
|
for (yo = 0; yo<smooth; ++yo) { |
183 |
|
for (xo = 0; xo<smooth; ++xo) { |
184 |
|
assert(co >= csp); |
185 |
|
r += co->r; |
186 |
|
g += co->g; |
187 |
|
b += co->b; |
188 |
|
a += co->a; |
189 |
|
co++; |
190 |
|
} |
191 |
|
co = (tColorRGBA *) ((Uint8 *) co + src->pitch); |
192 |
|
co -= smooth; |
193 |
|
} |
194 |
|
|
195 |
|
dp->r = r/smooth2; |
196 |
|
dp->g = g/smooth2; |
197 |
|
dp->b = b/smooth2; |
198 |
|
dp->a = a/smooth2; |
199 |
|
|
200 |
|
/* |
201 |
|
* Advance source pointers |
202 |
|
*/ |
203 |
|
csax++; |
204 |
|
sstep = (*csax >> 16); |
205 |
|
c += sstep; |
206 |
|
|
207 |
|
/* |
208 |
|
* Advance destination pointer |
209 |
|
*/ |
210 |
|
dp++; |
211 |
|
} |
212 |
|
} |
213 |
/* |
/* |
214 |
* Advance source pointer |
* Advance source pointer |
215 |
*/ |
*/ |
216 |
csay++; |
csay++; |
217 |
csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); |
csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); |
218 |
/* |
/* |
219 |
* Advance destination pointers |
* Advance destination pointers |
220 |
*/ |
*/ |
221 |
dp = (tColorRGBA *) ((Uint8 *) dp + dgap); |
dp = (tColorRGBA *) ((Uint8 *) dp + dgap); |
222 |
} |
} |
223 |
|
|
224 |
} else { |
} else { |
225 |
|
|
226 |
/* |
/* |
227 |
* Non-Interpolating Zoom |
* Non-Interpolating Zoom |
228 |
*/ |
*/ |
229 |
|
|
230 |
csay = say; |
csay = say; |
233 |
csax = sax; |
csax = sax; |
234 |
for (x = 0; x < dst->w; x++) { |
for (x = 0; x < dst->w; x++) { |
235 |
/* |
/* |
236 |
* Draw |
* Draw |
237 |
*/ |
*/ |
238 |
*dp = *sp; |
*dp = *sp; |
239 |
/* |
/* |
240 |
* Advance source pointers |
* Advance source pointers |
241 |
*/ |
*/ |
242 |
csax++; |
csax++; |
243 |
sp += (*csax >> 16); |
sp += (*csax >> 16); |
244 |
/* |
/* |
245 |
* Advance destination pointer |
* Advance destination pointer |
246 |
*/ |
*/ |
247 |
dp++; |
dp++; |
248 |
} |
} |
249 |
/* |
/* |
250 |
* Advance source pointer |
* Advance source pointer |
251 |
*/ |
*/ |
252 |
csay++; |
csay++; |
253 |
csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); |
csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); |
254 |
/* |
/* |
255 |
* Advance destination pointers |
* Advance destination pointers |
256 |
*/ |
*/ |
257 |
dp = (tColorRGBA *) ((Uint8 *) dp + dgap); |
dp = (tColorRGBA *) ((Uint8 *) dp + dgap); |
258 |
} |
} |
260 |
} |
} |
261 |
|
|
262 |
/* |
/* |
263 |
* Remove temp arrays |
* Remove temp arrays |
264 |
*/ |
*/ |
265 |
free(sax); |
free(sax); |
266 |
free(say); |
free(say); |
268 |
return (0); |
return (0); |
269 |
} |
} |
270 |
|
|
271 |
/* |
/* |
272 |
|
|
273 |
8bit Zoomer without smoothing. |
8bit Zoomer without smoothing. |
274 |
|
|
275 |
Zoomes 8bit palette/Y 'src' surface to 'dst' surface. |
Zoomes 8bit palette/Y 'src' surface to 'dst' surface. |
276 |
|
|
277 |
*/ |
*/ |
278 |
|
|
279 |
int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst) |
int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst) |
283 |
int dgap; |
int dgap; |
284 |
|
|
285 |
/* |
/* |
286 |
* Variable setup |
* Variable setup |
287 |
*/ |
*/ |
288 |
sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w); |
sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w); |
289 |
sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h); |
sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h); |
290 |
|
|
291 |
/* |
/* |
292 |
* Allocate memory for row increments |
* Allocate memory for row increments |
293 |
*/ |
*/ |
294 |
if ((sax = (Uint32 *) malloc(dst->w * sizeof(Uint32))) == NULL) { |
if ((sax = (Uint32 *) malloc(dst->w * sizeof(Uint32))) == NULL) { |
295 |
return (-1); |
return (-1); |
302 |
} |
} |
303 |
|
|
304 |
/* |
/* |
305 |
* Precalculate row increments |
* Precalculate row increments |
306 |
*/ |
*/ |
307 |
csx = 0; |
csx = 0; |
308 |
csax = sax; |
csax = sax; |
335 |
} |
} |
336 |
|
|
337 |
/* |
/* |
338 |
* Pointer setup |
* Pointer setup |
339 |
*/ |
*/ |
340 |
sp = csp = (Uint8 *) src->pixels; |
sp = csp = (Uint8 *) src->pixels; |
341 |
dp = (Uint8 *) dst->pixels; |
dp = (Uint8 *) dst->pixels; |
342 |
dgap = dst->pitch - dst->w; |
dgap = dst->pitch - dst->w; |
343 |
|
|
344 |
/* |
/* |
345 |
* Draw |
* Draw |
346 |
*/ |
*/ |
347 |
csay = say; |
csay = say; |
348 |
for (y = 0; y < dst->h; y++) { |
for (y = 0; y < dst->h; y++) { |
350 |
sp = csp; |
sp = csp; |
351 |
for (x = 0; x < dst->w; x++) { |
for (x = 0; x < dst->w; x++) { |
352 |
/* |
/* |
353 |
* Draw |
* Draw |
354 |
*/ |
*/ |
355 |
*dp = *sp; |
*dp = *sp; |
356 |
/* |
/* |
357 |
* Advance source pointers |
* Advance source pointers |
358 |
*/ |
*/ |
359 |
sp += (*csax); |
sp += (*csax); |
360 |
csax++; |
csax++; |
361 |
/* |
/* |
362 |
* Advance destination pointer |
* Advance destination pointer |
363 |
*/ |
*/ |
364 |
dp++; |
dp++; |
365 |
} |
} |
366 |
/* |
/* |
367 |
* Advance source pointer (for row) |
* Advance source pointer (for row) |
368 |
*/ |
*/ |
369 |
csp += ((*csay) * src->pitch); |
csp += ((*csay) * src->pitch); |
370 |
csay++; |
csay++; |
371 |
/* |
/* |
372 |
* Advance destination pointers |
* Advance destination pointers |
373 |
*/ |
*/ |
374 |
dp += dgap; |
dp += dgap; |
375 |
} |
} |
376 |
|
|
377 |
/* |
/* |
378 |
* Remove temp arrays |
* Remove temp arrays |
379 |
*/ |
*/ |
380 |
free(sax); |
free(sax); |
381 |
free(say); |
free(say); |
383 |
return (0); |
return (0); |
384 |
} |
} |
385 |
|
|
386 |
/* |
/* |
387 |
|
|
388 |
32bit Rotozoomer with optional anti-aliasing by bilinear interpolation. |
32bit Rotozoomer with optional anti-aliasing by bilinear interpolation. |
389 |
|
|
390 |
Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. |
Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. |
391 |
|
|
392 |
*/ |
*/ |
393 |
|
|
394 |
void transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int smooth) |
void transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int smooth) |
399 |
int gap; |
int gap; |
400 |
|
|
401 |
/* |
/* |
402 |
* Variable setup |
* Variable setup |
403 |
*/ |
*/ |
404 |
xd = ((src->w - dst->w) << 15); |
xd = ((src->w - dst->w) << 15); |
405 |
yd = ((src->h - dst->h) << 15); |
yd = ((src->h - dst->h) << 15); |
411 |
gap = dst->pitch - dst->w * 4; |
gap = dst->pitch - dst->w * 4; |
412 |
|
|
413 |
/* |
/* |
414 |
* Switch between interpolating and non-interpolating code |
* Switch between interpolating and non-interpolating code |
415 |
*/ |
*/ |
416 |
if (smooth) { |
if (smooth) { |
417 |
for (y = 0; y < dst->h; y++) { |
for (y = 0; y < dst->h; y++) { |
493 |
c11 = *sp; |
c11 = *sp; |
494 |
} |
} |
495 |
/* |
/* |
496 |
* Interpolate colors |
* Interpolate colors |
497 |
*/ |
*/ |
498 |
ex = (sdx & 0xffff); |
ex = (sdx & 0xffff); |
499 |
ey = (sdy & 0xffff); |
ey = (sdy & 0xffff); |
538 |
} |
} |
539 |
} |
} |
540 |
|
|
541 |
/* |
/* |
542 |
|
|
543 |
8bit Rotozoomer without smoothing |
8bit Rotozoomer without smoothing |
544 |
|
|
545 |
Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface. |
Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface. |
546 |
|
|
547 |
*/ |
*/ |
548 |
|
|
549 |
void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos) |
void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos) |
553 |
int gap; |
int gap; |
554 |
|
|
555 |
/* |
/* |
556 |
* Variable setup |
* Variable setup |
557 |
*/ |
*/ |
558 |
xd = ((src->w - dst->w) << 15); |
xd = ((src->w - dst->w) << 15); |
559 |
yd = ((src->h - dst->h) << 15); |
yd = ((src->h - dst->h) << 15); |
564 |
pc = dst->pixels; |
pc = dst->pixels; |
565 |
gap = dst->pitch - dst->w; |
gap = dst->pitch - dst->w; |
566 |
/* |
/* |
567 |
* Clear surface to colorkey |
* Clear surface to colorkey |
568 |
*/ |
*/ |
569 |
memset(pc, (unsigned char) (src->format->colorkey & 0xff), dst->pitch * dst->h); |
memset(pc, (unsigned char) (src->format->colorkey & 0xff), dst->pitch * dst->h); |
570 |
/* |
/* |
571 |
* Iterate through destination surface |
* Iterate through destination surface |
572 |
*/ |
*/ |
573 |
for (y = 0; y < dst->h; y++) { |
for (y = 0; y < dst->h; y++) { |
574 |
dy = cy - y; |
dy = cy - y; |
590 |
} |
} |
591 |
} |
} |
592 |
|
|
593 |
/* |
/* |
594 |
|
|
595 |
rotozoomSurface() |
rotozoomSurface() |
596 |
|
|
597 |
Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. |
Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. |
614 |
int dstwidthhalf, dstheighthalf; |
int dstwidthhalf, dstheighthalf; |
615 |
|
|
616 |
/* |
/* |
617 |
* Determine destination width and height by rotating a centered source box |
* Determine destination width and height by rotating a centered source box |
618 |
*/ |
*/ |
619 |
radangle = angle * (M_PI / 180.0); |
radangle = angle * (M_PI / 180.0); |
620 |
*sanglezoom = sin(radangle); |
*sanglezoom = sin(radangle); |
660 |
int i, src_converted; |
int i, src_converted; |
661 |
|
|
662 |
/* |
/* |
663 |
* Sanity check |
* Sanity check |
664 |
*/ |
*/ |
665 |
if (src == NULL) |
if (src == NULL) |
666 |
return (NULL); |
return (NULL); |
667 |
|
|
668 |
/* |
/* |
669 |
* Determine if source surface is 32bit or 8bit |
* Determine if source surface is 32bit or 8bit |
670 |
*/ |
*/ |
671 |
is32bit = (src->format->BitsPerPixel == 32); |
is32bit = (src->format->BitsPerPixel == 32); |
672 |
if ((is32bit) || (src->format->BitsPerPixel == 8)) { |
if ((is32bit) || (src->format->BitsPerPixel == 8)) { |
673 |
/* |
/* |
674 |
* Use source surface 'as is' |
* Use source surface 'as is' |
675 |
*/ |
*/ |
676 |
rz_src = src; |
rz_src = src; |
677 |
src_converted = 0; |
src_converted = 0; |
678 |
} else { |
} else { |
679 |
/* |
/* |
680 |
* New source surface is 32bit with a defined RGBA ordering |
* New source surface is 32bit with a defined RGBA ordering |
681 |
*/ |
*/ |
682 |
rz_src = |
rz_src = |
683 |
SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); |
SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); |
687 |
} |
} |
688 |
|
|
689 |
/* |
/* |
690 |
* Sanity check zoom factor |
* Sanity check zoom factor |
691 |
*/ |
*/ |
692 |
if (zoom < VALUE_LIMIT) { |
if (zoom < VALUE_LIMIT) { |
693 |
zoom = VALUE_LIMIT; |
zoom = VALUE_LIMIT; |
695 |
zoominv = 65536.0 / (zoom * zoom); |
zoominv = 65536.0 / (zoom * zoom); |
696 |
|
|
697 |
/* |
/* |
698 |
* Check if we have a rotozoom or just a zoom |
* Check if we have a rotozoom or just a zoom |
699 |
*/ |
*/ |
700 |
if (fabs(angle) > VALUE_LIMIT) { |
if (fabs(angle) > VALUE_LIMIT) { |
701 |
|
|
702 |
/* |
/* |
703 |
* Angle!=0: full rotozoom |
* Angle!=0: full rotozoom |
704 |
*/ |
*/ |
705 |
/* |
/* |
706 |
* ----------------------- |
* ----------------------- |
707 |
*/ |
*/ |
708 |
|
|
709 |
/* Determine target size */ |
/* Determine target size */ |
710 |
rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoom, &dstwidth, &dstheight, &canglezoom, &sanglezoom); |
rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoom, &dstwidth, &dstheight, &canglezoom, &sanglezoom); |
711 |
|
|
712 |
/* |
/* |
713 |
* Calculate target factors from sin/cos and zoom |
* Calculate target factors from sin/cos and zoom |
714 |
*/ |
*/ |
715 |
sanglezoominv = sanglezoom; |
sanglezoominv = sanglezoom; |
716 |
canglezoominv = canglezoom; |
canglezoominv = canglezoom; |
722 |
dstheighthalf = dstheight / 2; |
dstheighthalf = dstheight / 2; |
723 |
|
|
724 |
/* |
/* |
725 |
* Alloc space to completely contain the rotated surface |
* Alloc space to completely contain the rotated surface |
726 |
*/ |
*/ |
727 |
rz_dst = NULL; |
rz_dst = NULL; |
728 |
if (is32bit) { |
if (is32bit) { |
729 |
/* |
/* |
730 |
* Target surface is 32bit with source RGBA/ABGR ordering |
* Target surface is 32bit with source RGBA/ABGR ordering |
731 |
*/ |
*/ |
732 |
rz_dst = |
rz_dst = |
733 |
SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, |
SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, |
735 |
rz_src->format->Bmask, rz_src->format->Amask); |
rz_src->format->Bmask, rz_src->format->Amask); |
736 |
} else { |
} else { |
737 |
/* |
/* |
738 |
* Target surface is 8bit |
* Target surface is 8bit |
739 |
*/ |
*/ |
740 |
rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); |
rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); |
741 |
} |
} |
742 |
|
|
743 |
/* |
/* |
744 |
* Lock source surface |
* Lock source surface |
745 |
*/ |
*/ |
746 |
SDL_LockSurface(rz_src); |
SDL_LockSurface(rz_src); |
747 |
/* |
/* |
748 |
* Check which kind of surface we have |
* Check which kind of surface we have |
749 |
*/ |
*/ |
750 |
if (is32bit) { |
if (is32bit) { |
751 |
/* |
/* |
752 |
* Call the 32bit transformation routine to do the rotation (using alpha) |
* Call the 32bit transformation routine to do the rotation (using alpha) |
753 |
*/ |
*/ |
754 |
transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf, |
transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf, |
755 |
(int) (sanglezoominv), (int) (canglezoominv), smooth); |
(int) (sanglezoominv), (int) (canglezoominv), smooth); |
756 |
/* |
/* |
757 |
* Turn on source-alpha support |
* Turn on source-alpha support |
758 |
*/ |
*/ |
759 |
SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); |
SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); |
760 |
} else { |
} else { |
761 |
/* |
/* |
762 |
* Copy palette and colorkey info |
* Copy palette and colorkey info |
763 |
*/ |
*/ |
764 |
for (i = 0; i < rz_src->format->palette->ncolors; i++) { |
for (i = 0; i < rz_src->format->palette->ncolors; i++) { |
765 |
rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; |
rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; |
766 |
} |
} |
767 |
rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; |
rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; |
768 |
/* |
/* |
769 |
* Call the 8bit transformation routine to do the rotation |
* Call the 8bit transformation routine to do the rotation |
770 |
*/ |
*/ |
771 |
transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf, |
transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf, |
772 |
(int) (sanglezoominv), (int) (canglezoominv)); |
(int) (sanglezoominv), (int) (canglezoominv)); |
773 |
SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); |
SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); |
774 |
} |
} |
775 |
/* |
/* |
776 |
* Unlock source surface |
* Unlock source surface |
777 |
*/ |
*/ |
778 |
SDL_UnlockSurface(rz_src); |
SDL_UnlockSurface(rz_src); |
779 |
|
|
780 |
} else { |
} else { |
781 |
|
|
782 |
/* |
/* |
783 |
* Angle=0: Just a zoom |
* Angle=0: Just a zoom |
784 |
*/ |
*/ |
785 |
/* |
/* |
786 |
* -------------------- |
* -------------------- |
787 |
*/ |
*/ |
788 |
|
|
789 |
/* |
/* |
792 |
zoomSurfaceSize(rz_src->w, rz_src->h, zoom, zoom, &dstwidth, &dstheight); |
zoomSurfaceSize(rz_src->w, rz_src->h, zoom, zoom, &dstwidth, &dstheight); |
793 |
|
|
794 |
/* |
/* |
795 |
* Alloc space to completely contain the zoomed surface |
* Alloc space to completely contain the zoomed surface |
796 |
*/ |
*/ |
797 |
rz_dst = NULL; |
rz_dst = NULL; |
798 |
if (is32bit) { |
if (is32bit) { |
799 |
/* |
/* |
800 |
* Target surface is 32bit with source RGBA/ABGR ordering |
* Target surface is 32bit with source RGBA/ABGR ordering |
801 |
*/ |
*/ |
802 |
rz_dst = |
rz_dst = |
803 |
SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, |
SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, |
805 |
rz_src->format->Bmask, rz_src->format->Amask); |
rz_src->format->Bmask, rz_src->format->Amask); |
806 |
} else { |
} else { |
807 |
/* |
/* |
808 |
* Target surface is 8bit |
* Target surface is 8bit |
809 |
*/ |
*/ |
810 |
rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); |
rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); |
811 |
} |
} |
812 |
|
|
813 |
/* |
/* |
814 |
* Lock source surface |
* Lock source surface |
815 |
*/ |
*/ |
816 |
SDL_LockSurface(rz_src); |
SDL_LockSurface(rz_src); |
817 |
/* |
/* |
818 |
* Check which kind of surface we have |
* Check which kind of surface we have |
819 |
*/ |
*/ |
820 |
if (is32bit) { |
if (is32bit) { |
821 |
/* |
/* |
822 |
* Call the 32bit transformation routine to do the zooming (using alpha) |
* Call the 32bit transformation routine to do the zooming (using alpha) |
823 |
*/ |
*/ |
824 |
zoomSurfaceRGBA(rz_src, rz_dst, smooth); |
zoomSurfaceRGBA(rz_src, rz_dst, smooth); |
825 |
/* |
/* |
826 |
* Turn on source-alpha support |
* Turn on source-alpha support |
827 |
*/ |
*/ |
828 |
SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); |
SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); |
829 |
} else { |
} else { |
830 |
/* |
/* |
831 |
* Copy palette and colorkey info |
* Copy palette and colorkey info |
832 |
*/ |
*/ |
833 |
for (i = 0; i < rz_src->format->palette->ncolors; i++) { |
for (i = 0; i < rz_src->format->palette->ncolors; i++) { |
834 |
rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; |
rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; |
835 |
} |
} |
836 |
rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; |
rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; |
837 |
/* |
/* |
838 |
* Call the 8bit transformation routine to do the zooming |
* Call the 8bit transformation routine to do the zooming |
839 |
*/ |
*/ |
840 |
zoomSurfaceY(rz_src, rz_dst); |
zoomSurfaceY(rz_src, rz_dst); |
841 |
SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); |
SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); |
842 |
} |
} |
843 |
/* |
/* |
844 |
* Unlock source surface |
* Unlock source surface |
845 |
*/ |
*/ |
846 |
SDL_UnlockSurface(rz_src); |
SDL_UnlockSurface(rz_src); |
847 |
} |
} |
848 |
|
|
849 |
/* |
/* |
850 |
* Cleanup temp surface |
* Cleanup temp surface |
851 |
*/ |
*/ |
852 |
if (src_converted) { |
if (src_converted) { |
853 |
SDL_FreeSurface(rz_src); |
SDL_FreeSurface(rz_src); |
854 |
} |
} |
855 |
|
|
856 |
/* |
/* |
857 |
* Return destination surface |
* Return destination surface |
858 |
*/ |
*/ |
859 |
return (rz_dst); |
return (rz_dst); |
860 |
} |
} |
861 |
|
|
862 |
/* |
/* |
863 |
|
|
864 |
zoomSurface() |
zoomSurface() |
865 |
|
|
866 |
Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. |
Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. |
875 |
void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) |
void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) |
876 |
{ |
{ |
877 |
/* |
/* |
878 |
* Sanity check zoom factors |
* Sanity check zoom factors |
879 |
*/ |
*/ |
880 |
if (zoomx < VALUE_LIMIT) { |
if (zoomx < VALUE_LIMIT) { |
881 |
zoomx = VALUE_LIMIT; |
zoomx = VALUE_LIMIT; |
885 |
} |
} |
886 |
|
|
887 |
/* |
/* |
888 |
* Calculate target size |
* Calculate target size |
889 |
*/ |
*/ |
890 |
*dstwidth = (int) ((double) width * zoomx); |
*dstwidth = (int) ((double) width * zoomx); |
891 |
*dstheight = (int) ((double) height * zoomy); |
*dstheight = (int) ((double) height * zoomy); |
906 |
int i, src_converted; |
int i, src_converted; |
907 |
|
|
908 |
/* |
/* |
909 |
* Sanity check |
* Sanity check |
910 |
*/ |
*/ |
911 |
if (src == NULL) |
if (src == NULL) |
912 |
return (NULL); |
return (NULL); |
913 |
|
|
914 |
/* |
/* |
915 |
* Determine if source surface is 32bit or 8bit |
* Determine if source surface is 32bit or 8bit |
916 |
*/ |
*/ |
917 |
is32bit = (src->format->BitsPerPixel == 32); |
is32bit = (src->format->BitsPerPixel == 32); |
918 |
if ((is32bit) || (src->format->BitsPerPixel == 8)) { |
if ((is32bit) || (src->format->BitsPerPixel == 8)) { |
919 |
/* |
/* |
920 |
* Use source surface 'as is' |
* Use source surface 'as is' |
921 |
*/ |
*/ |
922 |
rz_src = src; |
rz_src = src; |
923 |
src_converted = 0; |
src_converted = 0; |
924 |
} else { |
} else { |
925 |
/* |
/* |
926 |
* New source surface is 32bit with a defined RGBA ordering |
* New source surface is 32bit with a defined RGBA ordering |
927 |
*/ |
*/ |
928 |
rz_src = |
rz_src = |
929 |
SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); |
SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); |
936 |
zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); |
zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); |
937 |
|
|
938 |
/* |
/* |
939 |
* Alloc space to completely contain the zoomed surface |
* Alloc space to completely contain the zoomed surface |
940 |
*/ |
*/ |
941 |
rz_dst = NULL; |
rz_dst = NULL; |
942 |
if (is32bit) { |
if (is32bit) { |
943 |
/* |
/* |
944 |
* Target surface is 32bit with source RGBA/ABGR ordering |
* Target surface is 32bit with source RGBA/ABGR ordering |
945 |
*/ |
*/ |
946 |
rz_dst = |
rz_dst = |
947 |
SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, |
SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, |
949 |
rz_src->format->Bmask, rz_src->format->Amask); |
rz_src->format->Bmask, rz_src->format->Amask); |
950 |
} else { |
} else { |
951 |
/* |
/* |
952 |
* Target surface is 8bit |
* Target surface is 8bit |
953 |
*/ |
*/ |
954 |
rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); |
rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); |
955 |
} |
} |
956 |
|
|
957 |
/* |
/* |
958 |
* Lock source surface |
* Lock source surface |
959 |
*/ |
*/ |
960 |
SDL_LockSurface(rz_src); |
SDL_LockSurface(rz_src); |
961 |
/* |
/* |
962 |
* Check which kind of surface we have |
* Check which kind of surface we have |
963 |
*/ |
*/ |
964 |
if (is32bit) { |
if (is32bit) { |
965 |
/* |
/* |
966 |
* Call the 32bit transformation routine to do the zooming (using alpha) |
* Call the 32bit transformation routine to do the zooming (using alpha) |
967 |
*/ |
*/ |
968 |
zoomSurfaceRGBA(rz_src, rz_dst, smooth); |
zoomSurfaceRGBA(rz_src, rz_dst, smooth); |
969 |
/* |
/* |
970 |
* Turn on source-alpha support |
* Turn on source-alpha support |
971 |
*/ |
*/ |
972 |
SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); |
SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); |
973 |
} else { |
} else { |
974 |
/* |
/* |
975 |
* Copy palette and colorkey info |
* Copy palette and colorkey info |
976 |
*/ |
*/ |
977 |
for (i = 0; i < rz_src->format->palette->ncolors; i++) { |
for (i = 0; i < rz_src->format->palette->ncolors; i++) { |
978 |
rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; |
rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; |
979 |
} |
} |
980 |
rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; |
rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; |
981 |
/* |
/* |
982 |
* Call the 8bit transformation routine to do the zooming |
* Call the 8bit transformation routine to do the zooming |
983 |
*/ |
*/ |
984 |
zoomSurfaceY(rz_src, rz_dst); |
zoomSurfaceY(rz_src, rz_dst); |
985 |
SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); |
SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); |
986 |
} |
} |
987 |
/* |
/* |
988 |
* Unlock source surface |
* Unlock source surface |
989 |
*/ |
*/ |
990 |
SDL_UnlockSurface(rz_src); |
SDL_UnlockSurface(rz_src); |
991 |
|
|
992 |
/* |
/* |
993 |
* Cleanup temp surface |
* Cleanup temp surface |
994 |
*/ |
*/ |
995 |
if (src_converted) { |
if (src_converted) { |
996 |
SDL_FreeSurface(rz_src); |
SDL_FreeSurface(rz_src); |
997 |
} |
} |
998 |
|
|
999 |
/* |
/* |
1000 |
* Return destination surface |
* Return destination surface |
1001 |
*/ |
*/ |
1002 |
return (rz_dst); |
return (rz_dst); |
1003 |
} |
} |