Advertisement

Inverted WindowDumps

Started by July 26, 2004 08:48 AM
5 comments, last by abvenia 20 years, 4 months ago
I had some code to dump what my openGL programs were doing into .ppm frames. I have made several mpegs with it; the last just this Friday. Today; I boot up my computer; use the same code and all of a sudden; it is outputting the frames upside down (and possibly flipped horizontal) I don't know how this could happen; I had the code in several different programs, and one of those I haven't modified in several weeks. The code is below if you can help; thanks!

void WindowDump(int width,int height)
{
  FILE *fptr;
  char fname[32], frame[30];
  char *image;

  //sprintf(frame,"%s.ppm",name);
  
  if((image=malloc(3*width*height*sizeof(char)))==NULL) 
    fprintf(stderr,"WindowDump - Failed to allocate memory for image\n");

  glPixelStorei(GL_PACK_ALIGNMENT,1); 
  sprintf(fname,"frame-%d.ppm",counter++);          //"frame-%d.ppm"
   
  if((fptr=fopen(fname,"w"))==NULL)
    fprintf(stderr,"WindowDump - Failed to open file for window dump\n");

  glReadBuffer(GL_BACK);
  glReadPixels(0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,image);

  printf("Saving Frame-%d.ppm\n",counter);
  fprintf(fptr,"P6\n%d %d\n255\n",width,height);
  fwrite(image,3*width*height*sizeof(char),1,fptr);
   
  fclose(fptr);
  free(image);
}

I'm sure I can do some kind of rotation/translation effect to right the image; but it's not really a good way to do it. If there is some glitch in my function, or a quick/easy way to compensate; I'd be glad to hear it. Thanks.
Advertisement
If I'm not mistaken, PPM-files have the origin in the upper left corner, but OpenGL works with the origin in the lower left corner. That means, the first row of pixels from OpenGL is the bottom row, but in the image, it's the top row. To write it correct to the file, you have to write each line from top to bottom, i.e. start with the last row in the buffer, and work towards the first row.
Quote: Original post by Brother Bob
To write it correct to the file, you have to write each line from top to bottom, i.e. start with the last row in the buffer, and work towards the first row.


So; the glReadPixels call has to change? I know that the height and width specify the lower left corner; but I don't know how to change that AND reverse the reading direction, something to do with GL_STENCIL_INDEX maybe? Thanks for finding the problem!
Ok; I have an idea how to go about solving the problem (I think).

Since the PPM's have an upper left origin and openGL assumes bottom left, the buffer has to be changed when it is read in.

I'm trying to do this by changing the starting values of the "left corner" and also changeing how the buffer is read via GL_INDEX_SHIFT / GL_INDEX_OFFSET. I can't find the combination to properly arrange it though...

Here's the modified bit of the function;
[SOURCE]  if((image=malloc(3*width*height*sizeof(char)))==NULL)     fprintf(stderr,"WindowDump - Failed to allocate memory for image\n");  glPixelStorei(GL_PACK_ALIGNMENT,1);   //sprintf(fname,frame,counter++);          //"frame-%d.ppm"     if((fptr=fopen(fname,"w"))==NULL)    fprintf(stderr,"WindowDump - Failed to open file for window dump\n");  glReadBuffer(GL_BACK);    glPixelTransferf(GL_INDEX_SHIFT,1.0);  glReadPixels(0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,image);  printf("Saving Frame-%d.ppm\n",i);  fprintf(fptr,"P6\n%d %d\n255\n",width,height);  fwrite(image,3*width*height*sizeof(char),1,fptr);     fclose(fptr);  free(image);[/SOURCE]


If I'm on the right track and you can tell me what I'm doing wrong. If I'm completely off; well, let me know. Thanks!
Index shifts and offset is not what you want, they are for shifting and offsetting the color value when readng back in indexed color mode. You don't want any glPixelTransfer commands at all. glPixelTransfer manipulates the color value being read back. What you want would, theoretically, go into glPixelStore, which affects how pixels are being stored in memory. Unfortunately, there are no options you can pass to glPixelStore to flip the image, so you have to do it yourself.

You can do that in two simple ways.
1: Read the entire image in one go, and write the image row by row from the top down.
2: Read the image row by row from the top down, and write the entire image in one go.

Here's some pseudo-code for option 1.
image=malloc(3*width*height*sizeof(char))fptr=fopen(fname,"w")glReadPixels(0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,image);fprintf(fptr,"P6\n%d %d\n255\n",width,height);for(int row = height - 1; row >= 0; --row){    fwrite(image + 3*row*width, 3*width, 1, fptr);}
Advertisement
Quote: Original post by Brother Bob
Here's some pseudo-code for option 1...


Ok; you just destroyed my problem. I was really pretty lost; the code wasn't originally mine (I was working with actual WindowDumps - .wmd's).

The frames seem to be coming out properly now; thanks!

This topic is closed to new replies.

Advertisement