Solved

How to display bitmap data FAST

Posted on 2002-07-15
4
468 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
repeatSeparator  java  challenge 13 58
notReplace  challenge 53 151
MaxSpan challenge 9 124
Fibonacci challenge 11 137
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 …
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
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 an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

726 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