2
$\begingroup$

I want to create a histogram of intensities 0.1, 0.2, .... 0.9, 1, from an image rendered using OpenGL and C++. How can I do this? Can I access the pixel intensities in the framebuffer somehow? Also, I'm not using any glsl shaders, and don't intend to.

So far I tried:

unsigned char *framebuffer = frameBuffer = new unsigned char[1920*1080 * 4];

glReadPixels(0, 0, 1920, 1080, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);

for (int j = 0; j<1920*1080 * 4; j += 4){
    if(frameBuffer[j] == 0.1)
        // find pixel with R channel at 0.1: this is where the problem is.
        // I know I have surfaces with this intensity but I never enter the if statement
}
$\endgroup$
  • 1
    $\begingroup$ Yes, you can do that. What issue are you having with doing that? What have you tried that hasn't worked? You need to give us more information. $\endgroup$ – user1118321 Jan 27 '18 at 22:48
  • $\begingroup$ I added more information above, does it help? Thanks. $\endgroup$ – Stackmm Jan 27 '18 at 23:21
2
$\begingroup$

Due the way floating point values work, you probably don't want to do an exact equality check. You probably want something more like this in your loop:

uint32 sums [ 11 ] = { 0 };
for (int j = 0; j < 1920 * 1080 * 4; j += 4) {
    size_t bucket = static_cast<size_t>(framebuffer [ j ] * 10.0);
    sums [ bucket ]++;
}

Note that there are 11 buckets because the range includes both 0 and 1. If you want only 10 buckets and want to put any pixels that have a value of 1 in them into the top bucket, you could do:

uint32 sums [ 10 ] = { 0 };

and change the bucket index calculation to:

size_t bucket = static_cast<size_t>(framebuffer [ j ] * 10.0);
bucket = std::min(bucket, 9);
$\endgroup$
  • $\begingroup$ Thanks for the solution. It makes sense! Although I'm testing things out, and I'm suspecting that framebuffer[j] isn't a value between 0 and 1. I'm trying to figure out if it's a value between 0 and 255 instead and hoping there isn't some other subtle transformation in the values. $\endgroup$ – Stackmm Jan 28 '18 at 3:01
  • 1
    $\begingroup$ @Stackmm, It is a value between 0 and 255. They are 8-bit normalized, meaning the values in the interval 0.0 through 1.0 are mapped to the 8-bit codes 0x00 through 0xFF. The 8-bit value you are looking for that equals 0.1 is: (unsigned char)(0.1 * 255.0 + 0.5) or about 26. $\endgroup$ – Wyck Jan 31 '18 at 15:57
  • $\begingroup$ Thank you very much! That solved everything. I'm glad I learned about the mapping. $\endgroup$ – Stackmm Jan 31 '18 at 22:55
  • $\begingroup$ Ah, I failed to notice that you were using GL_UNSIGNED_BYTE as the type for the call to glReadPixels. You could use GL_FLOAT to get floating point values. (Just make sure to allocate space for them. Your current allocation specifies new unsigned char [].) $\endgroup$ – user1118321 Feb 1 '18 at 1:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.