I have a union defined as so:
typedef union RGB
{
unsigned Color;
struct
{
unsigned char B, G, R, A;
};
} *PRGB;
I'm reading 32 bit and 24 bit bitmaps. I'm trying to Read Pixels from my RGB union and set pixels as well. I know bitmaps are sometimes stored upside down and sometimes up-right. How can I set the pixels at a specific position in the bitmap to a color?
I tried:
RGB BMPS::GET(int x, int y)
{
return Pixels[y * width + x];
}
void BMPS::SET(int x,int y, RGB color)
{
Pixels[y * width + x] = color;
}
But sometimes the changed pixels never show and sometimes when they do, they are on the opposite end of the bmp. I'm told I need to flip the bitmap which is contained in my union but I don't know how to flip the union upside down. I'm also told I need to pad the 24 bit bmp but not the 32 bit bmp. I have no idea how to do that using scanlines even though I read a ton of tutorials on this so I used CreateDIBitmap instead as shown below:
HeaderFile:
#ifndef BITMAPS_HPP_INCLUDED
#define BITMAPS_HPP_INCLUDED
#include "GDIPlus.h"
class Bitmap
{
private:
PRGB Pixels;
BITMAPINFO Info;
int width, height, size;
BITMAPFILEHEADER bFileHeader;
protected:
HDC DC;
HBITMAP Image;
public:
~Bitmap();
Bitmap(){}
Bitmap(const char* FilePath);
bool Save(const char* FilePath);
HDC ReturnDC(){return DC;}
int Width(){return (width < 0 ? -width : width);}
int Height(){return (height < 0 ? -height : height);}
void Size(int& Width, int& Height){Width = width; Height = height;}
int Size(){return size;}
PRGB GetPixels(){return Pixels;}
};
#endif // BITMAPS_HPP_INCLUDED
Implementation File:
#include "Bitmaps.hpp"
Bitmap::~Bitmap()
{
if (Pixels)
delete[] Pixels;
DeleteDC(DC);
DeleteObject(Image);
}
Bitmap::Bitmap(const char* FilePath)
{
HANDLE hFile = CreateFile(FilePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile == 0){ throw "Error Bitmap Doesn't Exist"; return; }
DWORD Read;
memset(&Info, 0, sizeof(BITMAPINFO));
ReadFile(hFile, &bFileHeader, sizeof(bFileHeader), &Read, 0);
ReadFile(hFile, &Info.bmiHeader, sizeof(Info.bmiHeader), &Read, 0);
if ((Info.bmiHeader.biBitCount != 24) && (Info.bmiHeader.biBitCount != 32))
{
CloseHandle(hFile);
throw "The Image Loaded is neither 24 or 32bits.";
return;
}
if (bFileHeader.bfType != 0x4D42)
{
CloseHandle(hFile);
throw "The File Is Not A Bitmap.";
return;
}
if (Info.bmiHeader.biCompression != BI_RGB)
{
CloseHandle(hFile);
return;
}
width = Info.bmiHeader.biWidth;
height = Info.bmiHeader.biHeight;
size = Info.bmiHeader.biSizeImage; //((bmp.bmWidth * BitsPerPixel + 31) / 32) * 4 * bmp.bmHeight;
Pixels = new RGB[size];
SetFilePointer(hFile, bFileHeader.bfOffBits, 0, FILE_BEGIN);
ReadFile(hFile, Pixels, size, &Read, 0);
DC = GetDC(0);
Image = CreateDIBitmap(DC, &Info.bmiHeader, CBM_INIT, Pixels, &Info, DIB_RGB_COLORS);
CloseHandle(hFile);
}
bool Bitmap::Save(const char* FilePath)
{
DWORD Written;
HANDLE hFile = CreateFile(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == 0)
{
CloseHandle(hFile);
return false;
}
if (!WriteFile(hFile, &bFileHeader, sizeof(BITMAPFILEHEADER), &Written, 0))
{
CloseHandle(hFile);
return false;
}
if (!WriteFile(hFile, &Info.bmiHeader, sizeof (BITMAPINFOHEADER), &Written, 0))
{
CloseHandle(hFile);
return false;
}
if (!WriteFile(hFile, Pixels, Info.bmiHeader.biSizeImage, &Written, 0))
{
CloseHandle(hFile);
return false;
}
return true;
}