如何在SDL1.2曲面上高效地更新单个像素



我正在写一个小东西,为图像的每个像素计算rgb值。

我想在计算后显示每一个。问题是我不知道如何把它做得这么快。计算完整的图像并显示它需要几秒钟,其中显示每个像素需要几分钟。

重要的是,我可以看到图像计算的进展。在SDL 1.2中,有没有一种方法可以有效地解决这项任务?

我的代码现在如下:

SDL_Surface* screen = NULL;
SDL_Surface* image = NULL;
SDL_Init(SDL_INIT_EVERYTHING);
//Set up screen
screen = SDL_SetVideoMode(img.width(), img.height(), 32, SDL_SWSURFACE);
// create surface with default values
image = SDL_CreateRGBSurface(SDL_SWSURFACE,img.width(),img.height(),32,0,0,0,0);
if(image == NULL) {
    std::cout << "failed creating SDL surface";
}
// create array for pixels
Uint32 *pixels = (Uint32 *)image->pixels;
//Apply image to screen
SDL_BlitSurface(image, NULL, screen, NULL);
//Update screen
SDL_Flip(screen);
// compute image
for (int i = 0; i < img.width(); i++) {
    for (int j = 0; j < img.height(); j++) {
        img(i, j) = computeColor(i, j, img.width(), img.height());
        pixels[i * img.width() + j] = SDL_MapRGB(image->format,(Uint8)getR(img(i,j)), (Uint8)getG(img(i,j)),(Uint8)getB(img(i,j)));
        SDL_BlitSurface(image, NULL, screen, NULL);
        SDL_UpdateRect(screen, i, j, i, j);
    }
}
//Pause
SDL_Delay(2000);
//Free the loaded image
SDL_FreeSurface(image);
//Quit SDL
SDL_Quit();

您不需要中间图像,可以将像素直接放在屏幕表面。您可以为每一行调用SDL_Flip()或SDL_UpdateRequest(),而不是为每一个像素调用,这样会更快。

此外,通过行而不是列循环将使您的速度略有提高,因为在物理内存中,单行上的像素彼此靠近,而在现代CPU上,顺序内存访问速度更快。

// create array for pixels
Uint32 *pixels = (Uint32 *)screen->pixels;
// Clear screen
SDL_FillRect(screen, NULL, 0);
//Update screen
SDL_Flip(screen);
// compute image
for (int j = 0; j < img.height(); j++) {
    for (int i = 0; i < img.width(); i++) {
        img(i, j) = computeColor(i, j, img.width(), img.height());
        pixels[i + j * img.width()] = SDL_MapRGB(image->format,(Uint8)getR(img(i,j)), (Uint8)getG(img(i,j)),(Uint8)getB(img(i,j)));
    }
    SDL_UpdateRect(screen, i, j, img.width(), 1);
}
// Display final result
SDL_Flip(screen);
SDL_Delay(2000);

您还可以为img.height()和img.width()创建一个单独的int变量,这样您就不会在每次迭代中调用函数,但编译器通常能够优化它。

每次更改一个像素的通信开销太高。这与您的特定API无关。

试着跟踪时间,并以指数形式改变更多的像素,直到足够的时间(比如1/100秒)过去。然后更新它们。(仅在指数增加间隔后检查时钟)

这将给你带来进步,而不会像一次解决方案中的像素那样让事情变得一团糟。

最新更新