• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 508
  • Last Modified:

How to display bitmap data FAST

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?
0
helpmealot
Asked:
helpmealot
1 Solution
 
skibud2Commented:
This is a great demo and it is pretty fast.
http://www.codeproject.com/miscctrl/customcontrol.asp

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

Let me know if you have any questions.
0
 
ShaunWildeCommented:
or you could try OleLoadPicture API it handles jpegs and gifs and lots of other formats also -

see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmag01/html/c0110Mag.asp
0
 
helpmealotAuthor Commented:
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;
      return;
    }

    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 ();

  BITMAPINFO bmi;
  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.
0
 
MindphaserCommented:
Points refunded and moved to PAQ

** Mindphaser - Community Support Moderator **
0
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.

Join & Write a Comment

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now