Storing bitmap color data
I have a bitmap class and I was having a problem with it being saved to a file. Come to find out, it was because when I was saving I was using sizeof(uint) instead of char. All of my code seems to work fine using uint, but should I be using char or BYTE instead?
Thanks!
Edit: If I do use char or BYTE, do I have to modify values differently (like when looping through the array, getting a pixel, etc.)
Hi Programmer16,
Bitmap functions are not directly related to DirectX (other than loading them as textures).
You would probably better off posting your question to one of the MS programming newsgroups.
You will need to give a lot more detail and possibly some of your code.
Good luck,
Cambo_frog
Bitmap functions are not directly related to DirectX (other than loading them as textures).
You would probably better off posting your question to one of the MS programming newsgroups.
You will need to give a lot more detail and possibly some of your code.
Good luck,
Cambo_frog
Oops, I meant to post it in the Graphics Programming forum, not the DirectX one. I'm using C++ and the class only loads 24bit files (no compression.) I'm using std::fstream.read() and write() to load/save bitmaps. Here's the class:
And here's the declarations:
I just wanted to know if m_pData should be
class CBitmap{ struct BmpFileHeader { unsigned short m_bfType; unsigned int m_bfSize; unsigned short m_bfReserved1, m_bfReserved2; unsigned int m_bfOffBits; }; struct BmpInfoHeader { unsigned int m_biSize; unsigned int m_biWidth; unsigned int m_biHeight; unsigned short m_biPlanes; unsigned short m_biBitCount; unsigned int m_biCompression; unsigned int m_biSizeImage; unsigned int m_biXPelsPerMeter; unsigned int m_biYPelsPerMeter; unsigned int m_biClrUsed; unsigned int m_biClrImportant; }; uint* m_pData; unsigned int m_nWidth, m_nHeight; BmpFileHeader m_FileHeader; BmpInfoHeader m_InfoHeader; public: CBitmap(); CBitmap(unsigned int nWidth, unsigned int nHeight); CBitmap(const char* pFileName); bool CreateBlank(unsigned int nWidth, unsigned int nHeight); bool CreateFromFile(const char* pFileName); void SaveToFile(const char* pFileName); void Release(); uint GetPixel(unsigned int nX, unsigned int nY) const; void SetPixel(unsigned int nX, unsigned int nY, uint nClrValue); unsigned int GetWidth() const; unsigned int GetHeight() const;};
And here's the declarations:
//-----------------------------------------------------------------------------// CBitmap()//-----------------------------------------------------------------------------CBitmap::CBitmap(){ // Clear the pointer m_pData = 0; // Clear the bitmap's dimensions m_nWidth = 0; m_nHeight = 0; // Clear out the headers memset(&m_FileHeader, 0, sizeof(BmpFileHeader)); memset(&m_InfoHeader, 0, sizeof(BmpInfoHeader));}//-----------------------------------------------------------------------------// CBitmap()//-----------------------------------------------------------------------------CBitmap::CBitmap(unsigned int nWidth, unsigned int nHeight){ // Allocate memory m_pData = new uint[nWidth * nHeight]; // Make sure that the memory was allocated. assert(m_pData != 0); // Store the bitmap's dimensions m_nWidth = nWidth; m_nHeight = nHeight; // Clear out the headers memset(&m_FileHeader, 0, sizeof(BmpFileHeader)); memset(&m_InfoHeader, 0, sizeof(BmpInfoHeader)); // Store bitmap's dimensions in the headers. m_InfoHeader.m_biWidth = m_nWidth; m_InfoHeader.m_biHeight = m_nHeight; // Clear the data memset(m_pData, 0, sizeof(uint) * (m_nWidth * m_nHeight));}//-----------------------------------------------------------------------------// CBitmap()//-----------------------------------------------------------------------------CBitmap::CBitmap(const char* pFileName){ // Open the file std::fstream File(pFileName, std::ios::in | std::ios::binary); // Make sure that the file is open. assert(File.is_open() != 0); // Read in the file header File.read((char*)&m_FileHeader.m_bfType, sizeof(ushort)); File.read((char*)&m_FileHeader.m_bfSize, sizeof(uint)); File.read((char*)&m_FileHeader.m_bfReserved1, sizeof(ushort)); File.read((char*)&m_FileHeader.m_bfReserved2, sizeof(ushort)); File.read((char*)&m_FileHeader.m_bfOffBits, sizeof(uint)); // Read in the info header File.read((char*)&m_InfoHeader.m_biSize, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biWidth, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biHeight, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biPlanes, sizeof(ushort)); File.read((char*)&m_InfoHeader.m_biBitCount, sizeof(ushort)); File.read((char*)&m_InfoHeader.m_biCompression, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biSizeImage, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biXPelsPerMeter, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biYPelsPerMeter, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biClrUsed, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biClrImportant, sizeof(uint)); // Store the bitmap's dimensions m_nWidth = m_InfoHeader.m_biWidth; m_nHeight = m_InfoHeader.m_biHeight; // Allocate memory m_pData = new uint[m_nWidth * m_nHeight]; // Make sure that the memory was allocated. assert(m_pData != 0); // Clear the data memset(m_pData, 0, sizeof(uint) * (m_nWidth * m_nHeight)); // Iterate backwards vertically for(int iY = m_nHeight - 1; iY >= 0; --iY) { // Iterate horizontally for(int iX = 0; iX < m_nWidth; ++iX) { // Read in the color data (B, G, R) char cR, cG, cB; File.read((char*)&cB, sizeof(char)); File.read((char*)&cG, sizeof(char)); File.read((char*)&cR, sizeof(char)); // Store the loaded values m_pData[(iY * m_nWidth) + iX] = MakeRGB((uint)cR, (uint)cG, (uint)cB); } } File.close();}//-----------------------------------------------------------------------------// CreateBlank()//-----------------------------------------------------------------------------bool CBitmap::CreateBlank(unsigned int nWidth, unsigned int nHeight){ // Allocate memory m_pData = new uint[nWidth * nHeight]; // Make sure that the memory was allocated. if(!m_pData) return false; // Store the bitmap's dimensions m_nWidth = nWidth; m_nHeight = nHeight; // Clear out the headers memset(&m_FileHeader, 0, sizeof(BmpFileHeader)); memset(&m_InfoHeader, 0, sizeof(BmpInfoHeader)); // Store bitmap's dimensions in the headers. m_InfoHeader.m_biWidth = m_nWidth; m_InfoHeader.m_biHeight = m_nHeight; // Clear the data memset(m_pData, 0, sizeof(uint) * (m_nWidth * m_nHeight)); return true;}//-----------------------------------------------------------------------------// CreateFromFile()//-----------------------------------------------------------------------------bool CBitmap::CreateFromFile(const char* pFileName){ // Open the file std::fstream File(pFileName, std::ios::in | std::ios::binary); // Make sure the file is open; if it isn't then return false. if(!File.is_open()) return false; // Read in the file header File.read((char*)&m_FileHeader.m_bfType, sizeof(ushort)); File.read((char*)&m_FileHeader.m_bfSize, sizeof(uint)); File.read((char*)&m_FileHeader.m_bfReserved1, sizeof(ushort)); File.read((char*)&m_FileHeader.m_bfReserved2, sizeof(ushort)); File.read((char*)&m_FileHeader.m_bfOffBits, sizeof(uint)); // Read in the info header File.read((char*)&m_InfoHeader.m_biSize, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biWidth, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biHeight, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biPlanes, sizeof(ushort)); File.read((char*)&m_InfoHeader.m_biBitCount, sizeof(ushort)); File.read((char*)&m_InfoHeader.m_biCompression, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biSizeImage, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biXPelsPerMeter, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biYPelsPerMeter, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biClrUsed, sizeof(uint)); File.read((char*)&m_InfoHeader.m_biClrImportant, sizeof(uint)); // Store the bitmap's dimensions m_nWidth = m_InfoHeader.m_biWidth; m_nHeight = m_InfoHeader.m_biHeight; // Allocate memory m_pData = new uint[m_nWidth * m_nHeight]; // Make sure that the memory was allocated. assert(m_pData != 0); // Return false if the memory wasn't allocated. if(!m_pData) return false; // Clear the data memset(m_pData, 0, sizeof(uint) * (m_nWidth * m_nHeight)); // Iterate backwards vertically for(int iY = m_nHeight - 1; iY >= 0; --iY) { // Iterate horizontally for(int iX = 0; iX < m_nWidth; ++iX) { // Read in the color data (B, G, R) char cR = 0, cG = 0, cB = 0; File.read((char*)&cB, sizeof(char)); File.read((char*)&cG, sizeof(char)); File.read((char*)&cR, sizeof(char)); // Store the loaded values m_pData[(iY * m_nWidth) + iX] = MakeRGB((uint)cR, (uint)cG, (uint)cB); } } File.close(); return true;}//-----------------------------------------------------------------------------// SaveToFile()//-----------------------------------------------------------------------------void CBitmap::SaveToFile(const char* pFileName){ // Open the file std::fstream File(pFileName, std::ios::out | std::ios::binary); // Make sure the file is open if(!File.is_open()) return; // Write the file header File.write((char*)&m_FileHeader.m_bfType, sizeof(ushort)); File.write((char*)&m_FileHeader.m_bfSize, sizeof(uint)); File.write((char*)&m_FileHeader.m_bfReserved1, sizeof(ushort)); File.write((char*)&m_FileHeader.m_bfReserved2, sizeof(ushort)); File.write((char*)&m_FileHeader.m_bfOffBits, sizeof(uint)); // Write the info header File.write((char*)&m_InfoHeader.m_biSize, sizeof(uint)); File.write((char*)&m_InfoHeader.m_biWidth, sizeof(uint)); File.write((char*)&m_InfoHeader.m_biHeight, sizeof(uint)); File.write((char*)&m_InfoHeader.m_biPlanes, sizeof(ushort)); File.write((char*)&m_InfoHeader.m_biBitCount, sizeof(ushort)); File.write((char*)&m_InfoHeader.m_biCompression, sizeof(uint)); File.write((char*)&m_InfoHeader.m_biSizeImage, sizeof(uint)); File.write((char*)&m_InfoHeader.m_biXPelsPerMeter, sizeof(uint)); File.write((char*)&m_InfoHeader.m_biYPelsPerMeter, sizeof(uint)); File.write((char*)&m_InfoHeader.m_biClrUsed, sizeof(uint)); File.write((char*)&m_InfoHeader.m_biClrImportant, sizeof(uint)); // Iterate backwards vertically for(int iY = m_nHeight - 1; iY >= 0; --iY) { // Iterate horizontally for(int iX = 0; iX < m_nWidth; ++iX) { // Separate the color components uint nR = 0, nG = 0, nB = 0; GetComponents(m_pData[(iY * m_nWidth) + iX], nR, nG, nB); // Write each component (B, G, R) File.write((char*)&nB, sizeof(char)); File.write((char*)&nG, sizeof(char)); File.write((char*)&nR, sizeof(char)); } } File.close();}//-----------------------------------------------------------------------------// Release()//-----------------------------------------------------------------------------void CBitmap::Release(){ // Deallocate the memory delete [] m_pData; // Clear the pointer m_pData = 0; // Clear the bitmap's dimensions m_nWidth = 0; m_nHeight = 0; // Clear out the headers memset(&m_FileHeader, 0, sizeof(BmpFileHeader)); memset(&m_InfoHeader, 0, sizeof(BmpInfoHeader));}//-----------------------------------------------------------------------------// GetPixel()//-----------------------------------------------------------------------------uint CBitmap::GetPixel(unsigned int nX, unsigned int nY) const{ return m_pData[(nY * m_nWidth) + nX];}//-----------------------------------------------------------------------------// SetPixel()//-----------------------------------------------------------------------------void CBitmap::SetPixel(unsigned int nX, unsigned int nY, uint nClrValue){ m_pData[(nY * m_nWidth) + nX] = nClrValue;}//-----------------------------------------------------------------------------// GetWidth()//-----------------------------------------------------------------------------unsigned int CBitmap::GetWidth() const{ return m_nWidth;}//-----------------------------------------------------------------------------// GetHeight()//-----------------------------------------------------------------------------unsigned int CBitmap::GetHeight() const{ return m_nHeight;}}
I just wanted to know if m_pData should be
char* m_pData;
BYTE* m_pData;
Well thats the beauty of data. Data is data. You know the information is stored as bytes, each byte being the R, B or G (or A, if you have a 32bit format) channel of an image. The size of the data is all that matters (more specifically the "stride"). Since you know the data is bytes, you can use char or byte, or a struct of 3 bytes to represent a single pixel, with r, g and b values.
Next trick is figuring out which if the bitmap is upside down or backwards.
Next trick is figuring out which if the bitmap is upside down or backwards.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement