• Advertisement

Archived

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

*.bmp -files, reading from/writing to

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