Plotting Pixels


   First of all, if you have not read both my palette DOC and my 13h DOC then you should do so before you continue.

What does "plotting a pixel" mean?

   Well, when you plot a pixel on the screen you're changing the value of a small piece of memory.  Your screen is represented by a piece of memory in the computer that is basicaly just a huge array of integers, and each integer represents a pixel on the screen.  When that piece of memory is displayed on the screen, all that really happens is that that array of integers is copied to the screen... well, actaully "copied" isn't exactly correct.  What really happenes is that the first integer value is taken as a palette index and then that color is displayed on the screen at the pixel which that integer represented (I hope I didn't loose you there... read it over a few times and you might under stand it a bit better), and it just continues to do that to the next integers with the next pixels until it has displayed the entire piece of memory.  So all we have to do to "plot a pixel" is change the integer value of the pixel to the color that we want it to be changed to.  So plotting a pixel isn't really placing a pixel on the screen, it's just changing the color of the existing pixel.
   There are a few terms that you need to know before proceding:
1) video memory or vga memory-  the memory that represents the screen, which is the same memory that is "copied" to the screen as stated above.
2) video buffer or vga buffer-  an array of integers that is declared by the user that is the same length as the real video memory.  It is later used to be changed as if it were the video memory and is then copied to the video memory.  All of this effort eliminates almost all flickering.
 
So how do I plot a pixel?

   Well, first you need to know where the video memory is.  Luckly we have alread declared a pointer to it named "vgamemory" with our "init_vga_mode" function (the code is given in the 13h DOCS).  But for those of you who are curious, the video memory is at 0xA0000, and continues on for 64,000 integer values.   But wait a second, how can this represent the screen when the screen is 320x200 and the memory is a long row 64,000?  For those of you who are quick to catch on, the reason this work is because of the following equation:  320 * 200 = 64,000.  Wow!  What a fluke!  But seriously, all you have to do is know that the first 320 values represent the first row of pixels, the second 320 values represent the second row of pixels, etc.
   Now how can we put the above knowlege to use?  Well...  WE COULD MAKE A PIXEL PLOTTING FUNCTION!!!   All we have to do is make a function that asks for the x and y values of the pixel that we want to change, and then ask for the color palette index that we want to change it to.  But how are we going to figure out which integer value to edit  with just the x and y value?  That's easy!  All we have to do is start at 0, add 320 for each row down it goes which is the same as Y*320, and then we add x.  Try doing that on some graph paper with a rectangle that's x=12 by y=10 or somthing, except replace 320 with the x RES and you'll se that it works.  The only problem with this is that the higher your y value, the further down the pixel is on your screen... and we're all used to a graph that the higher the y value the higher the position.  Well, that's not really a problem, I just make sure that I rember tto imagine the screen as a graph that's been fliped up side down.  But if you just can't think of it that way then you can use the following equation, assuming that "A" is the index of the video memory index of the integer that you want to change:  A = 64000 - (320*Y+(320)) + X.  Other wise, if you can handle the imaginary graph flipping then you can use the following equation:  A = 320 * Y + X.  Now all we have to do is to make a function using that equation, which wouldbe the following:

void putpix(int x, int y, int color)
{
   vgamemory[y*320+x] = color;
}

   So now we have a plot pixel function.  Although it's not as fast as it could be...  what we want to do is take the multiplication and make it a binary shift.  But wait, we can't shift y by a number that will multply it by 320... can we?  No, we can't, at least not in just 1 shift.  What we are going to have to do is shift y multiple times and then add the results of each, like this:

A = (y<<8) + (y<<6)

   And that would do the same thing as "A = 320 * y" because:

y^8 = y * 256
y^6 = y * 64
256 + 64 = 320

   So now we just have to impliment that:

void putpix(int x, int y, int color)
{
   vgamemory[(y<<8)+(y<<6)+x] = color;
}

   But wait, there's still one problem...  What if x is more then 320?  Well, first of all: x isn't suppost to even be more then 319 because it ranges from 0 to 319 not 1 to 320 and it's the same thing with y: it ranges from 0 to 199 not 1 to 200.  So now that we have that cleared up, would you like to re-state your question:  What if x is more then 319?  Well, if x is more then 319 then the pixel it edits wil circle around and go down one row instead of not being displayed like it's suppost to.  You can also test that out on graph paper.  So now we need to protect against that... and how would we do that?  We just make an if statement:

void putpix(int x, int y, int color)
{
   if(x < 320)
   {
      vgamemory[(y<<8)+(y<<6)+x] = color;
   }
}

   So now our pixel function is perfect, right?   WRONG!!!  What if the x value is less then 0?  Then it will do the exact opposite... it will circle around and go up one row.  So how do we protect against that?  We just add to the if statement that we already made:

void putpix(int x, int y, int color)
{
   if(x < 320 && x > -1)
   {
      vgamemory[(y<<8)+(y<<6)+x] = color;
   }
}

  So NOW our pixel function is perfect... right?  I hope? please?  Nope, sorry.  We still have to protect against the y value being more then 199 or less then 0.  If we don't, it may not draw the pixel on the screen, but it will change some other piece of memory that we don't want it to, and that could crash the computer or at least mess up your program.  So we just add to the if statement a couple more times:

void putpix(int x, int y, int color)
{
   if(x < 320 && x > -1 && y < 200 && y > -1)
   {
      vgamemory[(y<<8)+(y<<6)+x] = color;
   }
}

   Sheesh, I never knew it would be so hard to plot a pixel... I bet there's somthing else wrong with it, right?  Nope, now our plot pixel function is perfect... took long enough!
 

So now I'm done?

   Yup!  Except for one thing... I would very much like to thank Paolo Pancheri who's code tought me how to do 2d graphics with DJGPP.  With out him these DOCS wouldn't be here at all.  Paolo Pancheri's code apears in tid bits through out these DOCS because I still use some of his code.  Also if you want to learn to do more then just plot pixels and stuff you can brows through my other documentation. 


Discuss this article in the forums


Date this article was posted to GameDev.net: 7/16/1999
(Note that this date does not necessarily correspond to the date the article was written)

See Also:
Graphics

© 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
Comments? Questions? Feedback? Click here!