Gdiplus::Bitmap to BYTE array?
Solution 1
You could use Bitmap::LockBits
to get access to a raw array of data. Here you could read about how to use Bitmap::LockBits
.
Solution 2
Here's something I wrote that returns a vector of vectors (with the contained vectors representing columns of pixels in the image) when passed a file path:
#include <vector>
std::vector<std::vector<unsigned>> getPixels(const wchar_t *filename, int &width, int &height) {
Gdiplus::Bitmap bitmap(filename);
//Pass up the width and height, as these are useful for accessing pixels in the vector o' vectors.
width = bitmap.GetWidth();
height = bitmap.GetHeight();
auto *bitmapData = new Gdiplus::BitmapData;
//Lock the whole bitmap so we can read pixel data easily.
Gdiplus::Rect rect(0, 0, width, height);
bitmap.LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, bitmapData);
//Get the individual pixels from the locked area.
auto *pixels = static_cast<unsigned *>(bitmapData->Scan0);
//Vector of vectors; each vector is a column.
std::vector<std::vector<unsigned>> resultPixels(width, std::vector<unsigned>(height));
const int stride = abs(bitmapData->Stride);
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
//Get the pixel colour from the pixels array which we got earlier.
const unsigned pxColor = pixels[y * stride / 4 + x];
//Get each individual colour component. Bitmap colours are in reverse order.
const unsigned red = (pxColor & 0xFF0000) >> 16;
const unsigned green = (pxColor & 0xFF00) >> 8;
const unsigned blue = pxColor & 0xFF;
//Combine the values in a more typical RGB format (as opposed to the bitmap way).
const int rgbValue = RGB(red, green, blue);
//Assign this RGB value to the pixel location in the vector o' vectors.
resultPixels[x][y] = rgbValue;
}
}
//Unlock the bits that we locked before.
bitmap.UnlockBits(bitmapData);
return resultPixels;
}
Solution 3
Here is how I would do it using GDIPlus Bitmap.LockBits method defined in the header GdiPlusBitmap.h:
Notice that since bitmaps are usually DWORD aligned you may want to discard this unused data that was needed for the alignment, as malat correctly commented..
Gdiplus::BitmapData bitmapData;
Gdiplus::Rect rect(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
//get the bitmap data
if(Gdiplus::Ok == bitmap.LockBits(
&rect, //A rectangle structure that specifies the portion of the Bitmap to lock.
Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite, //ImageLockMode values that specifies the access level (read/write) for the Bitmap.
bitmap.GetPixelFormat(),// PixelFormat values that specifies the data format of the Bitmap.
&bitmapData //BitmapData that will contain the information about the lock operation.
))
{
//get the lenght of the bitmap data in bytes
int len = bitmapData.Height * std::abs(bitmapData.Stride);
BYTE* buffer = new BYTE[len];
memcpy(bitmapData.Scan0, buffer, len);//copy it to an array of BYTEs
//...
//cleanup
bitmap.UnlockBits(&bitmapData);
delete []buffer;
}
Solution 4
Have you tried supplying the bytes when you create the bitmap:
int width = BMP_WIDTH;
int height = BMP_HEIGHT;
int stride = 4 * width;
BYTE bytes[stride * height];
Gdiplus::Bitmap cBitmap(width, height, stride, PixelFormat32bppRGB, bytes);
Admin
Updated on June 04, 2022Comments
-
Admin almost 2 years
Here's my attempt (ugly GDI+ and GDI mix...)
// ... BYTE pixels[BMP_WIDTH * BMP_HEIGHT * BMP_BPP]; HBITMAP hBitmap; Gdiplus::Bitmap cBitmap(BMP_WIDTH, BMP_HEIGHT, PixelFormat32bppRGB); Gdiplus::Graphics cGraphics(&cBitmap); Gdiplus::Pen cPen(Gdiplus::Color(255, 255, 0, 0)); cGraphics.DrawRectangle(&cPen, 0, 0, cBitmap.GetWidth() - 1, cBitmap.GetHeight() - 1); // and here it get's real ugly, I'd like to change that... cBitmap.GetHBITMAP(Gdiplus::Color(255, 255, 255), &hBitmap); GetBitmapBits(hBitmap, sizeof(pixels), pixels); // ...
Someone told me to use LockBits but I really didn't understand how. I tried it, but I failed so I'm not going to post that attempt, too.
-
malat about 9 yearsNo this will not work,
bitmapData.Stride
is different frombitmapData.Width * sizeof( bitmapData.PixelFormat)
, since it contains also unused data. This requires a for loop to discard unused data. -
malat about 9 yearsThis is an easy case, one should pay attention that
stride % 4 == 0
in the general case (not all 3 components RGB works). -
Gray Programmerz over 2 yearscode crashes at
memcpy(...)
-
Gray Programmerz over 2 yearshow do that, when
BITMAP
is created usingBITMAP::FromHBITMAP(...)
?