High Speed
Fundamental Graphics
Site Map Feedback

Download:

Up Colours Drawing Effects Patterns PixelBlock Textures

Draw to RAM, Blit to Screen

If you want to re-invent the wheel and do your own graphics primitives, this is for you!
To draw to the screen really fast you need an area of memory you can access directly and Blit to the screen.
The fundamental thing you want to do is be able to call functions SetPixel(x,y,Colour) and GetPixel(x,y).
It's incredibly slow to do this using operating-system setpixel/getpixel or even writing directly to your Video Card: they're just not designed to be used that way (circa 1990s).
Instead you're expected to write to your own copy of the screen in RAM memory and use a Video Card function called "Blit" which copies your logical screen to the physical screen.
The word "Blit" came from "Bit Block Transfer"... somehow.
Just how you go about creating and blitting depends on your operating system and isn't always obvious.
Windows, for example, has a Blit function, but this transfers areas of the screen to RAM or other areas of screen, which isn't what is wanted.
It turns out that the function to use is SetDIBitsToDevice.
Since the easiest way to draw is 24 bits per pixel ('True Colour'), that is what this system uses.
Hopefully the code in the following class will be sufficient for you to encapsulate the same behaviour whatever operating system you are using.

The Pixel Block of RAM that you draw to, is an array of DWORDs each holding the colour in the format 0xRRGGBB
RR the Red, GG the Green and BB the Blue (the most significant byte isn't used). This is the opposite way round to what the RGB() Macro provides.
The only other important data structure is a BITMAPINFO with its bmiHeader.biCompression set to BI_RGB.
Code is included to initialise the Pixel Block by blitting to the PixelBlock.
You can also Save the PixelBlock as a 24bpp Bitmap File (.bmp).

Here's an example using an Owner-draw button as the DC to draw to:
#include "PixelBlock.h"
void CMyDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) {
  if(nIDCtl==IDC_Pic) {
    CPixelBlock PixelBlock(100,100);
    DrawThingsOn(PixelBlock);
    PixelBlock.Paint(lpDrawItemStruct->hDC, 10,10);
  }
  CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}
Actually, it isn't yet possible to draw on the PixelBlock because the Bits Array is protected!
You have to derive a class from CPixelBlock and add methods to allow drawing in whatever way you require.
The most basic requirements are as follows:
  static DWORD BGR2RGB(DWORD Colour) {return BYTE(Colour>>16)|(Colour & 0xFF00)|(Colour<<16);}

  bool   IsValid   (WORD x, WORD y)                 const {return x<Width && y<Height;}
  void   SetPixel  (WORD x, WORD y, DWORD Colour)         {    if(IsValid(x,y))   Bits[Width*y+x] = Colour;}
  DWORD  GetPixel  (WORD x, WORD y, DWORD Colour=0) const {return IsValid(x,y) ?  Bits[Width*y+x] : Colour;}
  DWORD* GetPointer(WORD x, WORD y)                 const {return IsValid(x,y) ? &Bits[Width*y+x] : 0;}
The Colours, Drawing and Patterns sections have further extensions.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.