In this set of articles, we describe the methods to display an image on a computer running Windows. We describe the ways to display a RAW image. A RAW image file is one which has no header information; it just has the image pixel values stored contiguously from top left to bottom right, row by row. These display methods can be extended to other image formats, for example TIFF (For TIFF, it is preferable to use the public domain LibTiff library to read the image). The prerequisites for reading a raw image are (a) Number of rows and columns in the image, and (b) Bits per pixel. In the code segment below, the image is considered to be a square, and the bits per pixel are considered to be 8. Sometimes, we may prefer to use the image name to store the image dimensions as also the bits per pixel. For example, the image name img512x512_16.RAW would indicate an image whose width and height are 512 pixels, and which uses 16 bits per pixel.
The different ways to display an image are: (i) Using Windows APIs, (ii) Using MFC, (iii) Using .NET languages such as C# or VB.NET, (iv) Using DirectX, (v) Using third party software like LeadTools, IMAQ, etc. Of course, there are many other ways too!
We would not discuss the Windows APIs methods, and would instead jump straight into the MFC way of doing things. Essentially, MFC is a wrapper around the Windows API.
The first way we explore is the function CDC::StretchBlt(). Using StretchBlt(), you can stretch or shrink the bitmap to the required dimensions. However, I have personally seen this method fail for large bitmaps (How large is large?). Here is the prototype for StretchBlt()
BOOL CDC:: StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop ); Sample code is given below. Here, imageWidth and imageHeight are the width and height of the image and are assumed to be known apriori. The function DisplayImage() may be called from the OnPaint() method of the View class. However, for a dialog based application, it may be called simply from the dialog class. Here is an example of the code:
void CDisplayImageDlg::DisplayImage()
{
char *ImageDisp32Bit = NULL;
ImageDisp32Bit = (char *)malloc(imageWidth * imageHeight * 4);
char *rawimg = NULL; // For a 16-bit image, change char to short at appropriate locations
rawimg = (char *)malloc(imageWidth * imageHeight); // assumed to be 8 bits per pixel
FILE *fl=fopen(fileName, "rb");
fread(rawimg, imageWidth * imageHeight, 1, fl);
fclose(fl);
int i = 0;
// Here, we are converting the 8-bit grayscale image into a color image with the values
// reg = green = blue = grayscale value. We are also setting the Alpha value to be the same.
for(int m = 0; m < imageWidth * imageHeight; m++)
{
*(ImageDisp32Bit + i) = *(rawimg + m); i++;
*(ImageDisp32Bit + i) = *(rawimg + m); i++;
*(ImageDisp32Bit + i) = *(rawimg + m); i++;
*(ImageDisp32Bit + i) = *(rawimg + m); i++;
}
CBitmap bm1;
bm1.CreateBitmap(imageWidth, imageHeight, 1, 32, ImageDisp32Bit);
free(ImageDisp32Bit);
free(rawimg);
CDC *dcptr=this->GetDC();
CDC bitmapdc1;
bitmapdc1.CreateCompatibleDC(this->GetDC());
bitmapdc1.SelectObject(&bm1);
dcptr->SetStretchBltMode(HALFTONE);
dcptr->SetBkMode(TRANSPARENT);
// All of the above code just for this single line to display it!!
dcptr->StretchBlt(10, 10, 300, 300, &bitmapdc1, 0, 0, imageWidth, imageHeight, SRCCOPY);
dcptr->SetTextColor(RGB(240,50,50));
dcptr->TextOut(10,10,fileName);
dcptr->ReleaseOutputDC();
}
That's all there is to display an image. In our next article, we'll see CDC::BitBlt().