root / sdl_zoom_template.h @ 636aa70a
History | View | Annotate | Download (7 kB)
1 |
/*
|
---|---|
2 |
* SDL_zoom_template - surface scaling
|
3 |
*
|
4 |
* Copyright (c) 2009 Citrix Systems, Inc.
|
5 |
*
|
6 |
* Derived from: SDL_rotozoom, LGPL (c) A. Schiffler from the SDL_gfx library.
|
7 |
* Modifications by Stefano Stabellini.
|
8 |
*
|
9 |
* This work is licensed under the terms of the GNU GPL version 2.
|
10 |
* See the COPYING file in the top-level directory.
|
11 |
*
|
12 |
*/
|
13 |
|
14 |
#if BPP == 16 |
15 |
#define SDL_TYPE Uint16
|
16 |
#elif BPP == 32 |
17 |
#define SDL_TYPE Uint32
|
18 |
#else
|
19 |
#error unsupport depth
|
20 |
#endif
|
21 |
|
22 |
/*
|
23 |
* Simple helper functions to make the code looks nicer
|
24 |
*
|
25 |
* Assume spf = source SDL_PixelFormat
|
26 |
* dpf = dest SDL_PixelFormat
|
27 |
*
|
28 |
*/
|
29 |
#define getRed(color) (((color) & spf->Rmask) >> spf->Rshift)
|
30 |
#define getGreen(color) (((color) & spf->Gmask) >> spf->Gshift)
|
31 |
#define getBlue(color) (((color) & spf->Bmask) >> spf->Bshift)
|
32 |
#define getAlpha(color) (((color) & spf->Amask) >> spf->Ashift)
|
33 |
|
34 |
#define setRed(r, pcolor) do { \ |
35 |
*pcolor = ((*pcolor) & (~(dpf->Rmask))) + \ |
36 |
(((r) & (dpf->Rmask >> dpf->Rshift)) << dpf->Rshift); \ |
37 |
} while (0); |
38 |
|
39 |
#define setGreen(g, pcolor) do { \ |
40 |
*pcolor = ((*pcolor) & (~(dpf->Gmask))) + \ |
41 |
(((g) & (dpf->Gmask >> dpf->Gshift)) << dpf->Gshift); \ |
42 |
} while (0); |
43 |
|
44 |
#define setBlue(b, pcolor) do { \ |
45 |
*pcolor = ((*pcolor) & (~(dpf->Bmask))) + \ |
46 |
(((b) & (dpf->Bmask >> dpf->Bshift)) << dpf->Bshift); \ |
47 |
} while (0); |
48 |
|
49 |
#define setAlpha(a, pcolor) do { \ |
50 |
*pcolor = ((*pcolor) & (~(dpf->Amask))) + \ |
51 |
(((a) & (dpf->Amask >> dpf->Ashift)) << dpf->Ashift); \ |
52 |
} while (0); |
53 |
|
54 |
static int glue(sdl_zoom_rgb, BPP)(SDL_Surface *src, SDL_Surface *dst, int smooth, |
55 |
SDL_Rect *dst_rect) |
56 |
{ |
57 |
int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, sstep_jump;
|
58 |
SDL_TYPE *c00, *c01, *c10, *c11, *sp, *csp, *dp; |
59 |
int d_gap;
|
60 |
SDL_PixelFormat *spf = src->format; |
61 |
SDL_PixelFormat *dpf = dst->format; |
62 |
|
63 |
if (smooth) {
|
64 |
/* For interpolation: assume source dimension is one pixel.
|
65 |
* Smaller here to avoid overflow on right and bottom edge.
|
66 |
*/
|
67 |
sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); |
68 |
sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); |
69 |
} else {
|
70 |
sx = (int) (65536.0 * (float) src->w / (float) dst->w); |
71 |
sy = (int) (65536.0 * (float) src->h / (float) dst->h); |
72 |
} |
73 |
|
74 |
if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { |
75 |
return (-1); |
76 |
} |
77 |
if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { |
78 |
free(sax); |
79 |
return (-1); |
80 |
} |
81 |
|
82 |
sp = csp = (SDL_TYPE *) src->pixels; |
83 |
dp = (SDL_TYPE *) (dst->pixels + dst_rect->y * dst->pitch + |
84 |
dst_rect->x * dst->format->BytesPerPixel); |
85 |
|
86 |
csx = 0;
|
87 |
csax = sax; |
88 |
for (x = 0; x <= dst->w; x++) { |
89 |
*csax = csx; |
90 |
csax++; |
91 |
csx &= 0xffff;
|
92 |
csx += sx; |
93 |
} |
94 |
csy = 0;
|
95 |
csay = say; |
96 |
for (y = 0; y <= dst->h; y++) { |
97 |
*csay = csy; |
98 |
csay++; |
99 |
csy &= 0xffff;
|
100 |
csy += sy; |
101 |
} |
102 |
|
103 |
d_gap = dst->pitch - dst_rect->w * dst->format->BytesPerPixel; |
104 |
|
105 |
if (smooth) {
|
106 |
csay = say; |
107 |
for (y = 0; y < dst_rect->y; y++) { |
108 |
csay++; |
109 |
sstep = (*csay >> 16) * src->pitch;
|
110 |
csp = (SDL_TYPE *) ((Uint8 *) csp + sstep); |
111 |
} |
112 |
|
113 |
/* Calculate sstep_jump */
|
114 |
csax = sax; |
115 |
sstep_jump = 0;
|
116 |
for (x = 0; x < dst_rect->x; x++) { |
117 |
csax++; |
118 |
sstep = (*csax >> 16);
|
119 |
sstep_jump += sstep; |
120 |
} |
121 |
|
122 |
for (y = 0; y < dst_rect->h ; y++) { |
123 |
/* Setup colour source pointers */
|
124 |
c00 = csp + sstep_jump; |
125 |
c01 = c00 + 1;
|
126 |
c10 = (SDL_TYPE *) ((Uint8 *) csp + src->pitch) + sstep_jump; |
127 |
c11 = c10 + 1;
|
128 |
csax = sax + dst_rect->x; |
129 |
|
130 |
for (x = 0; x < dst_rect->w; x++) { |
131 |
|
132 |
/* Interpolate colours */
|
133 |
ex = (*csax & 0xffff);
|
134 |
ey = (*csay & 0xffff);
|
135 |
t1 = ((((getRed(*c01) - getRed(*c00)) * ex) >> 16) +
|
136 |
getRed(*c00)) & (dpf->Rmask >> dpf->Rshift); |
137 |
t2 = ((((getRed(*c11) - getRed(*c10)) * ex) >> 16) +
|
138 |
getRed(*c10)) & (dpf->Rmask >> dpf->Rshift); |
139 |
setRed((((t2 - t1) * ey) >> 16) + t1, dp);
|
140 |
t1 = ((((getGreen(*c01) - getGreen(*c00)) * ex) >> 16) +
|
141 |
getGreen(*c00)) & (dpf->Gmask >> dpf->Gshift); |
142 |
t2 = ((((getGreen(*c11) - getGreen(*c10)) * ex) >> 16) +
|
143 |
getGreen(*c10)) & (dpf->Gmask >> dpf->Gshift); |
144 |
setGreen((((t2 - t1) * ey) >> 16) + t1, dp);
|
145 |
t1 = ((((getBlue(*c01) - getBlue(*c00)) * ex) >> 16) +
|
146 |
getBlue(*c00)) & (dpf->Bmask >> dpf->Bshift); |
147 |
t2 = ((((getBlue(*c11) - getBlue(*c10)) * ex) >> 16) +
|
148 |
getBlue(*c10)) & (dpf->Bmask >> dpf->Bshift); |
149 |
setBlue((((t2 - t1) * ey) >> 16) + t1, dp);
|
150 |
t1 = ((((getAlpha(*c01) - getAlpha(*c00)) * ex) >> 16) +
|
151 |
getAlpha(*c00)) & (dpf->Amask >> dpf->Ashift); |
152 |
t2 = ((((getAlpha(*c11) - getAlpha(*c10)) * ex) >> 16) +
|
153 |
getAlpha(*c10)) & (dpf->Amask >> dpf->Ashift); |
154 |
setAlpha((((t2 - t1) * ey) >> 16) + t1, dp);
|
155 |
|
156 |
/* Advance source pointers */
|
157 |
csax++; |
158 |
sstep = (*csax >> 16);
|
159 |
c00 += sstep; |
160 |
c01 += sstep; |
161 |
c10 += sstep; |
162 |
c11 += sstep; |
163 |
/* Advance destination pointer */
|
164 |
dp++; |
165 |
} |
166 |
/* Advance source pointer */
|
167 |
csay++; |
168 |
csp = (SDL_TYPE *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
|
169 |
/* Advance destination pointers */
|
170 |
dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap); |
171 |
} |
172 |
|
173 |
|
174 |
} else {
|
175 |
csay = say; |
176 |
|
177 |
for (y = 0; y < dst_rect->y; y++) { |
178 |
csay++; |
179 |
sstep = (*csay >> 16) * src->pitch;
|
180 |
csp = (SDL_TYPE *) ((Uint8 *) csp + sstep); |
181 |
} |
182 |
|
183 |
/* Calculate sstep_jump */
|
184 |
csax = sax; |
185 |
sstep_jump = 0;
|
186 |
for (x = 0; x < dst_rect->x; x++) { |
187 |
csax++; |
188 |
sstep = (*csax >> 16);
|
189 |
sstep_jump += sstep; |
190 |
} |
191 |
|
192 |
for (y = 0 ; y < dst_rect->h ; y++) { |
193 |
sp = csp + sstep_jump; |
194 |
csax = sax + dst_rect->x; |
195 |
|
196 |
for (x = 0; x < dst_rect->w; x++) { |
197 |
|
198 |
/* Draw */
|
199 |
*dp = *sp; |
200 |
|
201 |
/* Advance source pointers */
|
202 |
csax++; |
203 |
sstep = (*csax >> 16);
|
204 |
sp += sstep; |
205 |
|
206 |
/* Advance destination pointer */
|
207 |
dp++; |
208 |
} |
209 |
/* Advance source pointers */
|
210 |
csay++; |
211 |
sstep = (*csay >> 16) * src->pitch;
|
212 |
csp = (SDL_TYPE *) ((Uint8 *) csp + sstep); |
213 |
|
214 |
/* Advance destination pointer */
|
215 |
dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap); |
216 |
} |
217 |
} |
218 |
|
219 |
free(sax); |
220 |
free(say); |
221 |
return (0); |
222 |
} |
223 |
|
224 |
#undef SDL_TYPE
|
225 |
|