Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying brightness and contrast with OpenGL ES

I want to change the brightness and contrast of a texture on the iPhone. I've been looking at the sample provided by apple (GLImageProcessing) but it only is able to do one at a time (calling both methods in the sample overwrites the previous result).

Brightness works great:

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
if (brightness >= 1.0f) {
    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
    glColor4f(brightness-1, brightness-1, brightness-1, brightness-1);
} else {
    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT);
    glColor4f(1-brightness, 1-brightness, 1-brightness, 1-brightness);
}
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

How would i go with adding contrast to the texture after this? Alternatively would it be a better choice to move to OpenGL ES 2.0 and do this with shaders?

Here's the code for contrast in the sample from apple:

glActiveTexture(GL_TEXTURE0);
glVertexPointer  (2, GL_FLOAT, sizeof(V2fT2f), &quad[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &quad[0].s);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);

glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD_SIGNED);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 2);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);

glColor4f(h, h, h, 0.75 - 0.5 * h); // 2x extrapolation
validateTexEnv();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Restore state
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1);
glActiveTexture(GL_TEXTURE0);

As you can probably guess my experience with OpenGL (ES) is pretty limited so anything that points me in the right direction is greatly appreciated

like image 944
Antti Avatar asked Oct 01 '09 20:10

Antti


2 Answers

This is much easier to do with a fragment shader, at least in OpenGL 2.1 (I haven't used OpenGL ES). The book "OpenGL Shading Language" covers image processing in chapter 19. They give shaders for adjusting brightness and contrast. Here is my version, which combines the two half-and-half:

uniform sampler2D Texture;
uniform float Brightness;
uniform float Contrast;
uniform vec4 AverageLuminance;

void main(void)
{
   vec4 texColour = texture2D(Texture, gl_TexCoord[0].st);
   gl_FragColor = mix(texColour * Brightness, 
      mix(AverageLuminance, texColour, Contrast), 0.5);
}

Edit: some more details for completeness...

Brightness and contrast have a base value of 1.0, so passing that in for both will leave the texture unchanged. A value less than 1.0 will decrease brightness, and a value greater than 1.0 will increase it. A value less than 1.0 for contrast will make the texture more grey (less contrast), and a value greater than 1.0 will make it less grey (more contrast).

You can pass in (0.5, 0.5, 0.5, 1.0) for AverageLuminance for a quick-and-dirty grey value, but better results will be obtained by calculating a proper average luminance for your texture.

like image 140
Incredulous Monk Avatar answered Nov 04 '22 16:11

Incredulous Monk


You could render the brightness-adjusted image to a framebuffer texture of the same size, then perform the contrast adjustment as you render this texture to the screen.

Image -> [Brightness] -> Texture -> [Contrast] -> Screen

Some useful reading on framebuffers and render-to-texture:

  • Rendering with Framebuffer objects
  • OpenGL ES Render to Texture (SO)
  • Background info on framebuffers
like image 31
gavinb Avatar answered Nov 04 '22 15:11

gavinb