SDL2_gfx  1.0.2
Graphics primitives and surface functions for SDL2
/build/libsdl2-gfx-F3NxcE/libsdl2-gfx-1.0.4+dfsg/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-2014 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;
50 
54 typedef struct tColorY {
55  Uint8 y;
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, bpr;
807  SDL_Surface* dst;
808  Uint8* srcBuf;
809  Uint8* dstBuf;
810  int normalizedClockwiseTurns;
811 
812  /* Has to be a valid surface pointer and be a Nbit surface where n is divisible by 8 */
813  if (!src ||
814  !src->format) {
815  SDL_SetError("NULL source surface or source surface format");
816  return NULL;
817  }
818 
819  if ((src->format->BitsPerPixel % 8) != 0) {
820  SDL_SetError("Invalid source surface bit depth");
821  return NULL;
822  }
823 
824  /* normalize numClockwiseTurns */
825  normalizedClockwiseTurns = (numClockwiseTurns % 4);
826  if (normalizedClockwiseTurns < 0) {
827  normalizedClockwiseTurns += 4;
828  }
829 
830  /* If turns are even, our new width/height will be the same as the source surface */
831  if (normalizedClockwiseTurns % 2) {
832  newWidth = src->h;
833  newHeight = src->w;
834  } else {
835  newWidth = src->w;
836  newHeight = src->h;
837  }
838 
839  dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel,
840  src->format->Rmask,
841  src->format->Gmask,
842  src->format->Bmask,
843  src->format->Amask);
844  if(!dst) {
845  SDL_SetError("Could not create destination surface");
846  return NULL;
847  }
848 
849  if (SDL_MUSTLOCK(src)) {
850  SDL_LockSurface(src);
851  }
852  if (SDL_MUSTLOCK(dst)) {
853  SDL_LockSurface(dst);
854  }
855 
856  /* Calculate byte-per-pixel */
857  bpp = src->format->BitsPerPixel / 8;
858 
859  switch(normalizedClockwiseTurns) {
860  case 0: /* Make a copy of the surface */
861  {
862  /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface
863  since it does not preserve alpha. */
864 
865  if (src->pitch == dst->pitch) {
866  /* If the pitch is the same for both surfaces, the memory can be copied all at once. */
867  memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
868  }
869  else
870  {
871  /* If the pitch differs, copy each row separately */
872  srcBuf = (Uint8*)(src->pixels);
873  dstBuf = (Uint8*)(dst->pixels);
874  bpr = src->w * bpp;
875  for (row = 0; row < src->h; row++) {
876  memcpy(dstBuf, srcBuf, bpr);
877  srcBuf += src->pitch;
878  dstBuf += dst->pitch;
879  }
880  }
881  }
882  break;
883 
884  /* rotate clockwise */
885  case 1: /* rotated 90 degrees clockwise */
886  {
887  for (row = 0; row < src->h; ++row) {
888  srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
889  dstBuf = (Uint8*)(dst->pixels) + (dst->w - row - 1) * bpp;
890  for (col = 0; col < src->w; ++col) {
891  memcpy (dstBuf, srcBuf, bpp);
892  srcBuf += bpp;
893  dstBuf += dst->pitch;
894  }
895  }
896  }
897  break;
898 
899  case 2: /* rotated 180 degrees clockwise */
900  {
901  for (row = 0; row < src->h; ++row) {
902  srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
903  dstBuf = (Uint8*)(dst->pixels) + ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp;
904  for (col = 0; col < src->w; ++col) {
905  memcpy (dstBuf, srcBuf, bpp);
906  srcBuf += bpp;
907  dstBuf -= bpp;
908  }
909  }
910  }
911  break;
912 
913  case 3: /* rotated 270 degrees clockwise */
914  {
915  for (row = 0; row < src->h; ++row) {
916  srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
917  dstBuf = (Uint8*)(dst->pixels) + (row * bpp) + ((dst->h - 1) * dst->pitch);
918  for (col = 0; col < src->w; ++col) {
919  memcpy (dstBuf, srcBuf, bpp);
920  srcBuf += bpp;
921  dstBuf -= dst->pitch;
922  }
923  }
924  }
925  break;
926  }
927  /* end switch */
928 
929  if (SDL_MUSTLOCK(src)) {
930  SDL_UnlockSurface(src);
931  }
932  if (SDL_MUSTLOCK(dst)) {
933  SDL_UnlockSurface(dst);
934  }
935 
936  return dst;
937 }
938 
939 
954 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy,
955  int *dstwidth, int *dstheight,
956  double *canglezoom, double *sanglezoom)
957 {
958  double x, y, cx, cy, sx, sy;
959  double radangle;
960  int dstwidthhalf, dstheighthalf;
961 
962  /*
963  * Determine destination width and height by rotating a centered source box
964  */
965  radangle = angle * (M_PI / 180.0);
966  *sanglezoom = sin(radangle);
967  *canglezoom = cos(radangle);
968  *sanglezoom *= zoomx;
969  *canglezoom *= zoomy;
970  x = (double)(width / 2);
971  y = (double)(height / 2);
972  cx = *canglezoom * x;
973  cy = *canglezoom * y;
974  sx = *sanglezoom * x;
975  sy = *sanglezoom * y;
976 
977  dstwidthhalf = MAX((int)
978  ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
979  dstheighthalf = MAX((int)
980  ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
981  *dstwidth = 2 * dstwidthhalf;
982  *dstheight = 2 * dstheighthalf;
983 }
984 
996 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
997 {
998  double dummy_sanglezoom, dummy_canglezoom;
999 
1000  _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
1001 }
1002 
1013 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
1014 {
1015  double dummy_sanglezoom, dummy_canglezoom;
1016 
1017  _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
1018 }
1019 
1035 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
1036 {
1037  return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
1038 }
1039 
1056 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
1057 {
1058  SDL_Surface *rz_src;
1059  SDL_Surface *rz_dst;
1060  double zoominv;
1061  double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
1062  int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
1063  int is32bit;
1064  int i, src_converted;
1065  int flipx,flipy;
1066 
1067  /*
1068  * Sanity check
1069  */
1070  if (src == NULL) {
1071  return (NULL);
1072  }
1073 
1074  /*
1075  * Determine if source surface is 32bit or 8bit
1076  */
1077  is32bit = (src->format->BitsPerPixel == 32);
1078  if ((is32bit) || (src->format->BitsPerPixel == 8)) {
1079  /*
1080  * Use source surface 'as is'
1081  */
1082  rz_src = src;
1083  src_converted = 0;
1084  } else {
1085  /*
1086  * New source surface is 32bit with a defined RGBA ordering
1087  */
1088  rz_src =
1089  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1090 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1091  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1092 #else
1093  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1094 #endif
1095  );
1096 
1097  SDL_BlitSurface(src, NULL, rz_src, NULL);
1098 
1099  src_converted = 1;
1100  is32bit = 1;
1101  }
1102 
1103  /*
1104  * Sanity check zoom factor
1105  */
1106  flipx = (zoomx<0.0);
1107  if (flipx) zoomx=-zoomx;
1108  flipy = (zoomy<0.0);
1109  if (flipy) zoomy=-zoomy;
1110  if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
1111  if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
1112  zoominv = 65536.0 / (zoomx * zoomx);
1113 
1114  /*
1115  * Check if we have a rotozoom or just a zoom
1116  */
1117  if (fabs(angle) > VALUE_LIMIT) {
1118 
1119  /*
1120  * Angle!=0: full rotozoom
1121  */
1122  /*
1123  * -----------------------
1124  */
1125 
1126  /* Determine target size */
1127  _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
1128 
1129  /*
1130  * Calculate target factors from sin/cos and zoom
1131  */
1132  sanglezoominv = sanglezoom;
1133  canglezoominv = canglezoom;
1134  sanglezoominv *= zoominv;
1135  canglezoominv *= zoominv;
1136 
1137  /* Calculate half size */
1138  dstwidthhalf = dstwidth / 2;
1139  dstheighthalf = dstheight / 2;
1140 
1141  /*
1142  * Alloc space to completely contain the rotated surface
1143  */
1144  rz_dst = NULL;
1145  if (is32bit) {
1146  /*
1147  * Target surface is 32bit with source RGBA/ABGR ordering
1148  */
1149  rz_dst =
1150  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1151  rz_src->format->Rmask, rz_src->format->Gmask,
1152  rz_src->format->Bmask, rz_src->format->Amask);
1153  } else {
1154  /*
1155  * Target surface is 8bit
1156  */
1157  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1158  }
1159 
1160  /* Check target */
1161  if (rz_dst == NULL)
1162  return NULL;
1163 
1164  /* Adjust for guard rows */
1165  rz_dst->h = dstheight;
1166 
1167  /*
1168  * Lock source surface
1169  */
1170  if (SDL_MUSTLOCK(rz_src)) {
1171  SDL_LockSurface(rz_src);
1172  }
1173 
1174  /*
1175  * Check which kind of surface we have
1176  */
1177  if (is32bit) {
1178  /*
1179  * Call the 32bit transformation routine to do the rotation (using alpha)
1180  */
1181  _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1182  (int) (sanglezoominv), (int) (canglezoominv),
1183  flipx, flipy,
1184  smooth);
1185  } else {
1186  /*
1187  * Copy palette and colorkey info
1188  */
1189  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1190  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1191  }
1192  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1193  /*
1194  * Call the 8bit transformation routine to do the rotation
1195  */
1196  transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1197  (int) (sanglezoominv), (int) (canglezoominv),
1198  flipx, flipy);
1199  }
1200  /*
1201  * Unlock source surface
1202  */
1203  if (SDL_MUSTLOCK(rz_src)) {
1204  SDL_UnlockSurface(rz_src);
1205  }
1206 
1207  } else {
1208 
1209  /*
1210  * Angle=0: Just a zoom
1211  */
1212  /*
1213  * --------------------
1214  */
1215 
1216  /*
1217  * Calculate target size
1218  */
1219  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
1220 
1221  /*
1222  * Alloc space to completely contain the zoomed surface
1223  */
1224  rz_dst = NULL;
1225  if (is32bit) {
1226  /*
1227  * Target surface is 32bit with source RGBA/ABGR ordering
1228  */
1229  rz_dst =
1230  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1231  rz_src->format->Rmask, rz_src->format->Gmask,
1232  rz_src->format->Bmask, rz_src->format->Amask);
1233  } else {
1234  /*
1235  * Target surface is 8bit
1236  */
1237  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1238  }
1239 
1240  /* Check target */
1241  if (rz_dst == NULL)
1242  return NULL;
1243 
1244  /* Adjust for guard rows */
1245  rz_dst->h = dstheight;
1246 
1247  /*
1248  * Lock source surface
1249  */
1250  if (SDL_MUSTLOCK(rz_src)) {
1251  SDL_LockSurface(rz_src);
1252  }
1253 
1254  /*
1255  * Check which kind of surface we have
1256  */
1257  if (is32bit) {
1258  /*
1259  * Call the 32bit transformation routine to do the zooming (using alpha)
1260  */
1261  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1262 
1263  } else {
1264  /*
1265  * Copy palette and colorkey info
1266  */
1267  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1268  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1269  }
1270  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1271 
1272  /*
1273  * Call the 8bit transformation routine to do the zooming
1274  */
1275  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1276  }
1277 
1278  /*
1279  * Unlock source surface
1280  */
1281  if (SDL_MUSTLOCK(rz_src)) {
1282  SDL_UnlockSurface(rz_src);
1283  }
1284  }
1285 
1286  /*
1287  * Cleanup temp surface
1288  */
1289  if (src_converted) {
1290  SDL_FreeSurface(rz_src);
1291  }
1292 
1293  /*
1294  * Return destination surface
1295  */
1296  return (rz_dst);
1297 }
1298 
1311 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
1312 {
1313  /*
1314  * Make zoom factors positive
1315  */
1316  int flipx, flipy;
1317  flipx = (zoomx<0.0);
1318  if (flipx) zoomx = -zoomx;
1319  flipy = (zoomy<0.0);
1320  if (flipy) zoomy = -zoomy;
1321 
1322  /*
1323  * Sanity check zoom factors
1324  */
1325  if (zoomx < VALUE_LIMIT) {
1326  zoomx = VALUE_LIMIT;
1327  }
1328  if (zoomy < VALUE_LIMIT) {
1329  zoomy = VALUE_LIMIT;
1330  }
1331 
1332  /*
1333  * Calculate target size
1334  */
1335  *dstwidth = (int) floor(((double) width * zoomx) + 0.5);
1336  *dstheight = (int) floor(((double) height * zoomy) + 0.5);
1337  if (*dstwidth < 1) {
1338  *dstwidth = 1;
1339  }
1340  if (*dstheight < 1) {
1341  *dstheight = 1;
1342  }
1343 }
1344 
1361 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
1362 {
1363  SDL_Surface *rz_src;
1364  SDL_Surface *rz_dst;
1365  int dstwidth, dstheight;
1366  int is32bit;
1367  int i, src_converted;
1368  int flipx, flipy;
1369 
1370  /*
1371  * Sanity check
1372  */
1373  if (src == NULL)
1374  return (NULL);
1375 
1376  /*
1377  * Determine if source surface is 32bit or 8bit
1378  */
1379  is32bit = (src->format->BitsPerPixel == 32);
1380  if ((is32bit) || (src->format->BitsPerPixel == 8)) {
1381  /*
1382  * Use source surface 'as is'
1383  */
1384  rz_src = src;
1385  src_converted = 0;
1386  } else {
1387  /*
1388  * New source surface is 32bit with a defined RGBA ordering
1389  */
1390  rz_src =
1391  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1392 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1393  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1394 #else
1395  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1396 #endif
1397  );
1398  if (rz_src == NULL) {
1399  return NULL;
1400  }
1401  SDL_BlitSurface(src, NULL, rz_src, NULL);
1402  src_converted = 1;
1403  is32bit = 1;
1404  }
1405 
1406  flipx = (zoomx<0.0);
1407  if (flipx) zoomx = -zoomx;
1408  flipy = (zoomy<0.0);
1409  if (flipy) zoomy = -zoomy;
1410 
1411  /* Get size if target */
1412  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
1413 
1414  /*
1415  * Alloc space to completely contain the zoomed surface
1416  */
1417  rz_dst = NULL;
1418  if (is32bit) {
1419  /*
1420  * Target surface is 32bit with source RGBA/ABGR ordering
1421  */
1422  rz_dst =
1423  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1424  rz_src->format->Rmask, rz_src->format->Gmask,
1425  rz_src->format->Bmask, rz_src->format->Amask);
1426  } else {
1427  /*
1428  * Target surface is 8bit
1429  */
1430  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1431  }
1432 
1433  /* Check target */
1434  if (rz_dst == NULL) {
1435  /*
1436  * Cleanup temp surface
1437  */
1438  if (src_converted) {
1439  SDL_FreeSurface(rz_src);
1440  }
1441  return NULL;
1442  }
1443 
1444  /* Adjust for guard rows */
1445  rz_dst->h = dstheight;
1446 
1447  /*
1448  * Lock source surface
1449  */
1450  if (SDL_MUSTLOCK(rz_src)) {
1451  SDL_LockSurface(rz_src);
1452  }
1453 
1454  /*
1455  * Check which kind of surface we have
1456  */
1457  if (is32bit) {
1458  /*
1459  * Call the 32bit transformation routine to do the zooming (using alpha)
1460  */
1461  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1462  } else {
1463  /*
1464  * Copy palette and colorkey info
1465  */
1466  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1467  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1468  }
1469  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1470  /*
1471  * Call the 8bit transformation routine to do the zooming
1472  */
1473  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1474  }
1475  /*
1476  * Unlock source surface
1477  */
1478  if (SDL_MUSTLOCK(rz_src)) {
1479  SDL_UnlockSurface(rz_src);
1480  }
1481 
1482  /*
1483  * Cleanup temp surface
1484  */
1485  if (src_converted) {
1486  SDL_FreeSurface(rz_src);
1487  }
1488 
1489  /*
1490  * Return destination surface
1491  */
1492  return (rz_dst);
1493 }
1494 
1511 /*@null@*/
1512 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
1513 {
1514  int result;
1515  SDL_Surface *rz_src;
1516  SDL_Surface *rz_dst = NULL;
1517  int dstwidth, dstheight;
1518  int is32bit;
1519  int i, src_converted;
1520  int haveError = 0;
1521 
1522  /*
1523  * Sanity check
1524  */
1525  if (src == NULL) {
1526  return (NULL);
1527  }
1528 
1529  /*
1530  * Determine if source surface is 32bit or 8bit
1531  */
1532  is32bit = (src->format->BitsPerPixel == 32);
1533  if ((is32bit) || (src->format->BitsPerPixel == 8)) {
1534  /*
1535  * Use source surface 'as is'
1536  */
1537  rz_src = src;
1538  src_converted = 0;
1539  } else {
1540  /*
1541  * New source surface is 32bit with a defined RGBA ordering
1542  */
1543  rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1544 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1545  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1546 #else
1547  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1548 #endif
1549  );
1550  if (rz_src==NULL) {
1551  haveError = 1;
1552  goto exitShrinkSurface;
1553  }
1554 
1555  SDL_BlitSurface(src, NULL, rz_src, NULL);
1556  src_converted = 1;
1557  is32bit = 1;
1558  }
1559 
1560  /*
1561  * Lock the surface
1562  */
1563  if (SDL_MUSTLOCK(rz_src)) {
1564  if (SDL_LockSurface(rz_src) < 0) {
1565  haveError = 1;
1566  goto exitShrinkSurface;
1567  }
1568  }
1569 
1570  /* Get size for target */
1571  dstwidth=rz_src->w/factorx;
1572  while (dstwidth*factorx>rz_src->w) { dstwidth--; }
1573  dstheight=rz_src->h/factory;
1574  while (dstheight*factory>rz_src->h) { dstheight--; }
1575 
1576  /*
1577  * Alloc space to completely contain the shrunken surface
1578  * (with added guard rows)
1579  */
1580  if (is32bit==1) {
1581  /*
1582  * Target surface is 32bit with source RGBA/ABGR ordering
1583  */
1584  rz_dst =
1585  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1586  rz_src->format->Rmask, rz_src->format->Gmask,
1587  rz_src->format->Bmask, rz_src->format->Amask);
1588  } else {
1589  /*
1590  * Target surface is 8bit
1591  */
1592  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1593  }
1594 
1595  /* Check target */
1596  if (rz_dst == NULL) {
1597  haveError = 1;
1598  goto exitShrinkSurface;
1599  }
1600 
1601  /* Adjust for guard rows */
1602  rz_dst->h = dstheight;
1603 
1604  /*
1605  * Check which kind of surface we have
1606  */
1607  if (is32bit==1) {
1608  /*
1609  * Call the 32bit transformation routine to do the shrinking (using alpha)
1610  */
1611  result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
1612  if ((result!=0) || (rz_dst==NULL)) {
1613  haveError = 1;
1614  goto exitShrinkSurface;
1615  }
1616  } else {
1617  /*
1618  * Copy palette and colorkey info
1619  */
1620  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1621  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1622  }
1623  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1624  /*
1625  * Call the 8bit transformation routine to do the shrinking
1626  */
1627  result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
1628  if (result!=0) {
1629  haveError = 1;
1630  goto exitShrinkSurface;
1631  }
1632  }
1633 
1634 exitShrinkSurface:
1635  if (rz_src!=NULL) {
1636  /*
1637  * Unlock source surface
1638  */
1639  if (SDL_MUSTLOCK(rz_src)) {
1640  SDL_UnlockSurface(rz_src);
1641  }
1642 
1643  /*
1644  * Cleanup temp surface
1645  */
1646  if (src_converted==1) {
1647  SDL_FreeSurface(rz_src);
1648  }
1649  }
1650 
1651  /* Check error state; maybe need to cleanup destination */
1652  if (haveError==1) {
1653  if (rz_dst!=NULL) {
1654  SDL_FreeSurface(rz_dst);
1655  }
1656  rz_dst=NULL;
1657  }
1658 
1659  /*
1660  * Return destination surface
1661  */
1662  return (rz_dst);
1663 }
#define M_PI
#define GUARD_ROWS
Number of guard rows added to destination surfaces.
Definition: SDL2_rotozoom.c:73
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.
struct tColorRGBA tColorRGBA
A 32 bit RGBA pixel.
SDL_Surface * rotozoomSurface(SDL_Surface *src, double angle, double zoom, int smooth)
Rotates and zooms a surface and optional anti-aliasing.
SDL_Surface * rotateSurface90Degrees(SDL_Surface *src, int numClockwiseTurns)
Rotates a 8/16/24/32 bit surface in increments of 90 degrees.
void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
Calculates the size of the target surface for a zoomSurface() call.
void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
Returns the size of the resulting target surface for a rotozoomSurface() call.
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.
#define VALUE_LIMIT
Lower limit of absolute zoom factor or rotation degrees.
Definition: SDL2_rotozoom.c:78
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-...
SDL_Surface * shrinkSurface(SDL_Surface *src, int factorx, int factory)
Shrink a surface by an integer ratio using averaging.
int _shrinkSurfaceY(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 8 bit integer-factor averaging shrinker.
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.
SDL_Surface * zoomSurface(SDL_Surface *src, double zoomx, double zoomy, int smooth)
Zoom a surface by independent horizontal and vertical factors with optional smoothing.
int _shrinkSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 32 bit integer-factor averaging Shrinker.
struct tColorY tColorY
A 8bit Y/palette pixel.
int _zoomSurfaceY(SDL_Surface *src, SDL_Surface *dst, int flipx, int flipy)
Internal 8 bit Zoomer without smoothing.
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.
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.
#define MAX(a, b)
Returns maximum of two numbers a and b.
Definition: SDL2_rotozoom.c:61
Uint32 _colorkey(SDL_Surface *src)
Returns colorkey info for a surface.
Definition: SDL2_rotozoom.c:83
A 32 bit RGBA pixel.
Definition: SDL2_rotozoom.c:44
A 8bit Y/palette pixel.
Definition: SDL2_rotozoom.c:54
Uint8 y
Definition: SDL2_rotozoom.c:55