LINUX.ORG.RU

Отобразить картинку в окне OpenGL


0

0

Есть веб-камера, я с нее получаю картинку и хочу отобразить ее в окне после некоторой обработки. Картинку с камеры я преобразую к простому RGB (ну или к чему удобнее будет). С OpenGL не знаком вообще, но хочется его применить. Помогите с простым примером отображения в окне статической картинки, взятой из памяти.

Ну или в принципе то-же самое просто для чистых X-ов.

★★★★
Ответ на: комментарий от mv

Подразумевался Си ну или что-то около. Я ничего не имею против лиспа и функциональных языков вообще, но в чем его профит для данного случая? Повыпендриваться? Ну что-ж...

alexru ★★★★
() автор топика

Камера тебе наверно YUV дает? Преобразовывать в RGB надо тоже через OpenGL иначе тормозить будет.

Вот программка для OpenGL 2.0 http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c

Если требование такое, чтоб работало на 1.4, то надо шейдер преобразовать к такому виду:

//команда для создания: cgc -oglsl -profile arbfp1
static const char *FProgram3=
"!!ARBfp1.0 \n"
"PARAM c[2] = { { 1.1643, 0.0625, 1.5958, 0.5 },\n"
"       { 0.39173001, 0.81290001, 2.017, 1 } };\n"
"TEMP R0;\n"
"TEMP R1;\n"
"TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n"
"ADD R0.z, R0.x, -c[0].y;\n"
"TEX R1.x, fragment.texcoord[0], texture[2], 2D;\n"
"TEX R0.x, fragment.texcoord[0], texture[1], 2D;\n"
"MUL R0.z, R0, c[0].x;\n"
"ADD R0.x, R0, -c[0].w;\n"
"ADD R0.y, R1.x, -c[0].w;\n"
"MAD R0.w, -R0.x, c[1].x, R0.z;\n"
"MAD result.color.x, R0.y, c[0].z, R0.z;\n"
"MAD result.color.y, -R0, c[1], R0.w;\n"
"MAD result.color.z, R0.x, c[1], R0;\n"
"MOV result.color.w, c[1];\n"
"END";

Загружаем через

glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, shader_data_len, shader_data);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader);
glEnable(GL_FRAGMENT_PROGRAM_ARB);

Рисуем как-то так

void * Y, * U, * V;
int texture_id_U, texture_id_V, texture_id_Y;

//инициализация texture_id, получение Y, U, V
// ....
......

//загружаем все в видео-память
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture_id_U);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w / 2, h / 2,
             GL_LUMINANCE, GL_UNSIGNED_BYTE, U);

glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texture_id_V);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w / 2, h / 2,
                GL_LUMINANCE, GL_UNSIGNED_BYTE, V);
                
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id_Y);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
              GL_LUMINANCE, GL_UNSIGNED_BYTE, Y);


// Рисуем:

glBegin(GL_QUADS);
glTexCoord2d(0, 0);
glVertex3i(x1, y1, -2);

glTexCoord2d(1, 0);
glVertex3i(x2, y1, -2);

glTexCoord2d(1, 1);
glVertex3i(x2, y2, -2);

glTexCoord2d(0, 1);
glVertex3i(x1, y2, -2);
glEnd();
Reset ★★★★★
()
Ответ на: комментарий от alexru

> Подразумевался Си ну или что-то около.

cl-gtk2, cl-opengl и cl-v4l2 более-менее топорно биндят соответствующие библиотеки. Даже незнакомый с Лиспом человек без труда высмотрит, как выводится картинка и, практически, 1-в-1 перепишет на нужном ему ЯП.

> Я ничего не имею против лиспа и функциональных языков вообще, но в чем его профит для данного случая? Повыпендриваться? Ну что-ж...


Профит в том, что ровно такой пример (захват картинки с веб-камеры и вывод на экран посредством gl) был под рукой. Тебе всего-то нужно посмотреть, как gl проинициализировать, да как картинку на полигон натянуть. Хаутушками про то, как рисовать на xlib или gtk2/gtkglext полинтернета завалено. Например, вот это: http://www.dis.uniroma1.it/~liberato/screensaver/

Повыпендриваться?.. А в чём здесь профит Си? Вызвать ioctl для получения картинки и вызвать функцию для её отрисовки? О, да...

mv ★★★★★
()

1. Установить нужную проекцию.
2. Создать текстуру, забиндить.
3. Залочить ее.
4. Закинуть в нее ваш битмэп.
5. Разлочить.
6. Отрисовать два треугольника установив при этом нужные текстурныее координаты.
Вроде все. В инете полно статей для новичка. Можете посмотреть gamedev.net, gamedev.ru, примеры от HeHe.

andreyu ★★★★★
()
Ответ на: комментарий от arsi

Вот с этим получилось с некоторыми оговорками: 1. все работает если делать просто glDrawPixels(), но изображение перевернутое 2. Если добавить glPixelZoom(), то изображение нормальное, но находится левым верхним углом по центру экрана. 3. glRasterPos2i() с параметрами отличными от 0 все ломает.

Преобразование YUYV в RGB пока процессором.

alexru ★★★★
() автор топика
Ответ на: комментарий от alexru

Получилось. Требуемого удалось добиться сочетанием glRasterPos2i(-1, 1); и glPixelZoom(1, -1);

Всем спасибо. С шейдерами пока подожду разбираться.

alexru ★★★★
() автор топика
Ответ на: комментарий от alexru

> Получилось. Требуемого удалось добиться сочетанием glRasterPos2i(-1, 1); и glPixelZoom(1, -1);

=)

забыл сказать, что glRasterPos*() и glPixelZoom() можно бы задавать только один раз, при инициализации gl-контекста, если конечно нет необходимости выводить несколько кадров на одном окне (точнее, в одном контексте). а по поводу перевёрнутой (вертикально) картинки — да, потому у меня и стоял минус перед вторым аргументом glPixelZoom.

кроме того, я использовал glRasterPos2i только потому, что у меня (0; 0) был в верхнем левом углу, Y увеличивался сверху вниз и, самое главное, единица деление была равной одному пикселю. возможно, вам больше подойдёт glRasterPos2f или glRasterPos2d для float/double-координат соответственно. и ещё забыл: если координаты, установленные с помощью glRasterPos* выходят за рамки вьюпорта, ничего рисоваться не будет, даже если остальные 99% изображения попадают в видимую область (во всяком случае, на нвидии так).

по поводу преобразования цветов: я использовал sws_scale() из ffmpeg, достаточно быстро работает и не сложная в работе. единственное замечание: в моём случае быстрее было конвертировать в PIX_FMT_BGR24, чем в PIX_FMT_RGB24 — вроде использовались какие-то оптимизированные алгоритмы именно этого преобразования для моего проца.

arsi ★★★★★
()
Ответ на: комментарий от arsi

> забыл сказать, что glRasterPos*() и glPixelZoom() можно бы задавать только один раз, при инициализации gl-контекста

Я так и сделал.

С преобразованием пока не важно. Я не видео писать хочу, а поиграться немного с обработкой изображения, так что самым тормозным будет не конвертация. Да и не факт, что она потребуется, возможно в YUYV будет проще работать.

alexru ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.