Nick Banks
Nick Banks

Reputation: 4408

How to edit a BITMAP once it has been loaded by win32

Once I have loaded a BITMAP from file, with LoadImage:

HBITMAP renderBMP = (HBITMAP)LoadImage( NULL, filePath, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE );

is there a way to easily access and edit the pixels individually?

I can use this to get the bitmap object, but it doesn't seem to help,

BITMAP bm;
GetObject(renderBMP, sizeof(bm), &bm);

because the value of bmBits in the structure is 0.

UPDATE:

Now I am getting a bug with this solution:

struct Pixel { unsigned char r,g,b,a; };
void Frame::PushMemory(HDC hdc)
{
  BITMAPINFO bi;
  ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
  bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

  GetDIBits(hdc, renderBMP, 0, bi.bmiHeader.biHeight, NULL, &bi, DIB_RGB_COLORS);

  /* Allocate memory for bitmap bits */
  Pixel* pixels = new Pixel[bi.bmiHeader.biHeight * bi.bmiHeader.biWidth];
  int n = sizeof(Pixel) * bi.bmiHeader.biHeight * bi.bmiHeader.biWidth;
  int m = bi.bmiHeader.biSizeImage;
  GetDIBits(hdc, renderBMP, 0, bi.bmiHeader.biHeight, pixels, &bi, DIB_RGB_COLORS);

  // Recompute the output
  //ComputeOutput(pixels);

  // Push back to windows
  //SetDIBits(hdc, renderBMP, 0, bi.bmiHeader.biHeight, pixels, &bi, DIB_RGB_COLORS );

  //delete pixels;
}

I get this error:

Run-Time Check Failure #2 - Stack around the variable 'bi' was corrupted.

The last three lines don't seem to matter whether commented in or not.

Upvotes: 1

Views: 3216

Answers (2)

DReJ
DReJ

Reputation: 1974

Use GetDIBits to access pixels. It copies all pixels into specified buffer. After pixels' modification you can use SetDIBits to write pixels back to bitmap.

EDIT: Example of code:

LPVOID lpvBits=NULL;    // pointer to bitmap bits array
BITMAPINFO bi;

ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

if (!GetDIBits(hDC, hBmp, 0, height, NULL, &bi, DIB_RGB_COLORS))
    return NULL;

/* Allocate memory for bitmap bits */
if ((lpvBits = new char[bi.bmiHeader.biSizeImage]) == NULL)
    return NULL;

if (!GetDIBits(hDC, hBmp, 0, height, lpvBits, &bi, DIB_RGB_COLORS))
    return NULL;


/* do something with bits */


::SetDIBits( hDC, hBmp, 0, height, ( LPVOID )lpvBits, &bi, DIB_RGB_COLORS );

Upvotes: 4

Chris Becke
Chris Becke

Reputation: 36026

If you pass the LR_CREATEDIBSECTION flag to LoadImage it creates a special kind of bitmap with a usermode memory section containing the bits of the bitmap.

GetObject on a DIBSection bitmap will fill in the bmPits pointer of the BITMAP structure, or even fill in a DIBSECTION struct with extra data.

Upvotes: 0

Related Questions