glReadPixels хранит значения x, y - PullRequest
2 голосов
/ 21 января 2012

Я пытаюсь сохранить данные пикселей с помощью glReadPixels, но до сих пор мне удавалось сохранять их только по одному пикселю за раз.Я не уверен, если это путь.В настоящее время у меня есть это:

unsigned char pixels[3];
glReadPixels(50,50, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixels);

Что было бы хорошим способом сохранить его в массиве, чтобы я мог получить значения, как это:

pixels[20][50][0]; // x=20 y=50 -> R value
pixels[20][50][1]; // x=20 y=50 -> G value
pixels[20][50][2]; // x=20 y=50 -> B value

Я думаю, я могПроще говоря, в цикле:

for ( all pixels on Y axis )
{
    for ( all pixels in X axis )
    {
        unsigned char pixels[width][height][3];
        glReadPixels(x,y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixels[x][y]);
    }
}

Но я чувствую, что должен быть гораздо лучший способ сделать это.Но мне все же нужно, чтобы мой массив был таким, как я описал выше в коде.Так будет ли идея цикла for хорошей или есть лучший способ?

Ответы [ 3 ]

5 голосов
/ 21 января 2012

glReadPixels просто возвращает байты в порядке R, G, B, R, G, B, ... (в зависимости от ваших настроек GL_RGB) от нижнего левого края экрана до верхнего правого . Из документации OpenGL :

glReadPixels возвращает данные пикселей из буфера кадров, начиная с пиксель, левый нижний угол которого находится в точке (x, y), в клиент память начинается с данных о местоположении. Несколько параметров контролируют обработка данных пикселей перед их помещением в память клиента. Эти параметры устанавливаются тремя командами: glPixelStore, glPixelTransfer и glPixelMap. Эта справочная страница описывает влияние на glReadPixels большинства, но не всех параметров определяется этими тремя командами.

Затраты на вызов glReadPixels тысячи раз, скорее всего, займут заметное количество времени (в зависимости от размера окна, я не удивлюсь, если цикл занял 1-2 секунды).

Рекомендуется только один раз вызвать glReadPixels и сохранить его в байтовом массиве размером (width - x) * (height - y) * 3. Оттуда вы можете ссылаться на местоположение компонента пикселя с помощью data[(py * width + px) * 3 + component], где px и py - это местоположения пикселя, которые вы хотите найти, а component - это компоненты R, G или B пикселя.

Если вы абсолютно должны иметь его в 3-мерном массиве, вы можете написать некоторый код для перестановки 1d массива после вызова glReadPixels.

1 голос
/ 21 января 2012

Если вы определите массив пикселей следующим образом: this:

unsigned char pixels[MAX_Y][MAX_X][3];

И вы получите к нему доступ следующим образом:

pixels[y][x][0] = r;
pixels[y][x][1] = g;
pixels[y][x][2] = b;

Тогда вы сможете прочитатьпикселей с одним вызовом glReadPixels:

glReadPixels(left, top, MAX_Y, MAX_X, GL_RGB, GL_UNSIGNED_BYTE, pixels);
0 голосов
/ 21 января 2012

Что вы можете сделать, это объявить простой одномерный массив в структуре и использовать перегрузку оператора для удобной записи нижнего индекса

struct Pixel2d
{
    static const int SIZE = 50;
    unsigned char& operator()( int nCol,  int nRow, int RGB)
    {
        return pixels[ ( nCol* SIZE + nRow) * 3 + RGB];
    }

    unsigned char pixels[SIZE * SIZE * 3 ];
};

int main()
{

    Pixel2d p2darray;
    glReadPixels(50,50, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &p.pixels);

    for( int i = 0; i < Pixel2d::SIZE ; ++i )
    {
        for( int j = 0; j < Pixel2d::SIZE ; ++j )
        {
            unsigned char rpixel = p2darray(i , j , 0);
            unsigned char gpixel = p2darray(i , j , 1);
            unsigned char bpixel = p2darray(i , j , 2);
        }
    }
}

Здесь вы читаете 50 * 50 пикселей за один кадр и используете operator()( int nCol, int nRow, int RGB) оператор обеспечивает необходимое удобство.По соображениям производительности вы не хотите совершать слишком много glReadPixels звонков

...