SDL2_gfx  1.0.0
GraphicsprimitivesandsurfacefunctionsforSDL2
/builddir/build/BUILD/SDL2_gfx-1.0.0/SDL2_rotozoom.c
Go to the documentation of this file.
1 /*
2 
3 SDL2_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
4 
5 Copyright (C) 2012 Andreas Schiffler
6 
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for any damages
9 arising from the use of this software.
10 
11 Permission is granted to anyone to use this software for any purpose,
12 including commercial applications, and to alter it and redistribute it
13 freely, subject to the following restrictions:
14 
15 1. The origin of this software must not be misrepresented; you must not
16 claim that you wrote the original software. If you use this software
17 in a product, an acknowledgment in the product documentation would be
18 appreciated but is not required.
19 
20 2. Altered source versions must be plainly marked as such, and must not be
21 misrepresented as being the original software.
22 
23 3. This notice may not be removed or altered from any source
24 distribution.
25 
26 Andreas Schiffler -- aschiffler at ferzkopp dot net
27 
28 */
29 
30 #ifdef WIN32
31 #include <windows.h>
32 #endif
33 
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include "SDL2_rotozoom.h"
38 
39 /* ---- Internally used structures */
40 
44 typedef struct tColorRGBA {
45  Uint8 r;
46  Uint8 g;
47  Uint8 b;
48  Uint8 a;
49 } tColorRGBA;
50 
54 typedef struct tColorY {
55  Uint8 y;
56 } tColorY;
57 
61 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
62 
73 #define GUARD_ROWS (2)
74 
78 #define VALUE_LIMIT 0.001
79 
83 Uint32 _colorkey(SDL_Surface *src)
84 {
85  Uint32 key = 0;
86  SDL_GetColorKey(src, &key);
87  return key;
88 }
89 
90 
106 int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
107 {
108  int x, y, dx, dy, dgap, ra, ga, ba, aa;
109  int n_average;
110  tColorRGBA *sp, *osp, *oosp;
111  tColorRGBA *dp;
112 
113  /*
114  * Averaging integer shrink
115  */
116 
117  /* Precalculate division factor */
118  n_average = factorx*factory;
119 
120  /*
121  * Scan destination
122  */
123  sp = (tColorRGBA *) src->pixels;
124 
125  dp = (tColorRGBA *) dst->pixels;
126  dgap = dst->pitch - dst->w * 4;
127 
128  for (y = 0; y < dst->h; y++) {
129 
130  osp=sp;
131  for (x = 0; x < dst->w; x++) {
132 
133  /* Trace out source box and accumulate */
134  oosp=sp;
135  ra=ga=ba=aa=0;
136  for (dy=0; dy < factory; dy++) {
137  for (dx=0; dx < factorx; dx++) {
138  ra += sp->r;
139  ga += sp->g;
140  ba += sp->b;
141  aa += sp->a;
142 
143  sp++;
144  }
145  /* src dx loop */
146  sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y
147  }
148  /* src dy loop */
149 
150  /* next box-x */
151  sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx);
152 
153  /* Store result in destination */
154  dp->r = ra/n_average;
155  dp->g = ga/n_average;
156  dp->b = ba/n_average;
157  dp->a = aa/n_average;
158 
159  /*
160  * Advance destination pointer
161  */
162  dp++;
163  }
164  /* dst x loop */
165 
166  /* next box-y */
167  sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory);
168 
169  /*
170  * Advance destination pointers
171  */
172  dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
173  }
174  /* dst y loop */
175 
176  return (0);
177 }
178 
194 int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
195 {
196  int x, y, dx, dy, dgap, a;
197  int n_average;
198  Uint8 *sp, *osp, *oosp;
199  Uint8 *dp;
200 
201  /*
202  * Averaging integer shrink
203  */
204 
205  /* Precalculate division factor */
206  n_average = factorx*factory;
207 
208  /*
209  * Scan destination
210  */
211  sp = (Uint8 *) src->pixels;
212 
213  dp = (Uint8 *) dst->pixels;
214  dgap = dst->pitch - dst->w;
215 
216  for (y = 0; y < dst->h; y++) {
217 
218  osp=sp;
219  for (x = 0; x < dst->w; x++) {
220 
221  /* Trace out source box and accumulate */
222  oosp=sp;
223  a=0;
224  for (dy=0; dy < factory; dy++) {
225  for (dx=0; dx < factorx; dx++) {
226  a += (*sp);
227  /* next x */
228  sp++;
229  }
230  /* end src dx loop */
231  /* next y */
232  sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx));
233  }
234  /* end src dy loop */
235 
236  /* next box-x */
237  sp = (Uint8 *)((Uint8*)oosp + factorx);
238 
239  /* Store result in destination */
240  *dp = a/n_average;
241 
242  /*
243  * Advance destination pointer
244  */
245  dp++;
246  }
247  /* end dst x loop */
248 
249  /* next box-y */
250  sp = (Uint8 *)((Uint8*)osp + src->pitch*factory);
251 
252  /*
253  * Advance destination pointers
254  */
255  dp = (Uint8 *)((Uint8 *)dp + dgap);
256  }
257  /* end dst y loop */
258 
259  return (0);
260 }
261 
277 int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
278 {
279  int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy;
280  tColorRGBA *c00, *c01, *c10, *c11;
281  tColorRGBA *sp, *csp, *dp;
282  int spixelgap, spixelw, spixelh, dgap, t1, t2;
283 
284  /*
285  * Allocate memory for row/column increments
286  */
287  if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
288  return (-1);
289  }
290  if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
291  free(sax);
292  return (-1);
293  }
294 
295  /*
296  * Precalculate row increments
297  */
298  spixelw = (src->w - 1);
299  spixelh = (src->h - 1);
300  if (smooth) {
301  sx = (int) (65536.0 * (float) spixelw / (float) (dst->w - 1));
302  sy = (int) (65536.0 * (float) spixelh / (float) (dst->h - 1));
303  } else {
304  sx = (int) (65536.0 * (float) (src->w) / (float) (dst->w));
305  sy = (int) (65536.0 * (float) (src->h) / (float) (dst->h));
306  }
307 
308  /* Maximum scaled source size */
309  ssx = (src->w << 16) - 1;
310  ssy = (src->h << 16) - 1;
311 
312  /* Precalculate horizontal row increments */
313  csx = 0;
314  csax = sax;
315  for (x = 0; x <= dst->w; x++) {
316  *csax = csx;
317  csax++;
318  csx += sx;
319 
320  /* Guard from overflows */
321  if (csx > ssx) {
322  csx = ssx;
323  }
324  }
325 
326  /* Precalculate vertical row increments */
327  csy = 0;
328  csay = say;
329  for (y = 0; y <= dst->h; y++) {
330  *csay = csy;
331  csay++;
332  csy += sy;
333 
334  /* Guard from overflows */
335  if (csy > ssy) {
336  csy = ssy;
337  }
338  }
339 
340  sp = (tColorRGBA *) src->pixels;
341  dp = (tColorRGBA *) dst->pixels;
342  dgap = dst->pitch - dst->w * 4;
343  spixelgap = src->pitch/4;
344 
345  if (flipx) sp += spixelw;
346  if (flipy) sp += (spixelgap * spixelh);
347 
348  /*
349  * Switch between interpolating and non-interpolating code
350  */
351  if (smooth) {
352 
353  /*
354  * Interpolating Zoom
355  */
356  csay = say;
357  for (y = 0; y < dst->h; y++) {
358  csp = sp;
359  csax = sax;
360  for (x = 0; x < dst->w; x++) {
361  /*
362  * Setup color source pointers
363  */
364  ex = (*csax & 0xffff);
365  ey = (*csay & 0xffff);
366  cx = (*csax >> 16);
367  cy = (*csay >> 16);
368  sstepx = cx < spixelw;
369  sstepy = cy < spixelh;
370  c00 = sp;
371  c01 = sp;
372  c10 = sp;
373  if (sstepy) {
374  if (flipy) {
375  c10 -= spixelgap;
376  } else {
377  c10 += spixelgap;
378  }
379  }
380  c11 = c10;
381  if (sstepx) {
382  if (flipx) {
383  c01--;
384  c11--;
385  } else {
386  c01++;
387  c11++;
388  }
389  }
390 
391  /*
392  * Draw and interpolate colors
393  */
394  t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
395  t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
396  dp->r = (((t2 - t1) * ey) >> 16) + t1;
397  t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
398  t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
399  dp->g = (((t2 - t1) * ey) >> 16) + t1;
400  t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
401  t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
402  dp->b = (((t2 - t1) * ey) >> 16) + t1;
403  t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
404  t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
405  dp->a = (((t2 - t1) * ey) >> 16) + t1;
406  /*
407  * Advance source pointer x
408  */
409  salast = csax;
410  csax++;
411  sstep = (*csax >> 16) - (*salast >> 16);
412  if (flipx) {
413  sp -= sstep;
414  } else {
415  sp += sstep;
416  }
417 
418  /*
419  * Advance destination pointer x
420  */
421  dp++;
422  }
423  /*
424  * Advance source pointer y
425  */
426  salast = csay;
427  csay++;
428  sstep = (*csay >> 16) - (*salast >> 16);
429  sstep *= spixelgap;
430  if (flipy) {
431  sp = csp - sstep;
432  } else {
433  sp = csp + sstep;
434  }
435 
436  /*
437  * Advance destination pointer y
438  */
439  dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
440  }
441  } else {
442  /*
443  * Non-Interpolating Zoom
444  */
445  csay = say;
446  for (y = 0; y < dst->h; y++) {
447  csp = sp;
448  csax = sax;
449  for (x = 0; x < dst->w; x++) {
450  /*
451  * Draw
452  */
453  *dp = *sp;
454 
455  /*
456  * Advance source pointer x
457  */
458  salast = csax;
459  csax++;
460  sstep = (*csax >> 16) - (*salast >> 16);
461  if (flipx) sstep = -sstep;
462  sp += sstep;
463 
464  /*
465  * Advance destination pointer x
466  */
467  dp++;
468  }
469  /*
470  * Advance source pointer y
471  */
472  salast = csay;
473  csay++;
474  sstep = (*csay >> 16) - (*salast >> 16);
475  sstep *= spixelgap;
476  if (flipy) sstep = -sstep;
477  sp = csp + sstep;
478 
479  /*
480  * Advance destination pointer y
481  */
482  dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
483  }
484  }
485 
486  /*
487  * Remove temp arrays
488  */
489  free(sax);
490  free(say);
491 
492  return (0);
493 }
494 
510 int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
511 {
512  int x, y;
513  Uint32 *sax, *say, *csax, *csay;
514  int csx, csy;
515  Uint8 *sp, *dp, *csp;
516  int dgap;
517 
518  /*
519  * Allocate memory for row increments
520  */
521  if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
522  return (-1);
523  }
524  if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
525  free(sax);
526  return (-1);
527  }
528 
529  /*
530  * Pointer setup
531  */
532  sp = csp = (Uint8 *) src->pixels;
533  dp = (Uint8 *) dst->pixels;
534  dgap = dst->pitch - dst->w;
535 
536  if (flipx) csp += (src->w-1);
537  if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) );
538 
539  /*
540  * Precalculate row increments
541  */
542  csx = 0;
543  csax = sax;
544  for (x = 0; x < dst->w; x++) {
545  csx += src->w;
546  *csax = 0;
547  while (csx >= dst->w) {
548  csx -= dst->w;
549  (*csax)++;
550  }
551  (*csax) = (*csax) * (flipx ? -1 : 1);
552  csax++;
553  }
554  csy = 0;
555  csay = say;
556  for (y = 0; y < dst->h; y++) {
557  csy += src->h;
558  *csay = 0;
559  while (csy >= dst->h) {
560  csy -= dst->h;
561  (*csay)++;
562  }
563  (*csay) = (*csay) * (flipy ? -1 : 1);
564  csay++;
565  }
566 
567  /*
568  * Draw
569  */
570  csay = say;
571  for (y = 0; y < dst->h; y++) {
572  csax = sax;
573  sp = csp;
574  for (x = 0; x < dst->w; x++) {
575  /*
576  * Draw
577  */
578  *dp = *sp;
579  /*
580  * Advance source pointers
581  */
582  sp += (*csax);
583  csax++;
584  /*
585  * Advance destination pointer
586  */
587  dp++;
588  }
589  /*
590  * Advance source pointer (for row)
591  */
592  csp += ((*csay) * src->pitch);
593  csay++;
594 
595  /*
596  * Advance destination pointers
597  */
598  dp += dgap;
599  }
600 
601  /*
602  * Remove temp arrays
603  */
604  free(sax);
605  free(say);
606 
607  return (0);
608 }
609 
629 void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
630 {
631  int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
632  tColorRGBA c00, c01, c10, c11, cswap;
633  tColorRGBA *pc, *sp;
634  int gap;
635 
636  /*
637  * Variable setup
638  */
639  xd = ((src->w - dst->w) << 15);
640  yd = ((src->h - dst->h) << 15);
641  ax = (cx << 16) - (icos * cx);
642  ay = (cy << 16) - (isin * cx);
643  sw = src->w - 1;
644  sh = src->h - 1;
645  pc = (tColorRGBA*) dst->pixels;
646  gap = dst->pitch - dst->w * 4;
647 
648  /*
649  * Switch between interpolating and non-interpolating code
650  */
651  if (smooth) {
652  for (y = 0; y < dst->h; y++) {
653  dy = cy - y;
654  sdx = (ax + (isin * dy)) + xd;
655  sdy = (ay - (icos * dy)) + yd;
656  for (x = 0; x < dst->w; x++) {
657  dx = (sdx >> 16);
658  dy = (sdy >> 16);
659  if (flipx) dx = sw - dx;
660  if (flipy) dy = sh - dy;
661  if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
662  sp = (tColorRGBA *)src->pixels;;
663  sp += ((src->pitch/4) * dy);
664  sp += dx;
665  c00 = *sp;
666  sp += 1;
667  c01 = *sp;
668  sp += (src->pitch/4);
669  c11 = *sp;
670  sp -= 1;
671  c10 = *sp;
672  if (flipx) {
673  cswap = c00; c00=c01; c01=cswap;
674  cswap = c10; c10=c11; c11=cswap;
675  }
676  if (flipy) {
677  cswap = c00; c00=c10; c10=cswap;
678  cswap = c01; c01=c11; c11=cswap;
679  }
680  /*
681  * Interpolate colors
682  */
683  ex = (sdx & 0xffff);
684  ey = (sdy & 0xffff);
685  t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
686  t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
687  pc->r = (((t2 - t1) * ey) >> 16) + t1;
688  t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
689  t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
690  pc->g = (((t2 - t1) * ey) >> 16) + t1;
691  t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
692  t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
693  pc->b = (((t2 - t1) * ey) >> 16) + t1;
694  t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
695  t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
696  pc->a = (((t2 - t1) * ey) >> 16) + t1;
697  }
698  sdx += icos;
699  sdy += isin;
700  pc++;
701  }
702  pc = (tColorRGBA *) ((Uint8 *) pc + gap);
703  }
704  } else {
705  for (y = 0; y < dst->h; y++) {
706  dy = cy - y;
707  sdx = (ax + (isin * dy)) + xd;
708  sdy = (ay - (icos * dy)) + yd;
709  for (x = 0; x < dst->w; x++) {
710  dx = (short) (sdx >> 16);
711  dy = (short) (sdy >> 16);
712  if (flipx) dx = (src->w-1)-dx;
713  if (flipy) dy = (src->h-1)-dy;
714  if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
715  sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
716  sp += dx;
717  *pc = *sp;
718  }
719  sdx += icos;
720  sdy += isin;
721  pc++;
722  }
723  pc = (tColorRGBA *) ((Uint8 *) pc + gap);
724  }
725  }
726 }
727 
746 void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
747 {
748  int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay;
749  tColorY *pc, *sp;
750  int gap;
751 
752  /*
753  * Variable setup
754  */
755  xd = ((src->w - dst->w) << 15);
756  yd = ((src->h - dst->h) << 15);
757  ax = (cx << 16) - (icos * cx);
758  ay = (cy << 16) - (isin * cx);
759  pc = (tColorY*) dst->pixels;
760  gap = dst->pitch - dst->w;
761  /*
762  * Clear surface to colorkey
763  */
764  memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h);
765  /*
766  * Iterate through destination surface
767  */
768  for (y = 0; y < dst->h; y++) {
769  dy = cy - y;
770  sdx = (ax + (isin * dy)) + xd;
771  sdy = (ay - (icos * dy)) + yd;
772  for (x = 0; x < dst->w; x++) {
773  dx = (short) (sdx >> 16);
774  dy = (short) (sdy >> 16);
775  if (flipx) dx = (src->w-1)-dx;
776  if (flipy) dy = (src->h-1)-dy;
777  if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
778  sp = (tColorY *) (src->pixels);
779  sp += (src->pitch * dy + dx);
780  *pc = *sp;
781  }
782  sdx += icos;
783  sdy += isin;
784  pc++;
785  }
786  pc += gap;
787  }
788 }
789 
803 SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns)
804 {
805  int row, col, newWidth, newHeight;
806  int bpp;
807  SDL_Surface* dst;
808  Uint8* srcBuf;
809  Uint8* dstBuf;
810 
811  /* Has to be a valid surface pointer and be a 8/16/24/32-bit surface */
812  if (!src || !src->format ||
813  !(src->format->BitsPerPixel == 8) ||
814  (src->format->BitsPerPixel == 16) ||
815  (src->format->BitsPerPixel == 24) ||
816  (src->format->BitsPerPixel == 32)) { return NULL; }
817 
818  /* normalize numClockwiseTurns */
819  while(numClockwiseTurns < 0) { numClockwiseTurns += 4; }
820  numClockwiseTurns = (numClockwiseTurns % 4);
821 
822  /* if it's even, our new width will be the same as the source surface */
823  newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w);
824  newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h);
825  dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel,
826  src->format->Rmask,
827  src->format->Gmask,
828  src->format->Bmask,
829  src->format->Amask);
830  if(!dst) {
831  return NULL;
832  }
833 
834  if (SDL_MUSTLOCK(src)) {
835  SDL_LockSurface(src);
836  }
837  if (SDL_MUSTLOCK(dst)) {
838  SDL_LockSurface(dst);
839  }
840 
841  /* Calculate byte-per-pixel */
842  bpp = src->format->BitsPerPixel / 8;
843 
844  switch(numClockwiseTurns) {
845  case 0: /* Make a copy of the surface */
846  {
847  /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface
848  since it does not preserve alpha. */
849 
850  if (src->pitch == dst->pitch) {
851  /* If the pitch is the same for both surfaces, the memory can be copied all at once. */
852  memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
853  }
854  else
855  {
856  /* If the pitch differs, copy each row separately */
857  srcBuf = (Uint8*)(src->pixels);
858  dstBuf = (Uint8*)(dst->pixels);
859  for (row = 0; row < src->h; row++) {
860  memcpy(dstBuf, srcBuf, dst->w * bpp);
861  srcBuf += src->pitch;
862  dstBuf += dst->pitch;
863  } /* end for(col) */
864  } /* end for(row) */
865  }
866  break;
867 
868  /* rotate clockwise */
869  case 1: /* rotated 90 degrees clockwise */
870  {
871  for (row = 0; row < src->h; ++row) {
872  srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
873  dstBuf = (Uint8*)(dst->pixels) + (dst->w - row - 1) * bpp;
874  for (col = 0; col < src->w; ++col) {
875  memcpy (dstBuf, srcBuf, bpp);
876  srcBuf += bpp;
877  dstBuf += dst->pitch;
878  }
879  }
880  }
881  break;
882 
883  case 2: /* rotated 180 degrees clockwise */
884  {
885  for (row = 0; row < src->h; ++row) {
886  srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
887  dstBuf = (Uint8*)(dst->pixels) + ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp;
888  for (col = 0; col < src->w; ++col) {
889  memcpy (dstBuf, srcBuf, bpp);
890  srcBuf += bpp;
891  dstBuf -= bpp;
892  }
893  }
894  }
895  break;
896 
897  case 3: /* rotated 270 degrees clockwise */
898  {
899  for (row = 0; row < src->h; ++row) {
900  srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
901  dstBuf = (Uint8*)(dst->pixels) + row + ((dst->h - 1) * dst->pitch);
902  for (col = 0; col < src->w; ++col) {
903  *dstBuf = *srcBuf;
904  srcBuf += bpp;
905  dstBuf -= dst->pitch;
906  }
907  }
908  }
909  break;
910  }
911  /* end switch */
912 
913  if (SDL_MUSTLOCK(src)) {
914  SDL_UnlockSurface(src);
915  }
916  if (SDL_MUSTLOCK(dst)) {
917  SDL_UnlockSurface(dst);
918  }
919 
920  return dst;
921 }
922 
923 
938 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy,
939  int *dstwidth, int *dstheight,
940  double *canglezoom, double *sanglezoom)
941 {
942  double x, y, cx, cy, sx, sy;
943  double radangle;
944  int dstwidthhalf, dstheighthalf;
945 
946  /*
947  * Determine destination width and height by rotating a centered source box
948  */
949  radangle = angle * (M_PI / 180.0);
950  *sanglezoom = sin(radangle);
951  *canglezoom = cos(radangle);
952  *sanglezoom *= zoomx;
953  *canglezoom *= zoomx;
954  x = (double)(width / 2);
955  y = (double)(height / 2);
956  cx = *canglezoom * x;
957  cy = *canglezoom * y;
958  sx = *sanglezoom * x;
959  sy = *sanglezoom * y;
960 
961  dstwidthhalf = MAX((int)
962  ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
963  dstheighthalf = MAX((int)
964  ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
965  *dstwidth = 2 * dstwidthhalf;
966  *dstheight = 2 * dstheighthalf;
967 }
968 
980 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
981 {
982  double dummy_sanglezoom, dummy_canglezoom;
983 
984  _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
985 }
986 
997 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
998 {
999  double dummy_sanglezoom, dummy_canglezoom;
1000 
1001  _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
1002 }
1003 
1019 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
1020 {
1021  return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
1022 }
1023 
1040 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
1041 {
1042  SDL_Surface *rz_src;
1043  SDL_Surface *rz_dst;
1044  double zoominv;
1045  double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
1046  int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
1047  int is32bit;
1048  int i, src_converted;
1049  int flipx,flipy;
1050 
1051  /*
1052  * Sanity check
1053  */
1054  if (src == NULL) {
1055  return (NULL);
1056  }
1057 
1058  /*
1059  * Determine if source surface is 32bit or 8bit
1060  */
1061  is32bit = (src->format->BitsPerPixel == 32);
1062  if ((is32bit) || (src->format->BitsPerPixel == 8)) {
1063  /*
1064  * Use source surface 'as is'
1065  */
1066  rz_src = src;
1067  src_converted = 0;
1068  } else {
1069  /*
1070  * New source surface is 32bit with a defined RGBA ordering
1071  */
1072  rz_src =
1073  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1074 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1075  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1076 #else
1077  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1078 #endif
1079  );
1080 
1081  SDL_BlitSurface(src, NULL, rz_src, NULL);
1082 
1083  src_converted = 1;
1084  is32bit = 1;
1085  }
1086 
1087  /*
1088  * Sanity check zoom factor
1089  */
1090  flipx = (zoomx<0.0);
1091  if (flipx) zoomx=-zoomx;
1092  flipy = (zoomy<0.0);
1093  if (flipy) zoomy=-zoomy;
1094  if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
1095  if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
1096  zoominv = 65536.0 / (zoomx * zoomx);
1097 
1098  /*
1099  * Check if we have a rotozoom or just a zoom
1100  */
1101  if (fabs(angle) > VALUE_LIMIT) {
1102 
1103  /*
1104  * Angle!=0: full rotozoom
1105  */
1106  /*
1107  * -----------------------
1108  */
1109 
1110  /* Determine target size */
1111  _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
1112 
1113  /*
1114  * Calculate target factors from sin/cos and zoom
1115  */
1116  sanglezoominv = sanglezoom;
1117  canglezoominv = canglezoom;
1118  sanglezoominv *= zoominv;
1119  canglezoominv *= zoominv;
1120 
1121  /* Calculate half size */
1122  dstwidthhalf = dstwidth / 2;
1123  dstheighthalf = dstheight / 2;
1124 
1125  /*
1126  * Alloc space to completely contain the rotated surface
1127  */
1128  rz_dst = NULL;
1129  if (is32bit) {
1130  /*
1131  * Target surface is 32bit with source RGBA/ABGR ordering
1132  */
1133  rz_dst =
1134  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1135  rz_src->format->Rmask, rz_src->format->Gmask,
1136  rz_src->format->Bmask, rz_src->format->Amask);
1137  } else {
1138  /*
1139  * Target surface is 8bit
1140  */
1141  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1142  }
1143 
1144  /* Check target */
1145  if (rz_dst == NULL)
1146  return NULL;
1147 
1148  /* Adjust for guard rows */
1149  rz_dst->h = dstheight;
1150 
1151  /*
1152  * Lock source surface
1153  */
1154  if (SDL_MUSTLOCK(rz_src)) {
1155  SDL_LockSurface(rz_src);
1156  }
1157 
1158  /*
1159  * Check which kind of surface we have
1160  */
1161  if (is32bit) {
1162  /*
1163  * Call the 32bit transformation routine to do the rotation (using alpha)
1164  */
1165  _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1166  (int) (sanglezoominv), (int) (canglezoominv),
1167  flipx, flipy,
1168  smooth);
1169  } else {
1170  /*
1171  * Copy palette and colorkey info
1172  */
1173  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1174  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1175  }
1176  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1177  /*
1178  * Call the 8bit transformation routine to do the rotation
1179  */
1180  transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1181  (int) (sanglezoominv), (int) (canglezoominv),
1182  flipx, flipy);
1183  }
1184  /*
1185  * Unlock source surface
1186  */
1187  if (SDL_MUSTLOCK(rz_src)) {
1188  SDL_UnlockSurface(rz_src);
1189  }
1190 
1191  } else {
1192 
1193  /*
1194  * Angle=0: Just a zoom
1195  */
1196  /*
1197  * --------------------
1198  */
1199 
1200  /*
1201  * Calculate target size
1202  */
1203  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
1204 
1205  /*
1206  * Alloc space to completely contain the zoomed surface
1207  */
1208  rz_dst = NULL;
1209  if (is32bit) {
1210  /*
1211  * Target surface is 32bit with source RGBA/ABGR ordering
1212  */
1213  rz_dst =
1214  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1215  rz_src->format->Rmask, rz_src->format->Gmask,
1216  rz_src->format->Bmask, rz_src->format->Amask);
1217  } else {
1218  /*
1219  * Target surface is 8bit
1220  */
1221  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1222  }
1223 
1224  /* Check target */
1225  if (rz_dst == NULL)
1226  return NULL;
1227 
1228  /* Adjust for guard rows */
1229  rz_dst->h = dstheight;
1230 
1231  /*
1232  * Lock source surface
1233  */
1234  if (SDL_MUSTLOCK(rz_src)) {
1235  SDL_LockSurface(rz_src);
1236  }
1237 
1238  /*
1239  * Check which kind of surface we have
1240  */
1241  if (is32bit) {
1242  /*
1243  * Call the 32bit transformation routine to do the zooming (using alpha)
1244  */
1245  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1246 
1247  } else {
1248  /*
1249  * Copy palette and colorkey info
1250  */
1251  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1252  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1253  }
1254  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1255 
1256  /*
1257  * Call the 8bit transformation routine to do the zooming
1258  */
1259  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1260  }
1261 
1262  /*
1263  * Unlock source surface
1264  */
1265  if (SDL_MUSTLOCK(rz_src)) {
1266  SDL_UnlockSurface(rz_src);
1267  }
1268  }
1269 
1270  /*
1271  * Cleanup temp surface
1272  */
1273  if (src_converted) {
1274  SDL_FreeSurface(rz_src);
1275  }
1276 
1277  /*
1278  * Return destination surface
1279  */
1280  return (rz_dst);
1281 }
1282 
1295 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
1296 {
1297  /*
1298  * Make zoom factors positive
1299  */
1300  int flipx, flipy;
1301  flipx = (zoomx<0.0);
1302  if (flipx) zoomx = -zoomx;
1303  flipy = (zoomy<0.0);
1304  if (flipy) zoomy = -zoomy;
1305 
1306  /*
1307  * Sanity check zoom factors
1308  */
1309  if (zoomx < VALUE_LIMIT) {
1310  zoomx = VALUE_LIMIT;
1311  }
1312  if (zoomy < VALUE_LIMIT) {
1313  zoomy = VALUE_LIMIT;
1314  }
1315 
1316  /*
1317  * Calculate target size
1318  */
1319  *dstwidth = (int) floor(((double) width * zoomx) + 0.5);
1320  *dstheight = (int) floor(((double) height * zoomy) + 0.5);
1321  if (*dstwidth < 1) {
1322  *dstwidth = 1;
1323  }
1324  if (*dstheight < 1) {
1325  *dstheight = 1;
1326  }
1327 }
1328 
1345 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
1346 {
1347  SDL_Surface *rz_src;
1348  SDL_Surface *rz_dst;
1349  int dstwidth, dstheight;
1350  int is32bit;
1351  int i, src_converted;
1352  int flipx, flipy;
1353 
1354  /*
1355  * Sanity check
1356  */
1357  if (src == NULL)
1358  return (NULL);
1359 
1360  /*
1361  * Determine if source surface is 32bit or 8bit
1362  */
1363  is32bit = (src->format->BitsPerPixel == 32);
1364  if ((is32bit) || (src->format->BitsPerPixel == 8)) {
1365  /*
1366  * Use source surface 'as is'
1367  */
1368  rz_src = src;
1369  src_converted = 0;
1370  } else {
1371  /*
1372  * New source surface is 32bit with a defined RGBA ordering
1373  */
1374  rz_src =
1375  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1376 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1377  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1378 #else
1379  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1380 #endif
1381  );
1382  if (rz_src == NULL) {
1383  return NULL;
1384  }
1385  SDL_BlitSurface(src, NULL, rz_src, NULL);
1386  src_converted = 1;
1387  is32bit = 1;
1388  }
1389 
1390  flipx = (zoomx<0.0);
1391  if (flipx) zoomx = -zoomx;
1392  flipy = (zoomy<0.0);
1393  if (flipy) zoomy = -zoomy;
1394 
1395  /* Get size if target */
1396  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
1397 
1398  /*
1399  * Alloc space to completely contain the zoomed surface
1400  */
1401  rz_dst = NULL;
1402  if (is32bit) {
1403  /*
1404  * Target surface is 32bit with source RGBA/ABGR ordering
1405  */
1406  rz_dst =
1407  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1408  rz_src->format->Rmask, rz_src->format->Gmask,
1409  rz_src->format->Bmask, rz_src->format->Amask);
1410  } else {
1411  /*
1412  * Target surface is 8bit
1413  */
1414  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1415  }
1416 
1417  /* Check target */
1418  if (rz_dst == NULL) {
1419  /*
1420  * Cleanup temp surface
1421  */
1422  if (src_converted) {
1423  SDL_FreeSurface(rz_src);
1424  }
1425  return NULL;
1426  }
1427 
1428  /* Adjust for guard rows */
1429  rz_dst->h = dstheight;
1430 
1431  /*
1432  * Lock source surface
1433  */
1434  if (SDL_MUSTLOCK(rz_src)) {
1435  SDL_LockSurface(rz_src);
1436  }
1437 
1438  /*
1439  * Check which kind of surface we have
1440  */
1441  if (is32bit) {
1442  /*
1443  * Call the 32bit transformation routine to do the zooming (using alpha)
1444  */
1445  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1446  } else {
1447  /*
1448  * Copy palette and colorkey info
1449  */
1450  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1451  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1452  }
1453  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1454  /*
1455  * Call the 8bit transformation routine to do the zooming
1456  */
1457  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1458  }
1459  /*
1460  * Unlock source surface
1461  */
1462  if (SDL_MUSTLOCK(rz_src)) {
1463  SDL_UnlockSurface(rz_src);
1464  }
1465 
1466  /*
1467  * Cleanup temp surface
1468  */
1469  if (src_converted) {
1470  SDL_FreeSurface(rz_src);
1471  }
1472 
1473  /*
1474  * Return destination surface
1475  */
1476  return (rz_dst);
1477 }
1478 
1495 /*@null@*/
1496 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
1497 {
1498  int result;
1499  SDL_Surface *rz_src;
1500  SDL_Surface *rz_dst = NULL;
1501  int dstwidth, dstheight;
1502  int is32bit;
1503  int i, src_converted;
1504  int haveError = 0;
1505 
1506  /*
1507  * Sanity check
1508  */
1509  if (src == NULL) {
1510  return (NULL);
1511  }
1512 
1513  /*
1514  * Determine if source surface is 32bit or 8bit
1515  */
1516  is32bit = (src->format->BitsPerPixel == 32);
1517  if ((is32bit) || (src->format->BitsPerPixel == 8)) {
1518  /*
1519  * Use source surface 'as is'
1520  */
1521  rz_src = src;
1522  src_converted = 0;
1523  } else {
1524  /*
1525  * New source surface is 32bit with a defined RGBA ordering
1526  */
1527  rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1528 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1529  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1530 #else
1531  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1532 #endif
1533  );
1534  if (rz_src==NULL) {
1535  haveError = 1;
1536  goto exitShrinkSurface;
1537  }
1538 
1539  SDL_BlitSurface(src, NULL, rz_src, NULL);
1540  src_converted = 1;
1541  is32bit = 1;
1542  }
1543 
1544  /*
1545  * Lock the surface
1546  */
1547  if (SDL_MUSTLOCK(rz_src)) {
1548  if (SDL_LockSurface(rz_src) < 0) {
1549  haveError = 1;
1550  goto exitShrinkSurface;
1551  }
1552  }
1553 
1554  /* Get size for target */
1555  dstwidth=rz_src->w/factorx;
1556  while (dstwidth*factorx>rz_src->w) { dstwidth--; }
1557  dstheight=rz_src->h/factory;
1558  while (dstheight*factory>rz_src->h) { dstheight--; }
1559 
1560  /*
1561  * Alloc space to completely contain the shrunken surface
1562  * (with added guard rows)
1563  */
1564  if (is32bit==1) {
1565  /*
1566  * Target surface is 32bit with source RGBA/ABGR ordering
1567  */
1568  rz_dst =
1569  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1570  rz_src->format->Rmask, rz_src->format->Gmask,
1571  rz_src->format->Bmask, rz_src->format->Amask);
1572  } else {
1573  /*
1574  * Target surface is 8bit
1575  */
1576  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1577  }
1578 
1579  /* Check target */
1580  if (rz_dst == NULL) {
1581  haveError = 1;
1582  goto exitShrinkSurface;
1583  }
1584 
1585  /* Adjust for guard rows */
1586  rz_dst->h = dstheight;
1587 
1588  /*
1589  * Check which kind of surface we have
1590  */
1591  if (is32bit==1) {
1592  /*
1593  * Call the 32bit transformation routine to do the shrinking (using alpha)
1594  */
1595  result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
1596  if ((result!=0) || (rz_dst==NULL)) {
1597  haveError = 1;
1598  goto exitShrinkSurface;
1599  }
1600  } else {
1601  /*
1602  * Copy palette and colorkey info
1603  */
1604  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1605  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1606  }
1607  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1608  /*
1609  * Call the 8bit transformation routine to do the shrinking
1610  */
1611  result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
1612  if (result!=0) {
1613  haveError = 1;
1614  goto exitShrinkSurface;
1615  }
1616  }
1617 
1618 exitShrinkSurface:
1619  if (rz_src!=NULL) {
1620  /*
1621  * Unlock source surface
1622  */
1623  if (SDL_MUSTLOCK(rz_src)) {
1624  SDL_UnlockSurface(rz_src);
1625  }
1626 
1627  /*
1628  * Cleanup temp surface
1629  */
1630  if (src_converted==1) {
1631  SDL_FreeSurface(rz_src);
1632  }
1633  }
1634 
1635  /* Check error state; maybe need to cleanup destination */
1636  if (haveError==1) {
1637  if (rz_dst!=NULL) {
1638  SDL_FreeSurface(rz_dst);
1639  }
1640  rz_dst=NULL;
1641  }
1642 
1643  /*
1644  * Return destination surface
1645  */
1646  return (rz_dst);
1647 }
void transformSurfaceY(SDL_Surface *src, SDL_Surface *dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing.
SDL_Surface * rotozoomSurface(SDL_Surface *src, double angle, double zoom, int smooth)
Rotates and zooms a surface and optional anti-aliasing.
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.
int _zoomSurfaceY(SDL_Surface *src, SDL_Surface *dst, int flipx, int flipy)
Internal 8 bit Zoomer without smoothing.
struct tColorY tColorY
A 8bit Y/palette pixel.
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.
Uint8 y
Definition: SDL2_rotozoom.c:55
struct tColorRGBA tColorRGBA
A 32 bit RGBA pixel.
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-...
Uint32 _colorkey(SDL_Surface *src)
Returns colorkey info for a surface.
Definition: SDL2_rotozoom.c:83
int _shrinkSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 32 bit integer-factor averaging Shrinker.
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 * zoomSurface(SDL_Surface *src, double zoomx, double zoomy, int smooth)
Zoom a surface by independent horizontal and vertical factors with optional smoothing.
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.
#define GUARD_ROWS
Number of guard rows added to destination surfaces.
Definition: SDL2_rotozoom.c:73
#define MAX(a, b)
Returns maximum of two numbers a and b.
Definition: SDL2_rotozoom.c:61
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 _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.
#define VALUE_LIMIT
Lower limit of absolute zoom factor or rotation degrees.
Definition: SDL2_rotozoom.c:78
int _shrinkSurfaceY(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 8 bit integer-factor averaging shrinker.
A 32 bit RGBA pixel.
Definition: SDL2_rotozoom.c:44
#define M_PI
SDL_Surface * shrinkSurface(SDL_Surface *src, int factorx, int factory)
Shrink a surface by an integer ratio using averaging.
A 8bit Y/palette pixel.
Definition: SDL2_rotozoom.c:54
SDL_Surface * rotateSurface90Degrees(SDL_Surface *src, int numClockwiseTurns)
Rotates a 8/16/24/32 bit surface in increments of 90 degrees.