Click here to Skip to main content
12,244,802 members (53,194 online)
Click here to Skip to main content
Add your own
alternative version

Stats

28.6K views
708 downloads
31 bookmarked
Posted

Unleash GDI+ power on Windows Mobile

, 21 Apr 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
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:

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:

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.

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

and in the bitmap implementation:

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:

#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)

Share

About the Author

Vincent_RICHOMME
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.

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
manoj kumar choubey17-Feb-12 1:16
membermanoj kumar choubey17-Feb-12 1:16 
Questionare you sure about png? Pin
EvIl_DeViL15-Mar-10 6:58
memberEvIl_DeViL15-Mar-10 6:58 
AnswerRe: are you sure about png? Pin
EvIl_DeViL16-Mar-10 3:55
memberEvIl_DeViL16-Mar-10 3:55 
GeneralRe: are you sure about png? Pin
EvIl_DeViL17-Mar-10 6:26
memberEvIl_DeViL17-Mar-10 6:26 
QuestionIs there can set clip? Pin
bigpin2dl25-Nov-09 16:50
memberbigpin2dl25-Nov-09 16:50 
QuestionAbout Bezier? Pin
bigpin2dl18-Nov-09 15:58
memberbigpin2dl18-Nov-09 15:58 
AnswerRe: About Bezier? Pin
bigpin2dl18-Nov-09 17:30
memberbigpin2dl18-Nov-09 17:30 
QuestionLegal issues? Pin
Alain Rist22-Apr-09 8:42
memberAlain Rist22-Apr-09 8:42 
AnswerRe: Legal issues? Pin
Vincent_RICHOMME23-Apr-09 2:25
memberVincent_RICHOMME23-Apr-09 2:25 
GeneralRe: Legal issues? Pin
Ernest Laurentin23-Apr-09 6:30
memberErnest Laurentin23-Apr-09 6: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.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160426.1 | Last Updated 21 Apr 2009
Article Copyright 2009 by Vincent_RICHOMME
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid