3 SDL_rotozoom.c - rotozoomer for 32bit or 8bit surfaces
12 #include "SDL_rotozoom.h"
14 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
19 32bit integer-factor averaging Shrinker
21 Shrinks 32bit RGBA/ABGR 'src' surface to 'dst' surface.
25 int shrinkSurfaceRGBA(SDL_Surface
* src
, SDL_Surface
* dst
, int factorx
, int factory
)
27 int x
, y
, dx
, dy
, sgap
, dgap
, ra
, ga
, ba
, aa
;
29 tColorRGBA
*sp
, *osp
, *oosp
;
33 * Averaging integer shrink
36 /* Precalculate division factor */
37 n_average
= factorx
*factory
;
42 sp
= (tColorRGBA
*) src
->pixels
;
43 sgap
= src
->pitch
- src
->w
* 4;
45 dp
= (tColorRGBA
*) dst
->pixels
;
46 dgap
= dst
->pitch
- dst
->w
* 4;
48 for (y
= 0; y
< dst
->h
; y
++) {
51 for (x
= 0; x
< dst
->w
; x
++) {
53 /* Trace out source box and accumulate */
56 for (dy
=0; dy
< factory
; dy
++) {
57 for (dx
=0; dx
< factorx
; dx
++) {
65 sp
= (tColorRGBA
*)((Uint8
*)sp
+ (src
->pitch
- 4*factorx
));
69 sp
= (tColorRGBA
*)((Uint8
*)oosp
+ 4*factorx
);
71 /* Store result in destination */
78 * Advance destination pointer
84 sp
= (tColorRGBA
*)((Uint8
*)osp
+ src
->pitch
*factory
);
87 * Advance destination pointers
89 dp
= (tColorRGBA
*) ((Uint8
*) dp
+ dgap
);
97 8bit integer-factor averaging Shrinker
99 Shrinks 8bit Y 'src' surface to 'dst' surface.
103 int shrinkSurfaceY(SDL_Surface
* src
, SDL_Surface
* dst
, int factorx
, int factory
)
105 int x
, y
, dx
, dy
, sgap
, dgap
, a
;
107 Uint8
*sp
, *osp
, *oosp
;
111 * Averaging integer shrink
114 /* Precalculate division factor */
115 n_average
= factorx
*factory
;
120 sp
= (Uint8
*) src
->pixels
;
121 sgap
= src
->pitch
- src
->w
;
123 dp
= (Uint8
*) dst
->pixels
;
124 dgap
= dst
->pitch
- dst
->w
;
126 for (y
= 0; y
< dst
->h
; y
++) {
129 for (x
= 0; x
< dst
->w
; x
++) {
131 /* Trace out source box and accumulate */
134 for (dy
=0; dy
< factory
; dy
++) {
135 for (dx
=0; dx
< factorx
; dx
++) {
139 sp
= (Uint8
*)((Uint8
*)sp
+ (src
->pitch
- factorx
));
143 sp
= (Uint8
*)((Uint8
*)oosp
+ factorx
);
145 /* Store result in destination */
149 * Advance destination pointer
155 sp
= (Uint8
*)((Uint8
*)osp
+ src
->pitch
*factory
);
158 * Advance destination pointers
160 dp
= (Uint8
*)((Uint8
*)dp
+ dgap
);
168 32bit Zoomer with optional anti-aliasing by bilinear interpolation.
170 Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
174 int zoomSurfaceRGBA(SDL_Surface
* src
, SDL_Surface
* dst
, int flipx
, int flipy
, int smooth
)
176 int x
, y
, sx
, sy
, *sax
, *say
, *csax
, *csay
, csx
, csy
, ex
, ey
, t1
, t2
, sstep
;
177 tColorRGBA
*c00
, *c01
, *c10
, *c11
;
178 tColorRGBA
*sp
, *csp
, *dp
;
186 * For interpolation: assume source dimension is one pixel
189 * smaller to avoid overflow on right and bottom edge.
191 sx
= (int) (65536.0 * (float) (src
->w
- 1) / (float) dst
->w
);
192 sy
= (int) (65536.0 * (float) (src
->h
- 1) / (float) dst
->h
);
194 sx
= (int) (65536.0 * (float) src
->w
/ (float) dst
->w
);
195 sy
= (int) (65536.0 * (float) src
->h
/ (float) dst
->h
);
199 * Allocate memory for row increments
201 if ((sax
= (int *) malloc((dst
->w
+ 1) * sizeof(Uint32
))) == NULL
) {
204 if ((say
= (int *) malloc((dst
->h
+ 1) * sizeof(Uint32
))) == NULL
) {
210 * Precalculate row increments
212 sp
= csp
= (tColorRGBA
*) src
->pixels
;
213 dp
= (tColorRGBA
*) dst
->pixels
;
215 if (flipx
) csp
+= (src
->w
-1);
216 if (flipy
) csp
= (tColorRGBA
*)( (Uint8
*)csp
+ src
->pitch
*(src
->h
-1) );
220 for (x
= 0; x
<= dst
->w
; x
++) {
228 for (y
= 0; y
<= dst
->h
; y
++) {
235 dgap
= dst
->pitch
- dst
->w
* 4;
238 * Switch between interpolating and non-interpolating code
250 for (y
= 0; y
< dst
->h
; y
++) {
252 * Setup color source pointers
257 c10
= (tColorRGBA
*) ((Uint8
*) csp
+ src
->pitch
);
261 for (x
= 0; x
< dst
->w
; x
++) {
266 ex
= (*csax
& 0xffff);
267 ey
= (*csay
& 0xffff);
268 t1
= ((((c01
->r
- c00
->r
) * ex
) >> 16) + c00
->r
) & 0xff;
269 t2
= ((((c11
->r
- c10
->r
) * ex
) >> 16) + c10
->r
) & 0xff;
270 dp
->r
= (((t2
- t1
) * ey
) >> 16) + t1
;
271 t1
= ((((c01
->g
- c00
->g
) * ex
) >> 16) + c00
->g
) & 0xff;
272 t2
= ((((c11
->g
- c10
->g
) * ex
) >> 16) + c10
->g
) & 0xff;
273 dp
->g
= (((t2
- t1
) * ey
) >> 16) + t1
;
274 t1
= ((((c01
->b
- c00
->b
) * ex
) >> 16) + c00
->b
) & 0xff;
275 t2
= ((((c11
->b
- c10
->b
) * ex
) >> 16) + c10
->b
) & 0xff;
276 dp
->b
= (((t2
- t1
) * ey
) >> 16) + t1
;
277 t1
= ((((c01
->a
- c00
->a
) * ex
) >> 16) + c00
->a
) & 0xff;
278 t2
= ((((c11
->a
- c10
->a
) * ex
) >> 16) + c10
->a
) & 0xff;
279 dp
->a
= (((t2
- t1
) * ey
) >> 16) + t1
;
282 * Advance source pointers
285 sstep
= (*csax
>> 16);
291 * Advance destination pointer
296 * Advance source pointer
299 csp
= (tColorRGBA
*) ((Uint8
*) csp
+ (*csay
>> 16) * src
->pitch
);
301 * Advance destination pointers
303 dp
= (tColorRGBA
*) ((Uint8
*) dp
+ dgap
);
309 * Non-Interpolating Zoom
313 for (y
= 0; y
< dst
->h
; y
++) {
316 for (x
= 0; x
< dst
->w
; x
++) {
322 * Advance source pointers
325 sstep
= (*csax
>> 16);
326 if (flipx
) sstep
= -sstep
;
329 * Advance destination pointer
334 * Advance source pointer
337 sstep
= (*csay
>> 16) * src
->pitch
;
338 if (flipy
) sstep
= -sstep
;
339 csp
= (tColorRGBA
*) ((Uint8
*) csp
+ sstep
);
342 * Advance destination pointers
344 dp
= (tColorRGBA
*) ((Uint8
*) dp
+ dgap
);
360 8bit Zoomer without smoothing.
362 Zoomes 8bit palette/Y 'src' surface to 'dst' surface.
366 int zoomSurfaceY(SDL_Surface
* src
, SDL_Surface
* dst
, int flipx
, int flipy
)
371 Uint32 x
, y
, sx
, sy
, *sax
, *say
, *csax
, *csay
, csx
, csy
;
372 Uint8
*sp
, *dp
, *csp
;
378 sx
= (Uint32
) (65536.0 * (float) src
->w
/ (float) dst
->w
);
379 sy
= (Uint32
) (65536.0 * (float) src
->h
/ (float) dst
->h
);
382 * Allocate memory for row increments
384 if ((sax
= (Uint32
*) malloc(dst
->w
* sizeof(Uint32
))) == NULL
) {
387 if ((say
= (Uint32
*) malloc(dst
->h
* sizeof(Uint32
))) == NULL
) {
395 * Precalculate row increments
399 for (x
= 0; x
< (Uint32
)dst
->w
; x
++) {
407 for (y
= 0; y
< (Uint32
)dst
->h
; y
++) {
416 for (x
= 0; x
< (Uint32
)dst
->w
; x
++) {
422 for (y
= 0; y
< (Uint32
)dst
->h
; y
++) {
430 sp
= csp
= (Uint8
*) src
->pixels
;
431 dp
= (Uint8
*) dst
->pixels
;
432 dgap
= dst
->pitch
- dst
->w
;
438 for (y
= 0; y
< (Uint32
)dst
->h
; y
++) {
441 for (x
= 0; x
< (Uint32
)dst
->w
; x
++) {
447 * Advance source pointers
452 * Advance destination pointer
457 * Advance source pointer (for row)
459 csp
+= ((*csay
) * src
->pitch
);
462 * Advance destination pointers
478 32bit Rotozoomer with optional anti-aliasing by bilinear interpolation.
480 Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
484 void transformSurfaceRGBA(SDL_Surface
* src
, SDL_Surface
* dst
, int cx
, int cy
, int isin
, int icos
, int flipx
, int flipy
, int smooth
)
486 int x
, y
, t1
, t2
, dx
, dy
, xd
, yd
, sdx
, sdy
, ax
, ay
, ex
, ey
, sw
, sh
;
487 tColorRGBA c00
, c01
, c10
, c11
;
494 xd
= ((src
->w
- dst
->w
) << 15);
495 yd
= ((src
->h
- dst
->h
) << 15);
496 ax
= (cx
<< 16) - (icos
* cx
);
497 ay
= (cy
<< 16) - (isin
* cx
);
500 pc
= (tColorRGBA
*)dst
->pixels
;
501 gap
= dst
->pitch
- dst
->w
* 4;
504 * Switch between interpolating and non-interpolating code
507 for (y
= 0; y
< dst
->h
; y
++) {
509 sdx
= (ax
+ (isin
* dy
)) + xd
;
510 sdy
= (ay
- (icos
* dy
)) + yd
;
511 for (x
= 0; x
< dst
->w
; x
++) {
514 if ((dx
>= -1) && (dy
>= -1) && (dx
< src
->w
) && (dy
< src
->h
)) {
515 if ((dx
>= 0) && (dy
>= 0) && (dx
< sw
) && (dy
< sh
)) {
516 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
521 sp
= (tColorRGBA
*) ((Uint8
*) sp
+ src
->pitch
);
526 } else if ((dx
== sw
) && (dy
== sh
)) {
527 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
533 } else if ((dx
== -1) && (dy
== -1)) {
534 sp
= (tColorRGBA
*) (src
->pixels
);
539 } else if ((dx
== -1) && (dy
== sh
)) {
540 sp
= (tColorRGBA
*) (src
->pixels
);
541 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
546 } else if ((dx
== sw
) && (dy
== -1)) {
547 sp
= (tColorRGBA
*) (src
->pixels
);
553 } else if (dx
== -1) {
554 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
558 sp
= (tColorRGBA
*) ((Uint8
*) sp
+ src
->pitch
);
560 } else if (dy
== -1) {
561 sp
= (tColorRGBA
*) (src
->pixels
);
568 } else if (dx
== sw
) {
569 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
573 sp
= (tColorRGBA
*) ((Uint8
*) sp
+ src
->pitch
);
576 } else if (dy
== sh
) {
577 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
590 t1
= ((((c01
.r
- c00
.r
) * ex
) >> 16) + c00
.r
) & 0xff;
591 t2
= ((((c11
.r
- c10
.r
) * ex
) >> 16) + c10
.r
) & 0xff;
592 pc
->r
= (((t2
- t1
) * ey
) >> 16) + t1
;
593 t1
= ((((c01
.g
- c00
.g
) * ex
) >> 16) + c00
.g
) & 0xff;
594 t2
= ((((c11
.g
- c10
.g
) * ex
) >> 16) + c10
.g
) & 0xff;
595 pc
->g
= (((t2
- t1
) * ey
) >> 16) + t1
;
596 t1
= ((((c01
.b
- c00
.b
) * ex
) >> 16) + c00
.b
) & 0xff;
597 t2
= ((((c11
.b
- c10
.b
) * ex
) >> 16) + c10
.b
) & 0xff;
598 pc
->b
= (((t2
- t1
) * ey
) >> 16) + t1
;
599 t1
= ((((c01
.a
- c00
.a
) * ex
) >> 16) + c00
.a
) & 0xff;
600 t2
= ((((c11
.a
- c10
.a
) * ex
) >> 16) + c10
.a
) & 0xff;
601 pc
->a
= (((t2
- t1
) * ey
) >> 16) + t1
;
607 pc
= (tColorRGBA
*) ((Uint8
*) pc
+ gap
);
610 for (y
= 0; y
< dst
->h
; y
++) {
612 sdx
= (ax
+ (isin
* dy
)) + xd
;
613 sdy
= (ay
- (icos
* dy
)) + yd
;
614 for (x
= 0; x
< dst
->w
; x
++) {
615 dx
= (short) (sdx
>> 16);
616 dy
= (short) (sdy
>> 16);
617 if (flipx
) dx
= (src
->w
-1)-dx
;
618 if (flipy
) dy
= (src
->h
-1)-dy
;
619 if ((dx
>= 0) && (dy
>= 0) && (dx
< src
->w
) && (dy
< src
->h
)) {
620 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
628 pc
= (tColorRGBA
*) ((Uint8
*) pc
+ gap
);
635 8bit Rotozoomer without smoothing
637 Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface.
641 void transformSurfaceY(SDL_Surface
* src
, SDL_Surface
* dst
, int cx
, int cy
, int isin
, int icos
)
643 int x
, y
, dx
, dy
, xd
, yd
, sdx
, sdy
, ax
, ay
, sw
, sh
;
650 xd
= ((src
->w
- dst
->w
) << 15);
651 yd
= ((src
->h
- dst
->h
) << 15);
652 ax
= (cx
<< 16) - (icos
* cx
);
653 ay
= (cy
<< 16) - (isin
* cx
);
656 pc
= (tColorY
*)dst
->pixels
;
657 gap
= dst
->pitch
- dst
->w
;
659 * Clear surface to colorkey
661 memset(pc
, (unsigned char) (src
->format
->colorkey
& 0xff), dst
->pitch
* dst
->h
);
663 * Iterate through destination surface
665 for (y
= 0; y
< dst
->h
; y
++) {
667 sdx
= (ax
+ (isin
* dy
)) + xd
;
668 sdy
= (ay
- (icos
* dy
)) + yd
;
669 for (x
= 0; x
< dst
->w
; x
++) {
670 dx
= (short) (sdx
>> 16);
671 dy
= (short) (sdy
>> 16);
672 if ((dx
>= 0) && (dy
>= 0) && (dx
< src
->w
) && (dy
< src
->h
)) {
673 sp
= (tColorY
*) (src
->pixels
);
674 sp
+= (src
->pitch
* dy
+ dx
);
688 32bit specialized 90degree rotator
690 Rotates and zooms 'src' surface to 'dst' surface in 90degree increments.
692 (contributed by Jeff Schiller)
695 SDL_Surface
* rotateSurface90Degrees(SDL_Surface
* pSurf
, int numClockwiseTurns
)
697 int row
, col
, newWidth
, newHeight
;
698 SDL_Surface
* pSurfOut
;
701 if (!pSurf
|| pSurf
->format
->BitsPerPixel
!= 32) { return NULL
; }
704 while(numClockwiseTurns
< 0) { numClockwiseTurns
+= 4; }
705 numClockwiseTurns
= (numClockwiseTurns
% 4);
708 newWidth
= (numClockwiseTurns
% 2) ? (pSurf
->h
) : (pSurf
->w
);
709 newHeight
= (numClockwiseTurns
% 2) ? (pSurf
->w
) : (pSurf
->h
);
710 pSurfOut
= SDL_CreateRGBSurface( pSurf
->flags
, newWidth
, newHeight
, pSurf
->format
->BitsPerPixel
,
711 pSurf
->format
->Rmask
,
712 pSurf
->format
->Gmask
,
713 pSurf
->format
->Bmask
,
714 pSurf
->format
->Amask
);
719 if(numClockwiseTurns
!= 0) {
720 SDL_LockSurface(pSurf
);
721 SDL_LockSurface(pSurfOut
);
722 switch(numClockwiseTurns
) {
726 Uint32
* srcBuf
= NULL
;
727 Uint32
* dstBuf
= NULL
;
729 for (row
= 0; row
< pSurf
->h
; ++row
) {
730 srcBuf
= (Uint32
*)(pSurf
->pixels
) + (row
*pSurf
->pitch
/4);
731 dstBuf
= (Uint32
*)(pSurfOut
->pixels
) + (pSurfOut
->w
- row
- 1);
732 for (col
= 0; col
< pSurf
->w
; ++col
) {
735 dstBuf
+= pSurfOut
->pitch
/4;
743 Uint32
* srcBuf
= NULL
;
744 Uint32
* dstBuf
= NULL
;
746 for(row
= 0; row
< pSurf
->h
; ++row
) {
747 srcBuf
= (Uint32
*)(pSurf
->pixels
) + (row
*pSurf
->pitch
/4);
748 dstBuf
= (Uint32
*)(pSurfOut
->pixels
) + ((pSurfOut
->h
- row
- 1)*pSurfOut
->pitch
/4) + (pSurfOut
->w
- 1);
749 for(col
= 0; col
< pSurf
->w
; ++col
) {
760 Uint32
* srcBuf
= NULL
;
761 Uint32
* dstBuf
= NULL
;
763 for(row
= 0; row
< pSurf
->h
; ++row
) {
764 srcBuf
= (Uint32
*)(pSurf
->pixels
) + (row
*pSurf
->pitch
/4);
765 dstBuf
= (Uint32
*)(pSurfOut
->pixels
) + row
+ ((pSurfOut
->h
- 1)*pSurfOut
->pitch
/4);
766 for(col
= 0; col
< pSurf
->w
; ++col
) {
769 dstBuf
-= pSurfOut
->pitch
/4;
776 SDL_UnlockSurface(pSurf
);
777 SDL_UnlockSurface(pSurfOut
);
780 /* simply copy surface to output */
781 if(SDL_BlitSurface(pSurf
, NULL
, pSurfOut
, NULL
)) {
792 Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
793 'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1
794 then the destination 32bit surface is anti-aliased. If the surface is not 8bit
795 or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
799 #define VALUE_LIMIT 0.001
802 /* Local rotozoom-size function with trig result return */
804 void rotozoomSurfaceSizeTrig(int width
, int height
, double angle
, double zoomx
, double zoomy
, int *dstwidth
, int *dstheight
,
805 double *canglezoom
, double *sanglezoom
)
809 double x
, y
, cx
, cy
, sx
, sy
;
811 int dstwidthhalf
, dstheighthalf
;
814 * Determine destination width and height by rotating a centered source box
816 radangle
= angle
* (M_PI
/ 180.0);
817 *sanglezoom
= sin(radangle
);
818 *canglezoom
= cos(radangle
);
819 *sanglezoom
*= zoomx
;
820 *canglezoom
*= zoomx
;
823 cx
= *canglezoom
* x
;
824 cy
= *canglezoom
* y
;
825 sx
= *sanglezoom
* x
;
826 sy
= *sanglezoom
* y
;
828 dstwidthhalf
= MAX((int)
829 ceil(MAX(MAX(MAX(fabs(cx
+ sy
), fabs(cx
- sy
)), fabs(-cx
+ sy
)), fabs(-cx
- sy
))), 1);
830 dstheighthalf
= MAX((int)
831 ceil(MAX(MAX(MAX(fabs(sx
+ cy
), fabs(sx
- cy
)), fabs(-sx
+ cy
)), fabs(-sx
- cy
))), 1);
832 *dstwidth
= 2 * dstwidthhalf
;
833 *dstheight
= 2 * dstheighthalf
;
837 /* Publically available rotozoom-size function */
839 void rotozoomSurfaceSizeXY(int width
, int height
, double angle
, double zoomx
, double zoomy
, int *dstwidth
, int *dstheight
)
841 double dummy_sanglezoom
, dummy_canglezoom
;
843 rotozoomSurfaceSizeTrig(width
, height
, angle
, zoomx
, zoomy
, dstwidth
, dstheight
, &dummy_sanglezoom
, &dummy_canglezoom
);
846 /* Publically available rotozoom-size function */
848 void rotozoomSurfaceSize(int width
, int height
, double angle
, double zoom
, int *dstwidth
, int *dstheight
)
850 double dummy_sanglezoom
, dummy_canglezoom
;
852 rotozoomSurfaceSizeTrig(width
, height
, angle
, zoom
, zoom
, dstwidth
, dstheight
, &dummy_sanglezoom
, &dummy_canglezoom
);
855 /* Publically available rotozoom function */
857 SDL_Surface
*rotozoomSurface(SDL_Surface
* src
, double angle
, double zoom
, int smooth
)
859 return rotozoomSurfaceXY(src
, angle
, zoom
, zoom
, smooth
);
862 /* Publically available rotozoom function */
864 SDL_Surface
*rotozoomSurfaceXY(SDL_Surface
* src
, double angle
, double zoomx
, double zoomy
, int smooth
)
869 double sanglezoom
, canglezoom
, sanglezoominv
, canglezoominv
;
870 int dstwidthhalf
, dstwidth
, dstheighthalf
, dstheight
;
872 int i
, src_converted
;
876 int colorKeyAvailable
= 0;
884 if( src
->flags
& SDL_SRCCOLORKEY
)
886 colorkey
= src
->format
->colorkey
;
887 SDL_GetRGB(colorkey
, src
->format
, &r
, &g
, &b
);
888 colorKeyAvailable
= 1;
891 * Determine if source surface is 32bit or 8bit
893 is32bit
= (src
->format
->BitsPerPixel
== 32);
894 if ((is32bit
) || (src
->format
->BitsPerPixel
== 8)) {
896 * Use source surface 'as is'
902 * New source surface is 32bit with a defined RGBA ordering
905 SDL_CreateRGBSurface(SDL_SWSURFACE
, src
->w
, src
->h
, 32,
906 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
907 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
909 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
912 if(colorKeyAvailable
)
913 SDL_SetColorKey(src
, 0, 0);
915 SDL_BlitSurface(src
, NULL
, rz_src
, NULL
);
917 if(colorKeyAvailable
)
918 SDL_SetColorKey(src
, SDL_SRCCOLORKEY
, colorkey
);
924 * Sanity check zoom factor
927 if (flipx
) zoomx
=-zoomx
;
929 if (flipy
) zoomy
=-zoomy
;
930 if (zoomx
< VALUE_LIMIT
) zoomx
= VALUE_LIMIT
;
931 if (zoomy
< VALUE_LIMIT
) zoomy
= VALUE_LIMIT
;
932 zoominv
= 65536.0 / (zoomx
* zoomx
);
935 * Check if we have a rotozoom or just a zoom
937 if (fabs(angle
) > VALUE_LIMIT
) {
940 * Angle!=0: full rotozoom
943 * -----------------------
946 /* Determine target size */
947 rotozoomSurfaceSizeTrig(rz_src
->w
, rz_src
->h
, angle
, zoomx
, zoomy
, &dstwidth
, &dstheight
, &canglezoom
, &sanglezoom
);
950 * Calculate target factors from sin/cos and zoom
952 sanglezoominv
= sanglezoom
;
953 canglezoominv
= canglezoom
;
954 sanglezoominv
*= zoominv
;
955 canglezoominv
*= zoominv
;
957 /* Calculate half size */
958 dstwidthhalf
= dstwidth
/ 2;
959 dstheighthalf
= dstheight
/ 2;
962 * Alloc space to completely contain the rotated surface
967 * Target surface is 32bit with source RGBA/ABGR ordering
970 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
971 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
972 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
975 * Target surface is 8bit
977 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
980 if (colorKeyAvailable
== 1){
981 colorkey
= SDL_MapRGB(rz_dst
->format
, r
, g
, b
);
983 SDL_FillRect(rz_dst
, NULL
, colorkey
);
987 * Lock source surface
989 SDL_LockSurface(rz_src
);
991 * Check which kind of surface we have
995 * Call the 32bit transformation routine to do the rotation (using alpha)
997 transformSurfaceRGBA(rz_src
, rz_dst
, dstwidthhalf
, dstheighthalf
,
998 (int) (sanglezoominv
), (int) (canglezoominv
),
1002 * Turn on source-alpha support
1004 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1007 * Copy palette and colorkey info
1009 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1010 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1012 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1014 * Call the 8bit transformation routine to do the rotation
1016 transformSurfaceY(rz_src
, rz_dst
, dstwidthhalf
, dstheighthalf
,
1017 (int) (sanglezoominv
), (int) (canglezoominv
));
1018 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1021 * Unlock source surface
1023 SDL_UnlockSurface(rz_src
);
1028 * Angle=0: Just a zoom
1031 * --------------------
1035 * Calculate target size
1037 zoomSurfaceSize(rz_src
->w
, rz_src
->h
, zoomx
, zoomy
, &dstwidth
, &dstheight
);
1040 * Alloc space to completely contain the zoomed surface
1045 * Target surface is 32bit with source RGBA/ABGR ordering
1048 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
1049 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
1050 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
1053 * Target surface is 8bit
1055 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
1058 if (colorKeyAvailable
== 1){
1059 colorkey
= SDL_MapRGB(rz_dst
->format
, r
, g
, b
);
1061 SDL_FillRect(rz_dst
, NULL
, colorkey
);
1065 * Lock source surface
1067 SDL_LockSurface(rz_src
);
1069 * Check which kind of surface we have
1073 * Call the 32bit transformation routine to do the zooming (using alpha)
1075 zoomSurfaceRGBA(rz_src
, rz_dst
, flipx
, flipy
, smooth
);
1077 * Turn on source-alpha support
1079 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1082 * Copy palette and colorkey info
1084 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1085 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1087 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1089 * Call the 8bit transformation routine to do the zooming
1091 zoomSurfaceY(rz_src
, rz_dst
, flipx
, flipy
);
1092 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1095 * Unlock source surface
1097 SDL_UnlockSurface(rz_src
);
1101 * Cleanup temp surface
1103 if (src_converted
) {
1104 SDL_FreeSurface(rz_src
);
1108 * Return destination surface
1117 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1118 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1
1119 then the destination 32bit surface is anti-aliased. If the surface is not 8bit
1120 or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
1124 #define VALUE_LIMIT 0.001
1126 void zoomSurfaceSize(int width
, int height
, double zoomx
, double zoomy
, int *dstwidth
, int *dstheight
)
1129 * Sanity check zoom factors
1131 if (zoomx
< VALUE_LIMIT
) {
1132 zoomx
= VALUE_LIMIT
;
1134 if (zoomy
< VALUE_LIMIT
) {
1135 zoomy
= VALUE_LIMIT
;
1139 * Calculate target size
1141 *dstwidth
= (int) ((double) width
* zoomx
);
1142 *dstheight
= (int) ((double) height
* zoomy
);
1143 if (*dstwidth
< 1) {
1146 if (*dstheight
< 1) {
1151 SDL_Surface
*zoomSurface(SDL_Surface
* src
, double zoomx
, double zoomy
, int smooth
)
1153 SDL_Surface
*rz_src
;
1154 SDL_Surface
*rz_dst
;
1155 int dstwidth
, dstheight
;
1157 int i
, src_converted
;
1167 * Determine if source surface is 32bit or 8bit
1169 is32bit
= (src
->format
->BitsPerPixel
== 32);
1170 if ((is32bit
) || (src
->format
->BitsPerPixel
== 8)) {
1172 * Use source surface 'as is'
1178 * New source surface is 32bit with a defined RGBA ordering
1181 SDL_CreateRGBSurface(SDL_SWSURFACE
, src
->w
, src
->h
, 32,
1182 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1183 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1185 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1188 SDL_BlitSurface(src
, NULL
, rz_src
, NULL
);
1194 if (flipx
) zoomx
= -zoomx
;
1196 if (flipy
) zoomy
= -zoomy
;
1198 /* Get size if target */
1199 zoomSurfaceSize(rz_src
->w
, rz_src
->h
, zoomx
, zoomy
, &dstwidth
, &dstheight
);
1202 * Alloc space to completely contain the zoomed surface
1207 * Target surface is 32bit with source RGBA/ABGR ordering
1210 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
1211 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
1212 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
1215 * Target surface is 8bit
1217 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
1221 * Lock source surface
1223 SDL_LockSurface(rz_src
);
1225 * Check which kind of surface we have
1229 * Call the 32bit transformation routine to do the zooming (using alpha)
1231 zoomSurfaceRGBA(rz_src
, rz_dst
, flipx
, flipy
, smooth
);
1233 * Turn on source-alpha support
1235 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1238 * Copy palette and colorkey info
1240 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1241 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1243 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1245 * Call the 8bit transformation routine to do the zooming
1247 zoomSurfaceY(rz_src
, rz_dst
, flipx
, flipy
);
1248 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1251 * Unlock source surface
1253 SDL_UnlockSurface(rz_src
);
1256 * Cleanup temp surface
1258 if (src_converted
) {
1259 SDL_FreeSurface(rz_src
);
1263 * Return destination surface
1268 SDL_Surface
*shrinkSurface(SDL_Surface
* src
, int factorx
, int factory
)
1270 SDL_Surface
*rz_src
;
1271 SDL_Surface
*rz_dst
;
1272 int dstwidth
, dstheight
;
1274 int i
, src_converted
;
1283 * Determine if source surface is 32bit or 8bit
1285 is32bit
= (src
->format
->BitsPerPixel
== 32);
1286 if ((is32bit
) || (src
->format
->BitsPerPixel
== 8)) {
1288 * Use source surface 'as is'
1294 * New source surface is 32bit with a defined RGBA ordering
1297 SDL_CreateRGBSurface(SDL_SWSURFACE
, src
->w
, src
->h
, 32,
1298 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1299 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1301 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1304 SDL_BlitSurface(src
, NULL
, rz_src
, NULL
);
1309 /* Get size for target */
1310 dstwidth
=rz_src
->w
/factorx
;
1311 while (dstwidth
*factorx
>rz_src
->w
) { dstwidth
--; }
1312 dstheight
=rz_src
->h
/factory
;
1313 while (dstheight
*factory
>rz_src
->h
) { dstheight
--; }
1316 * Alloc space to completely contain the shrunken surface
1321 * Target surface is 32bit with source RGBA/ABGR ordering
1324 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
1325 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
1326 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
1329 * Target surface is 8bit
1331 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
1335 * Lock source surface
1337 SDL_LockSurface(rz_src
);
1339 * Check which kind of surface we have
1343 * Call the 32bit transformation routine to do the shrinking (using alpha)
1345 shrinkSurfaceRGBA(rz_src
, rz_dst
, factorx
, factory
);
1347 * Turn on source-alpha support
1349 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1352 * Copy palette and colorkey info
1354 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1355 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1357 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1359 * Call the 8bit transformation routine to do the shrinking
1361 shrinkSurfaceY(rz_src
, rz_dst
, factorx
, factory
);
1362 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1365 * Unlock source surface
1367 SDL_UnlockSurface(rz_src
);
1370 * Cleanup temp surface
1372 if (src_converted
) {
1373 SDL_FreeSurface(rz_src
);
1377 * Return destination surface