![]() ![]() ![]() 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. DownloadsDownload source - 20 Kb
missing the file "GDIPLUS.H".
Legacy CodeGuru |
02/07/2003 12:00am
![]() ![]() Originally posted by:
JeongDong, Lee
Compiling...
ImgProc.exe - 1 error(s), 0 warning(s)
This code has leak.
Legacy CodeGuru |
02/11/2003 12:00am
![]() ![]() Originally posted by:
AbhijeetR
When exiting with more than one image opend, the current image item is not released. Need to modify CImgProcDoc destructor as below. CImgProcDoc::~CImgProcDoc()
error case not handled
Legacy CodeGuru |
02/11/2003 12:00am
![]() ![]() Originally posted by:
Na-iem Dollie
Hi I notice the following code in method:
doesn't handle the case of width < 0 && height < 0. Regards,
Image on scrollview
Legacy CodeGuru |
03/05/2003 12:00am
![]() ![]() Originally posted by:
simmy
Hi Deepak,
transparented GIF
Legacy CodeGuru |
03/14/2003 12:00am
![]() ![]() Originally posted by:
Mihai
How can I save an Bitmap object in .gif file - BUT with transparency background ? I use: GetEncoderClsid(_T("image/gif"), &encoderClsid);
Thank you in advance,
Help Need in doing
ImageComparission
Legacy CodeGuru | 04/11/2003 12:00am
![]() ![]() Originally posted by:
Raju Selvaraj
Dear Friend,
I went thru u r code,it seems very useful but the thing is i couldnt understatnd funcnalities.It'll be better if u send me ur code with some documentation. Reply to me if possible to "raju_obuli@yahoo.com". Expecting u r valule reply.
Image Processing using
GDI+ and VC++ 6.0
Legacy CodeGuru | 04/11/2003 12:00am
![]() ![]() Originally posted by:
Raju Selvaraj
Hi Deepa,
Memory Reference
Errors occured: Using above code for real-time applications
Legacy CodeGuru |
04/24/2003 12:00am
![]() ![]() Originally posted by:
Atif Bashir
AOA Memory Reference error is occured and the application terminates when I want to use the image-processing code provided by you i.e. When I use to process the images/frames at some rate e.g. 20 fps,
the program executes for a minute approximately and suudenly gives
Memory Reference Error and also demands to
Can you advise me about the matter. I'll be very grateful for your early response. Kind Regards
colors used in a
bitmap with 24 bit color depth
Legacy CodeGuru | 05/04/2003 12:00am
![]() ![]() Originally posted by:
MAJED
I have a bitmap with few number of colors but it is stored in format of
24 bit.
if there is an effective way so please advice me.
Eng.Majed
I prefer Free Image
Processing Library !
Legacy CodeGuru | 05/08/2003 12:00am
![]() ![]() Originally posted by:
Mohamed El Kayyali
Hi. I didnt use your GDI++ Code till now. but what i understand is that
you were spending too much time reading Image formates. Actually I do
not recommend any one interesting to develop image processing
applications to use GDI++ or other platforms unless there is many image
processing library can fit your applications.
Mohamed El Kayyali
Can you please specify
names, URL of some library...
Jigar Mehta | 05/12/2004 6:23am
![]() ![]() Hye,
Can you please tell us some names of image processing libraries...
compiling error
Legacy CodeGuru |
05/21/2003 12:00am
![]() ![]() Originally posted by:
Hello
error C2664: 'LockBits' : cannot convert parameter 1 from 'class Gdiplus::Rect' to 'const class Gdiplus::Rect *' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called Am I wrong to set some configuration?
Compiling error as
well
Legacy
CodeGuru | 05/30/2003 12:00am
![]() ![]() Originally posted by:
miguel Mendez
I also got the same C2664 compiling error
Thanks,
Miguel Mendez
How To use
Legacy CodeGuru |
12/02/2003 12:00am
![]() ![]() Originally posted by:
Venkatesh
I am able to complie the program but how I can load an image and look at
it by Negate and Gray scale menu option.
Nice program...
SanjeevKumar |
05/05/2004 10:36am
![]() ![]() Its a very nice program man...
need help on Image
processing
sonali_dp
| 05/28/2004 2:48am
![]() ![]() Hello
This is Sonali and i went through ur article
i need help on how to store an image in an array and then read each
pixel from the arrays and then perform some computations and then
display from the array
please help.
please help me
naveenkumarsk |
08/11/2004 8:57am
![]() ![]() hi naveen here,i need help on to read a file
which contains hexadecimal numbers i.e 96x6 format,after reading i want
to store in a buffer,
again from buffer i want to display the pixels on screen
Gdiplus need to be
initialized
Joowoong
Kim | 04/16/2005 10:49pm
![]() ![]() To compile and run above code sample, you have to initialize the GDI+ library first. // By Kim Joo-woong // must be class or global variable, because of being used in initializing and deinitializing ULONG_PTR gdiplusToken; // initializing code - add below code to startup GDI+ library GdiplusStartupInput gdiplusStartupInput; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); // deinitializing code - add below code to free GDI+ library GdiplusShutdown( gdiplusToken ); The Memory could not
be ''read''
Dreamzdoll
| 12/04/2008 1:18am
![]() ![]() Hi!
Even i have a similar problem. In a MFC, MDI, MultiThreaded Application
with Serial Communication in it (Rs-232), i have to update the toolbar
buttons every 180 millisecs and save the recieved data into a ''DBF''
every time.
How do i handle this problem.
Please help!
|
|