3 SDL_rotozoom.c - rotozoomer for 32bit or 8bit surfaces
16 #include "SDL_rotozoom.h"
18 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
23 32bit integer-factor averaging Shrinker
25 Shrinks 32bit RGBA/ABGR 'src' surface to 'dst' surface.
29 int shrinkSurfaceRGBA(SDL_Surface
* src
, SDL_Surface
* dst
, int factorx
, int factory
)
31 int x
, y
, dx
, dy
, sgap
, dgap
, ra
, ga
, ba
, aa
;
33 tColorRGBA
*sp
, *osp
, *oosp
;
37 * Averaging integer shrink
40 /* Precalculate division factor */
41 n_average
= factorx
*factory
;
46 sp
= (tColorRGBA
*) src
->pixels
;
47 sgap
= src
->pitch
- src
->w
* 4;
49 dp
= (tColorRGBA
*) dst
->pixels
;
50 dgap
= dst
->pitch
- dst
->w
* 4;
52 for (y
= 0; y
< dst
->h
; y
++) {
55 for (x
= 0; x
< dst
->w
; x
++) {
57 /* Trace out source box and accumulate */
60 for (dy
=0; dy
< factory
; dy
++) {
61 for (dx
=0; dx
< factorx
; dx
++) {
69 sp
= (tColorRGBA
*)((Uint8
*)sp
+ (src
->pitch
- 4*factorx
));
73 sp
= (tColorRGBA
*)((Uint8
*)oosp
+ 4*factorx
);
75 /* Store result in destination */
82 * Advance destination pointer
88 sp
= (tColorRGBA
*)((Uint8
*)osp
+ src
->pitch
*factory
);
91 * Advance destination pointers
93 dp
= (tColorRGBA
*) ((Uint8
*) dp
+ dgap
);
101 8bit integer-factor averaging Shrinker
103 Shrinks 8bit Y 'src' surface to 'dst' surface.
107 int shrinkSurfaceY(SDL_Surface
* src
, SDL_Surface
* dst
, int factorx
, int factory
)
109 int x
, y
, dx
, dy
, sgap
, dgap
, a
;
111 Uint8
*sp
, *osp
, *oosp
;
115 * Averaging integer shrink
118 /* Precalculate division factor */
119 n_average
= factorx
*factory
;
124 sp
= (Uint8
*) src
->pixels
;
125 sgap
= src
->pitch
- src
->w
;
127 dp
= (Uint8
*) dst
->pixels
;
128 dgap
= dst
->pitch
- dst
->w
;
130 for (y
= 0; y
< dst
->h
; y
++) {
133 for (x
= 0; x
< dst
->w
; x
++) {
135 /* Trace out source box and accumulate */
138 for (dy
=0; dy
< factory
; dy
++) {
139 for (dx
=0; dx
< factorx
; dx
++) {
143 sp
= (Uint8
*)((Uint8
*)sp
+ (src
->pitch
- factorx
));
147 sp
= (Uint8
*)((Uint8
*)oosp
+ factorx
);
149 /* Store result in destination */
153 * Advance destination pointer
159 sp
= (Uint8
*)((Uint8
*)osp
+ src
->pitch
*factory
);
162 * Advance destination pointers
164 dp
= (Uint8
*)((Uint8
*)dp
+ dgap
);
172 32bit Zoomer with optional anti-aliasing by bilinear interpolation.
174 Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
178 int zoomSurfaceRGBA(SDL_Surface
* src
, SDL_Surface
* dst
, int flipx
, int flipy
, int smooth
)
180 int x
, y
, sx
, sy
, *sax
, *say
, *csax
, *csay
, csx
, csy
, ex
, ey
, t1
, t2
, sstep
;
181 tColorRGBA
*c00
, *c01
, *c10
, *c11
;
182 tColorRGBA
*sp
, *csp
, *dp
;
190 * For interpolation: assume source dimension is one pixel
193 * smaller to avoid overflow on right and bottom edge.
195 sx
= (int) (65536.0 * (float) (src
->w
- 1) / (float) dst
->w
);
196 sy
= (int) (65536.0 * (float) (src
->h
- 1) / (float) dst
->h
);
198 sx
= (int) (65536.0 * (float) src
->w
/ (float) dst
->w
);
199 sy
= (int) (65536.0 * (float) src
->h
/ (float) dst
->h
);
203 * Allocate memory for row increments
205 if ((sax
= (int *) malloc((dst
->w
+ 1) * sizeof(Uint32
))) == NULL
) {
208 if ((say
= (int *) malloc((dst
->h
+ 1) * sizeof(Uint32
))) == NULL
) {
214 * Precalculate row increments
216 sp
= csp
= (tColorRGBA
*) src
->pixels
;
217 dp
= (tColorRGBA
*) dst
->pixels
;
219 if (flipx
) csp
+= (src
->w
-1);
220 if (flipy
) csp
= (tColorRGBA
*)( (Uint8
*)csp
+ src
->pitch
*(src
->h
-1) );
224 for (x
= 0; x
<= dst
->w
; x
++) {
232 for (y
= 0; y
<= dst
->h
; y
++) {
239 dgap
= dst
->pitch
- dst
->w
* 4;
242 * Switch between interpolating and non-interpolating code
254 for (y
= 0; y
< dst
->h
; y
++) {
256 * Setup color source pointers
261 c10
= (tColorRGBA
*) ((Uint8
*) csp
+ src
->pitch
);
265 for (x
= 0; x
< dst
->w
; x
++) {
270 ex
= (*csax
& 0xffff);
271 ey
= (*csay
& 0xffff);
272 t1
= ((((c01
->r
- c00
->r
) * ex
) >> 16) + c00
->r
) & 0xff;
273 t2
= ((((c11
->r
- c10
->r
) * ex
) >> 16) + c10
->r
) & 0xff;
274 dp
->r
= (((t2
- t1
) * ey
) >> 16) + t1
;
275 t1
= ((((c01
->g
- c00
->g
) * ex
) >> 16) + c00
->g
) & 0xff;
276 t2
= ((((c11
->g
- c10
->g
) * ex
) >> 16) + c10
->g
) & 0xff;
277 dp
->g
= (((t2
- t1
) * ey
) >> 16) + t1
;
278 t1
= ((((c01
->b
- c00
->b
) * ex
) >> 16) + c00
->b
) & 0xff;
279 t2
= ((((c11
->b
- c10
->b
) * ex
) >> 16) + c10
->b
) & 0xff;
280 dp
->b
= (((t2
- t1
) * ey
) >> 16) + t1
;
281 t1
= ((((c01
->a
- c00
->a
) * ex
) >> 16) + c00
->a
) & 0xff;
282 t2
= ((((c11
->a
- c10
->a
) * ex
) >> 16) + c10
->a
) & 0xff;
283 dp
->a
= (((t2
- t1
) * ey
) >> 16) + t1
;
286 * Advance source pointers
289 sstep
= (*csax
>> 16);
295 * Advance destination pointer
300 * Advance source pointer
303 csp
= (tColorRGBA
*) ((Uint8
*) csp
+ (*csay
>> 16) * src
->pitch
);
305 * Advance destination pointers
307 dp
= (tColorRGBA
*) ((Uint8
*) dp
+ dgap
);
313 * Non-Interpolating Zoom
317 for (y
= 0; y
< dst
->h
; y
++) {
320 for (x
= 0; x
< dst
->w
; x
++) {
326 * Advance source pointers
329 sstep
= (*csax
>> 16);
330 if (flipx
) sstep
= -sstep
;
333 * Advance destination pointer
338 * Advance source pointer
341 sstep
= (*csay
>> 16) * src
->pitch
;
342 if (flipy
) sstep
= -sstep
;
343 csp
= (tColorRGBA
*) ((Uint8
*) csp
+ sstep
);
346 * Advance destination pointers
348 dp
= (tColorRGBA
*) ((Uint8
*) dp
+ dgap
);
364 8bit Zoomer without smoothing.
366 Zoomes 8bit palette/Y 'src' surface to 'dst' surface.
370 int zoomSurfaceY(SDL_Surface
* src
, SDL_Surface
* dst
, int flipx
, int flipy
)
372 Uint32 x
, y
, sx
, sy
, *sax
, *say
, *csax
, *csay
, csx
, csy
;
373 Uint8
*sp
, *dp
, *csp
;
379 sx
= (Uint32
) (65536.0 * (float) src
->w
/ (float) dst
->w
);
380 sy
= (Uint32
) (65536.0 * (float) src
->h
/ (float) dst
->h
);
383 * Allocate memory for row increments
385 if ((sax
= (Uint32
*) malloc(dst
->w
* sizeof(Uint32
))) == NULL
) {
388 if ((say
= (Uint32
*) malloc(dst
->h
* sizeof(Uint32
))) == NULL
) {
396 * Precalculate row increments
400 for (x
= 0; x
< dst
->w
; x
++) {
408 for (y
= 0; y
< dst
->h
; y
++) {
417 for (x
= 0; x
< dst
->w
; x
++) {
423 for (y
= 0; y
< dst
->h
; y
++) {
431 sp
= csp
= (Uint8
*) src
->pixels
;
432 dp
= (Uint8
*) dst
->pixels
;
433 dgap
= dst
->pitch
- dst
->w
;
439 for (y
= 0; y
< dst
->h
; y
++) {
442 for (x
= 0; x
< dst
->w
; x
++) {
448 * Advance source pointers
453 * Advance destination pointer
458 * Advance source pointer (for row)
460 csp
+= ((*csay
) * src
->pitch
);
463 * Advance destination pointers
479 32bit Rotozoomer with optional anti-aliasing by bilinear interpolation.
481 Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
485 void transformSurfaceRGBA(SDL_Surface
* src
, SDL_Surface
* dst
, int cx
, int cy
, int isin
, int icos
, int flipx
, int flipy
, int smooth
)
487 int x
, y
, t1
, t2
, dx
, dy
, xd
, yd
, sdx
, sdy
, ax
, ay
, ex
, ey
, sw
, sh
;
488 tColorRGBA c00
, c01
, c10
, c11
;
495 xd
= ((src
->w
- dst
->w
) << 15);
496 yd
= ((src
->h
- dst
->h
) << 15);
497 ax
= (cx
<< 16) - (icos
* cx
);
498 ay
= (cy
<< 16) - (isin
* cx
);
502 gap
= dst
->pitch
- dst
->w
* 4;
505 * Switch between interpolating and non-interpolating code
508 for (y
= 0; y
< dst
->h
; y
++) {
510 sdx
= (ax
+ (isin
* dy
)) + xd
;
511 sdy
= (ay
- (icos
* dy
)) + yd
;
512 for (x
= 0; x
< dst
->w
; x
++) {
515 if ((dx
>= -1) && (dy
>= -1) && (dx
< src
->w
) && (dy
< src
->h
)) {
516 if ((dx
>= 0) && (dy
>= 0) && (dx
< sw
) && (dy
< sh
)) {
517 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
522 sp
= (tColorRGBA
*) ((Uint8
*) sp
+ src
->pitch
);
527 } else if ((dx
== sw
) && (dy
== sh
)) {
528 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
534 } else if ((dx
== -1) && (dy
== -1)) {
535 sp
= (tColorRGBA
*) (src
->pixels
);
540 } else if ((dx
== -1) && (dy
== sh
)) {
541 sp
= (tColorRGBA
*) (src
->pixels
);
542 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
547 } else if ((dx
== sw
) && (dy
== -1)) {
548 sp
= (tColorRGBA
*) (src
->pixels
);
554 } else if (dx
== -1) {
555 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
559 sp
= (tColorRGBA
*) ((Uint8
*) sp
+ src
->pitch
);
561 } else if (dy
== -1) {
562 sp
= (tColorRGBA
*) (src
->pixels
);
569 } else if (dx
== sw
) {
570 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
574 sp
= (tColorRGBA
*) ((Uint8
*) sp
+ src
->pitch
);
577 } else if (dy
== sh
) {
578 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
591 t1
= ((((c01
.r
- c00
.r
) * ex
) >> 16) + c00
.r
) & 0xff;
592 t2
= ((((c11
.r
- c10
.r
) * ex
) >> 16) + c10
.r
) & 0xff;
593 pc
->r
= (((t2
- t1
) * ey
) >> 16) + t1
;
594 t1
= ((((c01
.g
- c00
.g
) * ex
) >> 16) + c00
.g
) & 0xff;
595 t2
= ((((c11
.g
- c10
.g
) * ex
) >> 16) + c10
.g
) & 0xff;
596 pc
->g
= (((t2
- t1
) * ey
) >> 16) + t1
;
597 t1
= ((((c01
.b
- c00
.b
) * ex
) >> 16) + c00
.b
) & 0xff;
598 t2
= ((((c11
.b
- c10
.b
) * ex
) >> 16) + c10
.b
) & 0xff;
599 pc
->b
= (((t2
- t1
) * ey
) >> 16) + t1
;
600 t1
= ((((c01
.a
- c00
.a
) * ex
) >> 16) + c00
.a
) & 0xff;
601 t2
= ((((c11
.a
- c10
.a
) * ex
) >> 16) + c10
.a
) & 0xff;
602 pc
->a
= (((t2
- t1
) * ey
) >> 16) + t1
;
608 pc
= (tColorRGBA
*) ((Uint8
*) pc
+ gap
);
611 for (y
= 0; y
< dst
->h
; y
++) {
613 sdx
= (ax
+ (isin
* dy
)) + xd
;
614 sdy
= (ay
- (icos
* dy
)) + yd
;
615 for (x
= 0; x
< dst
->w
; x
++) {
616 dx
= (short) (sdx
>> 16);
617 dy
= (short) (sdy
>> 16);
618 if (flipx
) dx
= (src
->w
-1)-dx
;
619 if (flipy
) dy
= (src
->h
-1)-dy
;
620 if ((dx
>= 0) && (dy
>= 0) && (dx
< src
->w
) && (dy
< src
->h
)) {
621 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
629 pc
= (tColorRGBA
*) ((Uint8
*) pc
+ gap
);
636 8bit Rotozoomer without smoothing
638 Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface.
642 void transformSurfaceY(SDL_Surface
* src
, SDL_Surface
* dst
, int cx
, int cy
, int isin
, int icos
)
644 int x
, y
, dx
, dy
, xd
, yd
, sdx
, sdy
, ax
, ay
, sw
, sh
;
651 xd
= ((src
->w
- dst
->w
) << 15);
652 yd
= ((src
->h
- dst
->h
) << 15);
653 ax
= (cx
<< 16) - (icos
* cx
);
654 ay
= (cy
<< 16) - (isin
* cx
);
658 gap
= dst
->pitch
- dst
->w
;
660 * Clear surface to colorkey
662 memset(pc
, (unsigned char) (src
->format
->colorkey
& 0xff), dst
->pitch
* dst
->h
);
664 * Iterate through destination surface
666 for (y
= 0; y
< dst
->h
; y
++) {
668 sdx
= (ax
+ (isin
* dy
)) + xd
;
669 sdy
= (ay
- (icos
* dy
)) + yd
;
670 for (x
= 0; x
< dst
->w
; x
++) {
671 dx
= (short) (sdx
>> 16);
672 dy
= (short) (sdy
>> 16);
673 if ((dx
>= 0) && (dy
>= 0) && (dx
< src
->w
) && (dy
< src
->h
)) {
674 sp
= (tColorY
*) (src
->pixels
);
675 sp
+= (src
->pitch
* dy
+ dx
);
689 32bit specialized 90degree rotator
691 Rotates and zooms 'src' surface to 'dst' surface in 90degree increments.
693 (contributed by Jeff Schiller)
696 SDL_Surface
* rotateSurface90Degrees(SDL_Surface
* pSurf
, int numClockwiseTurns
)
698 int row
, col
, newWidth
, newHeight
;
699 SDL_Surface
* pSurfOut
;
702 if (!pSurf
|| pSurf
->format
->BitsPerPixel
!= 32) { return NULL
; }
705 while(numClockwiseTurns
< 0) { numClockwiseTurns
+= 4; }
706 numClockwiseTurns
= (numClockwiseTurns
% 4);
709 newWidth
= (numClockwiseTurns
% 2) ? (pSurf
->h
) : (pSurf
->w
);
710 newHeight
= (numClockwiseTurns
% 2) ? (pSurf
->w
) : (pSurf
->h
);
711 pSurfOut
= SDL_CreateRGBSurface( pSurf
->flags
, newWidth
, newHeight
, pSurf
->format
->BitsPerPixel
,
712 pSurf
->format
->Rmask
,
713 pSurf
->format
->Gmask
,
714 pSurf
->format
->Bmask
,
715 pSurf
->format
->Amask
);
720 if(numClockwiseTurns
!= 0) {
721 SDL_LockSurface(pSurf
);
722 SDL_LockSurface(pSurfOut
);
723 switch(numClockwiseTurns
) {
727 Uint32
* srcBuf
= NULL
;
728 Uint32
* dstBuf
= NULL
;
730 for (row
= 0; row
< pSurf
->h
; ++row
) {
731 srcBuf
= (Uint32
*)(pSurf
->pixels
) + (row
*pSurf
->pitch
/4);
732 dstBuf
= (Uint32
*)(pSurfOut
->pixels
) + (pSurfOut
->w
- row
- 1);
733 for (col
= 0; col
< pSurf
->w
; ++col
) {
736 dstBuf
+= pSurfOut
->pitch
/4;
744 Uint32
* srcBuf
= NULL
;
745 Uint32
* dstBuf
= NULL
;
747 for(row
= 0; row
< pSurf
->h
; ++row
) {
748 srcBuf
= (Uint32
*)(pSurf
->pixels
) + (row
*pSurf
->pitch
/4);
749 dstBuf
= (Uint32
*)(pSurfOut
->pixels
) + ((pSurfOut
->h
- row
- 1)*pSurfOut
->pitch
/4) + (pSurfOut
->w
- 1);
750 for(col
= 0; col
< pSurf
->w
; ++col
) {
761 Uint32
* srcBuf
= NULL
;
762 Uint32
* dstBuf
= NULL
;
764 for(row
= 0; row
< pSurf
->h
; ++row
) {
765 srcBuf
= (Uint32
*)(pSurf
->pixels
) + (row
*pSurf
->pitch
/4);
766 dstBuf
= (Uint32
*)(pSurfOut
->pixels
) + row
+ ((pSurfOut
->h
- 1)*pSurfOut
->pitch
/4);
767 for(col
= 0; col
< pSurf
->w
; ++col
) {
770 dstBuf
-= pSurfOut
->pitch
/4;
777 SDL_UnlockSurface(pSurf
);
778 SDL_UnlockSurface(pSurfOut
);
781 /* simply copy surface to output */
782 if(SDL_BlitSurface(pSurf
, NULL
, pSurfOut
, NULL
)) {
793 Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
794 'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1
795 then the destination 32bit surface is anti-aliased. If the surface is not 8bit
796 or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
800 #define VALUE_LIMIT 0.001
803 /* Local rotozoom-size function with trig result return */
805 void rotozoomSurfaceSizeTrig(int width
, int height
, double angle
, double zoomx
, double zoomy
, int *dstwidth
, int *dstheight
,
806 double *canglezoom
, double *sanglezoom
)
808 double x
, y
, cx
, cy
, sx
, sy
;
810 int dstwidthhalf
, dstheighthalf
;
813 * Determine destination width and height by rotating a centered source box
815 radangle
= angle
* (M_PI
/ 180.0);
816 *sanglezoom
= sin(radangle
);
817 *canglezoom
= cos(radangle
);
818 *sanglezoom
*= zoomx
;
819 *canglezoom
*= zoomx
;
822 cx
= *canglezoom
* x
;
823 cy
= *canglezoom
* y
;
824 sx
= *sanglezoom
* x
;
825 sy
= *sanglezoom
* y
;
827 dstwidthhalf
= MAX((int)
828 ceil(MAX(MAX(MAX(fabs(cx
+ sy
), fabs(cx
- sy
)), fabs(-cx
+ sy
)), fabs(-cx
- sy
))), 1);
829 dstheighthalf
= MAX((int)
830 ceil(MAX(MAX(MAX(fabs(sx
+ cy
), fabs(sx
- cy
)), fabs(-sx
+ cy
)), fabs(-sx
- cy
))), 1);
831 *dstwidth
= 2 * dstwidthhalf
;
832 *dstheight
= 2 * dstheighthalf
;
836 /* Publically available rotozoom-size function */
838 void rotozoomSurfaceSizeXY(int width
, int height
, double angle
, double zoomx
, double zoomy
, int *dstwidth
, int *dstheight
)
840 double dummy_sanglezoom
, dummy_canglezoom
;
842 rotozoomSurfaceSizeTrig(width
, height
, angle
, zoomx
, zoomy
, dstwidth
, dstheight
, &dummy_sanglezoom
, &dummy_canglezoom
);
845 /* Publically available rotozoom-size function */
847 void rotozoomSurfaceSize(int width
, int height
, double angle
, double zoom
, int *dstwidth
, int *dstheight
)
849 double dummy_sanglezoom
, dummy_canglezoom
;
851 rotozoomSurfaceSizeTrig(width
, height
, angle
, zoom
, zoom
, dstwidth
, dstheight
, &dummy_sanglezoom
, &dummy_canglezoom
);
854 /* Publically available rotozoom function */
856 SDL_Surface
*rotozoomSurface(SDL_Surface
* src
, double angle
, double zoom
, int smooth
)
858 return rotozoomSurfaceXY(src
, angle
, zoom
, zoom
, smooth
);
861 /* Publically available rotozoom function */
863 SDL_Surface
*rotozoomSurfaceXY(SDL_Surface
* src
, double angle
, double zoomx
, double zoomy
, int smooth
)
868 double sanglezoom
, canglezoom
, sanglezoominv
, canglezoominv
;
869 int dstwidthhalf
, dstwidth
, dstheighthalf
, dstheight
;
871 int i
, src_converted
;
875 int colorKeyAvailable
= 0;
883 if( src
->flags
& SDL_SRCCOLORKEY
)
885 colorkey
= src
->format
->colorkey
;
886 SDL_GetRGB(colorkey
, src
->format
, &r
, &g
, &b
);
887 colorKeyAvailable
= 1;
890 * Determine if source surface is 32bit or 8bit
892 is32bit
= (src
->format
->BitsPerPixel
== 32);
893 if ((is32bit
) || (src
->format
->BitsPerPixel
== 8)) {
895 * Use source surface 'as is'
901 * New source surface is 32bit with a defined RGBA ordering
904 SDL_CreateRGBSurface(SDL_SWSURFACE
, src
->w
, src
->h
, 32,
905 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
906 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
908 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
911 if(colorKeyAvailable
)
912 SDL_SetColorKey(src
, 0, 0);
914 SDL_BlitSurface(src
, NULL
, rz_src
, NULL
);
916 if(colorKeyAvailable
)
917 SDL_SetColorKey(src
, SDL_SRCCOLORKEY
, colorkey
);
923 * Sanity check zoom factor
926 if (flipx
) zoomx
=-zoomx
;
928 if (flipy
) zoomy
=-zoomy
;
929 if (zoomx
< VALUE_LIMIT
) zoomx
= VALUE_LIMIT
;
930 if (zoomy
< VALUE_LIMIT
) zoomy
= VALUE_LIMIT
;
931 zoominv
= 65536.0 / (zoomx
* zoomx
);
934 * Check if we have a rotozoom or just a zoom
936 if (fabs(angle
) > VALUE_LIMIT
) {
939 * Angle!=0: full rotozoom
942 * -----------------------
945 /* Determine target size */
946 rotozoomSurfaceSizeTrig(rz_src
->w
, rz_src
->h
, angle
, zoomx
, zoomy
, &dstwidth
, &dstheight
, &canglezoom
, &sanglezoom
);
949 * Calculate target factors from sin/cos and zoom
951 sanglezoominv
= sanglezoom
;
952 canglezoominv
= canglezoom
;
953 sanglezoominv
*= zoominv
;
954 canglezoominv
*= zoominv
;
956 /* Calculate half size */
957 dstwidthhalf
= dstwidth
/ 2;
958 dstheighthalf
= dstheight
/ 2;
961 * Alloc space to completely contain the rotated surface
966 * Target surface is 32bit with source RGBA/ABGR ordering
969 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
970 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
971 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
974 * Target surface is 8bit
976 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
979 if (colorKeyAvailable
== 1){
980 colorkey
= SDL_MapRGB(rz_dst
->format
, r
, g
, b
);
982 SDL_FillRect(rz_dst
, NULL
, colorkey
);
986 * Lock source surface
988 SDL_LockSurface(rz_src
);
990 * Check which kind of surface we have
994 * Call the 32bit transformation routine to do the rotation (using alpha)
996 transformSurfaceRGBA(rz_src
, rz_dst
, dstwidthhalf
, dstheighthalf
,
997 (int) (sanglezoominv
), (int) (canglezoominv
),
1001 * Turn on source-alpha support
1003 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1006 * Copy palette and colorkey info
1008 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1009 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1011 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1013 * Call the 8bit transformation routine to do the rotation
1015 transformSurfaceY(rz_src
, rz_dst
, dstwidthhalf
, dstheighthalf
,
1016 (int) (sanglezoominv
), (int) (canglezoominv
));
1017 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1020 * Unlock source surface
1022 SDL_UnlockSurface(rz_src
);
1027 * Angle=0: Just a zoom
1030 * --------------------
1034 * Calculate target size
1036 zoomSurfaceSize(rz_src
->w
, rz_src
->h
, zoomx
, zoomy
, &dstwidth
, &dstheight
);
1039 * Alloc space to completely contain the zoomed surface
1044 * Target surface is 32bit with source RGBA/ABGR ordering
1047 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
1048 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
1049 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
1052 * Target surface is 8bit
1054 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
1057 if (colorKeyAvailable
== 1){
1058 colorkey
= SDL_MapRGB(rz_dst
->format
, r
, g
, b
);
1060 SDL_FillRect(rz_dst
, NULL
, colorkey
);
1064 * Lock source surface
1066 SDL_LockSurface(rz_src
);
1068 * Check which kind of surface we have
1072 * Call the 32bit transformation routine to do the zooming (using alpha)
1074 zoomSurfaceRGBA(rz_src
, rz_dst
, flipx
, flipy
, smooth
);
1076 * Turn on source-alpha support
1078 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1081 * Copy palette and colorkey info
1083 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1084 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1086 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1088 * Call the 8bit transformation routine to do the zooming
1090 zoomSurfaceY(rz_src
, rz_dst
, flipx
, flipy
);
1091 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1094 * Unlock source surface
1096 SDL_UnlockSurface(rz_src
);
1100 * Cleanup temp surface
1102 if (src_converted
) {
1103 SDL_FreeSurface(rz_src
);
1107 * Return destination surface
1116 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1117 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1
1118 then the destination 32bit surface is anti-aliased. If the surface is not 8bit
1119 or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
1123 #define VALUE_LIMIT 0.001
1125 void zoomSurfaceSize(int width
, int height
, double zoomx
, double zoomy
, int *dstwidth
, int *dstheight
)
1128 * Sanity check zoom factors
1130 if (zoomx
< VALUE_LIMIT
) {
1131 zoomx
= VALUE_LIMIT
;
1133 if (zoomy
< VALUE_LIMIT
) {
1134 zoomy
= VALUE_LIMIT
;
1138 * Calculate target size
1140 *dstwidth
= (int) ((double) width
* zoomx
);
1141 *dstheight
= (int) ((double) height
* zoomy
);
1142 if (*dstwidth
< 1) {
1145 if (*dstheight
< 1) {
1150 SDL_Surface
*zoomSurface(SDL_Surface
* src
, double zoomx
, double zoomy
, int smooth
)
1152 SDL_Surface
*rz_src
;
1153 SDL_Surface
*rz_dst
;
1154 int dstwidth
, dstheight
;
1156 int i
, src_converted
;
1166 * Determine if source surface is 32bit or 8bit
1168 is32bit
= (src
->format
->BitsPerPixel
== 32);
1169 if ((is32bit
) || (src
->format
->BitsPerPixel
== 8)) {
1171 * Use source surface 'as is'
1177 * New source surface is 32bit with a defined RGBA ordering
1180 SDL_CreateRGBSurface(SDL_SWSURFACE
, src
->w
, src
->h
, 32,
1181 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1182 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1184 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1187 SDL_BlitSurface(src
, NULL
, rz_src
, NULL
);
1193 if (flipx
) zoomx
= -zoomx
;
1195 if (flipy
) zoomy
= -zoomy
;
1197 /* Get size if target */
1198 zoomSurfaceSize(rz_src
->w
, rz_src
->h
, zoomx
, zoomy
, &dstwidth
, &dstheight
);
1201 * Alloc space to completely contain the zoomed surface
1206 * Target surface is 32bit with source RGBA/ABGR ordering
1209 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
1210 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
1211 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
1214 * Target surface is 8bit
1216 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
1220 * Lock source surface
1222 SDL_LockSurface(rz_src
);
1224 * Check which kind of surface we have
1228 * Call the 32bit transformation routine to do the zooming (using alpha)
1230 zoomSurfaceRGBA(rz_src
, rz_dst
, flipx
, flipy
, smooth
);
1232 * Turn on source-alpha support
1234 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1237 * Copy palette and colorkey info
1239 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1240 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1242 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1244 * Call the 8bit transformation routine to do the zooming
1246 zoomSurfaceY(rz_src
, rz_dst
, flipx
, flipy
);
1247 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1250 * Unlock source surface
1252 SDL_UnlockSurface(rz_src
);
1255 * Cleanup temp surface
1257 if (src_converted
) {
1258 SDL_FreeSurface(rz_src
);
1262 * Return destination surface
1267 SDL_Surface
*shrinkSurface(SDL_Surface
* src
, int factorx
, int factory
)
1269 SDL_Surface
*rz_src
;
1270 SDL_Surface
*rz_dst
;
1271 int dstwidth
, dstheight
;
1273 int i
, src_converted
;
1282 * Determine if source surface is 32bit or 8bit
1284 is32bit
= (src
->format
->BitsPerPixel
== 32);
1285 if ((is32bit
) || (src
->format
->BitsPerPixel
== 8)) {
1287 * Use source surface 'as is'
1293 * New source surface is 32bit with a defined RGBA ordering
1296 SDL_CreateRGBSurface(SDL_SWSURFACE
, src
->w
, src
->h
, 32,
1297 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1298 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1300 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1303 SDL_BlitSurface(src
, NULL
, rz_src
, NULL
);
1308 /* Get size for target */
1309 dstwidth
=rz_src
->w
/factorx
;
1310 while (dstwidth
*factorx
>rz_src
->w
) { dstwidth
--; }
1311 dstheight
=rz_src
->h
/factory
;
1312 while (dstheight
*factory
>rz_src
->h
) { dstheight
--; }
1315 * Alloc space to completely contain the shrunken surface
1320 * Target surface is 32bit with source RGBA/ABGR ordering
1323 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
1324 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
1325 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
1328 * Target surface is 8bit
1330 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
1334 * Lock source surface
1336 SDL_LockSurface(rz_src
);
1338 * Check which kind of surface we have
1342 * Call the 32bit transformation routine to do the shrinking (using alpha)
1344 shrinkSurfaceRGBA(rz_src
, rz_dst
, factorx
, factory
);
1346 * Turn on source-alpha support
1348 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1351 * Copy palette and colorkey info
1353 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1354 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1356 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1358 * Call the 8bit transformation routine to do the shrinking
1360 shrinkSurfaceY(rz_src
, rz_dst
, factorx
, factory
);
1361 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1364 * Unlock source surface
1366 SDL_UnlockSurface(rz_src
);
1369 * Cleanup temp surface
1371 if (src_converted
) {
1372 SDL_FreeSurface(rz_src
);
1376 * Return destination surface