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:
How can I consstruct Bitmap to scan photo by pixel to know each pixel's color?
CodePudding user response:
first you need to supply headers for bitmap image file format ... then read it byte by byte.
then image pixel data is next to where headers end. headers also contain offset from where the pixel data starts ...
then you can read pixel data at once by calculating from width height and bytes per pixel...
you also need to take padding at the end of the row to take account of images whose width is not divisible by four.
you need to write a bitmap image parser basically ...
make sure to open the bitmap file in binary mode...
more info here ...
https://en.wikipedia.org/wiki/BMP_file_format
CodePudding user response:
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;
}