?
Solved

glDrawPixels only works some times?

Posted on 2006-04-11
17
Medium Priority
?
848 Views
Last Modified: 2013-12-06
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
0
Comment
Question by:LongFist
  • 10
  • 5
16 Comments
 
LVL 1

Author Comment

by:LongFist
ID: 16427328
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
 
LVL 1

Author Comment

by:LongFist
ID: 16427334
...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
 
LVL 1

Author Comment

by:LongFist
ID: 16427395
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 20

Expert Comment

by:ikework
ID: 16434594
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
 
LVL 20

Expert Comment

by:ikework
ID: 16434605
how did you set up the view, ortho/perspective? please show us that function and the renderfunction as well ...

ike
0
 
LVL 1

Author Comment

by:LongFist
ID: 16451295
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
 
LVL 1

Author Comment

by:LongFist
ID: 16451299
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
 
LVL 20

Expert Comment

by:ikework
ID: 16452887
(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
 
LVL 1

Author Comment

by:LongFist
ID: 16453106
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
 
LVL 1

Author Comment

by:LongFist
ID: 16453486
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
 
LVL 1

Author Comment

by:LongFist
ID: 16516698
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
 
LVL 20

Expert Comment

by:ikework
ID: 16576482
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
 
LVL 20

Expert Comment

by:ikework
ID: 16576529
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
 
LVL 1

Author Comment

by:LongFist
ID: 16592244
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
 
LVL 1

Author Comment

by:LongFist
ID: 16773685
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
 

Accepted Solution

by:
GranMod earned 0 total points
ID: 16974714
PAQed with points refunded (500)

GranMod
Community Support Moderator
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What is RenderMan: RenderMan is a not any particular piece of software. RenderMan is an industry standard, defining set of rules that any rendering software should use, to be RenderMan-compliant. Pixar's RenderMan is a flagship implementation of …
Artificial Intelligence comes in many forms, and for game developers, Path-Finding is an important ability for making an NPC (Non-Playable Character) maneuver through terrain.  A* is a particularly easy way to approach it.  I’ll start with the algor…
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
this video summaries big data hadoop online training demo (http://onlineitguru.com/big-data-hadoop-online-training-placement.html) , and covers basics in big data hadoop .
Suggested Courses
Course of the Month14 days, 1 hour left to enroll

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question