ManaPlus
Data Structures | Macros | Typedefs | Functions
SDL2_rotozoom.cpp File Reference

(986a3bf)

#include <stdlib.h>
#include <string.h>
#include "sdl2gfx/SDL2_rotozoom.h"
#include "debug.h"

Go to the source code of this file.

Data Structures

struct  tColorRGBA
 A 32 bit RGBA pixel. More...
 
struct  tColorY
 A 8bit Y/palette pixel. More...
 

Macros

#define MAX(a, b)   (((a) > (b)) ? (a) : (b))
 Returns maximum of two numbers a and b. More...
 
#define GUARD_ROWS   (2)
 Number of guard rows added to destination surfaces. More...
 
#define VALUE_LIMIT   0.001
 Lower limit of absolute zoom factor or rotation degrees. More...
 

Typedefs

typedef struct tColorRGBA tColorRGBA
 A 32 bit RGBA pixel. More...
 
typedef struct tColorY tColorY
 A 8bit Y/palette pixel. More...
 

Functions

static Uint32 _colorkey (SDL_Surface *src)
 Returns colorkey info for a surface. More...
 
static int _shrinkSurfaceRGBA (SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
 Internal 32 bit integer-factor averaging Shrinker. More...
 
static int _shrinkSurfaceY (SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
 Internal 8 bit integer-factor averaging shrinker. More...
 
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. More...
 
static int _zoomSurfaceY (SDL_Surface *src, SDL_Surface *dst, int flipx, int flipy)
 Internal 8 bit Zoomer without smoothing. More...
 
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. More...
 
static 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. More...
 
SDL_Surface * rotateSurface90Degrees (SDL_Surface *src, int numClockwiseTurns)
 Rotates a 8/16/24/32 bit surface in increments of 90 degrees. More...
 
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. More...
 
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. More...
 
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. More...
 
SDL_Surface * rotozoomSurface (SDL_Surface *src, double angle, double zoom, int smooth)
 Rotates and zooms a surface and optional anti-aliasing. More...
 
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-aliasing. More...
 
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. More...
 
SDL_Surface * zoomSurface (SDL_Surface *src, double zoomx, double zoomy, int smooth)
 Zoom a surface by independent horizontal and vertical factors with optional smoothing. More...
 
SDL_Surface * shrinkSurface (SDL_Surface *src, int factorx, int factory)
 Shrink a surface by an integer ratio using averaging. More...
 

Macro Definition Documentation

◆ GUARD_ROWS

#define GUARD_ROWS   (2)

Number of guard rows added to destination surfaces.

This is a simple but effective workaround for observed issues. These rows allocate extra memory and are then hidden from the surface. Rows are added to the end of destination surfaces when they are allocated. This catches any potential overflows which seem to happen with just the right src image dimensions and scale/rotation and can lead to a situation where the program can segfault.

Definition at line 79 of file SDL2_rotozoom.cpp.

◆ MAX

#define MAX (   a,
 
)    (((a) > (b)) ? (a) : (b))

Returns maximum of two numbers a and b.

Definition at line 67 of file SDL2_rotozoom.cpp.

◆ VALUE_LIMIT

#define VALUE_LIMIT   0.001

Lower limit of absolute zoom factor or rotation degrees.

Definition at line 84 of file SDL2_rotozoom.cpp.

Typedef Documentation

◆ tColorRGBA

typedef struct tColorRGBA tColorRGBA

A 32 bit RGBA pixel.

◆ tColorY

typedef struct tColorY tColorY

A 8bit Y/palette pixel.

Function Documentation

◆ _colorkey()

static Uint32 _colorkey ( SDL_Surface *  src)
static

Returns colorkey info for a surface.

Definition at line 89 of file SDL2_rotozoom.cpp.

90 {
91  Uint32 key = 0;
92  SDL_GetColorKey(src, &key);
93  return key;
94 }

Referenced by transformSurfaceY().

◆ _rotozoomSurfaceSizeTrig()

static void _rotozoomSurfaceSizeTrig ( int  width,
int  height,
double  angle,
double  zoomx,
double  zoomy,
int *  dstwidth,
int *  dstheight,
double *  canglezoom,
double *  sanglezoom 
)
static

Internal target surface sizing function for rotozooms with trig result return.

Parameters
widthThe source surface width.
heightThe source surface height.
angleThe angle to rotate in degrees.
zoomxThe horizontal scaling factor.
zoomyThe vertical scaling factor.
dstwidthThe calculated width of the destination surface.
dstheightThe calculated height of the destination surface.
canglezoomThe sine of the angle adjusted by the zoom factor.
sanglezoomThe cosine of the angle adjusted by the zoom factor.

Definition at line 1099 of file SDL2_rotozoom.cpp.

1108 {
1109  double x, y, cx, cy, sx, sy;
1110  double radangle;
1111  int dstwidthhalf, dstheighthalf;
1112 
1113  /*
1114  * Determine destination width and height by rotating a centered source box
1115  */
1116  radangle = angle * (M_PI / 180.0);
1117  *sanglezoom = sin(radangle);
1118  *canglezoom = cos(radangle);
1119  *sanglezoom *= zoomx;
1120  *canglezoom *= zoomy;
1121  x = static_cast<double>(width / 2);
1122  y = static_cast<double>(height / 2);
1123  cx = *canglezoom * x;
1124  cy = *canglezoom * y;
1125  sx = *sanglezoom * x;
1126  sy = *sanglezoom * y;
1127 
1128  dstwidthhalf = MAX(static_cast<int>(
1129  ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)),
1130  fabs(-cx + sy)), fabs(-cx - sy)))), 1);
1131  dstheighthalf = MAX(static_cast<int>(
1132  ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)),
1133  fabs(-sx + cy)), fabs(-sx - cy)))), 1);
1134  *dstwidth = 2 * dstwidthhalf;
1135  *dstheight = 2 * dstheighthalf;
1136 }
#define MAX(a, b)
Returns maximum of two numbers a and b.

References MAX, x, and y.

Referenced by rotozoomSurfaceSize(), rotozoomSurfaceSizeXY(), and rotozoomSurfaceXY().

◆ _shrinkSurfaceRGBA()

static int _shrinkSurfaceRGBA ( SDL_Surface *  src,
SDL_Surface *  dst,
int  factorx,
int  factory 
)
static

Internal 32 bit integer-factor averaging Shrinker.

Shrinks 32 bit RGBA/ABGR 'src' surface to 'dst' surface. Averages color and alpha values values of src pixels to calculate dst pixels. Assumes src and dst surfaces are of 32 bit depth. Assumes dst surface was allocated with the correct dimensions.

Parameters
srcThe surface to shrink (input).
dstThe shrunken surface (output).
factorxThe horizontal shrinking ratio.
factoryThe vertical shrinking ratio.
Returns
0 for success or -1 for error.

Definition at line 112 of file SDL2_rotozoom.cpp.

116 {
117  int x, y, dx, dy, dgap, ra, ga, ba, aa;
118  int n_average;
119  tColorRGBA *sp, *osp, *oosp;
120  tColorRGBA *dp;
121 
122  /*
123  * Averaging integer shrink
124  */
125 
126  /* Precalculate division factor */
127  n_average = factorx*factory;
128 
129  /*
130  * Scan destination
131  */
132  sp = static_cast<tColorRGBA *>(src->pixels);
133 
134  dp = static_cast<tColorRGBA *>(dst->pixels);
135  dgap = dst->pitch - dst->w * 4;
136 
137  for (y = 0; y < dst->h; y++)
138  {
139  osp=sp;
140  for (x = 0; x < dst->w; x++)
141  {
142  /* Trace out source box and accumulate */
143  oosp=sp;
144  ra=ga=ba=aa=0;
145  for (dy=0; dy < factory; dy++)
146  {
147  for (dx=0; dx < factorx; dx++)
148  {
149  ra += sp->r;
150  ga += sp->g;
151  ba += sp->b;
152  aa += sp->a;
153 
154  sp++;
155  }
156  /* src dx loop */
157  sp = reinterpret_cast<tColorRGBA *>(
158  reinterpret_cast<Uint8*>(sp) +
159  (src->pitch - 4*factorx)); // next y
160  }
161  /* src dy loop */
162 
163  /* next box-x */
164  sp = reinterpret_cast<tColorRGBA *>(
165  reinterpret_cast<Uint8*>(oosp) + 4*factorx);
166 
167  /* Store result in destination */
168  dp->r = ra/n_average;
169  dp->g = ga/n_average;
170  dp->b = ba/n_average;
171  dp->a = aa/n_average;
172 
173  /*
174  * Advance destination pointer
175  */
176  dp++;
177  }
178  /* dst x loop */
179 
180  /* next box-y */
181  sp = reinterpret_cast<tColorRGBA *>(reinterpret_cast<Uint8*>(osp) +
182  src->pitch*factory);
183 
184  /*
185  * Advance destination pointers
186  */
187  dp = reinterpret_cast<tColorRGBA *>(reinterpret_cast<Uint8*>(dp) +
188  dgap);
189  }
190  /* dst y loop */
191 
192  return (0);
193 }
A 32 bit RGBA pixel.

References tColorRGBA::a, tColorRGBA::b, tColorRGBA::g, tColorRGBA::r, x, and y.

Referenced by shrinkSurface().

◆ _shrinkSurfaceY()

static int _shrinkSurfaceY ( SDL_Surface *  src,
SDL_Surface *  dst,
int  factorx,
int  factory 
)
static

Internal 8 bit integer-factor averaging shrinker.

Shrinks 8bit Y 'src' surface to 'dst' surface. Averages color (brightness) values values of src pixels to calculate dst pixels. Assumes src and dst surfaces are of 8 bit depth. Assumes dst surface was allocated with the correct dimensions.

Parameters
srcThe surface to shrink (input).
dstThe shrunken surface (output).
factorxThe horizontal shrinking ratio.
factoryThe vertical shrinking ratio.
Returns
0 for success or -1 for error.

Definition at line 210 of file SDL2_rotozoom.cpp.

214 {
215  int x, y, dx, dy, dgap, a;
216  int n_average;
217  Uint8 *sp, *osp, *oosp;
218  Uint8 *dp;
219 
220  /*
221  * Averaging integer shrink
222  */
223 
224  /* Precalculate division factor */
225  n_average = factorx*factory;
226 
227  /*
228  * Scan destination
229  */
230  sp = static_cast<Uint8*>(src->pixels);
231 
232  dp = static_cast<Uint8*>(dst->pixels);
233  dgap = dst->pitch - dst->w;
234 
235  for (y = 0; y < dst->h; y++)
236  {
237  osp=sp;
238  for (x = 0; x < dst->w; x++)
239  {
240  /* Trace out source box and accumulate */
241  oosp=sp;
242  a=0;
243  for (dy=0; dy < factory; dy++)
244  {
245  for (dx=0; dx < factorx; dx++)
246  {
247  a += (*sp);
248  /* next x */
249  sp++;
250  }
251  /* end src dx loop */
252  /* next y */
253  sp = static_cast<Uint8*>(static_cast<Uint8*>(sp) +
254  (src->pitch - factorx));
255  }
256  /* end src dy loop */
257 
258  /* next box-x */
259  sp = static_cast<Uint8*>(static_cast<Uint8*>(oosp) + factorx);
260 
261  /* Store result in destination */
262  *dp = a/n_average;
263 
264  /*
265  * Advance destination pointer
266  */
267  dp++;
268  }
269  /* end dst x loop */
270 
271  /* next box-y */
272  sp = static_cast<Uint8*>(static_cast<Uint8*>(osp) +
273  src->pitch*factory);
274 
275  /*
276  * Advance destination pointers
277  */
278  dp = static_cast<Uint8*>(static_cast<Uint8*>(dp) + dgap);
279  }
280  /* end dst y loop */
281 
282  return (0);
283 }

References x, and y.

Referenced by shrinkSurface().

◆ _transformSurfaceRGBA()

static void _transformSurfaceRGBA ( SDL_Surface *  src,
SDL_Surface *  dst,
int  cx,
int  cy,
int  isin,
int  icos,
int  flipx,
int  flipy,
int  smooth 
)
static

Internal 32 bit rotozoomer with optional anti-aliasing.

Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control parameters by scanning the destination surface and applying optionally anti-aliasing by bilinear interpolation. Assumes src and dst surfaces are of 32 bit depth. Assumes dst surface was allocated with the correct dimensions.

Parameters
srcSource surface.
dstDestination surface.
cxHorizontal center coordinate.
cyVertical center coordinate.
isinInteger version of sine of angle.
icosInteger version of cosine of angle.
flipxFlag indicating horizontal mirroring should be applied.
flipyFlag indicating vertical mirroring should be applied.
smoothFlag indicating anti-aliasing should be used.

Definition at line 706 of file SDL2_rotozoom.cpp.

715 {
716  int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
717  tColorRGBA c00, c01, c10, c11, cswap;
718  tColorRGBA *pc, *sp;
719  int gap;
720 
721  /*
722  * Variable setup
723  */
724  xd = ((src->w - dst->w) << 15);
725  yd = ((src->h - dst->h) << 15);
726  ax = (cx << 16) - (icos * cx);
727  ay = (cy << 16) - (isin * cx);
728  sw = src->w - 1;
729  sh = src->h - 1;
730  pc = static_cast<tColorRGBA*>(dst->pixels);
731  gap = dst->pitch - dst->w * 4;
732 
733  /*
734  * Switch between interpolating and non-interpolating code
735  */
736  if (smooth)
737  {
738  for (y = 0; y < dst->h; y++)
739  {
740  dy = cy - y;
741  sdx = (ax + (isin * dy)) + xd;
742  sdy = (ay - (icos * dy)) + yd;
743  for (x = 0; x < dst->w; x++)
744  {
745  dx = (sdx >> 16);
746  dy = (sdy >> 16);
747  if (flipx) dx = sw - dx;
748  if (flipy) dy = sh - dy;
749  if ((dx > -1) && (dy > -1) &&
750  (dx < (src->w-1)) && (dy < (src->h-1)))
751  {
752  sp = static_cast<tColorRGBA *>(src->pixels);
753  sp += ((src->pitch/4) * dy);
754  sp += dx;
755  c00 = *sp;
756  sp += 1;
757  c01 = *sp;
758  sp += (src->pitch/4);
759  c11 = *sp;
760  sp -= 1;
761  c10 = *sp;
762  if (flipx)
763  {
764  cswap = c00; c00=c01; c01=cswap;
765  cswap = c10; c10=c11; c11=cswap;
766  }
767  if (flipy)
768  {
769  cswap = c00; c00=c10; c10=cswap;
770  cswap = c01; c01=c11; c11=cswap;
771  }
772  /*
773  * Interpolate colors
774  */
775  ex = (sdx & 0xffff);
776  ey = (sdy & 0xffff);
777  t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
778  t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
779  pc->r = (((t2 - t1) * ey) >> 16) + t1;
780  t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
781  t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
782  pc->g = (((t2 - t1) * ey) >> 16) + t1;
783  t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
784  t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
785  pc->b = (((t2 - t1) * ey) >> 16) + t1;
786  t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
787  t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
788  pc->a = (((t2 - t1) * ey) >> 16) + t1;
789  }
790  sdx += icos;
791  sdy += isin;
792  pc++;
793  }
794  pc = reinterpret_cast<tColorRGBA *>(
795  reinterpret_cast<Uint8*>(pc) + gap);
796  }
797  }
798  else
799  {
800  for (y = 0; y < dst->h; y++)
801  {
802  dy = cy - y;
803  sdx = (ax + (isin * dy)) + xd;
804  sdy = (ay - (icos * dy)) + yd;
805  for (x = 0; x < dst->w; x++)
806  {
807  dx = static_cast<short>(sdx >> 16);
808  dy = static_cast<short>(sdy >> 16);
809  if (flipx) dx = (src->w-1)-dx;
810  if (flipy) dy = (src->h-1)-dy;
811  if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h))
812  {
813  sp = reinterpret_cast<tColorRGBA *>(
814  reinterpret_cast<Uint8*>(src->pixels) +
815  src->pitch * dy);
816  sp += dx;
817  *pc = *sp;
818  }
819  sdx += icos;
820  sdy += isin;
821  pc++;
822  }
823  pc = reinterpret_cast<tColorRGBA *>(
824  reinterpret_cast<Uint8*>(pc) + gap);
825  }
826  }
827 }

References tColorRGBA::a, tColorRGBA::b, tColorRGBA::g, tColorRGBA::r, x, and y.

Referenced by rotozoomSurfaceXY().

◆ _zoomSurfaceRGBA()

static int _zoomSurfaceRGBA ( SDL_Surface *  src,
SDL_Surface *  dst,
int  flipx,
int  flipy,
int  smooth 
)
static

Internal 32 bit Zoomer with optional anti-aliasing by bilinear interpolation.

Zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface. Assumes src and dst surfaces are of 32 bit depth. Assumes dst surface was allocated with the correct dimensions.

Parameters
srcThe surface to zoom (input).
dstThe zoomed surface (output).
flipxFlag indicating if the image should be horizontally flipped.
flipyFlag indicating if the image should be vertically flipped.
smoothAntialiasing flag; set to SMOOTHING_ON to enable.
Returns
0 for success or -1 for error.

Definition at line 300 of file SDL2_rotozoom.cpp.

305 {
306  int x, y, sx, sy, ssx, ssy;
307  int *sax, *say, *csax, *csay, *salast;
308  int csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy;
309  tColorRGBA *c00, *c01, *c10, *c11;
310  tColorRGBA *sp, *csp, *dp;
311  int spixelgap, spixelw, spixelh, dgap, t1, t2;
312 
313  /*
314  * Allocate memory for row/column increments
315  */
316  if ((sax = static_cast<int *>(malloc((dst->w + 1) * sizeof(Uint32)))) == nullptr)
317  {
318  return (-1);
319  }
320  if ((say = static_cast<int *>(malloc((dst->h + 1) * sizeof(Uint32)))) == nullptr)
321  {
322  free(sax);
323  return (-1);
324  }
325 
326  /*
327  * Precalculate row increments
328  */
329  spixelw = (src->w - 1);
330  spixelh = (src->h - 1);
331  if (smooth)
332  {
333  sx = static_cast<int>(65536.0 * static_cast<float>(spixelw) /
334  static_cast<float>(dst->w - 1));
335  sy = static_cast<int>(65536.0 * static_cast<float>(spixelh) /
336  static_cast<float>(dst->h - 1));
337  }
338  else
339  {
340  sx = static_cast<int>(65536.0 * static_cast<float>(src->w) /
341  static_cast<float>(dst->w));
342  sy = static_cast<int>(65536.0 * static_cast<float>(src->h) /
343  static_cast<float>(dst->h));
344  }
345 
346  /* Maximum scaled source size */
347  ssx = (src->w << 16) - 1;
348  ssy = (src->h << 16) - 1;
349 
350  /* Precalculate horizontal row increments */
351  csx = 0;
352  csax = sax;
353  for (x = 0; x <= dst->w; x++)
354  {
355  *csax = csx;
356  csax++;
357  csx += sx;
358 
359  /* Guard from overflows */
360  if (csx > ssx)
361  {
362  csx = ssx;
363  }
364  }
365 
366  /* Precalculate vertical row increments */
367  csy = 0;
368  csay = say;
369  for (y = 0; y <= dst->h; y++)
370  {
371  *csay = csy;
372  csay++;
373  csy += sy;
374 
375  /* Guard from overflows */
376  if (csy > ssy)
377  {
378  csy = ssy;
379  }
380  }
381 
382  sp = static_cast<tColorRGBA *>(src->pixels);
383  dp = static_cast<tColorRGBA *>(dst->pixels);
384  dgap = dst->pitch - dst->w * 4;
385  spixelgap = src->pitch/4;
386 
387  if (flipx) sp += spixelw;
388  if (flipy) sp += (spixelgap * spixelh);
389 
390  /*
391  * Switch between interpolating and non-interpolating code
392  */
393  if (smooth)
394  {
395  /*
396  * Interpolating Zoom
397  */
398  csay = say;
399  for (y = 0; y < dst->h; y++)
400  {
401  csp = sp;
402  csax = sax;
403  for (x = 0; x < dst->w; x++)
404  {
405  /*
406  * Setup color source pointers
407  */
408  ex = (*csax & 0xffff);
409  ey = (*csay & 0xffff);
410  cx = (*csax >> 16);
411  cy = (*csay >> 16);
412  sstepx = cx < spixelw;
413  sstepy = cy < spixelh;
414  c00 = sp;
415  c01 = sp;
416  c10 = sp;
417  if (sstepy)
418  {
419  if (flipy)
420  {
421  c10 -= spixelgap;
422  }
423  else
424  {
425  c10 += spixelgap;
426  }
427  }
428  c11 = c10;
429  if (sstepx)
430  {
431  if (flipx)
432  {
433  c01--;
434  c11--;
435  }
436  else
437  {
438  c01++;
439  c11++;
440  }
441  }
442 
443  /*
444  * Draw and interpolate colors
445  */
446  t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
447  t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
448  dp->r = (((t2 - t1) * ey) >> 16) + t1;
449  t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
450  t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
451  dp->g = (((t2 - t1) * ey) >> 16) + t1;
452  t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
453  t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
454  dp->b = (((t2 - t1) * ey) >> 16) + t1;
455  t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
456  t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
457  dp->a = (((t2 - t1) * ey) >> 16) + t1;
458  /*
459  * Advance source pointer x
460  */
461  salast = csax;
462  csax++;
463  sstep = (*csax >> 16) - (*salast >> 16);
464  if (flipx)
465  {
466  sp -= sstep;
467  }
468  else
469  {
470  sp += sstep;
471  }
472 
473  /*
474  * Advance destination pointer x
475  */
476  dp++;
477  }
478  /*
479  * Advance source pointer y
480  */
481  salast = csay;
482  csay++;
483  sstep = (*csay >> 16) - (*salast >> 16);
484  sstep *= spixelgap;
485  if (flipy)
486  {
487  sp = csp - sstep;
488  }
489  else
490  {
491  sp = csp + sstep;
492  }
493 
494  /*
495  * Advance destination pointer y
496  */
497  dp = reinterpret_cast<tColorRGBA *>(
498  reinterpret_cast<Uint8*>(dp) + dgap);
499  }
500  }
501  else
502  {
503  /*
504  * Non-Interpolating Zoom
505  */
506  csay = say;
507  for (y = 0; y < dst->h; y++)
508  {
509  csp = sp;
510  csax = sax;
511  for (x = 0; x < dst->w; x++)
512  {
513  /*
514  * Draw
515  */
516  *dp = *sp;
517 
518  /*
519  * Advance source pointer x
520  */
521  salast = csax;
522  csax++;
523  sstep = (*csax >> 16) - (*salast >> 16);
524  if (flipx) sstep = -sstep;
525  sp += sstep;
526 
527  /*
528  * Advance destination pointer x
529  */
530  dp++;
531  }
532  /*
533  * Advance source pointer y
534  */
535  salast = csay;
536  csay++;
537  sstep = (*csay >> 16) - (*salast >> 16);
538  sstep *= spixelgap;
539  if (flipy) sstep = -sstep;
540  sp = csp + sstep;
541 
542  /*
543  * Advance destination pointer y
544  */
545  dp = reinterpret_cast<tColorRGBA *>(
546  reinterpret_cast<Uint8*>(dp) + dgap);
547  }
548  }
549 
550  /*
551  * Remove temp arrays
552  */
553  free(sax);
554  free(say);
555 
556  return (0);
557 }

References tColorRGBA::a, tColorRGBA::b, tColorRGBA::g, tColorRGBA::r, x, and y.

Referenced by rotozoomSurfaceXY(), and zoomSurface().

◆ _zoomSurfaceY()

static int _zoomSurfaceY ( SDL_Surface *  src,
SDL_Surface *  dst,
int  flipx,
int  flipy 
)
static

Internal 8 bit Zoomer without smoothing.

Zooms 8bit palette/Y 'src' surface to 'dst' surface. Assumes src and dst surfaces are of 8 bit depth. Assumes dst surface was allocated with the correct dimensions.

Parameters
srcThe surface to zoom (input).
dstThe zoomed surface (output).
flipxFlag indicating if the image should be horizontally flipped.
flipyFlag indicating if the image should be vertically flipped.
Returns
0 for success or -1 for error.

Definition at line 574 of file SDL2_rotozoom.cpp.

578 {
579  int x, y;
580  Uint32 *sax, *say, *csax, *csay;
581  int csx, csy;
582  Uint8 *sp, *dp, *csp;
583  int dgap;
584 
585  /*
586  * Allocate memory for row increments
587  */
588  if ((sax = static_cast<Uint32 *>(malloc((dst->w + 1) *
589  sizeof(Uint32)))) == nullptr)
590  {
591  return (-1);
592  }
593  if ((say = static_cast<Uint32 *>(malloc((dst->h + 1) *
594  sizeof(Uint32)))) == nullptr)
595  {
596  free(sax);
597  return (-1);
598  }
599 
600  /*
601  * Pointer setup
602  */
603  sp = csp = static_cast<Uint8*>(src->pixels);
604  dp = static_cast<Uint8*>(dst->pixels);
605  dgap = dst->pitch - dst->w;
606 
607  if (flipx) csp += (src->w-1);
608  if (flipy) csp = (static_cast<Uint8*>(csp) + src->pitch*(src->h-1));
609 
610  /*
611  * Precalculate row increments
612  */
613  csx = 0;
614  csax = sax;
615  for (x = 0; x < dst->w; x++)
616  {
617  csx += src->w;
618  *csax = 0;
619  while (csx >= dst->w)
620  {
621  csx -= dst->w;
622  (*csax)++;
623  }
624  (*csax) = (*csax) * (flipx ? -1 : 1);
625  csax++;
626  }
627  csy = 0;
628  csay = say;
629  for (y = 0; y < dst->h; y++)
630  {
631  csy += src->h;
632  *csay = 0;
633  while (csy >= dst->h)
634  {
635  csy -= dst->h;
636  (*csay)++;
637  }
638  (*csay) = (*csay) * (flipy ? -1 : 1);
639  csay++;
640  }
641 
642  /*
643  * Draw
644  */
645  csay = say;
646  for (y = 0; y < dst->h; y++)
647  {
648  csax = sax;
649  sp = csp;
650  for (x = 0; x < dst->w; x++)
651  {
652  /*
653  * Draw
654  */
655  *dp = *sp;
656  /*
657  * Advance source pointers
658  */
659  sp += (*csax);
660  csax++;
661  /*
662  * Advance destination pointer
663  */
664  dp++;
665  }
666  /*
667  * Advance source pointer (for row)
668  */
669  csp += ((*csay) * src->pitch);
670  csay++;
671 
672  /*
673  * Advance destination pointers
674  */
675  dp += dgap;
676  }
677 
678  /*
679  * Remove temp arrays
680  */
681  free(sax);
682  free(say);
683 
684  return (0);
685 }

References x, and y.

Referenced by rotozoomSurfaceXY(), and zoomSurface().

◆ rotateSurface90Degrees()

SDL_Surface* rotateSurface90Degrees ( SDL_Surface *  src,
int  numClockwiseTurns 
)

Rotates a 8/16/24/32 bit surface in increments of 90 degrees.

Specialized 90 degree rotator which rotates a 'src' surface in 90 degree increments clockwise returning a new surface. Faster than rotozoomer since no scanning or interpolation takes place. Input surface must be 8/16/24/32 bit. (code contributed by J. Schiller, improved by C. Allport and A. Schiffler)

Parameters
srcSource surface to rotate.
numClockwiseTurnsNumber of clockwise 90 degree turns to apply to the source.
Returns
The new, rotated surface; or nullptr for surfaces with incorrect input format.

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

Definition at line 914 of file SDL2_rotozoom.cpp.

916 {
917  int row, col, newWidth, newHeight;
918  int bpp, bpr;
919  SDL_Surface* dst;
920  Uint8* srcBuf;
921  Uint8* dstBuf;
922  int normalizedClockwiseTurns;
923 
924  /* Has to be a valid surface pointer and be a Nbit surface where n is divisible by 8 */
925  if (!src ||
926  !src->format)
927  {
928  SDL_SetError("NULL source surface or source surface format");
929  return nullptr;
930  }
931 
932  if ((src->format->BitsPerPixel % 8) != 0)
933  {
934  SDL_SetError("Invalid source surface bit depth");
935  return nullptr;
936  }
937 
938  /* normalize numClockwiseTurns */
939  normalizedClockwiseTurns = (numClockwiseTurns % 4);
940  if (normalizedClockwiseTurns < 0)
941  {
942  normalizedClockwiseTurns += 4;
943  }
944 
945  /* If turns are even, our new width/height will be the same as the source surface */
946  if (normalizedClockwiseTurns % 2)
947  {
948  newWidth = src->h;
949  newHeight = src->w;
950  }
951  else
952  {
953  newWidth = src->w;
954  newHeight = src->h;
955  }
956 
957  dst = SDL_CreateRGBSurface(src->flags,
958  newWidth,
959  newHeight,
960  src->format->BitsPerPixel,
961  src->format->Rmask,
962  src->format->Gmask,
963  src->format->Bmask,
964  src->format->Amask);
965  if (!dst)
966  {
967  SDL_SetError("Could not create destination surface");
968  return nullptr;
969  }
970 
971  if (SDL_MUSTLOCK(src))
972  {
973  SDL_LockSurface(src);
974  }
975  if (SDL_MUSTLOCK(dst))
976  {
977  SDL_LockSurface(dst);
978  }
979 
980  /* Calculate byte-per-pixel */
981  bpp = src->format->BitsPerPixel / 8;
982 
983  switch (normalizedClockwiseTurns)
984  {
985  case 0: /* Make a copy of the surface */
986  {
987  /* Unfortunately SDL_BlitSurface cannot be used to
988  make a copy of the surface
989  since it does not preserve alpha. */
990 
991  if (src->pitch == dst->pitch)
992  {
993  /* If the pitch is the same for both surfaces,
994  the memory can be copied all at once. */
995  memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
996  }
997  else
998  {
999  /* If the pitch differs, copy each row separately */
1000  srcBuf = static_cast<Uint8*>(src->pixels);
1001  dstBuf = static_cast<Uint8*>(dst->pixels);
1002  bpr = src->w * bpp;
1003  for (row = 0; row < src->h; row++)
1004  {
1005  memcpy(dstBuf, srcBuf, bpr);
1006  srcBuf += src->pitch;
1007  dstBuf += dst->pitch;
1008  }
1009  }
1010  }
1011  break;
1012 
1013  /* rotate clockwise */
1014  case 1: /* rotated 90 degrees clockwise */
1015  {
1016  for (row = 0; row < src->h; ++row)
1017  {
1018  srcBuf = static_cast<Uint8*>(src->pixels) +
1019  (row * src->pitch);
1020  dstBuf = static_cast<Uint8*>(dst->pixels) +
1021  (dst->w - row - 1) * bpp;
1022  for (col = 0; col < src->w; ++col)
1023  {
1024  memcpy (dstBuf, srcBuf, bpp);
1025  srcBuf += bpp;
1026  dstBuf += dst->pitch;
1027  }
1028  }
1029  }
1030  break;
1031 
1032  case 2: /* rotated 180 degrees clockwise */
1033  {
1034  for (row = 0; row < src->h; ++row)
1035  {
1036  srcBuf = static_cast<Uint8*>(src->pixels) +
1037  (row * src->pitch);
1038  dstBuf = static_cast<Uint8*>(dst->pixels) +
1039  ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp;
1040  for (col = 0; col < src->w; ++col)
1041  {
1042  memcpy (dstBuf, srcBuf, bpp);
1043  srcBuf += bpp;
1044  dstBuf -= bpp;
1045  }
1046  }
1047  }
1048  break;
1049 
1050  case 3: /* rotated 270 degrees clockwise */
1051  {
1052  for (row = 0; row < src->h; ++row)
1053  {
1054  srcBuf = static_cast<Uint8*>(src->pixels) + (row * src->pitch);
1055  dstBuf = static_cast<Uint8*>(dst->pixels) +
1056  (row * bpp) + (dst->h * dst->pitch);
1057  for (col = 0; col < src->w; ++col)
1058  {
1059  memcpy (dstBuf, srcBuf, bpp);
1060  srcBuf += bpp;
1061  dstBuf -= dst->pitch;
1062  }
1063  }
1064  }
1065  break;
1066  default:
1067  break;
1068  }
1069  /* end switch */
1070 
1071  if (SDL_MUSTLOCK(src))
1072  {
1073  SDL_UnlockSurface(src);
1074  }
1075  if (SDL_MUSTLOCK(dst))
1076  {
1077  SDL_UnlockSurface(dst);
1078  }
1079 
1080  return dst;
1081 }

◆ rotozoomSurface()

SDL_Surface* rotozoomSurface ( SDL_Surface *  src,
double  angle,
double  zoom,
int  smooth 
)

Rotates and zooms a surface and optional anti-aliasing.

Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'angle' is the rotation in degrees and 'zoom' a scaling factor. If 'smooth' is set then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.

Parameters
srcThe surface to rotozoom.
angleThe angle to rotate in degrees.
zoomThe scaling factor.
smoothAntialiasing flag; set to SMOOTHING_ON to enable.
Returns
The new rotozoomed surface.

Definition at line 1204 of file SDL2_rotozoom.cpp.

1208 {
1209  return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
1210 }
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-...

References rotozoomSurfaceXY().

◆ rotozoomSurfaceSize()

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.

Parameters
widthThe source surface width.
heightThe source surface height.
angleThe angle to rotate in degrees.
zoomThe scaling factor.
dstwidthThe calculated width of the rotozoomed destination surface.
dstheightThe calculated height of the rotozoomed destination surface.

Definition at line 1175 of file SDL2_rotozoom.cpp.

1181 {
1182  double dummy_sanglezoom, dummy_canglezoom;
1183 
1184  _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom,
1185  dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
1186 }
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.

References _rotozoomSurfaceSizeTrig().

◆ rotozoomSurfaceSizeXY()

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.

Parameters
widthThe source surface width.
heightThe source surface height.
angleThe angle to rotate in degrees.
zoomxThe horizontal scaling factor.
zoomyThe vertical scaling factor.
dstwidthThe calculated width of the rotozoomed destination surface.
dstheightThe calculated height of the rotozoomed destination surface.

Definition at line 1150 of file SDL2_rotozoom.cpp.

1157 {
1158  double dummy_sanglezoom, dummy_canglezoom;
1159 
1160  _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy,
1161  dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
1162 }

References _rotozoomSurfaceSizeTrig().

◆ rotozoomSurfaceXY()

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-aliasing.

Rotates and zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'angle' is the rotation in degrees, 'zoomx and 'zoomy' scaling factors. If 'smooth' is set then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.

Parameters
srcThe surface to rotozoom.
angleThe angle to rotate in degrees.
zoomxThe horizontal scaling factor.
zoomyThe vertical scaling factor.
smoothAntialiasing flag; set to SMOOTHING_ON to enable.
Returns
The new rotozoomed surface.

< Surface is in system memory

< Surface is in system memory

< Surface is in system memory

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

< Surface is in system memory

< Surface is in system memory

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

Definition at line 1230 of file SDL2_rotozoom.cpp.

1235 {
1236  SDL_Surface *rz_src;
1237  SDL_Surface *rz_dst;
1238  double zoominv;
1239  double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
1240  int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
1241  int is32bit;
1242  int i, src_converted;
1243  int flipx,flipy;
1244 
1245  /*
1246  * Sanity check
1247  */
1248  if (src == nullptr)
1249  {
1250  return (nullptr);
1251  }
1252 
1253  /*
1254  * Determine if source surface is 32bit or 8bit
1255  */
1256  is32bit = (src->format->BitsPerPixel == 32);
1257  if ((is32bit) || (src->format->BitsPerPixel == 8))
1258  {
1259  /*
1260  * Use source surface 'as is'
1261  */
1262  rz_src = src;
1263  src_converted = 0;
1264  }
1265  else
1266  {
1267  /*
1268  * New source surface is 32bit with a defined RGBA ordering
1269  */
1270  rz_src =
1271  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1272 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1273  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1274 #else
1275  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1276 #endif
1277  );
1278 
1279  SDL_BlitSurface(src, nullptr, rz_src, nullptr);
1280 
1281  src_converted = 1;
1282  is32bit = 1;
1283  }
1284 
1285  /*
1286  * Sanity check zoom factor
1287  */
1288  flipx = (zoomx<0.0);
1289  if (flipx) zoomx=-zoomx;
1290  flipy = (zoomy<0.0);
1291  if (flipy) zoomy=-zoomy;
1292  if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
1293  if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
1294  zoominv = 65536.0 / (zoomx * zoomx);
1295 
1296  /*
1297  * Check if we have a rotozoom or just a zoom
1298  */
1299  if (fabs(angle) > VALUE_LIMIT)
1300  {
1301 
1302  /*
1303  * Angle!=0: full rotozoom
1304  */
1305  /*
1306  * -----------------------
1307  */
1308 
1309  /* Determine target size */
1310  _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy,
1311  &dstwidth, &dstheight, &canglezoom, &sanglezoom);
1312 
1313  /*
1314  * Calculate target factors from sin/cos and zoom
1315  */
1316  sanglezoominv = sanglezoom;
1317  canglezoominv = canglezoom;
1318  sanglezoominv *= zoominv;
1319  canglezoominv *= zoominv;
1320 
1321  /* Calculate half size */
1322  dstwidthhalf = dstwidth / 2;
1323  dstheighthalf = dstheight / 2;
1324 
1325  /*
1326  * Alloc space to completely contain the rotated surface
1327  */
1328  rz_dst = nullptr;
1329  if (is32bit)
1330  {
1331  /*
1332  * Target surface is 32bit with source RGBA/ABGR ordering
1333  */
1334  rz_dst =
1335  SDL_CreateRGBSurface(SDL_SWSURFACE,
1336  dstwidth, dstheight + GUARD_ROWS, 32,
1337  rz_src->format->Rmask, rz_src->format->Gmask,
1338  rz_src->format->Bmask, rz_src->format->Amask);
1339  }
1340  else
1341  {
1342  /*
1343  * Target surface is 8bit
1344  */
1345  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth,
1346  dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1347  }
1348 
1349  /* Check target */
1350  if (rz_dst == nullptr)
1351  return nullptr;
1352 
1353  /* Adjust for guard rows */
1354  rz_dst->h = dstheight;
1355 
1356  /*
1357  * Lock source surface
1358  */
1359  if (SDL_MUSTLOCK(rz_src))
1360  {
1361  SDL_LockSurface(rz_src);
1362  }
1363 
1364  /*
1365  * Check which kind of surface we have
1366  */
1367  if (is32bit)
1368  {
1369  /*
1370  * Call the 32bit transformation routine to do the rotation
1371  * (using alpha)
1372  */
1373  _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1374  static_cast<int>(sanglezoominv),
1375  static_cast<int>(canglezoominv),
1376  flipx, flipy,
1377  smooth);
1378  }
1379  else
1380  {
1381  /*
1382  * Copy palette and colorkey info
1383  */
1384  for (i = 0; i < rz_src->format->palette->ncolors; i++)
1385  {
1386  rz_dst->format->palette->colors[i] =
1387  rz_src->format->palette->colors[i];
1388  }
1389  rz_dst->format->palette->ncolors =
1390  rz_src->format->palette->ncolors;
1391  /*
1392  * Call the 8bit transformation routine to do the rotation
1393  */
1394  transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1395  static_cast<int>(sanglezoominv),
1396  static_cast<int>(canglezoominv),
1397  flipx, flipy);
1398  }
1399  /*
1400  * Unlock source surface
1401  */
1402  if (SDL_MUSTLOCK(rz_src))
1403  {
1404  SDL_UnlockSurface(rz_src);
1405  }
1406 
1407  }
1408  else
1409  {
1410  /*
1411  * Angle=0: Just a zoom
1412  */
1413  /*
1414  * --------------------
1415  */
1416 
1417  /*
1418  * Calculate target size
1419  */
1420  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy,
1421  &dstwidth, &dstheight);
1422 
1423  /*
1424  * Alloc space to completely contain the zoomed surface
1425  */
1426  rz_dst = nullptr;
1427  if (is32bit)
1428  {
1429  /*
1430  * Target surface is 32bit with source RGBA/ABGR ordering
1431  */
1432  rz_dst =
1433  SDL_CreateRGBSurface(SDL_SWSURFACE,
1434  dstwidth, dstheight + GUARD_ROWS, 32,
1435  rz_src->format->Rmask, rz_src->format->Gmask,
1436  rz_src->format->Bmask, rz_src->format->Amask);
1437  }
1438  else
1439  {
1440  /*
1441  * Target surface is 8bit
1442  */
1443  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
1444  dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1445  }
1446 
1447  /* Check target */
1448  if (rz_dst == nullptr)
1449  return nullptr;
1450 
1451  /* Adjust for guard rows */
1452  rz_dst->h = dstheight;
1453 
1454  /*
1455  * Lock source surface
1456  */
1457  if (SDL_MUSTLOCK(rz_src))
1458  {
1459  SDL_LockSurface(rz_src);
1460  }
1461 
1462  /*
1463  * Check which kind of surface we have
1464  */
1465  if (is32bit)
1466  {
1467  /*
1468  * Call the 32bit transformation routine to do the zooming
1469  * (using alpha)
1470  */
1471  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1472 
1473  }
1474  else
1475  {
1476  /*
1477  * Copy palette and colorkey info
1478  */
1479  for (i = 0; i < rz_src->format->palette->ncolors; i++)
1480  {
1481  rz_dst->format->palette->colors[i] =
1482  rz_src->format->palette->colors[i];
1483  }
1484  rz_dst->format->palette->ncolors =
1485  rz_src->format->palette->ncolors;
1486 
1487  /*
1488  * Call the 8bit transformation routine to do the zooming
1489  */
1490  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1491  }
1492 
1493  /*
1494  * Unlock source surface
1495  */
1496  if (SDL_MUSTLOCK(rz_src))
1497  {
1498  SDL_UnlockSurface(rz_src);
1499  }
1500  }
1501 
1502  /*
1503  * Cleanup temp surface
1504  */
1505  if (src_converted)
1506  {
1507  SDL_FreeSurface(rz_src);
1508  }
1509 
1510  /*
1511  * Return destination surface
1512  */
1513  return (rz_dst);
1514 }
#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.
static int _zoomSurfaceY(SDL_Surface *src, SDL_Surface *dst, int flipx, int flipy)
Internal 8 bit Zoomer without 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 VALUE_LIMIT
Lower limit of absolute zoom factor or rotation degrees.
static 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.

References _rotozoomSurfaceSizeTrig(), _transformSurfaceRGBA(), _zoomSurfaceRGBA(), _zoomSurfaceY(), GUARD_ROWS, transformSurfaceY(), VALUE_LIMIT, and zoomSurfaceSize().

Referenced by rotozoomSurface().

◆ shrinkSurface()

SDL_Surface* shrinkSurface ( SDL_Surface *  src,
int  factorx,
int  factory 
)

Shrink a surface by an integer ratio using averaging.

Shrinks a 32bit or 8bit 'src' surface to a newly created 'dst' surface. 'factorx' and 'factory' are the shrinking ratios (i.e. 2=1/2 the size, 3=1/3 the size, etc.) The destination surface is antialiased by averaging the source box RGBA or Y information. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. The input surface is not modified. The output surface is newly allocated.

Parameters
srcThe surface to shrink.
factorxThe horizontal shrinking ratio.
factoryThe vertical shrinking ratio.
Returns
The new, shrunken surface.

< Surface is in system memory

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

< Surface is in system memory

< Surface is in system memory

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

Definition at line 1762 of file SDL2_rotozoom.cpp.

1765 {
1766  int result;
1767  SDL_Surface *rz_src;
1768  SDL_Surface *rz_dst = nullptr;
1769  int dstwidth, dstheight;
1770  int is32bit;
1771  int i, src_converted = 0;
1772  int haveError = 0;
1773 
1774  /*
1775  * Sanity check
1776  */
1777  if (src == nullptr)
1778  {
1779  return (nullptr);
1780  }
1781 
1782  /*
1783  * Determine if source surface is 32bit or 8bit
1784  */
1785  is32bit = (src->format->BitsPerPixel == 32);
1786  if ((is32bit) || (src->format->BitsPerPixel == 8))
1787  {
1788  /*
1789  * Use source surface 'as is'
1790  */
1791  rz_src = src;
1792  src_converted = 0;
1793  }
1794  else
1795  {
1796  /*
1797  * New source surface is 32bit with a defined RGBA ordering
1798  */
1799  rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1800 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1801  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1802 #else
1803  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1804 #endif
1805  );
1806  if (rz_src==nullptr)
1807  {
1808  haveError = 1;
1809  goto exitShrinkSurface;
1810  }
1811 
1812  SDL_BlitSurface(src, nullptr, rz_src, nullptr);
1813  src_converted = 1;
1814  is32bit = 1;
1815  }
1816 
1817  /*
1818  * Lock the surface
1819  */
1820  if (SDL_MUSTLOCK(rz_src))
1821  {
1822  if (SDL_LockSurface(rz_src) < 0)
1823  {
1824  haveError = 1;
1825  goto exitShrinkSurface;
1826  }
1827  }
1828 
1829  /* Get size for target */
1830  dstwidth=rz_src->w/factorx;
1831  while (dstwidth*factorx>rz_src->w)
1832  {
1833  dstwidth--;
1834  }
1835  dstheight=rz_src->h/factory;
1836  while (dstheight*factory>rz_src->h)
1837  {
1838  dstheight--;
1839  }
1840 
1841  /*
1842  * Alloc space to completely contain the shrunken surface
1843  * (with added guard rows)
1844  */
1845  if (is32bit==1)
1846  {
1847  /*
1848  * Target surface is 32bit with source RGBA/ABGR ordering
1849  */
1850  rz_dst = SDL_CreateRGBSurface(
1851  SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1852  rz_src->format->Rmask, rz_src->format->Gmask,
1853  rz_src->format->Bmask, rz_src->format->Amask);
1854  }
1855  else
1856  {
1857  /*
1858  * Target surface is 8bit
1859  */
1860  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
1861  dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1862  }
1863 
1864  /* Check target */
1865  if (rz_dst == nullptr)
1866  {
1867  haveError = 1;
1868  goto exitShrinkSurface;
1869  }
1870 
1871  /* Adjust for guard rows */
1872  rz_dst->h = dstheight;
1873 
1874  /*
1875  * Check which kind of surface we have
1876  */
1877  if (is32bit==1)
1878  {
1879  /*
1880  * Call the 32bit transformation routine to do the shrinking (using alpha)
1881  */
1882  result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
1883  if ((result!=0) || (rz_dst==nullptr))
1884  {
1885  haveError = 1;
1886  goto exitShrinkSurface;
1887  }
1888  }
1889  else
1890  {
1891  /*
1892  * Copy palette and colorkey info
1893  */
1894  for (i = 0; i < rz_src->format->palette->ncolors; i++)
1895  {
1896  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1897  }
1898  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1899  /*
1900  * Call the 8bit transformation routine to do the shrinking
1901  */
1902  result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
1903  if (result!=0)
1904  {
1905  haveError = 1;
1906  goto exitShrinkSurface;
1907  }
1908  }
1909 
1910 exitShrinkSurface:
1911  if (rz_src!=nullptr)
1912  {
1913  /*
1914  * Unlock source surface
1915  */
1916  if (SDL_MUSTLOCK(rz_src))
1917  {
1918  SDL_UnlockSurface(rz_src);
1919  }
1920 
1921  /*
1922  * Cleanup temp surface
1923  */
1924  if (src_converted==1)
1925  {
1926  SDL_FreeSurface(rz_src);
1927  }
1928  }
1929 
1930  /* Check error state; maybe need to cleanup destination */
1931  if (haveError==1)
1932  {
1933  if (rz_dst!=nullptr)
1934  {
1935  SDL_FreeSurface(rz_dst);
1936  }
1937  rz_dst=nullptr;
1938  }
1939 
1940  /*
1941  * Return destination surface
1942  */
1943  return (rz_dst);
1944 }
static int _shrinkSurfaceY(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 8 bit integer-factor averaging shrinker.
static int _shrinkSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 32 bit integer-factor averaging Shrinker.

References _shrinkSurfaceRGBA(), _shrinkSurfaceY(), and GUARD_ROWS.

◆ transformSurfaceY()

static void transformSurfaceY ( SDL_Surface *  src,
SDL_Surface *  dst,
int  cx,
int  cy,
int  isin,
int  icos,
int  flipx,
int  flipy 
)
static

Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing.

Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control parameters by scanning the destination surface. Assumes src and dst surfaces are of 8 bit depth. Assumes dst surface was allocated with the correct dimensions.

Parameters
srcSource surface.
dstDestination surface.
cxHorizontal center coordinate.
cyVertical center coordinate.
isinInteger version of sine of angle.
icosInteger version of cosine of angle.
flipxFlag indicating horizontal mirroring should be applied.
flipyFlag indicating vertical mirroring should be applied.

Definition at line 847 of file SDL2_rotozoom.cpp.

855 {
856  int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay;
857  tColorY *pc, *sp;
858  int gap;
859 
860  /*
861  * Variable setup
862  */
863  xd = ((src->w - dst->w) << 15);
864  yd = ((src->h - dst->h) << 15);
865  ax = (cx << 16) - (icos * cx);
866  ay = (cy << 16) - (isin * cx);
867  pc = static_cast<tColorY*>(dst->pixels);
868  gap = dst->pitch - dst->w;
869  /*
870  * Clear surface to colorkey
871  */
872  memset(pc, static_cast<int>(_colorkey(src) & 0xff), dst->pitch * dst->h);
873  /*
874  * Iterate through destination surface
875  */
876  for (y = 0; y < dst->h; y++)
877  {
878  dy = cy - y;
879  sdx = (ax + (isin * dy)) + xd;
880  sdy = (ay - (icos * dy)) + yd;
881  for (x = 0; x < dst->w; x++)
882  {
883  dx = static_cast<short>(sdx >> 16);
884  dy = static_cast<short>(sdy >> 16);
885  if (flipx) dx = (src->w-1)-dx;
886  if (flipy) dy = (src->h-1)-dy;
887  if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h))
888  {
889  sp = static_cast<tColorY *>(src->pixels);
890  sp += (src->pitch * dy + dx);
891  *pc = *sp;
892  }
893  sdx += icos;
894  sdy += isin;
895  pc++;
896  }
897  pc += gap;
898  }
899 }
static Uint32 _colorkey(SDL_Surface *src)
Returns colorkey info for a surface.
A 8bit Y/palette pixel.

References _colorkey(), x, and y.

Referenced by rotozoomSurfaceXY().

◆ zoomSurface()

SDL_Surface* zoomSurface ( SDL_Surface *  src,
double  zoomx,
double  zoomy,
int  smooth 
)

Zoom a surface by independent horizontal and vertical factors with optional smoothing.

Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is on then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. If zoom factors are negative, the image is flipped on the axes.

Parameters
srcThe surface to zoom.
zoomxThe horizontal zoom factor.
zoomyThe vertical zoom factor.
smoothAntialiasing flag; set to SMOOTHING_ON to enable.
Returns
The new, zoomed surface.

< Surface is in system memory

< Surface is in system memory

< Surface is in system memory

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

< Surface is in video memory

< Use asynchronous blits if possible

< Surface is RLE encoded

Definition at line 1590 of file SDL2_rotozoom.cpp.

1594 {
1595  SDL_Surface *rz_src;
1596  SDL_Surface *rz_dst;
1597  int dstwidth, dstheight;
1598  int is32bit;
1599  int i, src_converted;
1600  int flipx, flipy;
1601 
1602  /*
1603  * Sanity check
1604  */
1605  if (src == nullptr)
1606  return (nullptr);
1607 
1608  /*
1609  * Determine if source surface is 32bit or 8bit
1610  */
1611  is32bit = (src->format->BitsPerPixel == 32);
1612  if ((is32bit) || (src->format->BitsPerPixel == 8))
1613  {
1614  /*
1615  * Use source surface 'as is'
1616  */
1617  rz_src = src;
1618  src_converted = 0;
1619  }
1620  else
1621  {
1622  /*
1623  * New source surface is 32bit with a defined RGBA ordering
1624  */
1625  rz_src =
1626  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1627 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1628  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1629 #else
1630  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1631 #endif
1632  );
1633  if (rz_src == nullptr)
1634  {
1635  return nullptr;
1636  }
1637  SDL_BlitSurface(src, nullptr, rz_src, nullptr);
1638  src_converted = 1;
1639  is32bit = 1;
1640  }
1641 
1642  flipx = (zoomx<0.0);
1643  if (flipx) zoomx = -zoomx;
1644  flipy = (zoomy<0.0);
1645  if (flipy) zoomy = -zoomy;
1646 
1647  /* Get size if target */
1648  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
1649 
1650  /*
1651  * Alloc space to completely contain the zoomed surface
1652  */
1653  rz_dst = nullptr;
1654  if (is32bit)
1655  {
1656  /*
1657  * Target surface is 32bit with source RGBA/ABGR ordering
1658  */
1659  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
1660  dstwidth, dstheight + GUARD_ROWS, 32,
1661  rz_src->format->Rmask, rz_src->format->Gmask,
1662  rz_src->format->Bmask, rz_src->format->Amask);
1663  }
1664  else
1665  {
1666  /*
1667  * Target surface is 8bit
1668  */
1669  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
1670  dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1671  }
1672 
1673  /* Check target */
1674  if (rz_dst == nullptr)
1675  {
1676  /*
1677  * Cleanup temp surface
1678  */
1679  if (src_converted)
1680  {
1681  SDL_FreeSurface(rz_src);
1682  }
1683  return nullptr;
1684  }
1685 
1686  /* Adjust for guard rows */
1687  rz_dst->h = dstheight;
1688 
1689  /*
1690  * Lock source surface
1691  */
1692  if (SDL_MUSTLOCK(rz_src))
1693  {
1694  SDL_LockSurface(rz_src);
1695  }
1696 
1697  /*
1698  * Check which kind of surface we have
1699  */
1700  if (is32bit)
1701  {
1702  /*
1703  * Call the 32bit transformation routine to do the zooming (using alpha)
1704  */
1705  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1706  }
1707  else
1708  {
1709  /*
1710  * Copy palette and colorkey info
1711  */
1712  for (i = 0; i < rz_src->format->palette->ncolors; i++)
1713  {
1714  rz_dst->format->palette->colors[i] =
1715  rz_src->format->palette->colors[i];
1716  }
1717  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1718  /*
1719  * Call the 8bit transformation routine to do the zooming
1720  */
1721  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1722  }
1723  /*
1724  * Unlock source surface
1725  */
1726  if (SDL_MUSTLOCK(rz_src))
1727  {
1728  SDL_UnlockSurface(rz_src);
1729  }
1730 
1731  /*
1732  * Cleanup temp surface
1733  */
1734  if (src_converted)
1735  {
1736  SDL_FreeSurface(rz_src);
1737  }
1738 
1739  /*
1740  * Return destination surface
1741  */
1742  return (rz_dst);
1743 }

References _zoomSurfaceRGBA(), _zoomSurfaceY(), GUARD_ROWS, and zoomSurfaceSize().

◆ zoomSurfaceSize()

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.

The minimum size of the target surface is 1. The input factors can be positive or negative.

Parameters
widthThe width of the source surface to zoom.
heightThe height of the source surface to zoom.
zoomxThe horizontal zoom factor.
zoomyThe vertical zoom factor.
dstwidthPointer to an integer to store the calculated width of the zoomed target surface.
dstheightPointer to an integer to store the calculated height of the zoomed target surface.

Definition at line 1531 of file SDL2_rotozoom.cpp.

1534 {
1535  /*
1536  * Make zoom factors positive
1537  */
1538  int flipx, flipy;
1539  flipx = (zoomx<0.0);
1540  if (flipx) zoomx = -zoomx;
1541  flipy = (zoomy<0.0);
1542  if (flipy) zoomy = -zoomy;
1543 
1544  /*
1545  * Sanity check zoom factors
1546  */
1547  if (zoomx < VALUE_LIMIT)
1548  {
1549  zoomx = VALUE_LIMIT;
1550  }
1551  if (zoomy < VALUE_LIMIT)
1552  {
1553  zoomy = VALUE_LIMIT;
1554  }
1555 
1556  /*
1557  * Calculate target size
1558  */
1559  *dstwidth = static_cast<int>(floor((static_cast<double>(
1560  width) * zoomx) + 0.5));
1561  *dstheight = static_cast<int>(floor((static_cast<double>(
1562  height) * zoomy) + 0.5));
1563  if (*dstwidth < 1)
1564  {
1565  *dstwidth = 1;
1566  }
1567  if (*dstheight < 1)
1568  {
1569  *dstheight = 1;
1570  }
1571 }

References VALUE_LIMIT.

Referenced by rotozoomSurfaceXY(), and zoomSurface().