Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

destrier

glreadpixels: if you know the ins and outs of...

This topic is 6150 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Thank you for having the kind heart to click on my question. on to business...this is my problem: I am using glreadpixels to write pixel data to a file but I don’t understand what the data I get back from the array means. for example for a 10 X 10 picture of a 5 X 5 square in the lower left hand corner I should be getting the data: 0 0 0 0 0 255 255 255 255 255 0 0 0 0 0 255 255 255 255 255 0 0 0 0 0 255 255 255 255 255 0 0 0 0 0 255 255 255 255 255 0 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 but instead I get this: 0 0 0 0 0 255 255 255 255 255 136 0 0 0 0 85 255 255 255 255 238 68 0 0 0 0 170 255 255 255 255 221 0 0 0 0 0 255 255 255 255 255 136 0 0 0 0 85 255 255 255 255 238 238 255 255 255 255 255 255 255 255 255 221 255 255 255 255 255 255 255 255 255 255 221 255 255 255 255 255 255 255 255 255 238 238 255 255 255 255 255 255 255 255 255 221 255 255 255 255 255 for this code: void send_image_data_to_text(void) // this function is part of a class, pixel is a pointer to an //array in the class { RGB value; int count; int r,g,b; int lum; glReadPixels(0, 0, 10, 10, GL_RGB, GL_UNSIGNED_BYTE, pixel); if (examplefile.is_open()) { examplefile << "PGM\n"; examplefile << " P2\n"; cout << "\n"; for(count=0; (count<=(nRows*nCols)); count++) { value = pixel[count]; r = static_cast(value.r); g = static_cast(value.g); b = static_cast(value.b); lum = (r+g+b)/3; examplefile.setf(ios::left, ios::adjustfield); examplefile.width(4); examplefile.fill('' ''); examplefile << lum ; cout.setf(ios::left, ios::adjustfield); cout.width(4); cout.fill('' ''); cout << lum; if (((count%nCols) == 0) && (count != 0)) { examplefile << "\n"; cout << "\n"; } } examplefile.flush(); examplefile.close(); } } So my Question is what is all this data and how can I get it close to my ideal data set which I showed first? thank you very much any pieces of the puzzel will be much appreciated.

Share this post


Link to post
Share on other sites
Advertisement
I haven''t played with the glReadPixel function, but one idea that I have (I think it reads it from the buffer as far as I remember - but as I said I haven''t used it, only read the documentation for it) is that your image may be anti-aliased. Just a though.



Beer - the love catalyst
good ol'' homepage

Share this post


Link to post
Share on other sites
(if it''s a factor I''m using glut)
how do I turn dithering on and off
here is my window initialization function:

void myInit(void)
{
glClearColor(1.0,1.0,1.0,0.0);
glColor3f(0.0f,0.0f,0.0f);
glPointSize(1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, xMAX, 0.0, yMAX);
}

Share this post


Link to post
Share on other sites
This is just a guess, but I think your stride is off in accessing the array "pixel". I dont know what you declare it to be, but you are accessing 3 bytes at a time (R,G,B), so you need to make sure that pixel is defined to be an array of 3 bytes (i.e., pointer to RGB). I dont believe its anti-aliasing or dithering because the numbers on the first column are getting set, which would not happen since they are at the edge. Your output is also off (your for loop should be
for(count=0; (count<(nRows*nCols)); count++)

and the row end check should be done first thing in the loop)

This is the correctly format table and as you see the numbers are even more out there than before, so I assume it''s a representation problem. Hope this helps.


0 0 0 0 0 255 255 255 255 255
136 0 0 0 0 85 255 255 255 255
238 68 0 0 0 0 170 255 255 255
255 221 0 0 0 0 0 255 255 255
255 255 136 0 0 0 0 85 255 255
255 255 238 238 255 255 255 255 255 255
255 255 255 221 255 255 255 255 255 255
255 255 255 255 221 255 255 255 255 255
255 255 255 255 238 238 255 255 255 255
255 255 255 255 255 221 255 255 255 255

Share this post


Link to post
Share on other sites
my array pixel is an array of type RGB which is defined as
class RGB
{
public:
unsigned char r,g,b;
};

so I don''t think that my stride is off.
those values are really there any other idea why
plus I screen captured the window and looked at it in adobe photoshop
there is no anti-aliasing so there should only be the values 0 and 255 in the array
in any case. also every row should start with a zero since that side is covered with a black square.
any other guesses?

if you don''t know
thanks again for the response, anyway.

Share this post


Link to post
Share on other sites
try
glReadPixels(0, 0, 10, 10, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel);
does it sorta give the right results

http://uk.geocities.com/sloppyturds/gotterdammerung.html

Share this post


Link to post
Share on other sites
The code looks fine, but I still think it''s some kind of memory access problem. I''ve always used GL_RGBA to get the pixel data, which is a nice quadword for memory access. Otherwise, I do the same thing that you are doing. Given that, I would allocate an array of unsigned char and pass that into the glReadPixels and see if you are getting the same data. It could be that you are getting some kind of memory fragmentation or padding with your RGB class.

Share this post


Link to post
Share on other sites
dont forget, all bmps are have dword aligned scanlines. so adjust your stride accordingly. aslo are you sure that you are writing the file correctly? (stupid question, but its a possiblity, though i dont use iostream for file access so i cant say if its correct or not).

also luminece is better calculated using weighted value instead of a straight avgerage.

try doing:
lum = (77*r + 153*g + 26*b)>>8;

that uses fixed point math, so its quite fast (no float to int conversions). this is a formula i found one day which tries to mimick a moniter and how the human eye sees color. the human eye is more sensitive to green then red then blue. this will give images that appear more naturally shaded. you can adust the weights as you see fit BUT the coefficents MUST add up to 256 or things wont work correctly (ie your image will be darker or lighter then it should). i only point this out so that if you want nicer looking grayscale images, you can stick to your method if it gives you the quality you want, but i find this gives overall a better shading visually.

also you may want to look over and make sure that msvc is not padding your struct. you can chekc this with a sizeof(), it is possible that vc++ padded to DWORD size so when opengl writes to the buffer its all off. since reading the color components is easy enough (especialy in 24bit mode that you seem to be using) just use a normal block of memory thats not using your struct.
and read it like:

  
// btw the stride problem is possible related to your buffer

// also i think the a double loop is better for writing the file

// much cleaner

// assumes pixel is a UCHAR*

// not bother to dword align the pitch

// since gl may not need to have its scanlines

// dword aligned

int bufPitch = nRows*3;
int xi, yi;
for(yi=0; yi<nCols; yi++)
{
for(xi=0; xi<nRows*3; xi+=3)
{
r = pixel[(xi+0)+yi*bufPitch];
g = pixel[(xi+1)+yi*bufPitch];
b = pixel[(xi+2)+yi*bufPitch];
lum = (77*r + 153*g + 26*b)>>8;
examplefile.setf(ios::left, ios::adjustfield);
examplefile.width(4);
examplefile.fill('' '');
examplefile << lum ;
cout.setf(ios::left, ios::adjustfield);
cout.width(4);
cout.fill('' '');
cout << lum;
}
examplefile << "\n";
cout << "\n";
}

examplefile.flush();
examplefile.close();

// much cleaner ne?


Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!