Pixel access with glGetTexImage()?
Asked Answered
L

1

6

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?

Lancastrian answered 22/2, 2018 at 23:30 Comment(1)
Although it is not because of the reason I commented, but for people searching for "OpenGL texture to image", who must notice glGetTexImage isn't available in OpenGL ES(according to this answer stackoverflow.com/a/11947751)Watchband
E
6

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; 
Equimolecular answered 23/2, 2018 at 5:41 Comment(6)
Thank you! I'm going to try this tomorrow and tell you how it workedLancastrian
Now that I implemented it like you told me erveything works. Thank you! You are a time and life saverLancastrian
Just one further question. I tried to replace every pixel with it's gray pixel by calculating it's average. The resulting texture seems a bit dark compared to ImageJ results. I know that that's not C++ but maybe you have an ideaLancastrian
sry to bother you again and if you don't know it it dosnt matter, but do you now an answer to my second question i asked in the comments?Lancastrian
thank you do i need to uncheck this mark so that u can alter it? I'm relatively new here. I just do itLancastrian
Yup the luma version worked just fine. Thank you again, kind man! I let the check mark checked now. You are the best!Lancastrian

© 2022 - 2024 — McMap. All rights reserved.