root/trunk/sdl_rotozoom/rotozoom.d

Revision 20, 24.6 kB (checked in by clayasaurus, 7 years ago)

added sdl rotozoomer

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