Storing bitmap color data

Started by
2 comments, last by Bonehed316 18 years, 9 months ago
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.)
Advertisement
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
For the love of god, please tell me that you've just omitted your error checking code for brevity, and you don't really assume that all those functions succeed.
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:

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.

This topic is closed to new replies.

Advertisement