ferzkopp / SDL_gfx

Copy of https://sdlgfx.svn.sourceforge.net/svnroot/sdlgfx - maybe out of date! The SVN version IS the official release.
http://www.ferzkopp.net
Other
49 stars 16 forks source link

Function rotozoomSurfaceXY() incorrect vertical factor behavior. #2

Open hydren opened 7 years ago

hydren commented 7 years ago

The function rotozoomSurfaceXY() appears to be using the zoomx parameter for both horizontal and vertical scaling factor, incorrectly resulting in a behavior similar to rotozoomSurface(). The correct behavior, according to the documentation, is to use zoomx as horizontal scaling factor and zoomy as vertical scaling factor.

I tested the behavior with SDL_gfx version 2.0.25.

Here is a test code (an image named "sample.bmp" is required):

/* When a non-zero angle is specified, the zoomy factor
 * is ignored and zoomx is used as both horizontal and
 * vertical scaling factor
 * An image named "sample.bmp" is required. */

#include <stdio.h>
#include <stdlib.h>

#include <SDL/SDL.h>
#include <SDL/SDL_rotozoom.h>

int main(void)
{
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Surface* window = SDL_SetVideoMode(800, 600, 0, 0);
    SDL_Surface* image = SDL_LoadBMP("sample.bmp");
    SDL_Rect pos = {window->w/2, window->h/2};

    int running = 1, flip=0;
    float angle=0, zoomx=1, zoomy=1;

    SDL_Event event;
    while(running)
    {
        if(SDL_PollEvent(&event))
        {
            if(event.type == SDL_QUIT)
                running = 0;

            if(event.type == SDL_KEYDOWN)
            {
                switch(event.key.keysym.sym)
                {
                    case SDLK_UP:    pos.y -= 10; break;
                    case SDLK_DOWN:  pos.y += 10; break;
                    case SDLK_LEFT:  pos.x -= 10; break;
                    case SDLK_RIGHT: pos.x += 10; break;

                    case SDLK_r: angle += 1; break;
                    case SDLK_t: angle -= 1; break;

                    case SDLK_x: zoomx += 0.5; break;
                    case SDLK_z: zoomx -= 0.5; break;

                    case SDLK_q: zoomy += 0.5; break;
                    case SDLK_a: zoomy -= 0.5; break;

                    case SDLK_f: flip = 1; break;
                    case SDLK_g: flip = 2; break;
                    case SDLK_h: flip = 0; break;

                    default: break;
                }
            }
        }

        SDL_FillRect(window, NULL, 0);
        SDL_Surface* transformedSurface = rotozoomSurfaceXY(
                image,
                angle,
                (flip==1? -zoomx : zoomx),
                (flip==2? -zoomy : zoomy),
                SMOOTHING_OFF);
        SDL_BlitSurface(transformedSurface, NULL, window, &pos);
        SDL_FreeSurface(transformedSurface);
        SDL_Flip(window);
    }

    return EXIT_SUCCESS;
}

Compiled with: gcc main.c -o "test" `sdl-config --cflags --libs` -lSDL_gfx

hydren commented 7 years ago

After digging in the SDL_gfx source, I had a hunch about where the issue is. My guess is that the problem lies at the line 963 of SDL_rotozoom.c, at the function _rotozoomSurfaceSizeTrig(). It seems that the zoomy parameter is not used.

    /*
    * Determine destination width and height by rotating a centered source box 
    */
    radangle = angle * (M_PI / 180.0);
    *sanglezoom = sin(radangle);
    *canglezoom = cos(radangle);
    *sanglezoom *= zoomx;
    *canglezoom *= zoomx;
    x = (double)(width / 2);
    y = (double)(height / 2);
    cx = *canglezoom * x;
    cy = *canglezoom * y;
    sx = *sanglezoom * x;
    sy = *sanglezoom * y;
ferzkopp commented 7 years ago

Thanks for the bug report. This error seems to be also present in the SDL2_gfx library.

hydren commented 7 years ago

You're welcome! I'm glad to help.

hydren commented 7 years ago

Err... I just tested the previous example with the new SDL_gfx release (both 2.0.26 and 1.0.3) and it seems that unfortunately the issue was not fixed. Now, instead of the unused vertical factor error, the issue seems to be incorrect zooming and sizing.

When both zoomx and zoomy are equal, the behavior is correct. But when zoomx != zoomy, the result seems to be equally hor. and ver. scaled by zoomx, more or less, and with incorrect sizing, to the point that when zoomx < zoomy, the image is cropped.

hydren commented 7 years ago

Here are some prints: Normal Scaled horizontally Scaled vertically Scaled horizontally and rotated Scaled vertically and rotated

Taken from a MinGW 4.9.3 build on Windows 7 (32bit).

ferzkopp commented 7 years ago

OK - let me have a look again. Probably zoomx and and zoomy use needs to be flipped.

hydren commented 4 years ago

Hi, any progress on this? Currently, as a workaround, I'm using zoomSurface() then rotozoomSurface() on the result to get the same effect.