Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pixel access with glGetTexImage()?

I have a problem with OpenGL and glGetTexImage().

I want to get the pixels of a texture that I've created before with code like this:

glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D,
    0, 
    GL_RGBA, 
    width,
    height,
    0, 
    GL_RGB, 
    GL_UNSIGNED_BYTE, 
    someRandomPixels);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

I'm using SDL2.

After I loaded that texture I tried to get the pixels of this texture in a GLuint* pixels pointer which I declared as follows:

GLuint* pixels = new GLuint[256*256*4];

the size of this image was 256x256 pixels.

I got the pixel data by using

GLuint* Textur::getPixelsOfTextur(GLuint textur, int width, int height, int numChannels)
{
    GLuint* pixels=new GLuint[width*height*numChannels];
    glBindTexture(GL_TEXTURE_2D, textur);
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT, pixels);
     return pixels;
}

Where "numChannels" is 4 for RGBA and 3 for RGB

Now my problem is that I really have no clue how to address Pixel p(x,y) correctly since the size of my array is 4 times bigger than the pixel count and every time I use a smaller size visual studios throws an error:

Exception thrown at 0x5ED71FCE (opengl32.dll) in sdl_opengl_Frameworktest.exe: 0xC0000005: Access violation writing location 0x09C33000.

Also, is it possible to get those data in a 2D array?

like image 411
StrayFurther Avatar asked Feb 22 '18 23:02

StrayFurther


1 Answers

The size of the array in bytes is 1048576 bytes (256 * 256 * 4 * sizeof(GLuint)). This is, because every color channel of a single pixel is stored in a separate GLuint with a size of 4 bytes (sizeof(GLuint) == 4). So the size of each pixel is 16 bytes because of 4 color channels per pixel and sizeof(GLuint) for each color channel.

Probably it will be sufficient to store every color in an GLubyte. Then the size of the array will be 262144 bytes (256 * 256 * 4 * sizeof(GLubyte))

GLubyte* pixels = new GLubyte[256*256*4];

glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

Regardless if you use GLuint or GLubyte, the colors of a single pixel can be accessed like this:

GLuint r, g, b, a; // or GLubyte r, g, b, a;

size_t x, y; // line and column of the pixel

size_t elmes_per_line = 256 * 4; // elements per line = 256 * "RGBA"

size_t row = y * elmes_per_line;
size_t col = x * 4;

r = pixels[row + col]; 
g = pixels[row + col + 1]; 
b = pixels[row + col + 2]; 
a = pixels[row + col + 3]; 


If you want to calculate a gray scale value from the r, g , b values, the this can be don like this:

GLubyte gray = (GLubyte)((r + g + b) / 3.0);

Another popular formula can be found at Luma:

GLubyte gray = (GLubyte)(r*0.2126 + g*0.7152 + b*0.0722);

Replace the color RGB channels by the grayscale:

pixels[row + col]     = gray; 
pixels[row + col + 1] = gray; 
pixels[row + col + 2] = gray; 
like image 109
Rabbid76 Avatar answered Sep 19 '22 16:09

Rabbid76