使用OpenGL将色调/饱和度滤镜应用于图像

时间:2010-08-23 19:18:47

标签: opengl image-processing

我在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]

因为无论如何它都是灰度级的,并且从一个类似的例子中,我原本以为我可能需要在调用glDrawPixels之前进行glPixelTransfer调用,但这非常慢。

1 个答案:

答案 0 :(得分:1)

哇,到底是什么意思?!

对于您的问题,我将分别用GL_RED,GL_GREEN和GL_BLUE替换3 glDrawPixels中的GL_LUMINANCE。

但是:

glPixelTransfer

glDrawPixels

是否有一个原因导致您没有使用超级简单片段着色器进行转换?这是一个简单的矩阵乘法,你在ogl3.0 ......

  • 从imageData创建纹理,这只需要完成一次。
  • 制作一个着色器,从纹理中读取颜色,将其乘以颜色转换矩阵,然后显示它
  • 绑定计算的颜色矩阵
  • 绘制全屏四边形。即使一张5岁的卡也会获得500 fps。