Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Jesper T

*.bmp -files, reading from/writing to

This topic is 6039 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

Basically what I want to do is: read pixel A, change pixel A, write pixel A back into the image (or alternatively a new image) Is this a straightfoward thing? Anyone know of some good tutorials or anything ? Thanks
My post up, your post down, my site here

Share this post


Link to post
Share on other sites
Advertisement
OK, I''ll share some code I wrote a while back as long as people don''t pick at it. I wrote it for my own use; I''m sure they''re problems and things it won''t handle. It works only with 8 bit color BMP files. It reads and writes these files, and allows you to get at the actual image data directly. Hope it helps; post any questions you might have. Please don''t just copy this if you''re doing homework, but use it as a reference or example to write your own.

Sorry for the formatting; it may be hard to follow. Looks great in my MSVC++ 6.0 Also, note that it refers to other types and objects not included here; they are not particularly important to the basic routines.

Header file
  

#ifndef COL2GRBMPFILE_DEF
#define COL2GRBMPFILE_DEF

#include "c2ucommon.h" // common definitions
#include "c2umem.h" // memory objects


// Col2GrBmpfile

// Description:

// This class supports a windows BMP file object. It contains the ability

// to read and write uncompressed Windows BMP files. It also allows

// the objects to be converted to Col2GrSurface objects.

//

// Currently, this class supports only Windows BMP files with a 256 color

// palette. In the future, it can be enhanced to support other bit

// depths (16 and 24 bit).


class Col2GrBmpfile {
public:
Col2GrBmpfile(); // Default constructor

Col2GrBmpfile(const Col2GrBmpfile& from); // Copy constructor

~Col2GrBmpfile(); // Destructor


// GetHeight/Width - gets the height and width of the object''s image.

long int GetHeight() { return C2GR_FINFO_HEIGHT(m_f); }
long int GetWidth() { return C2GR_FINFO_WIDTH(m_f); }

// GetPalette - returns the color palette.

c2gr_pal_entry *GetPalette() { return m_palette; }

// GetNumColors - returns the number of colors in the image.

long int GetNumColors() { return m_num_colors; }

// GetImage - returns a pointer to the actual image data.

c2gr_ddata_ptr GetImage() { return m_image.GetPtr(); }

// Get/SetFileName - accesses the bitmap filename.

c2string GetFileName() { return m_path; }
void SetFileName(c2string filename) { m_path = filename; return; }

// CreateFromFile

// Creates a new BMP file using the palette information from the supplied ''fromFile''

// and the new file name supplied in ''filename''. New file has no pixel data, and

// is not saved to disk.

void CreateFromFile(Col2GrBmpfile& fromFile, char *filename);

// CopyFile

// Copies palette and pixel data from given ''fromFile'', and gives new BMP the file

// name supplied in ''newFileName''. Does not save file to disk.

void CopyFile(Col2GrBmpfile& fromFile, char *newFileName);

// ReadFile

// Copies palette and pixel data into memory from given file ''bmpFile''.

void ReadFile(char *bmpFile);

// WriteFile

// Writes palette and pixel data to disk, given internal filename already associated

// with Col2GrBmpfile object.

void WriteFile();

// AssociateData

// Copies given data, with given ''width'' and ''height'', into this Col2GrBmpfile object.

// Method will allocate storage and copy the data given in ''data'' into the Col2GrBmpfile''s

// internal data storage. Method does nothing to palette data.

void AssociateData(c2gr_ddata_ptr data, long int width, long int height,
bool reverse=false);

// GetColorDepth - returns the color depth of the bitmap. Can be 1, 4, 8, 16, 24, or 32.

long int GetColorDepth();

// GetRGBMasks - returns the bitmasks for the red/green/blue values. Valid only for

// 16, 24, and 32 bit color depth.

void GetRGBMasks(long int *redMask, long int *greenMask, long int *blueMask);

private:
bool m_has_bitmap; // Does this obj have an image?

c2gr_finfo m_f; // File header

long int m_num_colors; // Current 256

c2gr_pal_entry m_palette[PALETTE_SIZE]; // Color palette

Col2UMem m_image; // Actual image data

c2string m_path; // File path name


private:
void AllocateStorage(long int width = -1, long int height = -1);

};

#endif


CPP File

  

#include "c2grbmpfile.h"
#include "c2err.h"

/////////////////////////////////////////////////////////////////////////////////////////////

// BitMap File Methods


Col2GrBmpfile::Col2GrBmpfile() : m_has_bitmap(false), m_image(0), m_path("")
{
}

Col2GrBmpfile::~Col2GrBmpfile()
{
}

// Copy Constructor

Col2GrBmpfile::Col2GrBmpfile(const Col2GrBmpfile& from) :
m_has_bitmap(from.m_has_bitmap), m_image(0)
{
m_f = from.m_f;
m_num_colors = from.m_num_colors;

// Copy palette. TODO: support other than 256 color palette (no palette?).

if (m_num_colors > 0)
{
memcpy(m_palette, (c2gr_pal_entry *)from.m_palette,
sizeof(c2gr_pal_entry)*m_num_colors);
};
m_image = 0;
m_path = from.m_path;

// Make a copy of the image data.

AssociateData(from.m_image.GetPtr(), C2GR_FINFO_WIDTH(m_f), C2GR_FINFO_HEIGHT(m_f));
}


void Col2GrBmpfile::AllocateStorage(long int width, long int height)
{
m_image.Free();

// If supplied, use the given width/height.

if (width != -1)
C2GR_FINFO_WIDTH(m_f) = width;
if (height != -1)
C2GR_FINFO_HEIGHT(m_f) = height;

// Allocate the storage

m_image.Resize(C2GR_FINFO_WIDTH(m_f) * C2GR_FINFO_HEIGHT(m_f) );

return;
}

void Col2GrBmpfile::AssociateData(c2ptr data, long int width, long int height, bool reverse)
{
AllocateStorage(width, height);

c2ptr iptr = m_image.GetPtr();
if (reverse)
{
unsigned char *dptr;
unsigned char *sptr;
for (int ind=height; ind>0; ind--)
{
sptr = data + ((ind-1) * width);
dptr = iptr + (width * (height - ind));
for (int jind=0; jind<width; jind++)
*dptr++ = *sptr++;
};
}
else
{
memcpy(iptr, data, width*height);
};
return;
}

void Col2GrBmpfile::CreateFromFile(Col2GrBmpfile& fromFile, char *filename)
{
m_has_bitmap = fromFile.m_has_bitmap;
m_f = fromFile.m_f;
m_num_colors = fromFile.m_num_colors;
memcpy((c2ptr)m_palette, (c2ptr)fromFile.m_palette, m_num_colors*sizeof(c2gr_pal_entry));

m_path = filename;

// Free up any previous data stored in the image.

m_image.Free();

return;
}

void Col2GrBmpfile::CopyFile(Col2GrBmpfile& fromFile, char *newFileName)
{
CreateFromFile(fromFile, newFileName);
AssociateData(fromFile.GetImage(), fromFile.GetWidth(), fromFile.GetHeight());
return;
}

void Col2GrBmpfile::ReadFile(char *filename)
{
m_path = filename;

#if WIN32
DWORD actualRead;
HANDLE hfile;

// Try to read the file.

hfile = CreateFile( C2STRING_CHAR_PTR(m_path), GENERIC_READ, FILE_SHARE_READ,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL );

// Look in the higher level directory.

if ( hfile == INVALID_HANDLE_VALUE )
{
m_path = (c2string)"
..\\" + filename;
hfile = CreateFile( C2STRING_CHAR_PTR(m_path), GENERIC_READ, FILE_SHARE_READ,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL );
if ( hfile == INVALID_HANDLE_VALUE )
throw Col2Error(C2ERR_CANT_FIND_BMPFILE, Col2UDVal(filename));
};

// Read the BMP header and info structures

if( !::ReadFile ( hfile, &m_f.header, sizeof ( m_f.header ),
&actualRead, NULL) )
return; // TODO: throw exception


if( !::ReadFile ( hfile, &m_f.info, sizeof ( m_f.info ),
&actualRead, NULL) )
return; // TODO: throw exception


// Make sure the BMP is 8-bit color

if ( m_f.info.biBitCount != 8 )
return; // TODO: throw exception


// Get the BMP palette

if (m_f.info.biClrUsed == 236)
{
if ( !::ReadFile ( hfile, &m_palette[10], m_f.info.biClrUsed * sizeof(RGBQUAD),
&actualRead, NULL ) )
return; // TODO: throw exception

}
else
{
if ( !::ReadFile ( hfile, m_palette, 256*sizeof(RGBQUAD),
&actualRead, NULL ) )
return; // TODO: throw exception

};

// Allocate space for the image data.

AllocateStorage();

// Read BMP data into memory

if ( !::ReadFile ( hfile, m_image.GetPtr(), m_f.info.biWidth * m_f.info.biHeight,
&actualRead, NULL) )
return; // TODO: throw exception


// Remember the width and height.

m_num_colors = 256L;
m_has_bitmap = TRUE;

// Close the file.

CloseHandle(hfile);

#endif // WIN32 specific


return;
}

void Col2GrBmpfile::WriteFile()
{
DWORD actualWritten;
HANDLE hfile;

if (m_has_bitmap == FALSE)
return; // TODO: throw exception


#if WIN32
// Create the file, either new or overwritting the existing one.

hfile = CreateFile( C2STRING_CHAR_PTR(m_path), GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL );
if ( hfile == INVALID_HANDLE_VALUE )
{
return; // TODO: throw exception

};

// Write the BMP header and info structures

m_f.info.biSizeImage = m_f.info.biHeight * m_f.info.biWidth;
m_f.header.bfSize = sizeof(m_f.header) + sizeof(m_f.info) + 256*sizeof(RGBQUAD) +
m_f.info.biSizeImage;
if( !::WriteFile ( hfile, &m_f.header, sizeof ( m_f.header ),
&actualWritten, NULL) )
return; // TODO: throw exception


if( !::WriteFile ( hfile, &m_f.info, sizeof ( m_f.info ),
&actualWritten, NULL) )
return; // TODO: throw exception


// Write the BMP palette

// 236 color case - without system colors.

if (m_f.info.biClrUsed == 236)
{
if ( !::WriteFile ( hfile, &m_palette[10], m_f.info.biClrUsed * sizeof(RGBQUAD),
&actualWritten, NULL ) )
return; // TODO: throw exception

}
// 256 color case - with system colors.

else
{
if ( !::WriteFile ( hfile, m_palette, 256*sizeof(RGBQUAD),
&actualWritten, NULL ) )
return; // TODO: throw exception

};

// Write BMP data

if ( !::WriteFile ( hfile, m_image.GetPtr(), m_f.info.biWidth * m_f.info.biHeight,
&actualWritten, NULL) )
return; // TODO: throw exception


// Close the file.

CloseHandle(hfile);

#endif // WIN32 specific


return;
}

long int Col2GrBmpfile::GetColorDepth()
{
#if WIN32
return m_f.info.biBitCount;
#else
return 0; // TODO: platform specific

#endif

}



Share this post


Link to post
Share on other sites
Wow that a lot of code.. me thinking that it might be along the lines of text files etc hehe was wrong there I guess.. anyway thanks for posting, but it looks like I need to find a good tutorial on this

Share this post


Link to post
Share on other sites

  • 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!