Как я могу изменить пиксели, используя SDL? - PullRequest
7 голосов
/ 28 июля 2011

У меня небольшая проблема: я не могу изменить пиксели экрана SDL.

В частности, следующий код не работает.

Uint32 * pixels = (Uint32 *) screen -> pixels; 
screen -> pixels = pixels;

Это компилируется, но ничего не показывает. Чего мне не хватает?

Ответы [ 5 ]

20 голосов
/ 28 июля 2011

У меня были следующие функции для установки пикселей в SDL_Surface. Существует две версии для 32-битной, 24-битной, 16-битной и 8-битной поверхностей. Если вы просто хотите установить один пиксель, вы должны использовать обычные версии. Но если вы хотите установить группу пикселей, сначала вы блокируете поверхность, затем вы используете версию nolock (названную так, потому что она не блокирует поверхность), затем вы разблокируете. Таким образом, вы не будете постоянно блокировать и разблокировать поверхность, что должно быть дорогостоящей операцией, хотя я не думаю, что когда-либо проверял ее.

void PutPixel32_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint32));
    *((Uint32*)pixel) = color;
}

void PutPixel24_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint8) * 3);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    pixel[0] = (color >> 24) & 0xFF;
    pixel[1] = (color >> 16) & 0xFF;
    pixel[2] = (color >> 8) & 0xFF;
#else
    pixel[0] = color & 0xFF;
    pixel[1] = (color >> 8) & 0xFF;
    pixel[2] = (color >> 16) & 0xFF;
#endif
}

void PutPixel16_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint16));
    *((Uint16*)pixel) = color & 0xFFFF;
}

void PutPixel8_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint8));
    *pixel = color & 0xFF;
}

void PutPixel32(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel32_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_UnlockSurface(surface);
}

void PutPixel24(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel24_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
}

void PutPixel16(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel16_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_UnlockSurface(surface);
}

void PutPixel8(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel8_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_UnlockSurface(surface);
}
2 голосов
/ 15 августа 2011

Манипулирование содержимым screen->pixels приведет к изменению пикселей с несколькими оговорками.

Во-первых, как показано в фрагменте кода, обратите внимание, что screen->pixels - указатель на данные пикселейповерхности.Доступ к самим данным пикселя осуществляется в виде линейного массива из этого указателя на основе ширины поверхности (surface->pitch) и размера пикселя в байтах.Размер пикселя (он же глубина) задается во время инициализации с помощью SDL_SetVideoMode() и может быть найден в screen->format->BytesPerPixel.

Может потребоваться блокировка поверхности перед внесением изменений.

Дополнительнов зависимости от параметров, которые были переданы SDL_SetVideoMode(), вам также может понадобиться вызвать SDL_Flip(), чтобы отобразить сделанные вами изменения.

Рабочий пример манипуляции пикселями можно найти здесь .


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

1 голос
/ 20 февраля 2015

Добавление варианта SDL2 для манипулирования пикселями не на поверхности, а в рендере

0 голосов
/ 15 апреля 2015

зачем менять пиксель?

создать новую поверхность и Rect

// CODE ------------>

SDL_Surface *screen, *PIXEL = NULL;

SDL_Rect PIXELRect;
PIXELRect.h=5;
PIXELRect.w=5;
PIXELRect.x=100;
PIXELRect.y=100;

screen = SDL_SetVideoMode(640, 468, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT);

while(running){
SDL_FillRect(screen, &PIXELRect, (#color));
}
0 голосов
/ 28 июля 2011

Вы не должны изменять содержимое структуры SDL_Surface.Если вы хотите скопировать пиксели, вам нужно malloc () немного памяти, а затем memcpy () пикселей.

...