Как эффективно обновить отдельные пиксели на поверхности SDL 1.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();

0

Решение

Вам не нужно промежуточное изображение, вы можете поместить пиксели прямо на поверхность экрана. Вы можете вызывать SDL_Flip () или SDL_UpdateRect () для каждой строки, а не для каждого пикселя, это будет намного быстрее.

Кроме того, циклический переход по строкам вместо столбцов даст вам небольшой прирост скорости, поскольку пиксели в одной строке расположены рядом друг с другом в физической памяти, и последовательный доступ к памяти быстрее на современных процессорах.

// 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);

Вы также можете создать отдельные переменные int для img.height () и img.width (), чтобы не вызывать вызов функции на каждой итерации, но компилятор обычно все равно может оптимизировать это.

0

Другие решения

Затраты на связь для смены одного пикселя за раз будут слишком высокими. Это имеет мало общего с вашим конкретным API.

Попробуйте отслеживать время и экспоненциально менять больше пикселей, пока не пройдет достаточно времени (скажем, 1/100 секунды). Затем обновите их. (проверяйте часы только после экспоненциально увеличивающихся интервалов)

Это даст вам прогресс, не затягивая вещи с накладными расходами, как ваш пиксель за раз.

0

По вопросам рекламы [email protected]