Jump to content
  • Advertisement
Sign in to follow this  
Programmer16

Storing bitmap color data

This topic is 4863 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.)

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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;

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!