Примените фильтры оттенка / насыщенности к изображению с OpenGL - PullRequest
2 голосов
/ 23 августа 2010

У меня есть изображение в OpenGL, к которому я пытаюсь применить простой фильтр HSB. Пользователь выбирает значение оттенка, я соответствующим образом закрашиваю изображение, отображаю его, и все довольны. Проблема, с которой я сталкиваюсь, заключается в том, что унаследованный мной код, который работал в предыдущей системе (Solaris, предполагая OpenGL 2.1), не работает в нашей текущей системе (RHEL 5, OpenGL 3.0).

Сейчас изображение отображается в оттенках серого, независимо от того, какое значение насыщенности установлено. Тем не менее, яркость, кажется, действует соответствующим образом. Соответствующий код был воспроизведен ниже:

// imageData - unsigned char[3*width*height]
// (red|green|blue)Channel - unsigned char[width*height]
// brightnessBias - float in range [-1/3,1/3]
// hsMatrix - float[4][4] Described by algorithm from 
//            http://www.graficaobscura.com/matrix/index.html 
//            (see Hue Rotation While Preserving Luminance)

glDrawPixels(width, height, format, GL_UNSIGNED_BYTE, imageData);

// Split into RGB channels
glReadPixels(0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, redChannel);
glReadPixels(0, 0, width, height, GL_GREEN, GL_UNSIGNED_BYTE, greenChannel);
glReadPixels(0, 0, width, height, GL_BLUE, GL_UNSIGNED_BYTE, blueChannel);

// Redraw and blend RGB channels with scaling and bias
glPixelZoom(1.0, 1.0);
glRasterPos2i(0, height);

glPixelTransferf(GL_RED_BIAS, brightnessBias);
glPixelTransferf(GL_GREEN_BIAS, brightnessBias);
glPixelTransferf(GL_BLUE_BIAS, brightnessBias);

glDisable(GL_BLEND);

glPixelTransferf(GL_RED_SCALE, hsMatrix[0][0]);
glPixelTransferf(GL_GREEN_SCALE, hsMatrix[1][0]);
glPixelTransferf(GL_BLUE_SCALE, hsMatrix[2][0]);
glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, redChannel);

glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);

glPixelTransferf(GL_RED_SCALE, hsMatrix[0][1]);
glPixelTransferf(GL_GREEN_SCALE, hsMatrix[1][1]);
glPixelTransferf(GL_BLUE_SCALE, hsMatrix[2][1]);
glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, greenChannel);

glPixelTransferf(GL_RED_SCALE, hsMatrix[0][2]);
glPixelTransferf(GL_GREEN_SCALE, hsMatrix[1][2]);
glPixelTransferf(GL_BLUE_SCALE, hsMatrix[2][2]);
glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, blueChannel);

// Reset pixel transfer parameters
glDisable(GL_BLEND);
glPixelTransferf(GL_RED_SCALE, 1.0f);
glPixelTransferf(GL_GREEN_SCALE, 1.0f);
glPixelTransferf(GL_BLUE_SCALE, 1.0f);
glPixelTransferf(GL_RED_BIAS, 0.0f);
glPixelTransferf(GL_GREEN_BIAS, 0.0f);
glPixelTransferf(GL_BLUE_BIAS, 0.0f);

Управление яркостью работает, как и предполагалось, однако, когда остаются вызовы glPixelTransferf (GL _ * _ SCALE), изображение отображается в оттенках серого. Все это усугубляет тот факт, что у меня нет опыта работы с OpenGL, поэтому я нахожу множество ссылок на более современные методы, которые я просто не могу понять.

РЕДАКТИРОВАТЬ:

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

// After glDrawPixels(..., redChannel)
new_red = red*hsMatrix[0][0]
new_green = red*hsMatrix[1][0]
new_blue = red*hsMatrix[2][0]
// After glDrawPixels(..., greenChannel)
new_red = red*hsMatrix[0][0] + green*hsMatrix[0][1]
new_green = red*hsMatrix[1][0] + green*hsMatrix[1][1]
new_blue = red*hsMatrix[2][0] + green*hsMatrix[2][1]
// After glDrawPixels(..., blueChannel)
new_red = red*hsMatrix[0][0] + green*hsMatrix[0][1] + blue*hsMatrix[0][2]
new_green = red*hsMatrix[1][0] + green*hsMatrix[1][1] + blue*hsMatrix[1][2]
new_blue = red*hsMatrix[2][0] + green*hsMatrix[2][1] + blue*hsMatrix[2][2]

Так как в любом случае это получалось в оттенках серого и на примере с похожим рисунком, я подумал, что, возможно, мне нужно было выполнить вызовы glPixelTransfer перед вызовом glDrawPixels, но это было удивительно медленно.

1 Ответ

1 голос
/ 24 августа 2010

Ух ты, что это, черт возьми?!

По вашему вопросу я заменил бы GL_LUMINANCE в ваших 3 glDrawPixels на GL_RED, GL_GREEN и GL_BLUE соответственно.

Однако:

glPixelTransfer is bad

glDrawPixels - это плохо

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

  • Создайте текстуру из imageData, это нужно сделать только один раз.
  • Создание шейдера, который считывает цвет из текстуры, умножает его на матрицу преобразования цветов и отображает его
  • Привязать вычисленную цветовую матрицу
  • Нарисуйте полноэкранный квад. Даже 5-летняя карта получит 500 кадров в секунду.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...