0

我用 C++ 编写了一个简单的 SDL 程序,以查看是什么。我让它进入(大部分)工作状态,除了它运行得很慢(虽然我在上网本上运行它,所以也许就是这样),并且在窗口中没有绘制超过两行像素。

此问题存在于软件和硬件模式中。

//colorizer.h
#include <iostream>
#include "SDL.h"
#include "math.h"

class Colorizer
{
    public:
        Colorizer(int width, int height, int bpp);
        ~Colorizer();
        void frame(int rx, int ry, int gx, int gy, int bx, int by);

    protected:
        SDL_Surface* screen;
        SDL_Surface* canvas;
        void set_pixel(int x, int y, int r, int g, int b);
        double distance(int from_x, int from_y, int to_x, int to_y);
        int canvasW;
        int canvasH;
        int canvasBPP;
        long framenumber;
};

//-------------------------------------------------------------------------------------------
//colorizer.cpp
#include "colorizer.h"

Colorizer::Colorizer(int width, int height, int bpp)
{
    screen = SDL_SetVideoMode(width, height, bpp, SDL_SWSURFACE);
    if(!screen)
    {
        throw(SDL_GetError());
    }
    canvasW = width;
    canvasH = height;
    canvasBPP = bpp;
    framenumber = 0;
}

void Colorizer::frame(int rx, int ry, int gx, int gy, int bx, int by)
{
    if(SDL_LockSurface(screen) < 0){
        std::cerr << "Can't lock screen: " << SDL_GetError() << std::endl;
    }

    for(int pix = 0; pix < screen->h; pix++) //Per column
    {
        for(int row = 0; row < screen->w; row++) //Per pixel
        {
            double src_r = sin(0.5*distance(row, pix, rx, ry)*framenumber);
            double src_g = cos(0.5*distance(row, pix, gx, gy)*framenumber);
            double src_b = sin(0.5*distance(row, pix, bx, by)*framenumber);
            int dst_r = static_cast<int> (fabs(floor(255*src_r)));
            int dst_g = static_cast<int> (fabs(floor(255*src_g)));
            int dst_b = static_cast<int> (fabs(floor(255*src_b)));
            if(dst_r > 255 or dst_g > 255 or dst_b > 255 or dst_r < 0 or dst_g < 0 or dst_b < 0){
                std::cerr << "Error: Pixel: (" << row << "," << pix << ") r=" << dst_r << " g=" << dst_g << " b=" << dst_b << std::endl;
                throw ("One of the colours is invalid.");
            }
            set_pixel(row, pix, dst_r, dst_g, dst_b);
        }
    }

    SDL_UnlockSurface(screen);
    SDL_Flip(screen);
    framenumber++;
}

double Colorizer::distance(int from_x, int from_y, int to_x, int to_y)
{
    double triW = static_cast<double> (from_x) - static_cast<double> (to_x);
    double triH = static_cast<double> (from_y) - static_cast<double> (to_y);
    double distSq = triW*triW + triH*triH;
    return sqrt(distSq);
}

void Colorizer::set_pixel(int x, int y, int r, int g, int b)
{
    if(x > 640 or y > 480){
        std::cerr << "Invalid pixel: " << x << "," << y << std::endl;
        return;
    }
    int color;
    color = SDL_MapRGB(screen->format, r, g, b);

    int *pixel;
    pixel = (int*) screen->pixels + x + y;
    *pixel = color;
}

Colorizer::~Colorizer()
{
    SDL_FreeSurface(screen);
}

//-------------------------------------------------------------------------------------------
//main.cpp
#include <iostream>
#include "SDL.h"
#include "colorizer.h"

/*snip pretty bash colour functions*/

int main (int argc, char* argv[])
{
    int sdlinit = SDL_Init( SDL_INIT_EVERYTHING );
    if( sdlinit < 0 ){
        std::cerr << "Cannot initialize SDL: " << SDL_GetError() << std::endl;
        return 1;
    }

    try{
        Colorizer app(640, 480, 32);
        bool keypress = false;

        SDL_Event evt;
        while(!keypress){
            std::cerr << "."; //per frame
            app.frame(100, 230, 25, 40, 200, 100); //default points
            while(SDL_PollEvent(&evt)){
                std::cerr << "!"; //per event
                if (evt.type == SDL_QUIT or evt.type == SDL_KEYDOWN)
                {
                    keypress = true;
                }
            }
        }
        std::cout << std::endl;
        return 0;
    }catch(const char* &ex){
        SDL_Quit();
        return 1;
    }
}
//-------------------------------------------------------------------------------------------
// compile with: g++ *.cpp -O2 -o colorizer `pkg-config --cflags --libs sdl`
//-------------------------------------------------------------------------------------------
4

2 回答 2

2

pixel = (int*) screen->pixels + x + y;应该是这样的pixel = (int*) screen->pixels + x + y * screen->w;吗?我实际上不知道像素在 SDL 中是如何排列的,但如果你不乘 x 或 y,那么 (2,1) 将与 (1,2) 的字节相同,这显然不会工作。

于 2012-07-20T15:37:08.217 回答
2

除了@Paul Tomblin 指出的内容外,您还假设typedef int Uint32,这是不可移植的,也是一种不好的做法。还考虑到 C++ 风格,

int color;
color = SDL_MapRGB(screen->format, r, g, b);

int *pixel;
pixel = (int*) screen->pixels + x + y;
*pixel = color;

应该是:

Uint32* pixels = reinterpret_cast<Uint32*>(screen->pixels);
pixels[screen->w * y + x] = SDL_MapRGB(screen->format, r, g, b);
于 2012-07-20T16:24:00.377 回答