Search code examples
c++imagebitmappixel

Unable to create image bitmap c++


My goal is to analyse image by pixels (to determine color). I want to create bitmap in C++ from image path:

string path = currImg.path;
cout << path << " " << endl;

Then I do some type changes which needed because Bitmap constructor does not accept simple string type:

wstring path_wstr = wstring(path.begin(), path.end()); 
const wchar_t* path_wchar_t = path_wstr.c_str();

And finally construct Bitmap:

   Bitmap* img = new Bitmap(path_wchar_t);

In debugging mode I see that Bitmap is just null: Bitmap is null

How can I consstruct Bitmap to scan photo by pixel to know each pixel's color?


Solution

  • Either Gdiplus::GdiplusStartup is not called, and the function fails. Or filename doesn't exist and the function fails. Either way img is NULL.

    Wrong filename is likely in above code, because of the wrong UTF16 conversion. Raw string to wstring copy can work only if the source is ASCII. This is very likely to fail on non-English systems (it can easily fail even on English systems). Use MultiByteToWideChar instead. Ideally, use UTF16 to start with (though it's a bit difficult in a console program)

    int main()
    {
        Gdiplus::GdiplusStartupInput tmp;
        ULONG_PTR token;
        Gdiplus::GdiplusStartup(&token, &tmp, NULL);
        test_gdi();
        Gdiplus::GdiplusShutdown(token);
        return 0;
    } 
    

    Test to make sure the function succeeded before going further.

    void test_gdi()
    {
        std::string str = "c:\\path\\filename.bmp";
        int size = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, 0, 0);
        std::wstring u16(size, 0);
        MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &u16[0], size);
    
        Gdiplus::Bitmap* bmp = new Gdiplus::Bitmap(u16.c_str());
        if (!bmp)
            return; //print error
    
        int w = bmp->GetWidth();
        int h = bmp->GetHeight();
        for (int y = 0; y < h; y++)
            for (int x = 0; x < w; x++)
            {
                Gdiplus::Color clr;
                bmp->GetPixel(x, y, &clr);
                auto red = clr.GetR();
                auto grn = clr.GetG();
                auto blu = clr.GetB();
            }
        delete bmp;
    }