Click here to Skip to main content
15,878,871 members
Articles / Mobile Apps / Windows Mobile

Unleash GDI+ power on Windows Mobile

Rate me:
Please Sign up or sign in to vote.
4.86/5 (7 votes)
21 Apr 2009CPOL3 min read 47.3K   834   31   10
How to use GDI+ on Windows Mobile.

GDIPlusCE

Introduction

Recently, I wanted to evaluate the use of OpenGL ES on Windows Mobile devices, and as always, I found very good articles but written in C#. So, I started to port them to WTL/C++ but during the port, I started wondering if I could find an easier way of translating the graphics parts, and after some research, I found a very good article from Alex Feinman entitled "Using GDI+ on Windows Mobile". The interesting part was the fact it was using Marshalling to call GDI+, so it meant that GDI+ could be used with native code. Then, after more research, I found a set of classes and a library from Ernest Laurentin that was a wrapper around GDI+ and that could be used in native code.

Background

GDI+ is a graphics library introduced in 2001 by Microsoft to make two-dimensional drawing easier. It runs on top of GDI32, and besides the changes in the programming model, it also adds new features such as gradient fills, anti-aliasing, more extensive image handling, etc. There are two main components of GDI+: a flat C API where the main implementation rests, and C++ wrappers that reside in the public headers associated with GDI+.

Unfortunately, on Windows Mobile, GDI+ is only partially implemented, and lots of functions (for instance, Font and FontFamily) return NotImplemented.

Using the code

To be able to use GDI+, you need to initialize it first, as shown below:

C++
ULONG_PTR _gdiplusToken;

// Initialize GDI+
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&_gdiplusToken, &gdiplusStartupInput, NULL);
...
int nRet = CMainFrame::AppRun(lpstrCmdLine, nCmdShow);
...

// Release GDI+
Gdiplus::GdiplusShutdown(_gdiplusToken);

Implementation of missing functions (Bitmap)

As I wrote above, GDI+ is split in two, a gdiplus.dll that exports some C functions used to handle memory and drawing, and some C++ classes declared inline and that calls the exported functions. Please note that the allocation/deallocation operator has been overloaded because memory management is done by the DLL.

So, if you write the following code:

C#
Gdiplus:: Pen pen = new Pen(Color::Black, 15);

the following functions are called:

  • DllExports::GdipAlloc(in_size); - corresponds to the new operator
  • DllExports::GdipCreatePen1 - corresponds to Pen(IN const Color& color, IN REAL width = 1.0f)

On Windows Mobile, some functions were not implemented, and in particular I focused on the Bitmap class.

If you look at MSDN, you will see that a Gdiplus::Bitmap can be created from a file, resource, stream, or HBITMAP, but from my experiments on a Windows Mobile 6, only the following functions are implemented:

  • DllExports::GdipCreateBitmapFromStreamICM(...)
  • DllExports::GdipCreateBitmapFromScan0(..)
  • DllExports::GdipCreateBitmapFromGraphics(...)
  • DllExports::GdipCreateBitmapFromGdiDib(...)
  • DllExports::GdipCreateBitmapFromHBITMAP(hbm, hpal, &bitmap)

So, I have implemented the missing functions to be able to easily load bitmaps from files or resources, and to save them.

Implementation of bitmap loading relies on GdipCreateBitmapFromStreamICM, and I have developed two classes used to stream files (CStreamOnFile) and resources (CStreamOnResource). I have added to the base Image class, two pointers on these objects.

C++
class Image : public GdiplusBase
{
...
#ifdef _WIN32_WCE
    CStreamOnFile* pFileStream;
    CStreamOnResource*  pResStream;
#endif
...
};

and in the bitmap implementation:

C++
inline 
Bitmap::Bitmap(
    IN HINSTANCE hInstance, 
    IN const WCHAR *bitmapName
    )
{
    GpBitmap *bitmap = NULL;

    lastResult = DllExports::GdipCreateBitmapFromResource(hInstance,
                                                          bitmapName,
                                                          &bitmap);
#if defined(UNDER_CE)
    if (lastResult == NotImplemented)
    {
        pResStream = new CStreamOnResource(bitmapName);
        if ( pResStream->Init(hInstance, bitmapName) )
        {
            if (pResStream->GetResType() == RT_BITMAP) {
                // code below doesn't work - image is upside down
                /*const BITMAPINFO* pBmi = (BITMAPINFO*)pResStream->GetResData();
                lastResult = DllExports::GdipCreateBitmapFromGdiDib(
                pBmi, (void*)(pBmi+sizeof(BITMAPINFO)), &bitmap);*/
                HBITMAP hBmp = LoadBitmap(hInstance, bitmapName);
                if (hBmp)  
                {
                    lastResult = DllExports::GdipCreateBitmapFromHBITMAP(hBmp, 
                                                           NULL, &bitmap);
                }
            }
            else if (pResStream->GetResType() == RT_GROUP_ICON) {
                HICON hIcon = LoadIcon(hInstance, bitmapName);
                if (hIcon)  
                {
                    lastResult = 
                      DllExports::GdipCreateBitmapFromHICON(hIcon, &bitmap);
                }
            }
            else
                lastResult = 
                  DllExports::GdipCreateBitmapFromStreamICM(pResStream, &bitmap);
        }
    }
#endif
    SetNativeImage(bitmap);
}

Unfortunately, on Windows Mobile, EnumResourceTypes is not implemented, so I chose to handle only the following resource types:

  • RT_BITMAP
  • PNG
  • JPEG
  • GIF

How to use it

So now, you should be able to easily load and save images, as shown below:

C++
#include "gdiplushelper.h"

HINSTANCE hResInstance = ModuleHelper::GetResourceInstance();

// Load image from resource
bmpRes = Bitmap::FromResource(hResInstance, MAKEINTRESOURCE(IDR_JPEG2));

// Load image from file
bmpFile = Bitmap::FromFile(_T("\\My Documents\\My Pictures\\Spring.jpg"));

// Save file
CLSID encoderClassId;
if (GetEncoderClsid(m_pImgFactory, L"image/png", &encoderClassId) == TRUE)
    GdiplusSaveBitmap(m_pImgFactory, &*bmp, 
      _T("testsave.png"), &encoderClassId);

Conclusion

GDI+ is not officially supported on Windows Mobile, and I wouldn't recommend using it for big applications. However, if you need to manipulate some bitmaps, this wrapper could help you. Please note that I haven't tested indexed bitmaps, and you might have some issues if you are using bitmaps with palettes.

History

  • 21 April, 2009: Article submitted.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Smartmobili
France France
I have founded a company specialized in mobile development and I am always trying to develop multi-platform things.
I am currently looking for new interesting job, so if you need someone please let me know.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey17-Feb-12 0:16
professionalManoj Kumar Choubey17-Feb-12 0:16 
Questionare you sure about png? Pin
EvIl_DeViL15-Mar-10 5:58
EvIl_DeViL15-Mar-10 5:58 
AnswerRe: are you sure about png? Pin
EvIl_DeViL16-Mar-10 2:55
EvIl_DeViL16-Mar-10 2:55 
GeneralRe: are you sure about png? Pin
EvIl_DeViL17-Mar-10 5:26
EvIl_DeViL17-Mar-10 5:26 
QuestionIs there can set clip? Pin
bigpin2dl25-Nov-09 15:50
bigpin2dl25-Nov-09 15:50 
I found that there is no clip function implemented.

Is the clip can be used in this lib?
QuestionAbout Bezier? Pin
bigpin2dl18-Nov-09 14:58
bigpin2dl18-Nov-09 14:58 
AnswerRe: About Bezier? Pin
bigpin2dl18-Nov-09 16:30
bigpin2dl18-Nov-09 16:30 
QuestionLegal issues? Pin
Alain Rist22-Apr-09 7:42
Alain Rist22-Apr-09 7:42 
AnswerRe: Legal issues? Pin
Vince Ricci23-Apr-09 1:25
Vince Ricci23-Apr-09 1:25 
GeneralRe: Legal issues? Pin
Ernest Laurentin23-Apr-09 5:30
Ernest Laurentin23-Apr-09 5:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.