Hi,


As promised, I investigated a problem with a 1-pixel postponement

during scaling. I'm not sure you have the time to look at it but I'd

welcome your opinion  :) 



Example: I scale an image 300%, so the scaling will essentially copy

each source pixel 3x on the destination surface.


The algorithm precomputes an array of pointer jumps ("should I advance

source pointer or not").


It uses the "fixed-point float" technique to store the jump increments

as 65536th units, and >>16 before storing it. When the increment >

65536 there's a jump.


What happens after 3 loops?

step = (int)(65536 / 3) = 21845

1: increment = 21845 (< 65536)

2: increment = 43690 (< 65536)

3: increment = 65535 (still < 65536)

4: increment = 87380 (> 65536) => jump=1 => incr-=65536


So the first pixel will be copied 4x instead of 3x.


I have a game editor that scales a background tile 900% and the

1-pixel shift looks bad, plus it doesn't align with the editor brush

:/



Solution: don't use fixed-point floats and avoid losing precision

- option 1: using doubles

- option 2: adding src->w until it reaches dst->w (SDL_stretch)



I attach 2 versions to fix zoomSurfaceY. If that's good I could work

on zoomSurfaceRGBA too.


(I also remove a small portion of the code that is actually unused)


-- Sylvain




Index: SDL_gfx-2.0.17/SDL_rotozoom.c

===================================================================

--- SDL_gfx-2.0.17.orig/SDL_rotozoom.c 2008-08-02 20:40:10.000000000 +0200

+++ SDL_gfx-2.0.17/SDL_rotozoom.c 2008-08-02 21:13:49.000000000 +0200

@@ -369,15 +369,16 @@

 

 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)

 {

-    Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;

+    Uint32 x, y, *sax, *say, *csax, *csay;

+    double sx, sy, csx, csy;

     Uint8 *sp, *dp, *csp;

     int dgap;

 

     /*

      * Variable setup 

      */

-    sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);

-    sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);

+    sx = 1.0 * src->w / dst->w;

+    sy = 1.0 * src->h / dst->h;

 

     /*

      * Allocate memory for row increments 

@@ -399,29 +400,18 @@

     csax = sax;

     for (x = 0; x < dst->w; x++) {

  csx += sx;

- *csax = (csx >> 16);

- csx &= 0xffff;

+ *csax = (int) csx;

+ while (csx >= 1)

+   csx -= 1;

  csax++;

     }

     csy = 0;

     csay = say;

     for (y = 0; y < dst->h; y++) {

  csy += sy;

- *csay = (csy >> 16);

- csy &= 0xffff;

- csay++;

-    }

-

-    csx = 0;

-    csax = sax;

-    for (x = 0; x < dst->w; x++) {

- csx += (*csax);

- csax++;

-    }

-    csy = 0;

-    csay = say;

-    for (y = 0; y < dst->h; y++) {

- csy += (*csay);

+ *csay = (int) csy;

+ while (csy >= 1)

+   csy -= 1;

  csay++;

     }

 




Index: SDL_gfx-2.0.17/SDL_rotozoom.c

===================================================================

--- SDL_gfx-2.0.17.orig/SDL_rotozoom.c 2008-08-02 20:40:10.000000000 +0200

+++ SDL_gfx-2.0.17/SDL_rotozoom.c 2008-08-02 22:47:36.000000000 +0200

@@ -369,17 +369,12 @@

 

 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)

 {

-    Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;

+    Uint32 x, y, *sax, *say, *csax, *csay;

+    int csx, csy;

     Uint8 *sp, *dp, *csp;

     int dgap;

 

     /*

-     * Variable setup 

-     */

-    sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);

-    sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);

-

-    /*

      * Allocate memory for row increments 

      */

     if ((sax = (Uint32 *) malloc(dst->w * sizeof(Uint32))) == NULL) {

@@ -398,30 +393,23 @@

     csx = 0;

     csax = sax;

     for (x = 0; x < dst->w; x++) {

- csx += sx;

- *csax = (csx >> 16);

- csx &= 0xffff;

- csax++;

-    }

-    csy = 0;

-    csay = say;

-    for (y = 0; y < dst->h; y++) {

- csy += sy;

- *csay = (csy >> 16);

- csy &= 0xffff;

- csay++;

-    }

-

-    csx = 0;

-    csax = sax;

-    for (x = 0; x < dst->w; x++) {

- csx += (*csax);

+ csx += src->w;

+ *csax = 0;

+ while (csx >= dst->w) {

+     csx -= dst->w;

+     (*csax)++;

+ }

  csax++;

     }

     csy = 0;

     csay = say;

     for (y = 0; y < dst->h; y++) {

- csy += (*csay);

+ csy += src->h;

+ *csay = 0;

+ while (csy >= dst->h) {

+   csy -= dst->h;

+   (*csay)++;

+ }

  csay++;

     }