Я пишу небольшую вещь, которая вычисляет значения 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_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 (), чтобы не вызывать вызов функции на каждой итерации, но компилятор обычно все равно может оптимизировать это.
Затраты на связь для смены одного пикселя за раз будут слишком высокими. Это имеет мало общего с вашим конкретным API.
Попробуйте отслеживать время и экспоненциально менять больше пикселей, пока не пройдет достаточно времени (скажем, 1/100 секунды). Затем обновите их. (проверяйте часы только после экспоненциально увеличивающихся интервалов)
Это даст вам прогресс, не затягивая вещи с накладными расходами, как ваш пиксель за раз.