Freeciv-3.4
Loading...
Searching...
No Matches
SDL3_rotozoom.c
Go to the documentation of this file.
1/*
2
3SDL2_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
4
5Copyright (C) 2012-2014 Andreas Schiffler
6
7This software is provided 'as-is', without any express or implied
8warranty. In no event will the authors be held liable for any damages
9arising from the use of this software.
10
11Permission is granted to anyone to use this software for any purpose,
12including commercial applications, and to alter it and redistribute it
13freely, subject to the following restrictions:
14
151. The origin of this software must not be misrepresented; you must not
16claim that you wrote the original software. If you use this software
17in a product, an acknowledgment in the product documentation would be
18appreciated but is not required.
19
202. Altered source versions must be plainly marked as such, and must not be
21misrepresented as being the original software.
22
233. This notice may not be removed or altered from any source
24distribution.
25
26Andreas Schiffler -- aschiffler at ferzkopp dot net
27
28
29 ---
30
31 Adopted to freeciv usage as SDL3_rotozoom.c
32
33
34*/
35
36#include "fc_prehdrs.h"
37
38#ifdef WIN32
39#include <windows.h>
40#endif
41
42#include <stdlib.h>
43#include <string.h>
44
45#include "SDL3_rotozoom.h"
46
47/* ---- Internally used structures */
48
58
62typedef struct tColorY {
65
69#define MAX(a,b) (((a) > (b)) ? (a) : (b))
70
81#define GUARD_ROWS (2)
82
86#define VALUE_LIMIT 0.001
87
88
104static int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
105{
106 int x, y, dx, dy, dgap, ra, ga, ba, aa;
107 int n_average;
108 tColorRGBA *sp, *osp, *oosp;
109 tColorRGBA *dp;
110
111 /*
112 * Averaging integer shrink
113 */
114
115 /* Precalculate division factor */
117
118 /*
119 * Scan destination
120 */
121 sp = (tColorRGBA *) src->pixels;
122
123 dp = (tColorRGBA *) dst->pixels;
124 dgap = dst->pitch - dst->w * 4;
125
126 for (y = 0; y < dst->h; y++) {
127
128 osp=sp;
129 for (x = 0; x < dst->w; x++) {
130
131 /* Trace out source box and accumulate */
132 oosp=sp;
133 ra=ga=ba=aa=0;
134 for (dy=0; dy < factory; dy++) {
135 for (dx=0; dx < factorx; dx++) {
136 ra += sp->r;
137 ga += sp->g;
138 ba += sp->b;
139 aa += sp->a;
140
141 sp++;
142 }
143 /* src dx loop */
144 sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y
145 }
146 /* src dy loop */
147
148 /* next box-x */
149 sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx);
150
151 /* Store result in destination */
152 dp->r = ra/n_average;
153 dp->g = ga/n_average;
154 dp->b = ba/n_average;
155 dp->a = aa/n_average;
156
157 /*
158 * Advance destination pointer
159 */
160 dp++;
161 }
162 /* dst x loop */
163
164 /* next box-y */
165 sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory);
166
167 /*
168 * Advance destination pointers
169 */
170 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
171 }
172 /* dst y loop */
173
174 return (0);
175}
176
192static int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
193{
194 int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy;
195 tColorRGBA *c00, *c01, *c10, *c11;
196 tColorRGBA *sp, *csp, *dp;
197 int spixelgap, spixelw, spixelh, dgap, t1, t2;
198
199 /*
200 * Allocate memory for row/column increments
201 */
202 if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
203 return (-1);
204 }
205 if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
206 free(sax);
207 return (-1);
208 }
209
210 /*
211 * Precalculate row increments
212 */
213 spixelw = (src->w - 1);
214 spixelh = (src->h - 1);
215 if (smooth) {
216 sx = (int) (65536.0 * (float) spixelw / (float) (dst->w - 1));
217 sy = (int) (65536.0 * (float) spixelh / (float) (dst->h - 1));
218 } else {
219 sx = (int) (65536.0 * (float) (src->w) / (float) (dst->w));
220 sy = (int) (65536.0 * (float) (src->h) / (float) (dst->h));
221 }
222
223 /* Maximum scaled source size */
224 ssx = (src->w << 16) - 1;
225 ssy = (src->h << 16) - 1;
226
227 /* Precalculate horizontal row increments */
228 csx = 0;
229 csax = sax;
230 for (x = 0; x <= dst->w; x++) {
231 *csax = csx;
232 csax++;
233 csx += sx;
234
235 /* Guard from overflows */
236 if (csx > ssx) {
237 csx = ssx;
238 }
239 }
240
241 /* Precalculate vertical row increments */
242 csy = 0;
243 csay = say;
244 for (y = 0; y <= dst->h; y++) {
245 *csay = csy;
246 csay++;
247 csy += sy;
248
249 /* Guard from overflows */
250 if (csy > ssy) {
251 csy = ssy;
252 }
253 }
254
255 sp = (tColorRGBA *) src->pixels;
256 dp = (tColorRGBA *) dst->pixels;
257 dgap = dst->pitch - dst->w * 4;
258 spixelgap = src->pitch/4;
259
260 if (flipx) sp += spixelw;
261 if (flipy) sp += (spixelgap * spixelh);
262
263 /*
264 * Switch between interpolating and non-interpolating code
265 */
266 if (smooth) {
267
268 /*
269 * Interpolating Zoom
270 */
271 csay = say;
272 for (y = 0; y < dst->h; y++) {
273 csp = sp;
274 csax = sax;
275 for (x = 0; x < dst->w; x++) {
276 /*
277 * Setup color source pointers
278 */
279 ex = (*csax & 0xffff);
280 ey = (*csay & 0xffff);
281 cx = (*csax >> 16);
282 cy = (*csay >> 16);
283 sstepx = cx < spixelw;
284 sstepy = cy < spixelh;
285 c00 = sp;
286 c01 = sp;
287 c10 = sp;
288 if (sstepy) {
289 if (flipy) {
290 c10 -= spixelgap;
291 } else {
292 c10 += spixelgap;
293 }
294 }
295 c11 = c10;
296 if (sstepx) {
297 if (flipx) {
298 c01--;
299 c11--;
300 } else {
301 c01++;
302 c11++;
303 }
304 }
305
306 /*
307 * Draw and interpolate colors
308 */
309 t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
310 t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
311 dp->r = (((t2 - t1) * ey) >> 16) + t1;
312 t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
313 t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
314 dp->g = (((t2 - t1) * ey) >> 16) + t1;
315 t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
316 t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
317 dp->b = (((t2 - t1) * ey) >> 16) + t1;
318 t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
319 t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
320 dp->a = (((t2 - t1) * ey) >> 16) + t1;
321 /*
322 * Advance source pointer x
323 */
324 salast = csax;
325 csax++;
326 sstep = (*csax >> 16) - (*salast >> 16);
327 if (flipx) {
328 sp -= sstep;
329 } else {
330 sp += sstep;
331 }
332
333 /*
334 * Advance destination pointer x
335 */
336 dp++;
337 }
338 /*
339 * Advance source pointer y
340 */
341 salast = csay;
342 csay++;
343 sstep = (*csay >> 16) - (*salast >> 16);
344 sstep *= spixelgap;
345 if (flipy) {
346 sp = csp - sstep;
347 } else {
348 sp = csp + sstep;
349 }
350
351 /*
352 * Advance destination pointer y
353 */
354 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
355 }
356 } else {
357 /*
358 * Non-Interpolating Zoom
359 */
360 csay = say;
361 for (y = 0; y < dst->h; y++) {
362 csp = sp;
363 csax = sax;
364 for (x = 0; x < dst->w; x++) {
365 /*
366 * Draw
367 */
368 *dp = *sp;
369
370 /*
371 * Advance source pointer x
372 */
373 salast = csax;
374 csax++;
375 sstep = (*csax >> 16) - (*salast >> 16);
376 if (flipx) sstep = -sstep;
377 sp += sstep;
378
379 /*
380 * Advance destination pointer x
381 */
382 dp++;
383 }
384 /*
385 * Advance source pointer y
386 */
387 salast = csay;
388 csay++;
389 sstep = (*csay >> 16) - (*salast >> 16);
390 sstep *= spixelgap;
391 if (flipy) sstep = -sstep;
392 sp = csp + sstep;
393
394 /*
395 * Advance destination pointer y
396 */
397 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
398 }
399 }
400
401 /*
402 * Remove temp arrays
403 */
404 free(sax);
405 free(say);
406
407 return (0);
408}
409
429static void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
430{
431 int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
433 tColorRGBA *pc, *sp;
434 int gap;
435
436 /*
437 * Variable setup
438 */
439 xd = ((src->w - dst->w) << 15);
440 yd = ((src->h - dst->h) << 15);
441 ax = (cx << 16) - (icos * cx);
442 ay = (cy << 16) - (isin * cx);
443 sw = src->w - 1;
444 sh = src->h - 1;
445 pc = (tColorRGBA*) dst->pixels;
446 gap = dst->pitch - dst->w * 4;
447
448 /*
449 * Switch between interpolating and non-interpolating code
450 */
451 if (smooth) {
452 for (y = 0; y < dst->h; y++) {
453 dy = cy - y;
454 sdx = (ax + (isin * dy)) + xd;
455 sdy = (ay - (icos * dy)) + yd;
456 for (x = 0; x < dst->w; x++) {
457 dx = (sdx >> 16);
458 dy = (sdy >> 16);
459 if (flipx) dx = sw - dx;
460 if (flipy) dy = sh - dy;
461 if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
462 sp = (tColorRGBA *)src->pixels;;
463 sp += ((src->pitch/4) * dy);
464 sp += dx;
465 c00 = *sp;
466 sp += 1;
467 c01 = *sp;
468 sp += (src->pitch/4);
469 c11 = *sp;
470 sp -= 1;
471 c10 = *sp;
472 if (flipx) {
473 cswap = c00; c00=c01; c01=cswap;
474 cswap = c10; c10=c11; c11=cswap;
475 }
476 if (flipy) {
477 cswap = c00; c00=c10; c10=cswap;
478 cswap = c01; c01=c11; c11=cswap;
479 }
480 /*
481 * Interpolate colors
482 */
483 ex = (sdx & 0xffff);
484 ey = (sdy & 0xffff);
485 t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
486 t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
487 pc->r = (((t2 - t1) * ey) >> 16) + t1;
488 t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
489 t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
490 pc->g = (((t2 - t1) * ey) >> 16) + t1;
491 t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
492 t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
493 pc->b = (((t2 - t1) * ey) >> 16) + t1;
494 t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
495 t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
496 pc->a = (((t2 - t1) * ey) >> 16) + t1;
497 }
498 sdx += icos;
499 sdy += isin;
500 pc++;
501 }
502 pc = (tColorRGBA *) ((Uint8 *) pc + gap);
503 }
504 } else {
505 for (y = 0; y < dst->h; y++) {
506 dy = cy - y;
507 sdx = (ax + (isin * dy)) + xd;
508 sdy = (ay - (icos * dy)) + yd;
509 for (x = 0; x < dst->w; x++) {
510 dx = (short) (sdx >> 16);
511 dy = (short) (sdy >> 16);
512 if (flipx) dx = (src->w-1)-dx;
513 if (flipy) dy = (src->h-1)-dy;
514 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
515 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
516 sp += dx;
517 *pc = *sp;
518 }
519 sdx += icos;
520 sdy += isin;
521 pc++;
522 }
523 pc = (tColorRGBA *) ((Uint8 *) pc + gap);
524 }
525 }
526}
527
542{
543 int row, col, newWidth, newHeight;
544 int bpp, bpr;
545 SDL_Surface* dst;
546 Uint8* srcBuf;
547 Uint8* dstBuf;
550
551 /* Has to be a valid surface pointer and be a Nbit surface where n is divisible by 8 */
552 if (!src) {
553 SDL_SetError("NULL source surface or source surface format");
554 return NULL;
555 }
556
557 details = SDL_GetPixelFormatDetails(src->format);
558
559 if ((details->bits_per_pixel % 8) != 0) {
560 SDL_SetError("Invalid source surface bit depth");
561 return NULL;
562 }
563
564 /* normalize numClockwiseTurns */
566 if (normalizedClockwiseTurns < 0) {
568 }
569
570 /* If turns are even, our new width/height will be the same as the source surface */
571 if (normalizedClockwiseTurns % 2) {
572 newWidth = src->h;
573 newHeight = src->w;
574 } else {
575 newWidth = src->w;
576 newHeight = src->h;
577 }
578
580 if(!dst) {
581 SDL_SetError("Could not create destination surface");
582 return NULL;
583 }
584
585 if (SDL_MUSTLOCK(src)) {
586 SDL_LockSurface(src);
587 }
588 if (SDL_MUSTLOCK(dst)) {
589 SDL_LockSurface(dst);
590 }
591
592 /* Calculate byte-per-pixel */
593 bpp = details->bits_per_pixel / 8;
594
596 case 0: /* Make a copy of the surface */
597 {
598 /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface
599 since it does not preserve alpha. */
600
601 if (src->pitch == dst->pitch) {
602 /* If the pitch is the same for both surfaces, the memory can be copied all at once. */
603 memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
604 }
605 else
606 {
607 /* If the pitch differs, copy each row separately */
608 srcBuf = (Uint8*)(src->pixels);
609 dstBuf = (Uint8*)(dst->pixels);
610 bpr = src->w * bpp;
611 for (row = 0; row < src->h; row++) {
613 srcBuf += src->pitch;
614 dstBuf += dst->pitch;
615 }
616 }
617 }
618 break;
619
620 /* rotate clockwise */
621 case 1: /* rotated 90 degrees clockwise */
622 {
623 for (row = 0; row < src->h; ++row) {
624 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
625 dstBuf = (Uint8*)(dst->pixels) + (dst->w - row - 1) * bpp;
626 for (col = 0; col < src->w; ++col) {
628 srcBuf += bpp;
629 dstBuf += dst->pitch;
630 }
631 }
632 }
633 break;
634
635 case 2: /* rotated 180 degrees clockwise */
636 {
637 for (row = 0; row < src->h; ++row) {
638 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
639 dstBuf = (Uint8*)(dst->pixels) + ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp;
640 for (col = 0; col < src->w; ++col) {
642 srcBuf += bpp;
643 dstBuf -= bpp;
644 }
645 }
646 }
647 break;
648
649 case 3: /* rotated 270 degrees clockwise */
650 {
651 for (row = 0; row < src->h; ++row) {
652 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
653 dstBuf = (Uint8*)(dst->pixels) + (row * bpp) + ((dst->h - 1) * dst->pitch);
654 for (col = 0; col < src->w; ++col) {
656 srcBuf += bpp;
657 dstBuf -= dst->pitch;
658 }
659 }
660 }
661 break;
662 }
663 /* end switch */
664
665 if (SDL_MUSTLOCK(src)) {
667 }
668 if (SDL_MUSTLOCK(dst)) {
670 }
671
672 return dst;
673}
674
675
690static void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy,
691 int *dstwidth, int *dstheight,
692 double *canglezoom, double *sanglezoom)
693{
694 double x, y, cx, cy, sx, sy;
695 double radangle;
697
698 /*
699 * Determine destination width and height by rotating a centered source box
700 */
701 radangle = angle * (M_PI / 180.0);
704 *sanglezoom *= zoomx;
705 *canglezoom *= zoomy;
706 x = (double)(width / 2);
707 y = (double)(height / 2);
708 cx = *canglezoom * x;
709 cy = *canglezoom * y;
710 sx = *sanglezoom * x;
711 sy = *sanglezoom * y;
712
713 dstwidthhalf = MAX((int)
714 ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
715 dstheighthalf = MAX((int)
716 ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
717 *dstwidth = 2 * dstwidthhalf;
719}
720
738
755
771SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
772{
773 return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
774}
775
792SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
793{
796 double zoominv;
799 int src_converted;
800 int flipx,flipy;
802
803 /*
804 * Sanity check
805 */
806 if (src == NULL) {
807 return (NULL);
808 }
809
810 details = SDL_GetPixelFormatDetails(src->format);
811
812 /*
813 * Determine if source surface is 32bit or 8bit
814 */
815 if ((details->bits_per_pixel == 32)
816 || (details->bits_per_pixel == 8)) {
817 /*
818 * Use source surface 'as is'
819 */
820 rz_src = src;
821 src_converted = 0;
822 } else {
823 /*
824 * New source surface is 32bit with a defined RGBA ordering
825 */
826 rz_src =
828
830
831 src_converted = 1;
832 }
833
834 /*
835 * Sanity check zoom factor
836 */
837 flipx = (zoomx<0.0);
838 if (flipx) zoomx=-zoomx;
839 flipy = (zoomy<0.0);
840 if (flipy) zoomy=-zoomy;
843 zoominv = 65536.0 / (zoomx * zoomx);
844
845 /*
846 * Check if we have a rotozoom or just a zoom
847 */
848 if (fabs(angle) > VALUE_LIMIT) {
849
850 /*
851 * Angle!=0: full rotozoom
852 */
853 /*
854 * -----------------------
855 */
856
857 /* Determine target size */
859
860 /*
861 * Calculate target factors from sin/cos and zoom
862 */
867
868 /* Calculate half size */
871
872 /*
873 * Alloc space to completely contain the rotated surface
874 */
875 rz_dst = NULL;
876
877 /*
878 * Target surface is 32bit with source RGBA/ABGR ordering
879 */
880 rz_dst =
882 rz_src->format);
883
884 /* Check target */
885 if (rz_dst == NULL)
886 return NULL;
887
888 /* Adjust for guard rows */
889 rz_dst->h = dstheight;
890
891 /*
892 * Lock source surface
893 */
894 if (SDL_MUSTLOCK(rz_src)) {
896 }
897
898 /*
899 * Check which kind of surface we have
900 */
901
902 /*
903 * Call the 32bit transformation routine to do the rotation (using alpha)
904 */
906 (int) (sanglezoominv), (int) (canglezoominv),
907 flipx, flipy,
908 smooth);
909
910 /*
911 * Unlock source surface
912 */
913 if (SDL_MUSTLOCK(rz_src)) {
915 }
916
917 } else {
918
919 /*
920 * Angle=0: Just a zoom
921 */
922 /*
923 * --------------------
924 */
925
926 /*
927 * Calculate target size
928 */
930
931 /*
932 * Alloc space to completely contain the zoomed surface
933 */
934 rz_dst = NULL;
935
936 /*
937 * Target surface is 32bit with source RGBA/ABGR ordering
938 */
939 rz_dst =
941 rz_src->format);
942
943 /* Check target */
944 if (rz_dst == NULL)
945 return NULL;
946
947 /* Adjust for guard rows */
948 rz_dst->h = dstheight;
949
950 /*
951 * Lock source surface
952 */
953 if (SDL_MUSTLOCK(rz_src)) {
955 }
956
957 /*
958 * Check which kind of surface we have
959 */
960
961 /*
962 * Call the 32bit transformation routine to do the zooming (using alpha)
963 */
965
966 /*
967 * Unlock source surface
968 */
969 if (SDL_MUSTLOCK(rz_src)) {
971 }
972 }
973
974 /*
975 * Cleanup temp surface
976 */
977 if (src_converted) {
979 }
980
981 /*
982 * Return destination surface
983 */
984 return (rz_dst);
985}
986
999void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
1000{
1001 /*
1002 * Make zoom factors positive
1003 */
1004 int flipx, flipy;
1005 flipx = (zoomx<0.0);
1006 if (flipx) zoomx = -zoomx;
1007 flipy = (zoomy<0.0);
1008 if (flipy) zoomy = -zoomy;
1009
1010 /*
1011 * Sanity check zoom factors
1012 */
1013 if (zoomx < VALUE_LIMIT) {
1015 }
1016 if (zoomy < VALUE_LIMIT) {
1018 }
1019
1020 /*
1021 * Calculate target size
1022 */
1023 *dstwidth = (int) floor(((double) width * zoomx) + 0.5);
1024 *dstheight = (int) floor(((double) height * zoomy) + 0.5);
1025 if (*dstwidth < 1) {
1026 *dstwidth = 1;
1027 }
1028 if (*dstheight < 1) {
1029 *dstheight = 1;
1030 }
1031}
1032
1050{
1053 int dstwidth, dstheight;
1054 int src_converted;
1055 int flipx, flipy;
1057
1058 /*
1059 * Sanity check
1060 */
1061 if (src == NULL)
1062 return (NULL);
1063
1064 details = SDL_GetPixelFormatDetails(src->format);
1065
1066 /*
1067 * Determine if source surface is 32bit or 8bit
1068 */
1069 if ((details->bits_per_pixel == 32)
1070 || (details->bits_per_pixel == 8)) {
1071 /*
1072 * Use source surface 'as is'
1073 */
1074 rz_src = src;
1075 src_converted = 0;
1076 } else {
1077 /*
1078 * New source surface is 32bit with a defined RGBA ordering
1079 */
1080 rz_src =
1081 SDL_CreateSurface(src->w, src->h,
1083 if (rz_src == NULL) {
1084 return NULL;
1085 }
1087 src_converted = 1;
1088 }
1089
1090 flipx = (zoomx<0.0);
1091 if (flipx) zoomx = -zoomx;
1092 flipy = (zoomy<0.0);
1093 if (flipy) zoomy = -zoomy;
1094
1095 /* Get size if target */
1097
1098 /*
1099 * Alloc space to completely contain the zoomed surface
1100 */
1101 rz_dst = NULL;
1102
1103 /*
1104 * Target surface is 32bit with source RGBA/ABGR ordering
1105 */
1106 rz_dst =
1108 rz_src->format);
1109
1110 /* Check target */
1111 if (rz_dst == NULL) {
1112 /*
1113 * Cleanup temp surface
1114 */
1115 if (src_converted) {
1117 }
1118 return NULL;
1119 }
1120
1121 /* Adjust for guard rows */
1122 rz_dst->h = dstheight;
1123
1124 /*
1125 * Lock source surface
1126 */
1127 if (SDL_MUSTLOCK(rz_src)) {
1129 }
1130
1131 /*
1132 * Check which kind of surface we have
1133 */
1134
1135 /*
1136 * Call the 32bit transformation routine to do the zooming (using alpha)
1137 */
1139
1140 /*
1141 * Unlock source surface
1142 */
1143 if (SDL_MUSTLOCK(rz_src)) {
1145 }
1146
1147 /*
1148 * Cleanup temp surface
1149 */
1150 if (src_converted) {
1152 }
1153
1154 /*
1155 * Return destination surface
1156 */
1157 return (rz_dst);
1158}
1159
1176/*@null@*/
1178{
1179 int result;
1182 int dstwidth, dstheight;
1183 int src_converted;
1184 int haveError = 0;
1186
1187 /*
1188 * Sanity check
1189 */
1190 if (src == NULL) {
1191 return (NULL);
1192 }
1193
1194 details = SDL_GetPixelFormatDetails(src->format);
1195
1196 /*
1197 * Determine if source surface is 32bit or 8bit
1198 */
1199 if ((details->bits_per_pixel == 32)
1200 || (details->bits_per_pixel == 8)) {
1201 /*
1202 * Use source surface 'as is'
1203 */
1204 rz_src = src;
1205 src_converted = 0;
1206 } else {
1207 /*
1208 * New source surface is 32bit with a defined RGBA ordering
1209 */
1210 rz_src = SDL_CreateSurface(src->w, src->h,
1212 if (rz_src==NULL) {
1213 haveError = 1;
1214 goto exitShrinkSurface;
1215 }
1216
1218 src_converted = 1;
1219 }
1220
1221 /*
1222 * Lock the surface
1223 */
1224 if (SDL_MUSTLOCK(rz_src)) {
1225 if (!SDL_LockSurface(rz_src)) {
1226 haveError = 1;
1227 goto exitShrinkSurface;
1228 }
1229 }
1230
1231 /* Get size for target */
1233 while (dstwidth*factorx>rz_src->w) { dstwidth--; }
1235 while (dstheight*factory>rz_src->h) { dstheight--; }
1236
1237 /*
1238 * Alloc space to completely contain the shrunken surface
1239 * (with added guard rows)
1240 */
1241
1242 /*
1243 * Target surface is 32bit with source RGBA/ABGR ordering
1244 */
1245 rz_dst =
1247 rz_src->format);
1248
1249 /* Check target */
1250 if (rz_dst == NULL) {
1251 haveError = 1;
1252 goto exitShrinkSurface;
1253 }
1254
1255 /* Adjust for guard rows */
1256 rz_dst->h = dstheight;
1257
1258 /*
1259 * Check which kind of surface we have
1260 */
1261
1262 /*
1263 * Call the 32bit transformation routine to do the shrinking (using alpha)
1264 */
1266 if ((result!=0) || (rz_dst==NULL)) {
1267 haveError = 1;
1268 goto exitShrinkSurface;
1269 }
1270
1272 if (rz_src!=NULL) {
1273 /*
1274 * Unlock source surface
1275 */
1276 if (SDL_MUSTLOCK(rz_src)) {
1278 }
1279
1280 /*
1281 * Cleanup temp surface
1282 */
1283 if (src_converted==1) {
1285 }
1286 }
1287
1288 /* Check error state; maybe need to cleanup destination */
1289 if (haveError==1) {
1290 if (rz_dst!=NULL) {
1292 }
1293 rz_dst=NULL;
1294 }
1295
1296 /*
1297 * Return destination surface
1298 */
1299 return (rz_dst);
1300}
SDL_Surface * rotozoomSurfaceXY(SDL_Surface *src, double angle, double zoomx, double zoomy, int smooth)
Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-...
#define GUARD_ROWS
Number of guard rows added to destination surfaces.
static void _transformSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
Internal 32 bit rotozoomer with optional anti-aliasing.
static int _zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int flipx, int flipy, int smooth)
Internal 32 bit Zoomer with optional anti-aliasing by bilinear interpolation.
SDL_Surface * rotozoomSurface(SDL_Surface *src, double angle, double zoom, int smooth)
Rotates and zooms a surface and optional anti-aliasing.
static int _shrinkSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 32 bit integer-factor averaging Shrinker.
SDL_Surface * rotateSurface90Degrees(SDL_Surface *src, int numClockwiseTurns)
Rotates a 8/16/24/32 bit surface in increments of 90 degrees.
SDL_Surface * zoomSurface(SDL_Surface *src, double zoomx, double zoomy, int smooth)
Zoom a surface by independent horizontal and vertical factors with optional smoothing.
SDL_Surface * shrinkSurface(SDL_Surface *src, int factorx, int factory)
Shrink a surface by an integer ratio using averaging.
void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
Calculates the size of the target surface for a zoomSurface() call.
void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
Returns the size of the resulting target surface for a rotozoomSurface() call.
#define VALUE_LIMIT
Lower limit of absolute zoom factor or rotation degrees.
static void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight, double *canglezoom, double *sanglezoom)
Internal target surface sizing function for rotozooms with trig result return.
void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
Returns the size of the resulting target surface for a rotozoomSurfaceXY() call.
#define MAX(a, b)
Returns maximum of two numbers a and b.
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
char * incite_cost
Definition comments.c:77
#define M_PI
Definition plrdlg.c:53
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
A 32 bit RGBA pixel.
A 8bit Y/palette pixel.