Merge branch 'master' of http://skoegl.net/uni/numpty
[numtypysics.git] / zoomer.cpp
blobd7ef199a0e1380d50cbad0e351a09e573215029d
2 #include <SDL/SDL.h>
3 #include <SDL/SDL_image.h>
4 #include <stdlib.h>
6 typedef struct tColorRGBA {
7 Uint8 r;
8 Uint8 g;
9 Uint8 b;
10 Uint8 a;
11 } tColorRGBA;
14 #define ZOOM_VALUE_LIMIT 0.0001
16 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy)
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;
26 * Sanity check
28 if (src == NULL)
29 return (NULL);
32 * Determine if source surface is 32bit or 8bit
34 is32bit = (src->format->BitsPerPixel == 32);
35 if ((is32bit) || (src->format->BitsPerPixel == 8)) {
37 * Use source surface 'as is'
39 rz_src = src;
40 src_converted = 0;
41 } else {
43 * New source surface is 32bit with a defined RGBA ordering
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;
52 flipx = (zoomx<0);
53 if (flipx) zoomx = -zoomx;
54 flipy = (zoomy<0);
55 if (flipy) zoomy = -zoomy;
57 /* Get size if target */
59 * Sanity check zoom factors
61 if (zoomx < ZOOM_VALUE_LIMIT) {
62 zoomx = ZOOM_VALUE_LIMIT;
64 if (zoomy < ZOOM_VALUE_LIMIT) {
65 zoomy = ZOOM_VALUE_LIMIT;
69 * Calculate target size
71 dstwidth = (int) ((double) rz_src->w * zoomx);
72 dstheight = (int) ((double) rz_src->h * zoomy);
73 if (dstwidth < 1) {
74 dstwidth = 1;
76 if (dstheight < 1) {
77 dstheight = 1;
83 * Alloc space to completely contain the zoomed surface
85 rz_dst = NULL;
86 if (is32bit) {
88 * Target surface is 32bit with source RGBA/ABGR ordering
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 {
96 * Target surface is 8bit
98 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
102 * Lock source surface
104 SDL_LockSurface(rz_src);
106 * Check which kind of surface we have
108 if (is32bit) {
110 * Call the 32bit transformation routine to do the zooming (using alpha)
112 // zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy);
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;
120 * For interpolation: assume source dimension is one pixel
123 * smaller to avoid overflow on right and bottom edge.
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);
130 * Allocate memory for row increments
132 if ((sax = (int *) malloc((rz_dst->w + 1) * sizeof(Uint32))) == NULL) {
133 return NULL;
135 if ((say = (int *) malloc((rz_dst->h + 1) * sizeof(Uint32))) == NULL) {
136 free(sax);
137 return NULL;
141 * Precalculate row increments
143 sp = csp = (tColorRGBA *) rz_src->pixels;
144 dp = (tColorRGBA *) rz_dst->pixels;
146 if (flipx) csp += (rz_src->w-1);
147 if (flipy) csp = (tColorRGBA*)( (Uint8*)csp + rz_src->pitch*(src->h-1) );
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;
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;
166 dgap = rz_dst->pitch - rz_dst->w * 4;
169 * Interpolating Zoom
173 * Scan destination
175 csay = say;
176 for (y = 0; y < rz_dst->h; y++) {
178 * Setup color source pointers
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++) {
190 * Interpolate colors
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;
208 * Advance source pointers
210 csax++;
211 sstep = (*csax >> 16);
212 c00 += sstep;
213 c01 += sstep;
214 c10 += sstep;
215 c11 += sstep;
217 * Advance destination pointer
219 dp++;
222 * Advance source pointer
224 csay++;
225 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * rz_src->pitch);
227 * Advance destination pointers
229 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
233 * Remove temp arrays
235 free(sax);
236 free(say);
243 * Turn on source-alpha support
245 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
246 } else {
248 * Copy palette and colorkey info
250 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
251 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
253 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
255 * Call the 8bit transformation routine to do the zooming
257 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
258 Uint8 *sp, *dp, *csp;
259 int dgap;
262 * Variable setup
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);
268 * Allocate memory for row increments
270 if ((sax = (Uint32 *) malloc(rz_dst->w * sizeof(Uint32))) == NULL) {
271 return NULL;
273 if ((say = (Uint32 *) malloc(rz_dst->h * sizeof(Uint32))) == NULL) {
274 if (sax != NULL) {
275 free(sax);
277 return NULL;
281 * Precalculate row increments
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++;
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++;
300 csx = 0;
301 csax = sax;
302 for (x = 0; x < rz_dst->w; x++) {
303 csx += (*csax);
304 csax++;
306 csy = 0;
307 csay = say;
308 for (y = 0; y < rz_dst->h; y++) {
309 csy += (*csay);
310 csay++;
314 * Pointer setup
316 sp = csp = (Uint8 *) rz_src->pixels;
317 dp = (Uint8 *) rz_dst->pixels;
318 dgap = rz_dst->pitch - rz_dst->w;
321 * Draw
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++) {
329 * Draw
331 *dp = *sp;
333 * Advance source pointers
335 sp += (*csax);
336 csax++;
338 * Advance destination pointer
340 dp++;
343 * Advance source pointer (for row)
345 csp += ((*csay) * src->pitch);
346 csay++;
348 * Advance destination pointers
350 dp += dgap;
354 * Remove temp arrays
356 free(sax);
357 free(say);
360 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
363 * Unlock source surface
365 SDL_UnlockSurface(rz_src);
368 * Cleanup temp surface
370 if (src_converted) {
371 SDL_FreeSurface(rz_src);
375 * Return destination surface
377 return (rz_dst);