Bmp File Loading into 2D array

Hi all. I am new to image processing and as a first step I am trying to load the pixels of a bmp into a 2D array

this is my code so far :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#ifndef BMP_HEADERS
#define BMP_HEADERS
/*
  I have found that the following pragma is necessary to ensure
  the correct size of the structs.
 
  In the file, the BmpFileHeader struct is 14 bytes long and
  the BmpInfoHeader is 40 bytes long
  Works for GNU, Borland bcc32, Microsoft VC++
 
*/ 


#pragma pack(push, 1)
typedef struct {
    unsigned short type;               /* Two chars "BM" in little-endian order  */
    unsigned int size;               /*unsigned int 4 bytes File size                              */
    unsigned short reserved1;          //unsigned short 2 bytes
	unsigned short reserved2;
    unsigned int offset;             /* Bytes from start of file to pixel data */
} BmpFileHeader;

typedef struct {
    unsigned int size;               /* Size of this header  (40 bytes)= DOWRD */
    int width;                       /* Bitmap width in pixels                 */
    int height;                      /* Bitmap height in pixels                */
    unsigned short planes;             /* Must be 1                              */
	unsigned short bits;               /* Bits per pixel. (8 for 256-color bmps) */

    unsigned int compression;        /* 0 means no compression                 */
    unsigned int imagesize;          /* Number of bytes in pixel data section  */
    int  xresolution;        /* Not used by any of my functions        */
    int  yresolution;        /* Not used by any of my functions        */

	
    unsigned int ncolors;            /* 0 means use all colors                 */
    unsigned int importantcolors;    /* 0 means all are important              */



} BmpInfoHeader;

typedef struct                       /**** Colormap entry structure ****/
    {
    unsigned char  rgbBlue;          /* Blue value */
    unsigned char  rgbGreen;         /* Green value */
    unsigned char  rgbRed;           /* Red value */
    unsigned char  rgbReserved;      /* Reserved */
    } RGBQUAD;


#pragma pack(pop)

#endif 


This was the header file for the bmp , now this is a little class I made
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#pragma once
#ifndef BMP_H
#define BMP_H
#include "bmp_headers.h"
#include <iostream>

using namespace std;
class Bmp
{
public:
	Bmp(BmpFileHeader&,BmpInfoHeader&,const int&,const int&,const unsigned short&,const unsigned int&);
 	Bmp(void);
	~Bmp(void);
	friend ostream& operator<<(ostream&,Bmp&);
    
	const int getWidth()const;
	const int getHeight()const;
	const unsigned short getBpp()const;
	unsigned char getImageArray(int,int,int);
	RGBQUAD getPallete(int);
	BmpFileHeader getBMPFH();
	BmpInfoHeader getBMPIH();
	void loadArrayPtr(unsigned char***,int,int,int);
	void loadPallete(RGBQUAD*,const unsigned int&);
	void setOffset(int);
	private :
	BmpFileHeader FH;
	BmpInfoHeader IH;
	unsigned char*** imageArray;
	RGBQUAD* pallete;
	
};
#endif 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "Bmp.h"


Bmp::Bmp(BmpFileHeader &myFH,BmpInfoHeader &myIH,const int &width,const int &height,const unsigned short&bpp,const unsigned int& arg):FH(myFH),IH(myIH)
{
	imageArray=new unsigned char**[height];
	for(int i=0;i<height;++i)
		{
		imageArray[i]=new unsigned char*[width];
		for(int j=0;j<width;++j)
			{
			imageArray[i][j]=new unsigned char[bpp/8];
			for(int k=0;k<bpp/8;++k)
				imageArray[i][j][k]=0;
			}
		}
	pallete = new RGBQUAD[arg];
	for(int i=0;i<arg;++i)
		{
		pallete[i].rgbBlue=arg;
		pallete[i].rgbGreen=arg;
		pallete[i].rgbRed=arg;
		pallete[i].rgbReserved=arg;
		}
	}
Bmp::Bmp()
{}

Bmp::~Bmp(void)
{
}

ostream& operator <<(ostream& output,Bmp& arg)
	{
		

		return output<<hex<<"Bmp File Type is : "<<arg.FH.type<<endl
		<<dec<<"Bmp Size is :"<<arg.FH.size<<endl
		<<"Bmp Reserved one is :"<<arg.FH.reserved1<<endl
		<<"Bmp Reserved two is :"<<arg.FH.reserved1<<endl
		<<"Bmp Header Offset is :"<<arg.FH.offset<<endl//Offset in bytes meaning that after byte 134 the actual pixels can be found
		<<"Bmp Header Size is :"<<arg.IH.size<<endl
		<<"Image width is : "<<arg.IH.width<<endl
		<<"Image height is : "<<arg.IH.height<<endl
		<<"Image bpp is : "<<arg.IH.bits<<endl
		<<"Image compression is : "<<arg.IH.compression<<endl
		<<"Bytes in pixel data section are : "<<arg.IH.imagesize<<endl
		<<"Number of colours is : "<<arg.IH.ncolors<<endl;
	}
const int Bmp::getHeight() const
	{
	return IH.height;
	}
const int Bmp::getWidth() const
	{
	return IH.width;
	}
const unsigned short Bmp::getBpp()const
	{
	return IH.bits;
	}
void Bmp::loadArrayPtr(unsigned char*** myArray,int height,int width,int bpp)
	{
	for(int i=0;i<height;++i)
		{
		for(int j=0;j<width;++j)
			{
			for(int k=0;k<bpp;++k)
				{
				imageArray[i][j][k]=myArray[i][j][k];
				}
			}
		}
	}
void Bmp::loadPallete(RGBQUAD*myPallete,const unsigned int &limit)
	{
	for(int i=0;i<limit;++i)
		{
		pallete[i]=myPallete[i];
		}
	}
BmpFileHeader Bmp::getBMPFH()
	{
	return FH;
	}
BmpInfoHeader Bmp::getBMPIH()
	{
	return IH;
	}
void Bmp::setOffset(int arg)
	{
	FH.offset=arg;
	}
unsigned char Bmp::getImageArray(int height,int width,int bpp)
	{
	return imageArray[height][width][bpp];
	}
RGBQUAD Bmp::getPallete(int arg)
	{
	return pallete[arg];
	}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <fstream>
#include <cstdlib>
#include "Bmp.h"

int main()
	{
	ifstream myBmpFile("lena512.bmp",ios::in|ios::binary);
	if(!myBmpFile)
		{
		cerr<<"File Could not be Opened."<<endl;
		exit(1);
		}
	BmpFileHeader myFH;
	BmpInfoHeader myIH;
	
	myBmpFile.read(reinterpret_cast<char*>(&myFH),sizeof(myFH));
	myBmpFile.read(reinterpret_cast<char*>(&myIH),sizeof(myIH));

	RGBQUAD* myPallete=new RGBQUAD[myIH.ncolors];
	for(int i=0;i<myIH.ncolors;++i)
		{
		myBmpFile.read(reinterpret_cast<char*>(&myPallete[i]),sizeof(RGBQUAD));
		}
	
	cout<<"Size of File Header is : "<<sizeof(myFH)<<endl
		<<"Size of Info Header is : "<<sizeof(myIH)<<endl;
	long endOfHeaders=myBmpFile.tellg();
	if(endOfHeaders!=1078)
		{
		cout<<"The file is corrupted"<<endl;
		exit(1);
		}	
	
	Bmp myBmp(myFH,myIH,myIH.width,myIH.height,myIH.bits,myIH.ncolors);//Constructing bmp object and initializing all private data members
	cout<<endl<<myBmp<<endl;
	
	myBmp.loadPallete(myPallete,myIH.ncolors);

	long startLocation=myBmpFile.tellg();
	cout<<"File pointer at the beginning of storing to the 2Darray :"<<myBmpFile.tellg()<<endl;
	

	unsigned char*** myArray;
	myArray=new unsigned char**[myBmp.getHeight()];
	for(int i=0;i<myBmp.getHeight();++i)
		{
		myArray[i]=new unsigned char*[myBmp.getWidth()];
		for(int j=0;j<myBmp.getWidth();++j)
			{
			myArray[i][j]=new unsigned char[(myBmp.getBpp()/8)];
			for(int k=0;k<(myBmp.getBpp()/8);++k)
				myArray[i][j][k]=0;
			}
		}
	for(int i=0;i<myBmp.getHeight();++i)
		{
		for(int j=0;j<myBmp.getWidth();++j)
			{
			for(int k=0;k<myBmp.getBpp()/8;++k)
				{
				myBmpFile.read(reinterpret_cast<char*>(&myArray[i][j][k]),sizeof(unsigned char));
				}
			
			}
		}
	myBmp.loadArrayPtr(myArray,myBmp.getHeight(),myBmp.getWidth(),(myBmp.getBpp()/8));
	long endLocation=myBmpFile.tellg();
	cout<<"File pointer at the end of storing to the 2Darray :"<<myBmpFile.tellg()<<endl
		<<"Total number of bytes read is : "<<endLocation-startLocation<<endl;
	myBmpFile.close();

	ofstream myCopiedBmp("copied.bmp",ios::out|ios::binary);
	if(!myCopiedBmp)
		{
		cerr<<"File Could not be Opened."<<endl;
		exit(1);
		}

	myCopiedBmp.write(reinterpret_cast<char*>(&myBmp.getBMPFH()),sizeof(myFH));
	myCopiedBmp.write(reinterpret_cast<char*>(&myBmp.getBMPIH()),sizeof(myIH));

	for(int i=0;i<myIH.ncolors;++i)
		{
		myCopiedBmp.write(reinterpret_cast<char*>(&myBmp.getPallete(i)),sizeof(RGBQUAD));
		}
	


	for(int i=0;i<myBmp.getHeight();++i)
		{
		for(int j=0;j<myBmp.getWidth();++j)
			{
			for(int k=0;k<myBmp.getBpp()/8;++k)
				{
				unsigned char data=myBmp.getImageArray(i,j,k);
				myCopiedBmp.write(reinterpret_cast<char*>(&data),sizeof(unsigned char));
				}
			
			}
		}
	

	



	
	while(1);
	return 0;
	}






Last edited on
Did you check the bmp standard?
Ιt says that the offset is supposed to be 54 which makes sense since the size of the 2 headers is 54 bytes.
http://atlc.sourceforge.net/bmp.html

says 436h for the header offset which is exactly 1078
Last edited on
the color pallete sits in that "empty space"
Thanks a lot but I am a little confused now. I am using a greyscale 8 bit 512X512 image. How can I determine the n in that collor pallete? Should I make an array of unsigned int to store that data?
Thanks a lot turbozedd. I managed to solve all the problems and made a little program that copies on bmp. Again thanks!
Topic archived. No new replies allowed.