Atrinik Client  4.0
SDL_rotozoom.c
1 /*
2  *
3  * SDL_rotozoom.c - rotozoomer, zoomer and shrinker for 32bit or 8bit
4  * surfaces
5  *
6  * LGPL (c) A. Schiffler
7  *
8  */
9 
10 #include <global.h>
11 
12 /* ---- Internally used structures */
13 
17 typedef struct tColorRGBA {
18  Uint8 r;
19  Uint8 g;
20  Uint8 b;
21  Uint8 a;
22 } tColorRGBA;
23 
27 typedef struct tColorY {
28  Uint8 y;
29 } tColorY;
30 
41 #define GUARD_ROWS (2)
42 
46 #define VALUE_LIMIT 0.001
47 
51 Uint32 _colorkey(SDL_Surface *src)
52 {
53  Uint32 key = 0;
54 #if (SDL_MINOR_VERSION == 3)
55  SDL_GetColorKey(src, &key);
56 #else
57 
58  if (src) {
59  key = src->format->colorkey;
60  }
61 #endif
62  return key;
63 }
64 
81 int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
82 {
83  int x, y, dx, dy, dgap, ra, ga, ba, aa;
84  int n_average;
85  tColorRGBA *sp, *osp, *oosp;
86  tColorRGBA *dp;
87 
88  /*
89  * Averaging integer shrink
90  */
91 
92  /* Precalculate division factor */
93  n_average = factorx*factory;
94 
95  /*
96  * Scan destination
97  */
98  sp = src->pixels;
99 
100  dp = dst->pixels;
101  dgap = dst->pitch - dst->w * 4;
102 
103  for (y = 0; y < dst->h; y++) {
104 
105  osp = sp;
106  for (x = 0; x < dst->w; x++) {
107 
108  /* Trace out source box and accumulate */
109  oosp = sp;
110  ra = ga = ba = aa = 0;
111  for (dy = 0; dy < factory; dy++) {
112  for (dx = 0; dx < factorx; dx++) {
113  ra += sp->r;
114  ga += sp->g;
115  ba += sp->b;
116  aa += sp->a;
117 
118  sp++;
119  }
120  /* src dx loop */
121  sp = (tColorRGBA *) ((Uint8*) sp + (src->pitch - 4 * factorx)); /*
122  *
123  *next
124  * y
125  *
126  **/
127  }
128  /* src dy loop */
129 
130  /* next box-x */
131  sp = (tColorRGBA *) ((Uint8*) oosp + 4 * factorx);
132 
133  /* Store result in destination */
134  dp->r = ra / n_average;
135  dp->g = ga / n_average;
136  dp->b = ba / n_average;
137  dp->a = aa / n_average;
138 
139  /*
140  * Advance destination pointer
141  */
142  dp++;
143  }
144  /* dst x loop */
145 
146  /* next box-y */
147  sp = (tColorRGBA *) ((Uint8*) osp + src->pitch * factory);
148 
149  /*
150  * Advance destination pointers
151  */
152  dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
153  }
154  /* dst y loop */
155 
156  return (0);
157 }
158 
175 int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
176 {
177  int x, y, dx, dy, dgap, a;
178  int n_average;
179  Uint8 *sp, *osp, *oosp;
180  Uint8 *dp;
181 
182  /*
183  * Averaging integer shrink
184  */
185 
186  /* Precalculate division factor */
187  n_average = factorx*factory;
188 
189  /*
190  * Scan destination
191  */
192  sp = src->pixels;
193 
194  dp = dst->pixels;
195  dgap = dst->pitch - dst->w;
196 
197  for (y = 0; y < dst->h; y++) {
198 
199  osp = sp;
200  for (x = 0; x < dst->w; x++) {
201 
202  /* Trace out source box and accumulate */
203  oosp = sp;
204  a = 0;
205  for (dy = 0; dy < factory; dy++) {
206  for (dx = 0; dx < factorx; dx++) {
207  a += (*sp);
208  /* next x */
209  sp++;
210  }
211  /* end src dx loop */
212  /* next y */
213  sp = (Uint8 *) ((Uint8*) sp + (src->pitch - factorx));
214  }
215  /* end src dy loop */
216 
217  /* next box-x */
218  sp = (Uint8 *) ((Uint8*) oosp + factorx);
219 
220  /* Store result in destination */
221  *dp = a / n_average;
222 
223  /*
224  * Advance destination pointer
225  */
226  dp++;
227  }
228  /* end dst x loop */
229 
230  /* next box-y */
231  sp = (Uint8 *) ((Uint8*) osp + src->pitch * factory);
232 
233  /*
234  * Advance destination pointers
235  */
236  dp = (Uint8 *) ((Uint8 *) dp + dgap);
237  }
238  /* end dst y loop */
239 
240  return (0);
241 }
242 
259 int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
260 {
261  int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, lx, ly;
262  tColorRGBA *c00, *c01, *c10, *c11, *cswap;
263  tColorRGBA *sp, *csp, *dp;
264  int dgap;
265 
266  /*
267  * Variable setup
268  */
269  if (smooth) {
270  /*
271  * For interpolation: assume source dimension is one pixel
272  * smaller to avoid overflow on right and bottom edge.
273  */
274  sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
275  sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
276  } else {
277  sx = (int) (65536.0 * (float) src->w / (float) dst->w);
278  sy = (int) (65536.0 * (float) src->h / (float) dst->h);
279  }
280 
281  /*
282  * Allocate memory for row increments
283  */
284  if ((sax = malloc((dst->w + 1) * sizeof(*sax))) == NULL) {
285  return (-1);
286  }
287 
288  if ((say = malloc((dst->h + 1) * sizeof(*say))) == NULL) {
289  free(sax);
290  return (-1);
291  }
292 
293  /*
294  * Precalculate row increments
295  */
296  sp = csp = src->pixels;
297  dp = dst->pixels;
298 
299  if (flipx) {
300  csp += (src->w - 1);
301  }
302 
303  if (flipy) {
304  csp += ((src->pitch / 4)*(src->h - 1));
305  }
306 
307  csx = 0;
308  csax = sax;
309  for (x = 0; x <= dst->w; x++) {
310  *csax = csx;
311  csax++;
312  csx &= 0xffff;
313  csx += sx;
314  }
315  csy = 0;
316  csay = say;
317  for (y = 0; y <= dst->h; y++) {
318  *csay = csy;
319  csay++;
320  csy &= 0xffff;
321  csy += sy;
322  }
323 
324  dgap = dst->pitch - dst->w * 4;
325 
326  /*
327  * Switch between interpolating and non-interpolating code
328  */
329  if (smooth) {
330 
331  /*
332  * Interpolating Zoom
333  */
334 
335  /*
336  * Scan destination
337  */
338  csay = say;
339  ly = 0;
340  for (y = 0; y < dst->h; y++) {
341  /*
342  * Setup color source pointers
343  */
344  c00 = csp;
345  c01 = csp;
346  c01++;
347  c10 = csp;
348  c10 += src->pitch / 4;
349  c11 = c10;
350  c11++;
351 
352  if (flipx) {
353  cswap = c00;
354  c00 = c01;
355  c01 = cswap;
356  cswap = c10;
357  c10 = c11;
358  c11 = cswap;
359  }
360 
361  if (flipy) {
362  cswap = c00;
363  c00 = c10;
364  c10 = cswap;
365  cswap = c01;
366  c01 = c11;
367  c11 = cswap;
368  }
369 
370  csax = sax;
371  lx = 0;
372  for (x = 0; x < dst->w; x++) {
373  /*
374  * Draw and interpolate colors
375  */
376  ex = (*csax & 0xffff);
377  ey = (*csay & 0xffff);
378  t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
379  t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
380  dp->r = (((t2 - t1) * ey) >> 16) + t1;
381  t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
382  t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
383  dp->g = (((t2 - t1) * ey) >> 16) + t1;
384  t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
385  t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
386  dp->b = (((t2 - t1) * ey) >> 16) + t1;
387  t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
388  t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
389  dp->a = (((t2 - t1) * ey) >> 16) + t1;
390 
391  /*
392  * Advance source pointers
393  */
394  csax++;
395 
396  if (*csax > 0) {
397  sstep = (*csax >> 16);
398  lx += sstep;
399 
400  if (flipx) {
401  sstep = -sstep;
402  }
403 
404  if (lx <= src->w) {
405  c00 += sstep;
406  c01 += sstep;
407  c10 += sstep;
408  c11 += sstep;
409  }
410  }
411 
412  /*
413  * Advance destination pointer
414  */
415  dp++;
416  }
417 
418  /*
419  * Advance source pointer
420  */
421  csay++;
422 
423  if (*csay > 0) {
424  sstep = (*csay >> 16);
425  ly += sstep;
426 
427  if (flipy) {
428  sstep = -sstep;
429  }
430 
431  if (ly < src->h) {
432  csp += (sstep * (src->pitch / 4));
433  }
434  }
435 
436  /*
437  * Advance destination pointers
438  */
439  dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
440  }
441  } else {
442 
443  /*
444  * Non-Interpolating Zoom
445  */
446  csay = say;
447  for (y = 0; y < dst->h; y++) {
448  sp = csp;
449  csax = sax;
450  for (x = 0; x < dst->w; x++) {
451  /*
452  * Draw
453  */
454  *dp = *sp;
455  /*
456  * Advance source pointers
457  */
458  csax++;
459 
460  if (*csax > 0) {
461  sstep = (*csax >> 16);
462 
463  if (flipx) {
464  sstep = -sstep;
465  }
466  sp += sstep;
467  }
468  /*
469  * Advance destination pointer
470  */
471  dp++;
472  }
473  /*
474  * Advance source pointer
475  */
476  csay++;
477 
478  if (*csay > 0) {
479  sstep = (*csay >> 16) * (src->pitch / 4);
480 
481  if (flipy) {
482  sstep = -sstep;
483  }
484  csp += sstep;
485  }
486 
487  /*
488  * Advance destination pointers
489  */
490  dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
491  }
492  }
493 
494  /*
495  * Remove temp arrays
496  */
497  free(sax);
498  free(say);
499 
500  return (0);
501 }
502 
518 int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
519 {
520  int x, y;
521  Uint32 *sax, *say, *csax, *csay;
522  int csx, csy;
523  Uint8 *sp, *dp, *csp;
524  int dgap;
525 
526  /*
527  * Allocate memory for row increments
528  */
529  if ((sax = malloc((dst->w + 1) * sizeof(*sax))) == NULL) {
530  return (-1);
531  }
532 
533  if ((say = malloc((dst->h + 1) * sizeof(*say))) == NULL) {
534  free(sax);
535  return (-1);
536  }
537 
538  /*
539  * Pointer setup
540  */
541  sp = csp = src->pixels;
542  dp = dst->pixels;
543  dgap = dst->pitch - dst->w;
544 
545  if (flipx) {
546  csp += (src->w - 1);
547  }
548 
549  if (flipy) {
550  csp = ( (Uint8*) csp + src->pitch * (src->h - 1) );
551  }
552 
553  /*
554  * Precalculate row increments
555  */
556  csx = 0;
557  csax = sax;
558  for (x = 0; x < dst->w; x++) {
559  csx += src->w;
560  *csax = 0;
561  while (csx >= dst->w) {
562  csx -= dst->w;
563  (*csax)++;
564  }
565  csax++;
566  }
567  csy = 0;
568  csay = say;
569  for (y = 0; y < dst->h; y++) {
570  csy += src->h;
571  *csay = 0;
572  while (csy >= dst->h) {
573  csy -= dst->h;
574  (*csay)++;
575  }
576  csay++;
577  }
578 
579  /*
580  * Draw
581  */
582  csay = say;
583  for (y = 0; y < dst->h; y++) {
584  csax = sax;
585  sp = csp;
586  for (x = 0; x < dst->w; x++) {
587  /*
588  * Draw
589  */
590  *dp = *sp;
591  /*
592  * Advance source pointers
593  */
594  sp += (*csax) * (flipx ? -1 : 1);
595  csax++;
596  /*
597  * Advance destination pointer
598  */
599  dp++;
600  }
601  /*
602  * Advance source pointer (for row)
603  */
604  csp += ((*csay) * src->pitch) * (flipy ? -1 : 1);
605  csay++;
606 
607  /*
608  * Advance destination pointers
609  */
610  dp += dgap;
611  }
612 
613  /*
614  * Remove temp arrays
615  */
616  free(sax);
617  free(say);
618 
619  return (0);
620 }
621 
643 void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
644 {
645  int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
646  tColorRGBA c00, c01, c10, c11, cswap;
647  tColorRGBA *pc, *sp;
648  int gap;
649 
650  /*
651  * Variable setup
652  */
653  xd = ((src->w - dst->w) << 15);
654  yd = ((src->h - dst->h) << 15);
655  ax = (cx << 16) - (icos * cx);
656  ay = (cy << 16) - (isin * cx);
657  sw = src->w - 1;
658  sh = src->h - 1;
659  pc = dst->pixels;
660  gap = dst->pitch - dst->w * 4;
661 
662  /*
663  * Switch between interpolating and non-interpolating code
664  */
665  if (smooth) {
666  for (y = 0; y < dst->h; y++) {
667  dy = cy - y;
668  sdx = (ax + (isin * dy)) + xd;
669  sdy = (ay - (icos * dy)) + yd;
670  for (x = 0; x < dst->w; x++) {
671  dx = (sdx >> 16);
672  dy = (sdy >> 16);
673 
674  if (flipx) {
675  dx = sw - dx;
676  }
677 
678  if (flipy) {
679  dy = sh - dy;
680  }
681 
682  if ((dx > -1) && (dy > -1) && (dx < (src->w - 1)) && (dy < (src->h - 1))) {
683  sp = src->pixels;
684  ;
685  sp += ((src->pitch / 4) * dy);
686  sp += dx;
687  c00 = *sp;
688  sp += 1;
689  c01 = *sp;
690  sp += (src->pitch / 4);
691  c11 = *sp;
692  sp -= 1;
693  c10 = *sp;
694 
695  if (flipx) {
696  cswap = c00;
697  c00 = c01;
698  c01 = cswap;
699  cswap = c10;
700  c10 = c11;
701  c11 = cswap;
702  }
703 
704  if (flipy) {
705  cswap = c00;
706  c00 = c10;
707  c10 = cswap;
708  cswap = c01;
709  c01 = c11;
710  c11 = cswap;
711  }
712  /*
713  * Interpolate colors
714  */
715  ex = (sdx & 0xffff);
716  ey = (sdy & 0xffff);
717  t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
718  t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
719  pc->r = (((t2 - t1) * ey) >> 16) + t1;
720  t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
721  t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
722  pc->g = (((t2 - t1) * ey) >> 16) + t1;
723  t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
724  t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
725  pc->b = (((t2 - t1) * ey) >> 16) + t1;
726  t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
727  t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
728  pc->a = (((t2 - t1) * ey) >> 16) + t1;
729  }
730  sdx += icos;
731  sdy += isin;
732  pc++;
733  }
734  pc = (tColorRGBA *) ((Uint8 *) pc + gap);
735  }
736  } else {
737  for (y = 0; y < dst->h; y++) {
738  dy = cy - y;
739  sdx = (ax + (isin * dy)) + xd;
740  sdy = (ay - (icos * dy)) + yd;
741  for (x = 0; x < dst->w; x++) {
742  dx = (int) (short) (sdx >> 16);
743  dy = (int) (short) (sdy >> 16);
744 
745  if (flipx) {
746  dx = (src->w - 1) - dx;
747  }
748 
749  if (flipy) {
750  dy = (src->h - 1) - dy;
751  }
752 
753  if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
754  sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
755  sp += dx;
756  *pc = *sp;
757  }
758  sdx += icos;
759  sdy += isin;
760  pc++;
761  }
762  pc = (tColorRGBA *) ((Uint8 *) pc + gap);
763  }
764  }
765 }
766 
787 void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
788 {
789  int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay;
790  tColorY *pc, *sp;
791  int gap;
792 
793  /*
794  * Variable setup
795  */
796  xd = ((src->w - dst->w) << 15);
797  yd = ((src->h - dst->h) << 15);
798  ax = (cx << 16) - (icos * cx);
799  ay = (cy << 16) - (isin * cx);
800  pc = dst->pixels;
801  gap = dst->pitch - dst->w;
802  /*
803  * Clear surface to colorkey
804  */
805  memset(pc, (unsigned char) (_colorkey(src) & 0xff),
806  (size_t) dst->pitch * dst->h);
807  /*
808  * Iterate through destination surface
809  */
810  for (y = 0; y < dst->h; y++) {
811  dy = cy - y;
812  sdx = (ax + (isin * dy)) + xd;
813  sdy = (ay - (icos * dy)) + yd;
814  for (x = 0; x < dst->w; x++) {
815  dx = (int) (short) (sdx >> 16);
816  dy = (int) (short) (sdy >> 16);
817 
818  if (flipx) {
819  dx = (src->w - 1) - dx;
820  }
821 
822  if (flipy) {
823  dy = (src->h - 1) - dy;
824  }
825 
826  if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
827  sp = src->pixels;
828  sp += (src->pitch * dy + dx);
829  *pc = *sp;
830  }
831  sdx += icos;
832  sdy += isin;
833  pc++;
834  }
835  pc += gap;
836  }
837 }
838 
854 SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns)
855 {
856  int row, col, newWidth, newHeight;
857  int bpp, src_ipr, dst_ipr;
858  SDL_Surface* dst;
859  Uint32* srcBuf;
860  Uint32* dstBuf;
861 
862  /* Has to be a valid surface pointer and only 32-bit surfaces (for now) */
863  if (!src || src->format->BitsPerPixel != 32) {
864  return NULL;
865  }
866 
867  /* normalize numClockwiseTurns */
868  while (numClockwiseTurns < 0) {
869  numClockwiseTurns += 4;
870  }
871  numClockwiseTurns = (numClockwiseTurns % 4);
872 
873  /* if it's even, our new width will be the same as the source surface */
874  newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w);
875  newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h);
876  dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel,
877  src->format->Rmask,
878  src->format->Gmask,
879  src->format->Bmask,
880  src->format->Amask);
881 
882  if (!dst) {
883  return NULL;
884  }
885 
886  if (SDL_MUSTLOCK(dst)) {
887  SDL_LockSurface(dst);
888  }
889 
890  if (SDL_MUSTLOCK(dst)) {
891  SDL_LockSurface(dst);
892  }
893 
894  /* Calculate int-per-row */
895  bpp = src->format->BitsPerPixel / 8;
896  src_ipr = src->pitch / bpp;
897  dst_ipr = dst->pitch / bpp;
898 
899  switch (numClockwiseTurns) {
900  case 0: /* Make a copy of the surface */
901  {
902  /* Unfortunately SDL_BlitSurface cannot be used to make a copy of
903  * the surface
904  * since it does not preserve alpha. */
905 
906  if (src->pitch == dst->pitch) {
907  /* If the pitch is the same for both surfaces, the memory can be
908  * copied all at once. */
909  memcpy(dst->pixels, src->pixels, src->h * (size_t) src->pitch);
910  } else {
911  /* If the pitch differs, copy each row separately */
912  srcBuf = src->pixels;
913  dstBuf = dst->pixels;
914  for (row = 0; row < src->h; row++) {
915  memcpy(dstBuf, srcBuf, dst->w * bpp);
916  srcBuf += src_ipr;
917  dstBuf += dst_ipr;
918  } /* end for(col) */
919  } /* end for(row) */
920  }
921  break;
922 
923  /* rotate clockwise */
924  case 1: /* rotated 90 degrees clockwise */
925  {
926  for (row = 0; row < src->h; ++row) {
927  srcBuf = (Uint32*) (src->pixels) + (row * src_ipr);
928  dstBuf = (Uint32*) (dst->pixels) + (dst->w - row - 1);
929  for (col = 0; col < src->w; ++col) {
930  *dstBuf = *srcBuf;
931  ++srcBuf;
932  dstBuf += dst_ipr;
933  }
934  /* end for(col) */
935  }
936  /* end for(row) */
937  }
938  break;
939 
940  case 2: /* rotated 180 degrees clockwise */
941  {
942  for (row = 0; row < src->h; ++row) {
943  srcBuf = (Uint32*) (src->pixels) + (row * src_ipr);
944  dstBuf = (Uint32*) (dst->pixels) + ((dst->h - row - 1) * dst_ipr) + (dst->w - 1);
945  for (col = 0; col < src->w; ++col) {
946  *dstBuf = *srcBuf;
947  ++srcBuf;
948  --dstBuf;
949  }
950  }
951  }
952  break;
953 
954  case 3:
955  {
956  for (row = 0; row < src->h; ++row) {
957  srcBuf = (Uint32*) (src->pixels) + (row * src_ipr);
958  dstBuf = (Uint32*) (dst->pixels) + row + ((dst->h - 1) * dst_ipr);
959  for (col = 0; col < src->w; ++col) {
960  *dstBuf = *srcBuf;
961  ++srcBuf;
962  dstBuf -= dst_ipr;
963  }
964  }
965  }
966  break;
967  }
968  /* end switch */
969 
970  if (SDL_MUSTLOCK(src)) {
971  SDL_UnlockSurface(src);
972  }
973 
974  if (SDL_MUSTLOCK(dst)) {
975  SDL_UnlockSurface(dst);
976  }
977 
978  return dst;
979 }
980 
996 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy,
997  int *dstwidth, int *dstheight,
998  double *canglezoom, double *sanglezoom)
999 {
1000  double x, y, cx, cy, sx, sy;
1001  double radangle;
1002  double dstwidthhalf, dstheighthalf;
1003 
1004  (void) zoomy;
1005 
1006  /*
1007  * Determine destination width and height by rotating a centered source box
1008  */
1009  radangle = angle * (M_PI / 180.0);
1010  *sanglezoom = sin(radangle);
1011  *canglezoom = cos(radangle);
1012  *sanglezoom *= zoomx;
1013  *canglezoom *= zoomx;
1014  x = width / 2.0;
1015  y = height / 2.0;
1016  cx = *canglezoom * x;
1017  cy = *canglezoom * y;
1018  sx = *sanglezoom * x;
1019  sy = *sanglezoom * y;
1020 
1021  dstwidthhalf = MAX(ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
1022  dstheighthalf = MAX(ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
1023  *dstwidth = (int) (dstwidthhalf * 2.0);
1024  *dstheight = (int) (dstheighthalf * 2.0);
1025 }
1026 
1041 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
1042 {
1043  double dummy_sanglezoom, dummy_canglezoom;
1044 
1045  _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_canglezoom, &dummy_sanglezoom);
1046 }
1047 
1061 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
1062 {
1063  double dummy_sanglezoom, dummy_canglezoom;
1064 
1065  _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_canglezoom, &dummy_sanglezoom);
1066 }
1067 
1087 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
1088 {
1089  return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
1090 }
1091 
1113 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
1114 {
1115  SDL_Surface *rz_src;
1116  SDL_Surface *rz_dst;
1117  double zoominv;
1118  double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
1119  int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
1120  int is32bit;
1121  int i, src_converted;
1122  int flipx, flipy;
1123  Uint8 r, g, b;
1124  Uint32 colorkey = 0;
1125  int colorKeyAvailable = 0;
1126 
1127  /*
1128  * Sanity check
1129  */
1130  if (src == NULL) {
1131  return (NULL);
1132  }
1133 
1134  if (src->flags & SDL_SRCCOLORKEY) {
1135  colorkey = _colorkey(src);
1136  SDL_GetRGB(colorkey, src->format, &r, &g, &b);
1137  colorKeyAvailable = 1;
1138  }
1139  /*
1140  * Determine if source surface is 32bit or 8bit
1141  */
1142  is32bit = (src->format->BitsPerPixel == 32);
1143 
1144  if ((is32bit) || (src->format->BitsPerPixel == 8)) {
1145  /*
1146  * Use source surface 'as is'
1147  */
1148  rz_src = src;
1149  src_converted = 0;
1150  } else {
1151  /*
1152  * New source surface is 32bit with a defined RGBA ordering
1153  */
1154  rz_src =
1155  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1156 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1157  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1158 #else
1159  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1160 #endif
1161  );
1162 
1163  if (colorKeyAvailable) {
1164  SDL_SetColorKey(src, 0, 0);
1165  }
1166 
1167  SDL_BlitSurface(src, NULL, rz_src, NULL);
1168 
1169  if (colorKeyAvailable) {
1170  SDL_SetColorKey(src, SDL_SRCCOLORKEY, colorkey);
1171  }
1172  src_converted = 1;
1173  is32bit = 1;
1174  }
1175 
1176  /*
1177  * Sanity check zoom factor
1178  */
1179  flipx = (zoomx < 0.0);
1180 
1181  if (flipx) {
1182  zoomx = -zoomx;
1183  }
1184  flipy = (zoomy < 0.0);
1185 
1186  if (flipy) {
1187  zoomy = -zoomy;
1188  }
1189 
1190  if (zoomx < VALUE_LIMIT) {
1191  zoomx = VALUE_LIMIT;
1192  }
1193 
1194  if (zoomy < VALUE_LIMIT) {
1195  zoomy = VALUE_LIMIT;
1196  }
1197  zoominv = 65536.0 / (zoomx * zoomx);
1198 
1199  /*
1200  * Check if we have a rotozoom or just a zoom
1201  */
1202  if (fabs(angle) > VALUE_LIMIT) {
1203 
1204  /*
1205  * Angle!=0: full rotozoom
1206  */
1207  /*
1208  * -----------------------
1209  */
1210 
1211  /* Determine target size */
1212  _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
1213 
1214  /*
1215  * Calculate target factors from sin/cos and zoom
1216  */
1217  sanglezoominv = sanglezoom;
1218  canglezoominv = canglezoom;
1219  sanglezoominv *= zoominv;
1220  canglezoominv *= zoominv;
1221 
1222  /* Calculate half size */
1223  dstwidthhalf = dstwidth / 2;
1224  dstheighthalf = dstheight / 2;
1225 
1226  /*
1227  * Alloc space to completely contain the rotated surface
1228  */
1229  rz_dst = NULL;
1230 
1231  if (is32bit) {
1232  /*
1233  * Target surface is 32bit with source RGBA/ABGR ordering
1234  */
1235  rz_dst =
1236  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1237  rz_src->format->Rmask, rz_src->format->Gmask,
1238  rz_src->format->Bmask, rz_src->format->Amask);
1239  } else {
1240  /*
1241  * Target surface is 8bit
1242  */
1243  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1244  }
1245 
1246  /* Check target */
1247  if (rz_dst == NULL) {
1248  return NULL;
1249  }
1250 
1251  /* Adjust for guard rows */
1252  rz_dst->h = dstheight;
1253 
1254  if (colorKeyAvailable == 1) {
1255  colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
1256 
1257  SDL_FillRect(rz_dst, NULL, colorkey );
1258  }
1259 
1260  /*
1261  * Lock source surface
1262  */
1263  if (SDL_MUSTLOCK(rz_src)) {
1264  SDL_LockSurface(rz_src);
1265  }
1266 
1267  /*
1268  * Check which kind of surface we have
1269  */
1270  if (is32bit) {
1271  /*
1272  * Call the 32bit transformation routine to do the rotation (using
1273  * alpha)
1274  */
1275  _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1276  (int) (sanglezoominv), (int) (canglezoominv),
1277  flipx, flipy,
1278  smooth);
1279  /*
1280  * Turn on source-alpha support
1281  */
1282  SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
1283  SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
1284  } else {
1285  /*
1286  * Copy palette and colorkey info
1287  */
1288  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1289  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1290  }
1291  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1292  /*
1293  * Call the 8bit transformation routine to do the rotation
1294  */
1295  transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1296  (int) (sanglezoominv), (int) (canglezoominv),
1297  flipx, flipy);
1298  SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
1299  }
1300 
1301  /*
1302  * Unlock source surface
1303  */
1304  if (SDL_MUSTLOCK(rz_src)) {
1305  SDL_UnlockSurface(rz_src);
1306  }
1307 
1308  } else {
1309 
1310  /*
1311  * Angle=0: Just a zoom
1312  */
1313  /*
1314  * --------------------
1315  */
1316 
1317  /*
1318  * Calculate target size
1319  */
1320  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
1321 
1322  /*
1323  * Alloc space to completely contain the zoomed surface
1324  */
1325  rz_dst = NULL;
1326 
1327  if (is32bit) {
1328  /*
1329  * Target surface is 32bit with source RGBA/ABGR ordering
1330  */
1331  rz_dst =
1332  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1333  rz_src->format->Rmask, rz_src->format->Gmask,
1334  rz_src->format->Bmask, rz_src->format->Amask);
1335  } else {
1336  /*
1337  * Target surface is 8bit
1338  */
1339  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1340  }
1341 
1342  /* Check target */
1343  if (rz_dst == NULL) {
1344  return NULL;
1345  }
1346 
1347  /* Adjust for guard rows */
1348  rz_dst->h = dstheight;
1349 
1350  if (colorKeyAvailable == 1) {
1351  colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
1352 
1353  SDL_FillRect(rz_dst, NULL, colorkey );
1354  }
1355 
1356  /*
1357  * Lock source surface
1358  */
1359  if (SDL_MUSTLOCK(rz_src)) {
1360  SDL_LockSurface(rz_src);
1361  }
1362 
1363  /*
1364  * Check which kind of surface we have
1365  */
1366  if (is32bit) {
1367  /*
1368  * Call the 32bit transformation routine to do the zooming (using
1369  * alpha)
1370  */
1371  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1372 
1373  /*
1374  * Turn on source-alpha support
1375  */
1376  SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
1377  SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
1378  } else {
1379  /*
1380  * Copy palette and colorkey info
1381  */
1382  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1383  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1384  }
1385  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1386 
1387  /*
1388  * Call the 8bit transformation routine to do the zooming
1389  */
1390  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1391  SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
1392  }
1393 
1394  /*
1395  * Unlock source surface
1396  */
1397  if (SDL_MUSTLOCK(rz_src)) {
1398  SDL_UnlockSurface(rz_src);
1399  }
1400  }
1401 
1402  /*
1403  * Cleanup temp surface
1404  */
1405  if (src_converted) {
1406  SDL_FreeSurface(rz_src);
1407  }
1408 
1409  /*
1410  * Return destination surface
1411  */
1412  return (rz_dst);
1413 }
1414 
1430 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
1431 {
1432  /*
1433  * Make zoom factors positive
1434  */
1435  int flipx, flipy;
1436  flipx = (zoomx < 0.0);
1437 
1438  if (flipx) {
1439  zoomx = -zoomx;
1440  }
1441  flipy = (zoomy < 0.0);
1442 
1443  if (flipy) {
1444  zoomy = -zoomy;
1445  }
1446 
1447  /*
1448  * Sanity check zoom factors
1449  */
1450  if (zoomx < VALUE_LIMIT) {
1451  zoomx = VALUE_LIMIT;
1452  }
1453 
1454  if (zoomy < VALUE_LIMIT) {
1455  zoomy = VALUE_LIMIT;
1456  }
1457 
1458  /*
1459  * Calculate target size
1460  */
1461  *dstwidth = (int) ((double) width * zoomx);
1462  *dstheight = (int) ((double) height * zoomy);
1463 
1464  if (*dstwidth < 1) {
1465  *dstwidth = 1;
1466  }
1467 
1468  if (*dstheight < 1) {
1469  *dstheight = 1;
1470  }
1471 }
1472 
1493 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
1494 {
1495  SDL_Surface *rz_src;
1496  SDL_Surface *rz_dst;
1497  int dstwidth, dstheight;
1498  int is32bit;
1499  int i, src_converted;
1500  int flipx, flipy;
1501 
1502  /*
1503  * Sanity check
1504  */
1505  if (src == NULL) {
1506  return (NULL);
1507  }
1508 
1509  /*
1510  * Determine if source surface is 32bit or 8bit
1511  */
1512  is32bit = (src->format->BitsPerPixel == 32);
1513 
1514  if ((is32bit) || (src->format->BitsPerPixel == 8)) {
1515  /*
1516  * Use source surface 'as is'
1517  */
1518  rz_src = src;
1519  src_converted = 0;
1520  } else {
1521  /*
1522  * New source surface is 32bit with a defined RGBA ordering
1523  */
1524  rz_src =
1525  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1526 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1527  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1528 #else
1529  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1530 #endif
1531  );
1532  SDL_BlitSurface(src, NULL, rz_src, NULL);
1533  src_converted = 1;
1534  is32bit = 1;
1535  }
1536 
1537  flipx = (zoomx < 0.0);
1538 
1539  if (flipx) {
1540  zoomx = -zoomx;
1541  }
1542  flipy = (zoomy < 0.0);
1543 
1544  if (flipy) {
1545  zoomy = -zoomy;
1546  }
1547 
1548  /* Get size if target */
1549  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
1550 
1551  /*
1552  * Alloc space to completely contain the zoomed surface
1553  */
1554  rz_dst = NULL;
1555 
1556  if (is32bit) {
1557  /*
1558  * Target surface is 32bit with source RGBA/ABGR ordering
1559  */
1560  rz_dst =
1561  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1562  rz_src->format->Rmask, rz_src->format->Gmask,
1563  rz_src->format->Bmask, rz_src->format->Amask);
1564  } else {
1565  /*
1566  * Target surface is 8bit
1567  */
1568  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1569  }
1570 
1571  /* Check target */
1572  if (rz_dst == NULL) {
1573  return NULL;
1574  }
1575 
1576  /* Adjust for guard rows */
1577  rz_dst->h = dstheight;
1578 
1579  /*
1580  * Lock source surface
1581  */
1582  if (SDL_MUSTLOCK(rz_src)) {
1583  SDL_LockSurface(rz_src);
1584  }
1585 
1586  /*
1587  * Check which kind of surface we have
1588  */
1589  if (is32bit) {
1590  /*
1591  * Call the 32bit transformation routine to do the zooming (using alpha)
1592  */
1593  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1594  /*
1595  * Turn on source-alpha support
1596  */
1597  SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
1598  } else {
1599  /*
1600  * Copy palette and colorkey info
1601  */
1602  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1603  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1604  }
1605  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1606  /*
1607  * Call the 8bit transformation routine to do the zooming
1608  */
1609  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1610  SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
1611  }
1612 
1613  /*
1614  * Unlock source surface
1615  */
1616  if (SDL_MUSTLOCK(rz_src)) {
1617  SDL_UnlockSurface(rz_src);
1618  }
1619 
1620  /*
1621  * Cleanup temp surface
1622  */
1623  if (src_converted) {
1624  SDL_FreeSurface(rz_src);
1625  }
1626 
1627  /*
1628  * Return destination surface
1629  */
1630  return (rz_dst);
1631 }
1632 
1650 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
1651 {
1652  SDL_Surface *rz_src;
1653  SDL_Surface *rz_dst;
1654  int dstwidth, dstheight;
1655  int is32bit;
1656  int i, src_converted;
1657 
1658  /*
1659  * Sanity check
1660  */
1661  if (src == NULL) {
1662  return (NULL);
1663  }
1664 
1665  /*
1666  * Determine if source surface is 32bit or 8bit
1667  */
1668  is32bit = (src->format->BitsPerPixel == 32);
1669 
1670  if ((is32bit) || (src->format->BitsPerPixel == 8)) {
1671  /*
1672  * Use source surface 'as is'
1673  */
1674  rz_src = src;
1675  src_converted = 0;
1676  } else {
1677  /*
1678  * New source surface is 32bit with a defined RGBA ordering
1679  */
1680  rz_src =
1681  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1682 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1683  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1684 #else
1685  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1686 #endif
1687  );
1688  SDL_BlitSurface(src, NULL, rz_src, NULL);
1689  src_converted = 1;
1690  is32bit = 1;
1691  }
1692 
1693  /* Get size for target */
1694  dstwidth = rz_src->w / factorx;
1695  while (dstwidth * factorx > rz_src->w) {
1696  dstwidth--;
1697  }
1698  dstheight = rz_src->h / factory;
1699  while (dstheight * factory > rz_src->h) {
1700  dstheight--;
1701  }
1702 
1703  /*
1704  * Alloc space to completely contain the shrunken surface
1705  * (with added guard rows)
1706  */
1707  rz_dst = NULL;
1708 
1709  if (is32bit) {
1710  /*
1711  * Target surface is 32bit with source RGBA/ABGR ordering
1712  */
1713  rz_dst =
1714  SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1715  rz_src->format->Rmask, rz_src->format->Gmask,
1716  rz_src->format->Bmask, rz_src->format->Amask);
1717  } else {
1718  /*
1719  * Target surface is 8bit
1720  */
1721  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1722  }
1723 
1724  /* Check target */
1725  if (rz_dst == NULL) {
1726  return NULL;
1727  }
1728 
1729  /* Adjust for guard rows */
1730  rz_dst->h = dstheight;
1731 
1732  /*
1733  * Lock source surface
1734  */
1735  if (SDL_MUSTLOCK(rz_src)) {
1736  SDL_LockSurface(rz_src);
1737  }
1738 
1739  /*
1740  * Check which kind of surface we have
1741  */
1742  if (is32bit) {
1743  /*
1744  * Call the 32bit transformation routine to do the shrinking (using
1745  * alpha)
1746  */
1747  _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
1748  /*
1749  * Turn on source-alpha support
1750  */
1751  SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
1752  } else {
1753  /*
1754  * Copy palette and colorkey info
1755  */
1756  for (i = 0; i < rz_src->format->palette->ncolors; i++) {
1757  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1758  }
1759  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1760  /*
1761  * Call the 8bit transformation routine to do the shrinking
1762  */
1763  _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
1764  SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
1765  }
1766 
1767  /*
1768  * Unlock source surface
1769  */
1770  if (SDL_MUSTLOCK(rz_src)) {
1771  SDL_UnlockSurface(rz_src);
1772  }
1773 
1774  /*
1775  * Cleanup temp surface
1776  */
1777  if (src_converted) {
1778  SDL_FreeSurface(rz_src);
1779  }
1780 
1781  /*
1782  * Return destination surface
1783  */
1784  return (rz_dst);
1785 }
A 32 bit RGBA pixel.
Definition: SDL_rotozoom.c:17
A 8bit Y/palette pixel.
Definition: SDL_rotozoom.c:27