How to display bitmap data FAST

Posted on 2002-07-15
Last Modified: 2013-11-20
I have this code.  The first part of it reads in a JPEG file (this code is omitted).  The remaining code displays this image on the screen.

The problem is that this operation is very slow.  The code I have included is the slow part, and when you see it, you will understand why it is slow.

I would like to know how to display this image FAST.  Full points to the best explanation that provides at least a 5x improvement over what is there now.

void CPhotoShowDlg::LoadPhoto (int pos, int dir)
{ // Some code here is omitted.
  // At this point, there are the variables
  // width, height, and a pointer imgData.
  // The first two specify the dimensions of the data,
  // the third specifies the data itself.

  // Now we want to display the image on the screen
  // in the m_StaticPic child CWnd.

  // Allocate primary DC
  CDC *dc = m_StaticPic.GetDC ();

  // Allocate and create memory DC
  CDC *memDC = new CDC ();
  memDC->CreateCompatibleDC (dc);

  // Initialize blank bitmap
  CBitmap *Bitmap = new CBitmap ();
  Bitmap->CreateCompatibleBitmap (dc, width, height);
  CBitmap *OldBitmap = memDC->SelectObject (Bitmap);

  // Draw the image onto the memory DC, one pixel at a
  // time.  Naturally, this is the SLOW part:
  int i = 0;
  int r, g, b;
  for (unsigned long y = 0; y < height; y++)
  { for (unsigned long x = 0; x < width; x++)
    { r = imgData[i++];
      g = imgData[i++];
      b = imgData[i++];
      memDC->SetPixelV (x, y, RGB (r, g, b));

  // Resize display window
  m_StaticPic.SetWindowPos (NULL, GetSystemMetrics (SM_CXSCREEN) / 2 - width / 2, GetSystemMetrics (SM_CYSCREEN) / 2 - height / 2, width, height, SWP_NOZORDER | SWP_SHOWWINDOW);
  //m_StaticPic.ShowWindow (SW_SHOW);
  dc->BitBlt (0, 0, width, height, memDC, 0, 0, SRCCOPY);

  // Deallocate bitmap
  memDC->SelectObject (OldBitmap);
  Bitmap->DeleteObject ();
  delete Bitmap;

  // Deallocate memory DC
  memDC->DeleteDC ();
  delete memDC;
  memDC = NULL;

  // Deallocate primary DC
  m_StaticPic.ReleaseDC (dc);

  // Deallocate image data
  delete [] imgData;
  imgData = NULL;

So, any takers?
Question by:helpmealot

Expert Comment

ID: 7156300
This is a great demo and it is pretty fast.

To load the data in to the bit map fast, use the CBitmap::SetBitmapBits function.

Let me know if you have any questions.

Expert Comment

ID: 7156761
or you could try OleLoadPicture API it handles jpegs and gifs and lots of other formats also -


Author Comment

ID: 7158370
Thank you skibud2 and ShaunWilde for your responses.

skibud2 - The demo does not really apply to my situation since it is loading the images from a resource.  I already have the image loaded into memory as raw, uncompressed RGB triplets.

The SetBitmapBits function also does not meet my needs since it requires that the CDC be of the same color depth as the image.  I was having considerable difficulty because my desktop is set to 32 bit color, but the bitmaps are "just" 24 bits.  I could get it to display a picture, but it was hopelessly garbled.

ShaunWilde - Although this solution looks like it might work, it really limits the functionality of this program.  What I am looking for is a way to display arbitrary RGB data onto the screen.

Anyway, I have found the answer with the SetDIBitsToDevice.  Here is my modified (complete and working) code.  It is substantially faster than that which I posted in the original question.

void CPhotoShowDlg::LoadPhoto (int pos, int dir)
{ CWaitCursor cur;

  unsigned char *imgData;
  int length;
  unsigned long width, height, bpp;

  // Display the filename
  m_FilenameCtl.SetWindowText (m_Settings.m_Pos[pos].m_Dirs[dir].m_Photo);

  // Allocate and fill imgData
  { unsigned char *data = new unsigned char[1000000];

    CFile file;
    if (file.Open (m_Settings.m_Pos[pos].m_Dirs[dir].m_Photo, CFile::modeRead) == 0)
    { delete [] data;

    length = file.Read (data, 1000000);
    file.Close ();

    DecodeFromJPEGBuffer (data, length, &imgData, &width, &height, &bpp);
    delete [] data;

  { unsigned long i = 0;
    unsigned char temp;
    for (;;)
    { temp = imgData[i];
      imgData[i] = imgData[i + 2];
      imgData[i + 2] = temp;
      i += 3;
      if (i >= width * height * bpp)
      { break; }

  // Resize display window
  m_StaticPic.SetWindowPos (NULL, GetSystemMetrics (SM_CXSCREEN) / 2 - width / 2, GetSystemMetrics (SM_CYSCREEN) / 2 - height / 2, width, height, SWP_NOZORDER | SWP_SHOWWINDOW);

  // Allocate primary DC
  CDC *dc = m_StaticPic.GetDC ();
  HDC hdc = dc->GetSafeHdc ();

  memset(&bmi, 0, sizeof(bmi));
  bmi.bmiHeader.biSize        = sizeof (BITMAPINFOHEADER);
  bmi.bmiHeader.biWidth       = width;
  bmi.bmiHeader.biHeight      = -((long) height); // top-down image
  bmi.bmiHeader.biPlanes      = 1;
  bmi.bmiHeader.biBitCount    = 24;
  bmi.bmiHeader.biCompression = BI_RGB;
  bmi.bmiHeader.biSizeImage   = 0;

  SetDIBitsToDevice (hdc, 0, 0, width, height, 0, 0, 0, height, imgData, &bmi, DIB_RGB_COLORS);

  // Deallocate primary DC
  m_StaticPic.ReleaseDC (dc);

  // Deallocate image data
  delete [] imgData;
  imgData = NULL;

I will therefore be requesting that community support delete this question unless there are objections.  Thanks again.

Accepted Solution

Mindphaser earned 50 total points
ID: 7162838
Points refunded and moved to PAQ

** Mindphaser - Community Support Moderator **

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Suggested Solutions

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

808 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