Image Processing using GDI+ and VC++ 6.0 | CodeGuru

Image Processing using GDI+ and VC++ 6.0

Environment: GDI+ and VC6 I was recently working on a small project to convert an image to the WAP’s WBMP format. WAP is the Wireless Application Protocol, for people who didn’t know and WBMP stands for Wireless Bitmap. I was having a hard time reading various formats (GIFs, JPGs, and BMPs) until I came across […]

Written By
CodeGuru Staff
CodeGuru Staff
Feb 7, 2003
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

Environment: GDI+ and VC6

I was recently working on a small project to convert an image to the WAP’s WBMP format. WAP is the Wireless Application Protocol, for people who didn’t know and WBMP stands for Wireless Bitmap.

I was having a hard time reading various formats (GIFs, JPGs, and BMPs) until I came across some excellent articles on using GDI+ at the CodeGuru site and also on the CodeProject site. These articles developed my interest further into image processing and I got hooked on it. What started out as a simple picture-to-WBMP convertor is fast growing into a complete image processing framework. The articles of Christian Grauss on using GDI+ and .NET for image processing are excellent resources. I wanted to code all stuff in VC++ and not .NET—simply because I am used to VC++.

For any image processing task, one needs to access raw pixel data. If you look at the GDI+ API for doing this, it’s quite complex; besides, I also wanted to code my image processing routines so that I can port them to other environments. In other words, I did not want any GDI+ specific code in the core image processing routines. This compelling requirement forced me to make a choice on which pixel data format to use. I decided to use only the ARGB (Alpha, red, green, blue) mode of the image data that can easily be encoded in an ‘int’. I wrote helper functions to create an array of ARGB encoded ints given a GDI+ Bitmap and also to create a GDI+ Bitmap from my integer array. Here are the functions:

// Given a Bitmap – get an integer encoded data of the pixels
int * Bitmap2PixelData(Bitmap *b) {
  // get width and height of Bitmap
  int width = b->GetWidth();
  int height = b->GetHeight();
  // make sure these are valid
  if ( width *height <= 0 )
    return NULL;
  // allocate memory for pixel data
  int *pixelData_ARGB = new int[width*height];
  if ( pixelData_ARGB == NULL )
    return NULL;
  // get the pixel values from the bitmap and encode
  // into the array allocated above.
  BitmapData bmData;
  Rect rect(0, 0, width, height);
  b->LockBits(rect,
    ImageLockModeRead,
    PixelFormat32bppARGB,
    &bmData);
  int stride = bmData.Stride;
  BYTE *p = (BYTE *)((void *)bmData.Scan0);
  int nOffset = stride – width*4;    // bytes to skip at end of
                                     // each row
  for(int y=0; y < height;y++) {
    for(int x=0; x < width; ++x ) {
      // GDI lies about RGB – internally it’s BGR
      pixelData_ARGB[y*width+x] =  ARGB2Pixel(p[3], p[2], p[1],
                                              p[0]);
      p += 4;
    }
    p += nOffset;
  }
  b->UnlockBits(&bmData);
  // return the pixel data array
  return (pixelData_ARGB);
}

The preceding code uses ARGB2Pixel. This is an inline function that computes the pixel value—given Alpha, Red, Green and Blue values. It also clamps the ARGB component such that they all lie between 0 and 255, inclusive. Here is the code for that:

inline int ARGB2Pixel(int alpha, int r, int g, int b) {
  if ( alpha > 255 )
    alpha = 255
  else if ( alpha < 0 )
    alpha = 0;
  if ( r > 255 )
    r = 255
  else if ( r < 0 )
    r = 0;
  if ( g > 255 )
    g = 255
  else if ( g < 0 )
    g = 0;
  if ( b > 255 )
    b = 255
  else if ( b < 0 )
    b = 0;
  // shift r and g to encode
  r = (r << 16);
  g = (g << 8 );
  return ( ((alpha << 24 )&0xff000000)  | r | g| b );
}

Given below is the function that takes an integer array and creates a GDI+ Bitmap that can then be displayed.

Bitmap * PixelData2BitMap(int width, int height,
                          int *pixData_ARGB) {
  // create a temporary Bitmap
  Bitmap bit(width, height, PixelFormat32bppARGB);
  // create its clone for returning
  Bitmap *b = bit.Clone(0, 0, bit.GetWidth(), bit.GetHeight(),
              PixelFormat32bppARGB);
  BitmapData bmData;
  Rect rect(0, 0, b->GetWidth(), b->GetHeight());
  b->LockBits(rect,
    ImageLockModeRead | ImageLockModeWrite,
    PixelFormat32bppARGB,
    &bmData);
  int stride = bmData.Stride;
  BYTE *p = (BYTE *)((void *)bmData.Scan0);
  int nOffset = stride – width*4;   // bytes to skip at end of
                                    // each row
  int pixel;
  for(int y=0; y < height;y++) {
    for(int x=0; x < width; ++x ) {
      // GDI lies about RGB – internally it’s BGR
      pixel = pixData_ARGB[y*width+x];
      p[3] = (BYTE) ((pixel >> 24) & 0xff);    // alpha
      p[2] = (BYTE) ((pixel >> 16) & 0xff);    // pixel red
      p[1] = (BYTE) ((pixel >> 8 ) & 0xff);    // pixel green
      p[0] = (BYTE) ((pixel      ) & 0xff);    // pixel blue
      p += 4;
    }
    p += nOffset;
  }
  b->>UnlockBits(&bmData);
  return (b);
}

The sample project also has some neat undo-redo stuff. It does not save any images yet. Nevertheless, it’s quite easy to add support for various image formats (use GDI+ to save as well). There are several articles on CodeGuru to do that.

Downloads

Download source – 20 Kb

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.