Writing raw C++ code to read a JPG or JPEG image can be a cumbersome task. Fortunately, libraries exist which we can use to perform the dirty work for us. In this tutorial, we will be using the GDI+ interface to easily read image files and draw them onto the window. In you are unfamiliar with GDI+, I would suggest you take a look at my previous tutorial on how to get up and running with GDI+. Please note that this tutorial is aimed for Windows programs only, since GDI+ is not available on other platforms.

The two GDI+ classes we will be using are Graphics and Bitmap. The Graphics class will be used to draw the Bitmap, and the Bitmap will be used to store the image inside of our program. Go ahead and create a new Win32 application with Visual Studio, and set it up to compile with GDI+ as described in the previous tutorial. At this point, we’ll be using a global variable for our bitmap.

Step 1: Prepare the Bitmap to store the image in your program

Bitmap *gpBitmap;                                           // The bitmap for displaying an image

In the WinMain function, go ahead and initialize gpBitmap to NULL. At the end of the main WinMain function, be sure to delete the bitmap if it is not NULL to prevent memory leaks.

Step 2: Create function to let user select and load a file

We will be using the standard windows file dialog by calling GetOpenFileName(). If the user selects a file, we will simply create a Bitmap object using the filename in the constructor. Afterwards, we must invalidate the window so it will essentially be forced to redraw immediately. Please note that this program is set to use Unicode. I generally recommend that all modern programs should be written with Unicode in mind because that is the way support has been trending for the last several years.

void MyOpenFile(HWND hWnd)
{
    OPENFILENAME ofn;
    wchar_t szFileName[MAX_PATH] = L"";
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hWnd;
    ofn.lpstrFilter = L"JPEG Files (*.jpg)\0*.jpg\0All Files (*.*)\0*.*\0";
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
    ofn.lpstrDefExt = L"jpg";
    if(GetOpenFileName(&ofn))
    {
		// If we got this far, the user has chosen a file.
		// GDI+ supports BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF.
		if(gpBitmap)
		{
			// We need to destroy the old bitmap
			delete gpBitmap;
		}
		gpBitmap = new Bitmap(szFileName);
		// We need to force the window to redraw itself
		InvalidateRect(hWnd, NULL, TRUE);
		UpdateWindow(hWnd);
    }
}

Step 3: Create function to draw the bitmap to the screen

Drawing a bitmap to the screen, or a DC (device context) is simple when using the GDI+ API. We can simply create the graphics object using the handle to our device context. Then we can use the DrawImage member function of our graphics object to draw the bitmap. Please keep in mind that the Bitmap class is derived from the Image class in GDI+.

void MyOnPaint(HDC hdc)
{
	if (gpBitmap)
	{
		Graphics graphics(hdc);
		graphics.DrawImage(gpBitmap, 0, 0);
	}
}

Summary

This tutorial quickly shows you how to use a standard open file dialog to let the user select, and load an image file. The image file can be a JPG, BMP, TIFF, or several other popular formats. Loading the image file is essentially done in one line, since one of the Bitmap constructor functions accepts a filename as the only argument, which makes this process very easy.

Download the source code here