glDrawPixels only works some times?

I load a bitmap into an unsigned char buffer, then (after reversing the BGR to RGB bytes) send it to glDrawPixels in the classic call:

[Code]
      glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
      glRasterPos2f (atX, atY);
      glDrawPixels (width, height, GL_RGB, GL_UNSIGNED_BYTE, bitmapImage);
[/Code]

[atX] and [atY] get changed around as I move the image on the screen (Yes: we're bordering on Game Programming here.  Since this is based on OpenGL mechanics - glDrawPixels - I figured it belonged here...), and sometimes (with the wierdest of locations) the image displays/shows up.  In the wrong place than I intended, but it appears!  (Sometimes...)

For instance, when I tell it to display atX = -11.0 atY = -0.7 --- this seems to put the image on the screen, sort of.  Long story short: why would this work sporadically?  Or would you like to see the code that calls this?  I can include it, if you like, but it's sort of involved...

I just don't get the sporadic works/don't work nature of the call...    ...could I be doing something insignificant elsewhere that is causing OpenGL to freak out?

Hoping for some light to shed on my poor, benighted program,

- The Lurking LongFist
LVL 1
LongFistAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

LongFistAuthor Commented:
This is the code for the object in question:

[Code]

// BitMapImage.Cpp //


// Scarfed together (from several different sources) to allow an image
// (or image segment) to be loaded into memory with all of its supporting
// data, and then take care of displaying itself on the screen, leaving
// the higher-level code cleaner and easier to read...


#include "BitMapImage.h"


#pragma once
#define BITMAP_ID 0x4D42                                                // the universal bitmap ID


      static BITMAPINFOHEADER imageHeader;                  // bitmap info header
      static unsigned char* imageData;                              // the bitmap data

      static GLfloat xLoc;                                                      // (last) Displayed X Position
      static GLfloat yLoc;                                                      // (last) Displayed Y Position

      static bool isLoaded;                                                // Is there an image here?



// (Private) Function Prototypes

void DrawBitmap (long width, long height, unsigned char* bitmapImage, GLfloat atX, GLfloat atY);
unsigned char *LoadBitmapFile (char *filename, BITMAPINFOHEADER *bitmapInfoHeader);




BitMapImage::BitMapImage (void)                                          // Default Constructor
{
      imageData = NULL;

      isLoaded = false;
}


BitMapImage::BitMapImage (char *fileName)                  // Named/Prepared Constructor
{
      imageData = LoadBitmapFile(fileName, &imageHeader);

      if (imageData == NULL)
            {
            isLoaded = false;
            }
      else
            {
            isLoaded = true;
            }
}


BitMapImage::~BitMapImage (void)                                                // Destructor
{
      // Prevent Memory Leaks...

      if (imageData != NULL)
            {
            free (imageData);
            imageData = NULL;
            }

}



BitMapImage::Load (char *fileName)                  // Named File Loader
{
      imageData = LoadBitmapFile(fileName, &imageHeader);

      if (imageData == NULL)
            {
            isLoaded = false;
            }
      else
            {
            isLoaded = true;
            }
}


BitMapImage::Loaded (void)
{
      return (isLoaded);
}



BitMapImage::Display (GLfloat xPos, GLfloat yPos)
{
      xLoc = xPos;
      yLoc = yPos;

      DrawBitmap (imageHeader.biWidth, imageHeader.biHeight, imageData, xLoc, yLoc);
}



BitMapImage::Display ()
{

      DrawBitmap (imageHeader.biWidth, imageHeader.biHeight, imageData, xLoc, yLoc);
}



BitMapImage::Locate (GLfloat xPos, GLfloat yPos)
{

      xLoc = xPos;
      yLoc = yPos;

}


BitMapImage::x(void)
{
      return (xLoc);
}

BitMapImage::x(GLfloat newX)
{
      xLoc = newX;
}


BitMapImage::y(void)
{
      return (yLoc);
}

BitMapImage::y(GLfloat newY)
{
      yLoc = newY;
}



BitMapImage::width (void)
{
      return (imageHeader.biWidth);
}

BitMapImage::height (void)
{
      return (imageHeader.biHeight);
}




void DrawBitmap(long width, long height, unsigned char* bitmapImage, GLfloat atX, GLfloat atY)
{
      if (isLoaded = true)
            {
            glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
            glRasterPos2f(atX, atY);
            glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, bitmapImage);
            }
}



unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
      FILE *filePtr;                                                // the file pointer
      BITMAPFILEHEADER      bitmapFileHeader;            // bitmap file header
      unsigned char            *bitmapImage;                  // bitmap image data
      int                              imageIdx = 0;                  // image index counter
      unsigned char            tempRGB;                        // swap variable

      // open filename in "read binary" mode
      filePtr = fopen(filename, "rb");
      if (filePtr == NULL)
            return NULL;

      // read the bitmap file header
      fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
      
      // verify that this is a bitmap by checking for the universal bitmap id
      if (bitmapFileHeader.bfType != BITMAP_ID)
      {
            fclose(filePtr);
            return NULL;
      }

      // read the bitmap information header
      fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);

      // move file pointer to beginning of bitmap data
      fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);

      // allocate enough memory for the bitmap image data
      bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);

      // verify memory allocation
      if (!bitmapImage)
      {
            free(bitmapImage);
            fclose(filePtr);
            return NULL;
      }

      // read in the bitmap image data
      fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);

      // make sure bitmap image data was read
      if (bitmapImage == NULL)
      {
            fclose(filePtr);
            return NULL;
      }

      // swap the R and B values to get RGB since the bitmap color format is in BGR
      for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3)
      {
            tempRGB = bitmapImage[imageIdx];
            bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
            bitmapImage[imageIdx + 2] = tempRGB;
      }

      // close the file and return the bitmap image data
      fclose(filePtr);
      return bitmapImage;
}

[/Code]
0
LongFistAuthor Commented:
...and here is the header file that feeds/describes it:

[Code]

// BitMapImage.h //


// Scarfed together (from several different sources) to allow an image
// (or image segment) to be loaded into memory with all of its supporting
// data, and then take care of displaying itself on the screen, leaving
// the higher-level code cleaner and easier to read...



#include <math.h>                        // for abs and sqrt
#include <stdlib.h>                  // for rand
#include <stdio.h>
#include <windows.h>
#include "glut.h"                        // standard GLUT functions



class BitMapImage
{
                                                                        // ------------------------------
      public:                                                      // Public interfaces of the class
                                                                        // ------------------------------

      BitMapImage ();                                                      // Default Constructor
      BitMapImage (char *fileName);                              // Named/Prepared Constructor

      ~BitMapImage (void);                                                // Destructor

      Load (char *fileName);                                          // Allows change/re-use of resources
      Loaded (void);                                                            // Allows determination if load was successful

      width (void);                                                            // Returns image width
      height (void);                                                            // Returns image height

      Locate (GLfloat xPos, GLfloat yPos);            // Allows change/setting X, Y locations
      x(void);                                                                        // Returns current X location
      x(GLfloat newX);                                                      // Allows setting of (new) X location
      y(void);                                                                        // Returns current Y location
      y(GLfloat newY);                                                      // Allows setting of (new) Y location

      Display (GLfloat xPos, GLfloat yPos);            // Method for display
      Display (void);                                                      // Method for (repeat) display

};

[/Code]
0
LongFistAuthor Commented:
Use: when I start the program, I like to pre-load everything, so I perform the following:

[Code]

void LoadTextures (void)
{
      SetTextureParameters();
      LoadBitmapTexture (ID_ALIEN);

      TitleFrame.Load ("Images\\TitleImage.bmp");
      TitleFrame.Locate (-11.7, -11.7);
}

[/Code]


Later on, when I want to draw out the title frame, I simply make the call:

[Code]

      TitleFrame.Display ();            // Put up the Title Frame

[/Code]

...and the TitleFrame should pop up on the screen.  Only it doesn't.  As a test, I started rendering additional data to the screen (in the form of a textured quad), and when I DON'T call TitleFrame.Display ();, I can see the textured QUAD.  But when I *do* call the TitleFrame.Display (); - I get a blank, black screen.

Could this be problems with the glDrawPixels() function?  I truly believe it to be.  Any light shed on this would be greatly appreciated!!!

- The Lurking LongFist
0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

ikeworkCommented:
hi LongFist,

seems your bitmap data rows are not aligned to 4 bytes, so you should use:

glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

this tells opengl, that there is no padding of the bitmap data rows to aligned memory


ike
0
ikeworkCommented:
how did you set up the view, ortho/perspective? please show us that function and the renderfunction as well ...

ike
0
LongFistAuthor Commented:
Q1: where would I put this command?  Just before the glDrawPixels in the DrawBitMap() function?

Q2:  First, I call PrepDisplay:

[Code]

void PrepDisplay (void)
{
      // Turn on those items we know we're gonna' need...
      glEnable (GL_LINE_SMOOTH);
      glEnable (GL_POINT_SMOOTH);
      glEnable (GL_POLYGON_SMOOTH);
      glEnable (GL_BLEND);
      glEnable (GL_ALPHA_TEST);


      // TEXTURE STUFF
      // these let the textures auto-generate coordinates for drawing
      glEnable(GL_TEXTURE_GEN_S); // texture's x coord
      glEnable(GL_TEXTURE_GEN_T); // texture's y coord


      // this tells OpenGL how to handle textures;
      // GL_MODULATE indicates that the texture should just stack on top of
      // the underlying material's color and shading
      // So, use GL_MODULATE instead of GL_REPLACE if lighting is being used
      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

      //enable textures
      glEnable(GL_TEXTURE_2D);

      // make sure we're drawing BOTH SIDES of polygons!
      glPolygonMode(GL_FRONT_AND_BACK, GL_POLYGON);

}

[/Code]


...then I make a call to InitLights () followed by a call to InitCamera ();


[Code]

void InitLights (void)
{
      // LIGHTING STUFF - One light source
      GLfloat amb[] = {0.5, 0.5, 0.5, 1.0};
      glLightfv (GL_LIGHT0, GL_AMBIENT, amb);

      GLfloat diff[] = {0.8, 0.8, 0.8, 1.0};
      glLightfv (GL_LIGHT0, GL_DIFFUSE, diff);

      GLfloat spec[] = {1.0, 1.0, 1.0, 1.0};
      glLightfv (GL_LIGHT0, GL_SPECULAR, spec);

      GLfloat pos[] = {300, 300, 200, 0};
      glLightfv (GL_LIGHT0, GL_POSITION, pos);

      glEnable (GL_LIGHT0);
      glEnable (GL_LIGHTING);

}



void InitCamera(void)                        // set appropriate camera parameters
{

      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();

      // Now, set a 3-D perspective view, with:
      // user-selected FOV in y direction (starts at 60 degrees),
      // user-selected aspect ratio for X (starts at 1:1),
      // starting at Z = 5,
      // ending at Z = 800, so you can see everything in between these values
      gluPerspective (60,                              // FOV: 60 degrees (in Y direction)
                               (4/3),                              // Aspect Ratio: 4:3  (X FOV)  [x:y ratio]
                                      5,                              // Near Clipping Plane is at 5 units
                                    800);                              // Far Clipping Plane is at 800 units

      // Now, set the camera at the eye position, looking at the target position,
      // and always have camera "up" be in the y direction
      gluLookAt(  0,   0,  20,                  // Eye is at (0, 0, 20)
                     0,   0,   0,                  // Eye is looking at (0, 0, 0)
                         0.0, 1.0, 0.0);                  // Eye's "up" is Y-Axis


      // get us back in the model-view matrix mode and reset it to identity
      glMatrixMode(GL_MODELVIEW); // set to display stuff
      glLoadIdentity(); // resets matrix again

}

[/Code]

...after that, I let 'er rip with the Object (Object Load Image, Object Display Image, etc.) - only it doesn't.

Sorry I'm such a noob - but I really would like this thing to work right.  I've somehow got to get the 2D and 3D renderings to work together, and I've started beleiving that maybe I should set my images out to 1024x1024, and texture up some GL_QUADs for background screens - but I'd rather figure out (or get help figuring out) glDrawPixels - it looks like it is supposed to do what I'm after...

Thanks for your help!!!

- The Lurking LongFist
0
LongFistAuthor Commented:
ALERT!  The R and B swapper had to be edited in order to prevent buffer overrun errors.  In some cases, it was possible that the last bytes weren't an order of 3, and thus out R/B reverser would count out further than the last byte, causing issues in other code.  Fixed: it should look like this:

[Code]

     // swap the R and B values to get RGB since the bitmap color format is in BGR
     for (imageIdx = 0; imageIdx < (bitmapInfoHeader->biSizeImage - 2); imageIdx += 3)
     {
          tempRGB = bitmapImage[imageIdx];
          bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
          bitmapImage[imageIdx + 2] = tempRGB;
     }

[/Code]

That way you don't end up with errors when you [free] the image data pointer.  Just thought you'd like to know.

- The Lurking LongFist
0
ikeworkCommented:
(Q1)

[Code]
     glPixelStorei (GL_UNPACK_ALIGNMENT, 1);  // << here 1 instead of 4 <<<<<<<<<<<<<<<<
     glRasterPos2f (atX, atY);
     glDrawPixels (width, height, GL_RGB, GL_UNSIGNED_BYTE, bitmapImage);
[/Code]

ike
0
LongFistAuthor Commented:
Okay, I'll give glPixelStorei() a shot and see what happens.

I guess I forgot to mention that the Render function simply makes calls to the TitleFrame object to display itself:

[Code]

     TitleFrame.Display();

[/Code]

...and everything should run pretty much on automatic.

Thanks alot - I'll try this, and be back in moments...

- The Lurking LongFist
0
LongFistAuthor Commented:
Okay, I'm still getting the blank screen instead of an image.  I'm not sure what to think at this point.

Could it be that I'm loading a 3+ MB file for an image?  Are there some other limitations that I might be hitting?  (Mind you, I'm running on a pretty snazzy GeForce Ti4200, so I figure it can handle it...)

Would giving you the image help things a little?  Here, you can find the image at
          <www.genes-machine.com/dlMaster/TitleImage.zip>
   - compressed for easier transit and to keep various browsers from blowing a fuse trying to display it.  This way you can see the issue from both ends, supply side and display side.

Curiouser and Curiouser,

- The Lurking LongFist
0
LongFistAuthor Commented:
Ah, did I somehow perchance offend everyone?  Or is glDrawPixels the red-headed stepchild of OpenGL?  Or am I expecting the impossible (yet again)?

Just curious,

- The Lurking LongFist
0
ikeworkCommented:
hi LongFist,

after rereading your task, i found this:

>> // make sure we're drawing BOTH SIDES of polygons!
>> glPolygonMode(GL_FRONT_AND_BACK, GL_POLYGON);

this is wrong, second parameter may be GL_POINT,GL_LINE or GL_FILL, so i guess you want this, polys filled on both sides:

>> glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);


have a look at:
http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/polygonmode.html


to make sure to avoid such errors put this error-check at significant places in your gl-code, at least after the render-function:

assert( glGetError() == GL_NO_ERROR );


if your problems are still there, please show us the relevant code again (gl-initialization,gl-render-func,gl-resize-func ... )
and try to explain in SHORT words, what is going to happen and what not ...


ike
0
ikeworkCommented:
in the evening i'm going to make a little sample-application, which does what you want, displaying your image on the screen at a given position and i'll post the code here, if you want to ...

please post your full-code again, so i can adapt and test it ...

0
LongFistAuthor Commented:
Okay.  As soon as I get back to that machine, I'll re-post the code, and we'll go from there.

Thanks for your efforts - this could be really cool, I think...

- The Lurking LongFist
0
LongFistAuthor Commented:
I cannot find the orignal code - it appears to have been waxed when the version of the product changed.  No news yet, but I'm now rolling through the last month's backups to find it.

Sorry it's taking so long, but in the meantime a workaround was discovered and revealedd to be that by using quad polygons, and texturing them with sqared-off versions (like 512x512) of the bitmap image it was possible to accomplish pretty much the same thing.  And since time was marching on, we used (and abused) it for all it was worth.

I'm still interested in making glDrawPixels work - I think I can see how it would improve response in an application - but I've gotta' figure it out to be sure.

So down through the last month's backups I go...
0
GranModCommented:
PAQed with points refunded (500)

GranMod
Community Support Moderator
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Game Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.