Thread: C/C++ - how use the GDIPLUS library?

  1. #1
    Registered User
    Join Date
    Aug 2013
    Posts
    451

    C/C++ - how use the GDIPLUS library?

    (i'm using the Code Blocks IDE)
    i'm add the include:

    #include <.\gdiplus\gdiplus.h>

    then i add the libgdiplus.a library to linker options.

    see the code:
    Code:
    hdcimage = CreateCompatibleDC(NULL);
                Gdiplus::Graphics graphics(hdcimage); //Handle to the device context
                //Load the image from a file
                Gdiplus::Image img(filename.c_str());
                graphics.DrawImage(&img, 0, 0, img.GetWidth(), img.GetHeight());
    the 'filename' is a string object.
    i'm getting an error:
    "no matching function for call to 'Gdiplus::Image::Image(const char*)'"

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Image.Image(const WCHAR*, BOOL) constructor (Windows)
    Perhaps you need to consider UNICODE translation issues.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Quote Originally Posted by Salem View Post
    Image.Image(const WCHAR*, BOOL) constructor (Windows)
    Perhaps you need to consider UNICODE translation issues.
    i did:
    Code:
    const size_t len = filename.length() + 1;
                wchar_t wcstring[len];
                swprintf(wcstring, len, L"%s", filename.c_str());
    now i can convert string to wchar_t
    now the code works:
    Code:
    hdcimage = CreateCompatibleDC(NULL);
    
                ULONG_PTR m_gdiplusToken;
                // Initialize GDI+
                Gdiplus::GdiplusStartupInput gdiplusStartupInput;
                Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
    
                //Load the image from a file
                const size_t len = filename.length() + 1;
                wchar_t wcstring[len];
                swprintf(wcstring, len, L"%s", filename.c_str());
    
                Gdiplus::Image img (wcstring);
                HBITMAP hbitmap=CreateBitmap(img.GetWidth(),img.GetHeight(),1,32,NULL);
                SelectObject(hdcimage, hbitmap);
                Gdiplus::Graphics graphics(hdcimage); //Handle to the device context
                graphics.DrawImage(&img, 0, 0, img.GetWidth(), img.GetHeight());
                imageweight=img.GetWidth();
                imageheight=img.GetHeight();
                //Gdiplus::GdiplusShutdown(m_gdiplusToken);
    the image is showed, but i see 2 problems:
    1 - that comment line give me a memory leak(that's why is a comment). what i did wrong?
    2 - why the image takes several seconds for be showed?
    (in that time the wait\busy cursor is showed)
    Last edited by joaquim; 09-22-2014 at 06:48 AM.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by joaquim View Post
    i did:
    Code:
    const size_t len = filename.length() + 1;
                wchar_t wcstring[len];
                swprintf(wcstring, len, L"%s", filename.c_str());
    now i can convert string to wchar_t
    Do absolutely not do that. The first issue that you are just doing a plain dumb widening of char -> wchar_t. But this is wrong. wchar_t is typically a different character set (often unicode). chars are typically ASCII or UTF-8, both of which cannot just be widened into a wchar_t. That will give you incorrect translation.
    You need to do a proper conversion. Seeing as GDI is Windows, I'll give you these functions as a starting point for translating between different character sets (you will need to add an error class for throwing errors or change the code to handle errors):

    Code:
    	std::wstring AToU16(const std::string& From)
    	{
    		if (From.empty())
    			return L"";
    		auto Len = MultiByteToWideChar(CP_ACP, 0, From.data(), (int)From.size(), nullptr, 0);
    		if (Len > 0)
    		{
    			std::wstring Str(Len, L'\0');
    			MultiByteToWideChar(CP_ACP, 0, From.data(), (int)From.size(), &Str[0], Len);
    			return Str;
    		}
    		throw stf::Errors::FailedToConvertString();
    	}
    
    	std::string U16ToU8(const std::wstring& From)
    	{
    		if (From.empty())
    			return "";
    		auto Len = WideCharToMultiByte(CP_UTF8, 0, From.data(), (int)From.size(), nullptr, 0, 0, 0);
    		if (Len > 0)
    		{
    			std::string Str(Len, L'\0');
    			WideCharToMultiByte(CP_UTF8, 0, From.data(), (int)From.size(), &Str[0], Len, 0, 0);
    			return Str;
    		}
    		throw stf::Errors::FailedToConvertString();
    	}
    
    	std::wstring U8ToU16(const std::string& From)
    	{
    		if (From.empty())
    			return L"";
    		auto Len = MultiByteToWideChar(CP_UTF8, 0, From.data(), (int)From.size(), nullptr, 0);
    		if (Len > 0)
    		{
    			std::wstring Str(Len, L'\0');
    			MultiByteToWideChar(CP_UTF8, 0, From.data(), (int)From.size(), &Str[0], Len);
    			return Str;
    		}
    		throw stf::Errors::FailedToConvertString();
    	}
    These functions convert between ASCII, UTF-8 and UTF-16 on Windows. char is typically ASCII on Windows unless you've explicitly converted it into UTF-8, so use AToU16.
    Furthermore, do not use swprintf/sprintf. You will run into issues with buffer sizes.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Quote Originally Posted by Elysia View Post
    Do absolutely not do that. The first issue that you are just doing a plain dumb widening of char -> wchar_t. But this is wrong. wchar_t is typically a different character set (often unicode). chars are typically ASCII or UTF-8, both of which cannot just be widened into a wchar_t. That will give you incorrect translation.
    You need to do a proper conversion. Seeing as GDI is Windows, I'll give you these functions as a starting point for translating between different character sets (you will need to add an error class for throwing errors or change the code to handle errors):

    Code:
        std::wstring AToU16(const std::string& From)
        {
            if (From.empty())
                return L"";
            auto Len = MultiByteToWideChar(CP_ACP, 0, From.data(), (int)From.size(), nullptr, 0);
            if (Len > 0)
            {
                std::wstring Str(Len, L'\0');
                MultiByteToWideChar(CP_ACP, 0, From.data(), (int)From.size(), &Str[0], Len);
                return Str;
            }
            throw stf::Errors::FailedToConvertString();
        }
    
        std::string U16ToU8(const std::wstring& From)
        {
            if (From.empty())
                return "";
            auto Len = WideCharToMultiByte(CP_UTF8, 0, From.data(), (int)From.size(), nullptr, 0, 0, 0);
            if (Len > 0)
            {
                std::string Str(Len, L'\0');
                WideCharToMultiByte(CP_UTF8, 0, From.data(), (int)From.size(), &Str[0], Len, 0, 0);
                return Str;
            }
            throw stf::Errors::FailedToConvertString();
        }
    
        std::wstring U8ToU16(const std::string& From)
        {
            if (From.empty())
                return L"";
            auto Len = MultiByteToWideChar(CP_UTF8, 0, From.data(), (int)From.size(), nullptr, 0);
            if (Len > 0)
            {
                std::wstring Str(Len, L'\0');
                MultiByteToWideChar(CP_UTF8, 0, From.data(), (int)From.size(), &Str[0], Len);
                return Str;
            }
            throw stf::Errors::FailedToConvertString();
        }
    These functions convert between ASCII, UTF-8 and UTF-16 on Windows. char is typically ASCII on Windows unless you've explicitly converted it into UTF-8, so use AToU16.
    Furthermore, do not use swprintf/sprintf. You will run into issues with buffer sizes.
    thanks for correct me

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. GDIPLUS::Image: how save it on a file in stream way?
    By joaquim in forum Game Programming
    Replies: 45
    Last Post: 10-10-2015, 04:03 PM
  2. GDIPlus: how use and what is Matrix?
    By joaquim in forum Game Programming
    Replies: 0
    Last Post: 09-13-2015, 04:58 AM
  3. C/C++ - GDIPLUS: how can i get the frame delay time?
    By joaquim in forum Game Programming
    Replies: 0
    Last Post: 09-24-2014, 02:53 PM
  4. #include <gdiPlus.h> problem with Code::Blocks
    By New_To_C++ in forum Windows Programming
    Replies: 18
    Last Post: 10-22-2011, 06:50 AM
  5. Gdiplus question
    By Joelito in forum Windows Programming
    Replies: 3
    Last Post: 07-11-2005, 07:31 AM