ManaPlus
Macros | Functions
SDL2_rotozoom.h File Reference

(986a3bf)

#include <math.h>
#include "localconsts.h"
#include <SDL.h>

Go to the source code of this file.

Macros

#define SMOOTHING_OFF   0
 Disable anti-aliasing (no smoothing). More...
 
#define SMOOTHING_ON   1
 Enable anti-aliasing (smoothing). More...
 
#define SDL2_ROTOZOOM_SCOPE   extern
 

Functions

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 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...
 
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...
 
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...
 
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 * shrinkSurface (SDL_Surface *src, int factorx, int factory)
 Shrink a surface by an integer ratio using averaging. More...
 
SDL_Surface * rotateSurface90Degrees (SDL_Surface *src, int numClockwiseTurns)
 Rotates a 8/16/24/32 bit surface in increments of 90 degrees. More...
 

Macro Definition Documentation

◆ SDL2_ROTOZOOM_SCOPE

#define SDL2_ROTOZOOM_SCOPE   extern

Definition at line 78 of file SDL2_rotozoom.h.

◆ SMOOTHING_OFF

#define SMOOTHING_OFF   0

Disable anti-aliasing (no smoothing).

Definition at line 59 of file SDL2_rotozoom.h.

◆ SMOOTHING_ON

#define SMOOTHING_ON   1

Enable anti-aliasing (smoothing).

Definition at line 64 of file SDL2_rotozoom.h.

Function Documentation

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

◆ 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().