1 
2 #include <SDL/SDL.h>
3 #include <SDL/SDL_image.h>
4 #include <stdlib.h>
5 
6 typedef struct tColorRGBA {
7    Uint8 r;
8    Uint8 g;
9    Uint8 b;
10    Uint8 a;
11     } tColorRGBA;
12 
13 
14 #define ZOOM_VALUE_LIMIT  0.0001
15 
zoomSurface(SDL_Surface * src,double zoomx,double zoomy)16 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy)
17 {
18     SDL_Surface *rz_src;
19     SDL_Surface *rz_dst;
20     int dstwidth, dstheight;
21     int is32bit;
22     int i, src_converted;
23     int flipx, flipy;
24 
25     /*
26      * Sanity check
27      */
28     if (src == NULL)
29    return (NULL);
30 
31     /*
32      * Determine if source surface is 32bit or 8bit
33      */
34     is32bit = (src->format->BitsPerPixel == 32);
35     if ((is32bit) || (src->format->BitsPerPixel == 8)) {
36    /*
37     * Use source surface 'as is'
38     */
39    rz_src = src;
40    src_converted = 0;
41     } else {
42    /*
43     * New source surface is 32bit with a defined RGBA ordering
44     */
45    rz_src =
46        SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
47    SDL_BlitSurface(src, NULL, rz_src, NULL);
48    src_converted = 1;
49    is32bit = 1;
50     }
51 
52     flipx = (zoomx<0);
53     if (flipx) zoomx = -zoomx;
54     flipy = (zoomy<0);
55     if (flipy) zoomy = -zoomy;
56 
57     /* Get size if target */
58            /*
59            * Sanity check zoom factors
60           */
61           if (zoomx < ZOOM_VALUE_LIMIT) {
62           zoomx = ZOOM_VALUE_LIMIT;
63           }
64           if (zoomy < ZOOM_VALUE_LIMIT) {
65           zoomy = ZOOM_VALUE_LIMIT;
66           }
67 
68           /*
69           * Calculate target size
70           */
71           dstwidth = (int) ((double) rz_src->w * zoomx);
72           dstheight = (int) ((double) rz_src->h * zoomy);
73           if (dstwidth < 1) {
74           dstwidth = 1;
75           }
76           if (dstheight < 1) {
77           dstheight = 1;
78           }
79 
80 
81 
82     /*
83      * Alloc space to completely contain the zoomed surface
84      */
85     rz_dst = NULL;
86     if (is32bit) {
87    /*
88     * Target surface is 32bit with source RGBA/ABGR ordering
89     */
90    rz_dst =
91        SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32,
92              rz_src->format->Rmask, rz_src->format->Gmask,
93              rz_src->format->Bmask, rz_src->format->Amask);
94     } else {
95    /*
96     * Target surface is 8bit
97     */
98    rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
99     }
100 
101     /*
102      * Lock source surface
103      */
104     SDL_LockSurface(rz_src);
105     /*
106      * Check which kind of surface we have
107      */
108     if (is32bit) {
109    /*
110     * Call the 32bit transformation routine to do the zooming (using alpha)
111     */
112 //   zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy);
113 
114     int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep;
115     tColorRGBA *c00, *c01, *c10, *c11;
116     tColorRGBA *sp, *csp, *dp;
117     int dgap;
118 
119    /*
120     * For interpolation: assume source dimension is one pixel
121     */
122    /*
123     * smaller to avoid overflow on right and bottom edge.
124     */
125    sx = (int) (65536.0 * (float) (src->w - 1) / (float) rz_dst->w);
126    sy = (int) (65536.0 * (float) (src->h - 1) / (float) rz_dst->h);
127 
128 
129     /*
130      * Allocate memory for row increments
131      */
132     if ((sax = (int *) malloc((rz_dst->w + 1) * sizeof(Uint32))) == NULL) {
133    return NULL;
134     }
135     if ((say = (int *) malloc((rz_dst->h + 1) * sizeof(Uint32))) == NULL) {
136    free(sax);
137    return NULL;
138     }
139 
140     /*
141      * Precalculate row increments
142      */
143     sp = csp = (tColorRGBA *) rz_src->pixels;
144     dp = (tColorRGBA *) rz_dst->pixels;
145 
146     if (flipx) csp += (rz_src->w-1);
147     if (flipy) csp  = (tColorRGBA*)( (Uint8*)csp + rz_src->pitch*(src->h-1) );
148 
149     csx = 0;
150     csax = sax;
151     for (x = 0; x <= rz_dst->w; x++) {
152    *csax = csx;
153    csax++;
154    csx &= 0xffff;
155    csx += sx;
156     }
157     csy = 0;
158     csay = say;
159     for (y = 0; y <= rz_dst->h; y++) {
160    *csay = csy;
161    csay++;
162    csy &= 0xffff;
163    csy += sy;
164     }
165 
166     dgap = rz_dst->pitch - rz_dst->w * 4;
167 
168    /*
169     * Interpolating Zoom
170     */
171 
172    /*
173     * Scan destination
174     */
175    csay = say;
176    for (y = 0; y < rz_dst->h; y++) {
177        /*
178         * Setup color source pointers
179         */
180        c00 = csp;
181        c01 = csp;
182        c01++;
183        c10 = (tColorRGBA *) ((Uint8 *) csp + rz_src->pitch);
184        c11 = c10;
185        c11++;
186        csax = sax;
187        for (x = 0; x < rz_dst->w; x++) {
188 
189       /*
190        * Interpolate colors
191        */
192       ex = (*csax & 0xffff);
193       ey = (*csay & 0xffff);
194       t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
195       t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
196       dp->r = (((t2 - t1) * ey) >> 16) + t1;
197       t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
198       t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
199       dp->g = (((t2 - t1) * ey) >> 16) + t1;
200       t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
201       t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
202       dp->b = (((t2 - t1) * ey) >> 16) + t1;
203       t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
204       t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
205       dp->a = (((t2 - t1) * ey) >> 16) + t1;
206 
207       /*
208        * Advance source pointers
209        */
210       csax++;
211       sstep = (*csax >> 16);
212       c00 += sstep;
213       c01 += sstep;
214       c10 += sstep;
215       c11 += sstep;
216       /*
217        * Advance destination pointer
218        */
219       dp++;
220        }
221        /*
222         * Advance source pointer
223         */
224        csay++;
225        csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * rz_src->pitch);
226        /*
227         * Advance destination pointers
228         */
229        dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
230    }
231 
232     /*
233      * Remove temp arrays
234      */
235     free(sax);
236     free(say);
237 
238 
239 
240 
241 
242    /*
243     * Turn on source-alpha support
244     */
245    SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
246     } else {
247    /*
248     * Copy palette and colorkey info
249     */
250    for (i = 0; i < rz_src->format->palette->ncolors; i++) {
251        rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
252    }
253    rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
254    /*
255     * Call the 8bit transformation routine to do the zooming
256     */
257          Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
258          Uint8 *sp, *dp, *csp;
259          int dgap;
260 
261          /*
262          * Variable setup
263          */
264         sx = (Uint32) (65536.0 * (float) rz_src->w / (float) rz_dst->w);
265         sy = (Uint32) (65536.0 * (float) rz_src->h / (float) rz_dst->h);
266 
267         /*
268          * Allocate memory for row increments
269          */
270         if ((sax = (Uint32 *) malloc(rz_dst->w * sizeof(Uint32))) == NULL) {
271        return NULL;
272         }
273         if ((say = (Uint32 *) malloc(rz_dst->h * sizeof(Uint32))) == NULL) {
274        if (sax != NULL) {
275            free(sax);
276        }
277        return NULL;
278         }
279 
280         /*
281          * Precalculate row increments
282          */
283         csx = 0;
284         csax = sax;
285         for (x = 0; x < rz_dst->w; x++) {
286        csx += sx;
287        *csax = (csx >> 16);
288        csx &= 0xffff;
289        csax++;
290         }
291         csy = 0;
292         csay = say;
293         for (y = 0; y < rz_dst->h; y++) {
294        csy += sy;
295        *csay = (csy >> 16);
296        csy &= 0xffff;
297        csay++;
298         }
299 
300         csx = 0;
301         csax = sax;
302         for (x = 0; x < rz_dst->w; x++) {
303        csx += (*csax);
304        csax++;
305         }
306         csy = 0;
307         csay = say;
308         for (y = 0; y < rz_dst->h; y++) {
309        csy += (*csay);
310        csay++;
311         }
312 
313         /*
314          * Pointer setup
315          */
316         sp = csp = (Uint8 *) rz_src->pixels;
317         dp = (Uint8 *) rz_dst->pixels;
318         dgap = rz_dst->pitch - rz_dst->w;
319 
320         /*
321          * Draw
322          */
323         csay = say;
324         for (y = 0; y < rz_dst->h; y++) {
325        csax = sax;
326        sp = csp;
327        for (x = 0; x < rz_dst->w; x++) {
328            /*
329             * Draw
330             */
331            *dp = *sp;
332            /*
333             * Advance source pointers
334             */
335            sp += (*csax);
336            csax++;
337            /*
338             * Advance destination pointer
339             */
340            dp++;
341        }
342        /*
343         * Advance source pointer (for row)
344         */
345        csp += ((*csay) * src->pitch);
346        csay++;
347        /*
348         * Advance destination pointers
349         */
350        dp += dgap;
351         }
352 
353         /*
354          * Remove temp arrays
355          */
356         free(sax);
357         free(say);
358 
359 
360    SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
361     }
362     /*
363      * Unlock source surface
364      */
365     SDL_UnlockSurface(rz_src);
366 
367     /*
368      * Cleanup temp surface
369      */
370     if (src_converted) {
371    SDL_FreeSurface(rz_src);
372     }
373 
374     /*
375      * Return destination surface
376      */
377     return (rz_dst);
378 }
379