Solved

How to display bitmap data FAST

Posted on 2002-07-15
4
425 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 50 total points
ID: 7162838
Points refunded and moved to PAQ

** Mindphaser - Community Support Moderator **
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
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.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

760 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now