[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

How to display bitmap data FAST

Posted on 2002-07-15
4
Medium Priority
?
503 Views
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?
0
Comment
Question by:helpmealot
4 Comments
 

Expert Comment

by:skibud2
ID: 7156300
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
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 7156761
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
 

Author Comment

by:helpmealot
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;
      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
 
LVL 6

Accepted Solution

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

** Mindphaser - Community Support Moderator **
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

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

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Ready to get certified? Check out some courses that help you prepare for third-party exams.
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.
Integration Management Part 2
Suggested Courses

872 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