Original Post
Hey guys, I wanted to know how one should go about accessing the pixel data of a BMP file. I want to open one BMP file and copy all its data into another BMP file, pixel by pixel. I am using C++. I used the code given on gamedev.net for reading the BMP file. Now I am having a problem in writing it. My code till now is - The Bitmap.h header file contains the basic structure definition of a BMP file. How do I complete my task? Thanks! [Edited by - ak11streetballer on March 12, 2008 5:59:54 AM]
#include "Bitmap.h"
#include <iostream>
#include <fstream>
using namespace std;
//basic constructor
Bitmap::Bitmap()
{
reset();
}
//constructor loads the bitmap when it is created
Bitmap::Bitmap(char *file)
{
reset();
loadBMP(file);
}
//destructor
Bitmap::~Bitmap()
{
if(colours!=0) {
delete[] colours;
}
if(data!=0) {
delete[] data;
}
}
//load a bitmap from a file and represent it correctly in memory
bool Bitmap::loadBMP(char *file)
{
FILE *in; //file stream for reading
char *tempData; //temp storage for image data
int numColours; //total available colours
loaded=false;
if(colours!=0)
delete[] colours;
if(data!=0)
delete[] data;
//open the file for reading in binary mode
in=fopen(file,"rb");
//if the file does not exist return in error
if(in==NULL)
{
error="File not found";
cout<<error<<endl;
fclose(in);
return false;
}
//read in the entire BITMAPFILEHEADER
fread(&bmfh,sizeof(BitmapFileHeader),1,in);
cout<<"sizeof(BitmapFileHeader)="<<sizeof(BitmapFileHeader)<<endl;
//check for the magic number that says this is a bitmap
if(bmfh.bfType!=BITMAP_MAGIC_NUMBER)
{
error="File is not in DIB format";
cout<<error<<endl;
fclose(in);
return false;
}
//read in the entire BITMAPINFOHEADER
fread(&bmih,sizeof(BitmapInfoHeader),1,in);
cout<<"sizeof(BitmapInfoHeader)="<<sizeof(BitmapInfoHeader)<<endl;
width=bmih.biWidth;
height=bmih.biHeight;
bpp=bmih.biBitCount;
cout<<"biBitCount ="<<bmih.biBitCount<<endl;
cout<<"biClrImportant ="<<bmih.biClrImportant<<endl;
cout<<"biClrUsed ="<<bmih.biClrUsed<<endl;
cout<<"biCompression ="<<bmih.biCompression<<endl;
cout<<"biHeight ="<<bmih.biHeight<<endl;
cout<<"biPlanes ="<<bmih.biPlanes<<endl;
cout<<"biSize ="<<bmih.biSize<<endl;
cout<<"biSizeImage ="<<bmih.biSizeImage<<endl;
cout<<"biWidth ="<<bmih.biWidth <<endl;
cout<<"biXPelsPerMeter ="<<bmih.biXPelsPerMeter<<endl;
cout<<"biYPelsPerMeter ="<<bmih.biYPelsPerMeter<<endl;
cout<<"bpp ="<<bpp<<endl;
//calculate the size of the image data with padding
dataSize=(width*height*(unsigned int)(bmih.biBitCount/8.0));
//calculate the number of available colours
numColours=1<<bmih.biBitCount;
cout<<"Number of available colors = "<<numColours<<endl;
//if the bitmap is not 8 bits per pixel or more return in error
if(bpp<8)
{
error="File is not 8 or 24 bits per pixel";
cout<<error<<endl;
fclose(in);
return false;
}
//load the palette for 8 bits per pixel
if(bpp==8)
{
colours=new RGBQuad[numColours];
fread(&colours,sizeof(RGBQuad),numColours,in);
}
//set up the temporary buffer for the image data
tempData=new char[dataSize];
//exit if there is not enough memory
if(tempData==NULL)
{
error="Not enough memory to allocate a temporary buffer";
cout<<error<<endl;
fclose(in);
return false;
}
//read in the entire image
fread(tempData,sizeof(tempData),dataSize,in);
fclose(in);
//calculate the witdh of the final image in bytes
byteWidth=padWidth=(int)((float)width*(float)bpp/8.0);
//adjust the width for padding as necessary
while(padWidth%4!=0)
{
padWidth++;
}
//change format from GBR to RGB
if(bpp==8)
{
loaded=convert8(tempData);
}
else if(bpp==24) {
loaded=convert24(tempData);
}
//clean up memory
delete[] tempData;
//bitmap is now loaded
error="Bitmap loaded";
cout<<error<<endl;
//return success
return loaded;
}
//function to set the inital values
void Bitmap::reset(void) {
loaded=false;
colours=0;
data=0;
error="";
}
bool Bitmap::convert24(char* tempData) {
int offset,diff;
diff=width*height*RGB_BYTE_SIZE;
//allocate the buffer for the final image data
data=new char[diff];
//exit if there is not enough memory
if(data==NULL)
{
error="Not enough memory to allocate an image buffer";
cout<<error<<endl;
delete[] data;
return false;
}
if(height>0)
{
offset=padWidth-byteWidth;
//count backwards so you start at the front of the image
for(int i=0;i<dataSize;i+=3)
{
//jump over the padding at the start of a new line
if((i+1)%padWidth==0)
i+=offset;
//transfer the data
*(data+i+2)=*(tempData+i);
*(data+i+1)=*(tempData+i+1);
*(data+i)=*(tempData+i+2);
}
}
//image parser for a forward image
else
{
offset=padWidth-byteWidth;
int j=dataSize-3;
//count backwards so you start at the front of the image
for(int i=0;i<dataSize;i+=3)
{
//jump over the padding at the start of a new line
if((i+1)%padWidth==0)
i+=offset;
//transfer the data
*(data+j+2)=*(tempData+i);
*(data+j+1)=*(tempData+i+1);
*(data+j)=*(tempData+i+2);
j-=3;
}
}
return true;
}
bool Bitmap::convert8(char* tempData) {
int offset,diff;
bool write;
char ans8='y', fileSave[100];
diff=width*height*RGB_BYTE_SIZE;
//allocate the buffer for the final image data
data=new char[diff];
//exit if there is not enough memory
if(data==NULL)
{
error="Not enough memory to allocate an image buffer";
cout<<error<<endl;
delete[] data;
return false;
}
if(height>0)
{
offset=padWidth-byteWidth;
int j=0;
//count backwards so you start at the front of the image
for(int i=0;i<dataSize*RGB_BYTE_SIZE;i+=3)
{
//jump over the padding at the start of a new line
if((i+1)%padWidth==0)
i+=offset;
//transfer the data
*(data+i)=colours[*(tempData+j)].rgbRed;
*(data+i+1)=colours[*(tempData+j)].rgbGreen;
*(data+i+2)=colours[*(tempData+j)].rgbBlue;
j++;
}
}
//image parser for a forward image
else {
offset=padWidth-byteWidth;
int j=dataSize-1;
//count backwards so you start at the front of the image
for(int i=0;i<dataSize*RGB_BYTE_SIZE;i+=3)
{
//jump over the padding at the start of a new line
if((i+1)%padWidth==0)
i+=offset;
//transfer the data
*(data+i)=colours[*(tempData+j)].rgbRed;
*(data+i+1)=colours[*(tempData+j)].rgbGreen;
*(data+i+2)=colours[*(tempData+j)].rgbBlue;
j--;
}
}
return true;
}
int main()
{
char path[100],ans='y', fileSave[100];
cout<<"Enter the file name: ";
cin>>path;
Bitmap bmp(path);
cout<<"Is this ok?";
cin>>ans;
}