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
)
368 Uint32 x
, y
, sx
, sy
, *sax
, *say
, *csax
, *csay
, csx
, csy
;
369 Uint8
*sp
, *dp
, *csp
;
375 sx
= (Uint32
) (65536.0 * (float) src
->w
/ (float) dst
->w
);
376 sy
= (Uint32
) (65536.0 * (float) src
->h
/ (float) dst
->h
);
379 * Allocate memory for row increments
381 if ((sax
= (Uint32
*) malloc(dst
->w
* sizeof(Uint32
))) == NULL
) {
384 if ((say
= (Uint32
*) malloc(dst
->h
* sizeof(Uint32
))) == NULL
) {
392 * Precalculate row increments
396 for (x
= 0; x
< dst
->w
; x
++) {
404 for (y
= 0; y
< dst
->h
; y
++) {
413 for (x
= 0; x
< dst
->w
; x
++) {
419 for (y
= 0; y
< dst
->h
; y
++) {
427 sp
= csp
= (Uint8
*) src
->pixels
;
428 dp
= (Uint8
*) dst
->pixels
;
429 dgap
= dst
->pitch
- dst
->w
;
435 for (y
= 0; y
< dst
->h
; y
++) {
438 for (x
= 0; x
< dst
->w
; x
++) {
444 * Advance source pointers
449 * Advance destination pointer
454 * Advance source pointer (for row)
456 csp
+= ((*csay
) * src
->pitch
);
459 * Advance destination pointers
475 32bit Rotozoomer with optional anti-aliasing by bilinear interpolation.
477 Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
481 void transformSurfaceRGBA(SDL_Surface
* src
, SDL_Surface
* dst
, int cx
, int cy
, int isin
, int icos
, int flipx
, int flipy
, int smooth
)
483 int x
, y
, t1
, t2
, dx
, dy
, xd
, yd
, sdx
, sdy
, ax
, ay
, ex
, ey
, sw
, sh
;
484 tColorRGBA c00
, c01
, c10
, c11
;
491 xd
= ((src
->w
- dst
->w
) << 15);
492 yd
= ((src
->h
- dst
->h
) << 15);
493 ax
= (cx
<< 16) - (icos
* cx
);
494 ay
= (cy
<< 16) - (isin
* cx
);
498 gap
= dst
->pitch
- dst
->w
* 4;
501 * Switch between interpolating and non-interpolating code
504 for (y
= 0; y
< dst
->h
; y
++) {
506 sdx
= (ax
+ (isin
* dy
)) + xd
;
507 sdy
= (ay
- (icos
* dy
)) + yd
;
508 for (x
= 0; x
< dst
->w
; x
++) {
511 if ((dx
>= -1) && (dy
>= -1) && (dx
< src
->w
) && (dy
< src
->h
)) {
512 if ((dx
>= 0) && (dy
>= 0) && (dx
< sw
) && (dy
< sh
)) {
513 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
518 sp
= (tColorRGBA
*) ((Uint8
*) sp
+ src
->pitch
);
523 } else if ((dx
== sw
) && (dy
== sh
)) {
524 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
530 } else if ((dx
== -1) && (dy
== -1)) {
531 sp
= (tColorRGBA
*) (src
->pixels
);
536 } else if ((dx
== -1) && (dy
== sh
)) {
537 sp
= (tColorRGBA
*) (src
->pixels
);
538 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
543 } else if ((dx
== sw
) && (dy
== -1)) {
544 sp
= (tColorRGBA
*) (src
->pixels
);
550 } else if (dx
== -1) {
551 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
555 sp
= (tColorRGBA
*) ((Uint8
*) sp
+ src
->pitch
);
557 } else if (dy
== -1) {
558 sp
= (tColorRGBA
*) (src
->pixels
);
565 } else if (dx
== sw
) {
566 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
570 sp
= (tColorRGBA
*) ((Uint8
*) sp
+ src
->pitch
);
573 } else if (dy
== sh
) {
574 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
587 t1
= ((((c01
.r
- c00
.r
) * ex
) >> 16) + c00
.r
) & 0xff;
588 t2
= ((((c11
.r
- c10
.r
) * ex
) >> 16) + c10
.r
) & 0xff;
589 pc
->r
= (((t2
- t1
) * ey
) >> 16) + t1
;
590 t1
= ((((c01
.g
- c00
.g
) * ex
) >> 16) + c00
.g
) & 0xff;
591 t2
= ((((c11
.g
- c10
.g
) * ex
) >> 16) + c10
.g
) & 0xff;
592 pc
->g
= (((t2
- t1
) * ey
) >> 16) + t1
;
593 t1
= ((((c01
.b
- c00
.b
) * ex
) >> 16) + c00
.b
) & 0xff;
594 t2
= ((((c11
.b
- c10
.b
) * ex
) >> 16) + c10
.b
) & 0xff;
595 pc
->b
= (((t2
- t1
) * ey
) >> 16) + t1
;
596 t1
= ((((c01
.a
- c00
.a
) * ex
) >> 16) + c00
.a
) & 0xff;
597 t2
= ((((c11
.a
- c10
.a
) * ex
) >> 16) + c10
.a
) & 0xff;
598 pc
->a
= (((t2
- t1
) * ey
) >> 16) + t1
;
604 pc
= (tColorRGBA
*) ((Uint8
*) pc
+ gap
);
607 for (y
= 0; y
< dst
->h
; y
++) {
609 sdx
= (ax
+ (isin
* dy
)) + xd
;
610 sdy
= (ay
- (icos
* dy
)) + yd
;
611 for (x
= 0; x
< dst
->w
; x
++) {
612 dx
= (short) (sdx
>> 16);
613 dy
= (short) (sdy
>> 16);
614 if (flipx
) dx
= (src
->w
-1)-dx
;
615 if (flipy
) dy
= (src
->h
-1)-dy
;
616 if ((dx
>= 0) && (dy
>= 0) && (dx
< src
->w
) && (dy
< src
->h
)) {
617 sp
= (tColorRGBA
*) ((Uint8
*) src
->pixels
+ src
->pitch
* dy
);
625 pc
= (tColorRGBA
*) ((Uint8
*) pc
+ gap
);
632 8bit Rotozoomer without smoothing
634 Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface.
638 void transformSurfaceY(SDL_Surface
* src
, SDL_Surface
* dst
, int cx
, int cy
, int isin
, int icos
)
640 int x
, y
, dx
, dy
, xd
, yd
, sdx
, sdy
, ax
, ay
, sw
, sh
;
647 xd
= ((src
->w
- dst
->w
) << 15);
648 yd
= ((src
->h
- dst
->h
) << 15);
649 ax
= (cx
<< 16) - (icos
* cx
);
650 ay
= (cy
<< 16) - (isin
* cx
);
654 gap
= dst
->pitch
- dst
->w
;
656 * Clear surface to colorkey
658 memset(pc
, (unsigned char) (src
->format
->colorkey
& 0xff), dst
->pitch
* dst
->h
);
660 * Iterate through destination surface
662 for (y
= 0; y
< dst
->h
; y
++) {
664 sdx
= (ax
+ (isin
* dy
)) + xd
;
665 sdy
= (ay
- (icos
* dy
)) + yd
;
666 for (x
= 0; x
< dst
->w
; x
++) {
667 dx
= (short) (sdx
>> 16);
668 dy
= (short) (sdy
>> 16);
669 if ((dx
>= 0) && (dy
>= 0) && (dx
< src
->w
) && (dy
< src
->h
)) {
670 sp
= (tColorY
*) (src
->pixels
);
671 sp
+= (src
->pitch
* dy
+ dx
);
685 32bit specialized 90degree rotator
687 Rotates and zooms 'src' surface to 'dst' surface in 90degree increments.
689 (contributed by Jeff Schiller)
692 SDL_Surface
* rotateSurface90Degrees(SDL_Surface
* pSurf
, int numClockwiseTurns
)
694 int row
, col
, newWidth
, newHeight
;
695 SDL_Surface
* pSurfOut
;
698 if (!pSurf
|| pSurf
->format
->BitsPerPixel
!= 32) { return NULL
; }
701 while(numClockwiseTurns
< 0) { numClockwiseTurns
+= 4; }
702 numClockwiseTurns
= (numClockwiseTurns
% 4);
705 newWidth
= (numClockwiseTurns
% 2) ? (pSurf
->h
) : (pSurf
->w
);
706 newHeight
= (numClockwiseTurns
% 2) ? (pSurf
->w
) : (pSurf
->h
);
707 pSurfOut
= SDL_CreateRGBSurface( pSurf
->flags
, newWidth
, newHeight
, pSurf
->format
->BitsPerPixel
,
708 pSurf
->format
->Rmask
,
709 pSurf
->format
->Gmask
,
710 pSurf
->format
->Bmask
,
711 pSurf
->format
->Amask
);
716 if(numClockwiseTurns
!= 0) {
717 SDL_LockSurface(pSurf
);
718 SDL_LockSurface(pSurfOut
);
719 switch(numClockwiseTurns
) {
723 Uint32
* srcBuf
= NULL
;
724 Uint32
* dstBuf
= NULL
;
726 for (row
= 0; row
< pSurf
->h
; ++row
) {
727 srcBuf
= (Uint32
*)(pSurf
->pixels
) + (row
*pSurf
->pitch
/4);
728 dstBuf
= (Uint32
*)(pSurfOut
->pixels
) + (pSurfOut
->w
- row
- 1);
729 for (col
= 0; col
< pSurf
->w
; ++col
) {
732 dstBuf
+= pSurfOut
->pitch
/4;
740 Uint32
* srcBuf
= NULL
;
741 Uint32
* dstBuf
= NULL
;
743 for(row
= 0; row
< pSurf
->h
; ++row
) {
744 srcBuf
= (Uint32
*)(pSurf
->pixels
) + (row
*pSurf
->pitch
/4);
745 dstBuf
= (Uint32
*)(pSurfOut
->pixels
) + ((pSurfOut
->h
- row
- 1)*pSurfOut
->pitch
/4) + (pSurfOut
->w
- 1);
746 for(col
= 0; col
< pSurf
->w
; ++col
) {
757 Uint32
* srcBuf
= NULL
;
758 Uint32
* dstBuf
= NULL
;
760 for(row
= 0; row
< pSurf
->h
; ++row
) {
761 srcBuf
= (Uint32
*)(pSurf
->pixels
) + (row
*pSurf
->pitch
/4);
762 dstBuf
= (Uint32
*)(pSurfOut
->pixels
) + row
+ ((pSurfOut
->h
- 1)*pSurfOut
->pitch
/4);
763 for(col
= 0; col
< pSurf
->w
; ++col
) {
766 dstBuf
-= pSurfOut
->pitch
/4;
773 SDL_UnlockSurface(pSurf
);
774 SDL_UnlockSurface(pSurfOut
);
777 /* simply copy surface to output */
778 if(SDL_BlitSurface(pSurf
, NULL
, pSurfOut
, NULL
)) {
789 Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
790 'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1
791 then the destination 32bit surface is anti-aliased. If the surface is not 8bit
792 or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
796 #define VALUE_LIMIT 0.001
799 /* Local rotozoom-size function with trig result return */
801 void rotozoomSurfaceSizeTrig(int width
, int height
, double angle
, double zoomx
, double zoomy
, int *dstwidth
, int *dstheight
,
802 double *canglezoom
, double *sanglezoom
)
804 double x
, y
, cx
, cy
, sx
, sy
;
806 int dstwidthhalf
, dstheighthalf
;
809 * Determine destination width and height by rotating a centered source box
811 radangle
= angle
* (M_PI
/ 180.0);
812 *sanglezoom
= sin(radangle
);
813 *canglezoom
= cos(radangle
);
814 *sanglezoom
*= zoomx
;
815 *canglezoom
*= zoomx
;
818 cx
= *canglezoom
* x
;
819 cy
= *canglezoom
* y
;
820 sx
= *sanglezoom
* x
;
821 sy
= *sanglezoom
* y
;
823 dstwidthhalf
= MAX((int)
824 ceil(MAX(MAX(MAX(fabs(cx
+ sy
), fabs(cx
- sy
)), fabs(-cx
+ sy
)), fabs(-cx
- sy
))), 1);
825 dstheighthalf
= MAX((int)
826 ceil(MAX(MAX(MAX(fabs(sx
+ cy
), fabs(sx
- cy
)), fabs(-sx
+ cy
)), fabs(-sx
- cy
))), 1);
827 *dstwidth
= 2 * dstwidthhalf
;
828 *dstheight
= 2 * dstheighthalf
;
832 /* Publically available rotozoom-size function */
834 void rotozoomSurfaceSizeXY(int width
, int height
, double angle
, double zoomx
, double zoomy
, int *dstwidth
, int *dstheight
)
836 double dummy_sanglezoom
, dummy_canglezoom
;
838 rotozoomSurfaceSizeTrig(width
, height
, angle
, zoomx
, zoomy
, dstwidth
, dstheight
, &dummy_sanglezoom
, &dummy_canglezoom
);
841 /* Publically available rotozoom-size function */
843 void rotozoomSurfaceSize(int width
, int height
, double angle
, double zoom
, int *dstwidth
, int *dstheight
)
845 double dummy_sanglezoom
, dummy_canglezoom
;
847 rotozoomSurfaceSizeTrig(width
, height
, angle
, zoom
, zoom
, dstwidth
, dstheight
, &dummy_sanglezoom
, &dummy_canglezoom
);
850 /* Publically available rotozoom function */
852 SDL_Surface
*rotozoomSurface(SDL_Surface
* src
, double angle
, double zoom
, int smooth
)
854 return rotozoomSurfaceXY(src
, angle
, zoom
, zoom
, smooth
);
857 /* Publically available rotozoom function */
859 SDL_Surface
*rotozoomSurfaceXY(SDL_Surface
* src
, double angle
, double zoomx
, double zoomy
, int smooth
)
864 double sanglezoom
, canglezoom
, sanglezoominv
, canglezoominv
;
865 int dstwidthhalf
, dstwidth
, dstheighthalf
, dstheight
;
867 int i
, src_converted
;
871 int colorKeyAvailable
= 0;
879 if( src
->flags
& SDL_SRCCOLORKEY
)
881 colorkey
= src
->format
->colorkey
;
882 SDL_GetRGB(colorkey
, src
->format
, &r
, &g
, &b
);
883 colorKeyAvailable
= 1;
886 * Determine if source surface is 32bit or 8bit
888 is32bit
= (src
->format
->BitsPerPixel
== 32);
889 if ((is32bit
) || (src
->format
->BitsPerPixel
== 8)) {
891 * Use source surface 'as is'
897 * New source surface is 32bit with a defined RGBA ordering
900 SDL_CreateRGBSurface(SDL_SWSURFACE
, src
->w
, src
->h
, 32,
901 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
902 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
904 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
907 if(colorKeyAvailable
)
908 SDL_SetColorKey(src
, 0, 0);
910 SDL_BlitSurface(src
, NULL
, rz_src
, NULL
);
912 if(colorKeyAvailable
)
913 SDL_SetColorKey(src
, SDL_SRCCOLORKEY
, colorkey
);
919 * Sanity check zoom factor
922 if (flipx
) zoomx
=-zoomx
;
924 if (flipy
) zoomy
=-zoomy
;
925 if (zoomx
< VALUE_LIMIT
) zoomx
= VALUE_LIMIT
;
926 if (zoomy
< VALUE_LIMIT
) zoomy
= VALUE_LIMIT
;
927 zoominv
= 65536.0 / (zoomx
* zoomx
);
930 * Check if we have a rotozoom or just a zoom
932 if (fabs(angle
) > VALUE_LIMIT
) {
935 * Angle!=0: full rotozoom
938 * -----------------------
941 /* Determine target size */
942 rotozoomSurfaceSizeTrig(rz_src
->w
, rz_src
->h
, angle
, zoomx
, zoomy
, &dstwidth
, &dstheight
, &canglezoom
, &sanglezoom
);
945 * Calculate target factors from sin/cos and zoom
947 sanglezoominv
= sanglezoom
;
948 canglezoominv
= canglezoom
;
949 sanglezoominv
*= zoominv
;
950 canglezoominv
*= zoominv
;
952 /* Calculate half size */
953 dstwidthhalf
= dstwidth
/ 2;
954 dstheighthalf
= dstheight
/ 2;
957 * Alloc space to completely contain the rotated surface
962 * Target surface is 32bit with source RGBA/ABGR ordering
965 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
966 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
967 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
970 * Target surface is 8bit
972 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
975 if (colorKeyAvailable
== 1){
976 colorkey
= SDL_MapRGB(rz_dst
->format
, r
, g
, b
);
978 SDL_FillRect(rz_dst
, NULL
, colorkey
);
982 * Lock source surface
984 SDL_LockSurface(rz_src
);
986 * Check which kind of surface we have
990 * Call the 32bit transformation routine to do the rotation (using alpha)
992 transformSurfaceRGBA(rz_src
, rz_dst
, dstwidthhalf
, dstheighthalf
,
993 (int) (sanglezoominv
), (int) (canglezoominv
),
997 * Turn on source-alpha support
999 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1002 * Copy palette and colorkey info
1004 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1005 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1007 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1009 * Call the 8bit transformation routine to do the rotation
1011 transformSurfaceY(rz_src
, rz_dst
, dstwidthhalf
, dstheighthalf
,
1012 (int) (sanglezoominv
), (int) (canglezoominv
));
1013 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1016 * Unlock source surface
1018 SDL_UnlockSurface(rz_src
);
1023 * Angle=0: Just a zoom
1026 * --------------------
1030 * Calculate target size
1032 zoomSurfaceSize(rz_src
->w
, rz_src
->h
, zoomx
, zoomy
, &dstwidth
, &dstheight
);
1035 * Alloc space to completely contain the zoomed surface
1040 * Target surface is 32bit with source RGBA/ABGR ordering
1043 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
1044 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
1045 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
1048 * Target surface is 8bit
1050 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
1053 if (colorKeyAvailable
== 1){
1054 colorkey
= SDL_MapRGB(rz_dst
->format
, r
, g
, b
);
1056 SDL_FillRect(rz_dst
, NULL
, colorkey
);
1060 * Lock source surface
1062 SDL_LockSurface(rz_src
);
1064 * Check which kind of surface we have
1068 * Call the 32bit transformation routine to do the zooming (using alpha)
1070 zoomSurfaceRGBA(rz_src
, rz_dst
, flipx
, flipy
, smooth
);
1072 * Turn on source-alpha support
1074 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1077 * Copy palette and colorkey info
1079 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1080 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1082 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1084 * Call the 8bit transformation routine to do the zooming
1086 zoomSurfaceY(rz_src
, rz_dst
, flipx
, flipy
);
1087 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1090 * Unlock source surface
1092 SDL_UnlockSurface(rz_src
);
1096 * Cleanup temp surface
1098 if (src_converted
) {
1099 SDL_FreeSurface(rz_src
);
1103 * Return destination surface
1112 Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1113 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1
1114 then the destination 32bit surface is anti-aliased. If the surface is not 8bit
1115 or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
1119 #define VALUE_LIMIT 0.001
1121 void zoomSurfaceSize(int width
, int height
, double zoomx
, double zoomy
, int *dstwidth
, int *dstheight
)
1124 * Sanity check zoom factors
1126 if (zoomx
< VALUE_LIMIT
) {
1127 zoomx
= VALUE_LIMIT
;
1129 if (zoomy
< VALUE_LIMIT
) {
1130 zoomy
= VALUE_LIMIT
;
1134 * Calculate target size
1136 *dstwidth
= (int) ((double) width
* zoomx
);
1137 *dstheight
= (int) ((double) height
* zoomy
);
1138 if (*dstwidth
< 1) {
1141 if (*dstheight
< 1) {
1146 SDL_Surface
*zoomSurface(SDL_Surface
* src
, double zoomx
, double zoomy
, int smooth
)
1148 SDL_Surface
*rz_src
;
1149 SDL_Surface
*rz_dst
;
1150 int dstwidth
, dstheight
;
1152 int i
, src_converted
;
1162 * Determine if source surface is 32bit or 8bit
1164 is32bit
= (src
->format
->BitsPerPixel
== 32);
1165 if ((is32bit
) || (src
->format
->BitsPerPixel
== 8)) {
1167 * Use source surface 'as is'
1173 * New source surface is 32bit with a defined RGBA ordering
1176 SDL_CreateRGBSurface(SDL_SWSURFACE
, src
->w
, src
->h
, 32,
1177 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1178 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1180 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1183 SDL_BlitSurface(src
, NULL
, rz_src
, NULL
);
1189 if (flipx
) zoomx
= -zoomx
;
1191 if (flipy
) zoomy
= -zoomy
;
1193 /* Get size if target */
1194 zoomSurfaceSize(rz_src
->w
, rz_src
->h
, zoomx
, zoomy
, &dstwidth
, &dstheight
);
1197 * Alloc space to completely contain the zoomed surface
1202 * Target surface is 32bit with source RGBA/ABGR ordering
1205 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
1206 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
1207 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
1210 * Target surface is 8bit
1212 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
1216 * Lock source surface
1218 SDL_LockSurface(rz_src
);
1220 * Check which kind of surface we have
1224 * Call the 32bit transformation routine to do the zooming (using alpha)
1226 zoomSurfaceRGBA(rz_src
, rz_dst
, flipx
, flipy
, smooth
);
1228 * Turn on source-alpha support
1230 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1233 * Copy palette and colorkey info
1235 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1236 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1238 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1240 * Call the 8bit transformation routine to do the zooming
1242 zoomSurfaceY(rz_src
, rz_dst
, flipx
, flipy
);
1243 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1246 * Unlock source surface
1248 SDL_UnlockSurface(rz_src
);
1251 * Cleanup temp surface
1253 if (src_converted
) {
1254 SDL_FreeSurface(rz_src
);
1258 * Return destination surface
1263 SDL_Surface
*shrinkSurface(SDL_Surface
* src
, int factorx
, int factory
)
1265 SDL_Surface
*rz_src
;
1266 SDL_Surface
*rz_dst
;
1267 int dstwidth
, dstheight
;
1269 int i
, src_converted
;
1278 * Determine if source surface is 32bit or 8bit
1280 is32bit
= (src
->format
->BitsPerPixel
== 32);
1281 if ((is32bit
) || (src
->format
->BitsPerPixel
== 8)) {
1283 * Use source surface 'as is'
1289 * New source surface is 32bit with a defined RGBA ordering
1292 SDL_CreateRGBSurface(SDL_SWSURFACE
, src
->w
, src
->h
, 32,
1293 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1294 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1296 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1299 SDL_BlitSurface(src
, NULL
, rz_src
, NULL
);
1304 /* Get size for target */
1305 dstwidth
=rz_src
->w
/factorx
;
1306 while (dstwidth
*factorx
>rz_src
->w
) { dstwidth
--; }
1307 dstheight
=rz_src
->h
/factory
;
1308 while (dstheight
*factory
>rz_src
->h
) { dstheight
--; }
1311 * Alloc space to completely contain the shrunken surface
1316 * Target surface is 32bit with source RGBA/ABGR ordering
1319 SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 32,
1320 rz_src
->format
->Rmask
, rz_src
->format
->Gmask
,
1321 rz_src
->format
->Bmask
, rz_src
->format
->Amask
);
1324 * Target surface is 8bit
1326 rz_dst
= SDL_CreateRGBSurface(SDL_SWSURFACE
, dstwidth
, dstheight
, 8, 0, 0, 0, 0);
1330 * Lock source surface
1332 SDL_LockSurface(rz_src
);
1334 * Check which kind of surface we have
1338 * Call the 32bit transformation routine to do the shrinking (using alpha)
1340 shrinkSurfaceRGBA(rz_src
, rz_dst
, factorx
, factory
);
1342 * Turn on source-alpha support
1344 SDL_SetAlpha(rz_dst
, SDL_SRCALPHA
, 255);
1347 * Copy palette and colorkey info
1349 for (i
= 0; i
< rz_src
->format
->palette
->ncolors
; i
++) {
1350 rz_dst
->format
->palette
->colors
[i
] = rz_src
->format
->palette
->colors
[i
];
1352 rz_dst
->format
->palette
->ncolors
= rz_src
->format
->palette
->ncolors
;
1354 * Call the 8bit transformation routine to do the shrinking
1356 shrinkSurfaceY(rz_src
, rz_dst
, factorx
, factory
);
1357 SDL_SetColorKey(rz_dst
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, rz_src
->format
->colorkey
);
1360 * Unlock source surface
1362 SDL_UnlockSurface(rz_src
);
1365 * Cleanup temp surface
1367 if (src_converted
) {
1368 SDL_FreeSurface(rz_src
);
1372 * Return destination surface