Blame view

stim/image/bmp.h 9.92 KB
7d01bb90   David Mayerich   matlab matrix sav...
1
2
  #ifndef STIM_BMP_H
  #define STIM_BMP_H
d9b2b2a8   David Mayerich   enabled basic rea...
3
  
e98c381d   David Mayerich   Changed image.h t...
4
5
6
  #include <fstream>
  #include <iostream>
  
d9b2b2a8   David Mayerich   enabled basic rea...
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
111
112
113
114
115
116
117
118
119
120
121
  namespace stim {
  #pragma pack(1)
  	typedef unsigned int DWORD;
  	typedef unsigned short WORD;
  	typedef signed int LONG;
  	typedef struct tagBITMAPFILEHEADER {
  		WORD  bfType;
  		DWORD bfSize;
  		WORD  bfReserved1;
  		WORD  bfReserved2;
  		DWORD bfOffBits;
  	} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
  
  	const unsigned int DIB_BITMAPCOREHEADER = 12;
  	const unsigned int DIB_OS21XBITMAPHEADER = 16;
  	const unsigned int DIB_BITMAPINFOHEADER = 40;
  	const unsigned int DIB_BITMAPV2INFOHEADER = 52;
  	const unsigned int DIB_BITMAPV3INFOHEADER = 56;
  	const unsigned int DIB_OS22XBITMAPHEADER = 64;
  	const unsigned int DIB_BITMAPV4HEADER = 108;
  	const unsigned int DIB_BITMAPV5HEADER = 124;
  
  	typedef struct tagBITMAPCOREHEADER {
  		DWORD bcSize;
  		WORD  bcWidth;
  		WORD  bcHeight;
  		WORD  bcPlanes;
  		WORD  bcBitCount;
  	} BITMAPCOREHEADER, *PBITMAPCOREHEADER;
  
  	typedef struct tagBITMAPINFOHEADER {
  		DWORD biSize;											//40 bytes
  		LONG  biWidth;
  		LONG  biHeight;
  		WORD  biPlanes;
  		WORD  biBitCount;
  		DWORD biCompression;
  		DWORD biSizeImage;
  		LONG  biXPelsPerMeter;
  		LONG  biYPelsPerMeter;
  		DWORD biClrUsed;
  		DWORD biClrImportant;
  	} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
  
  	// From FileFormat.info
  	typedef struct {
  		DWORD Size;            /* Size of this header in bytes */
  		LONG  Width;           /* Image width in pixels */
  		LONG  Height;          /* Image height in pixels */
  		WORD  Planes;          /* Number of color planes */
  		WORD  BitsPerPixel;    /* Number of bits per pixel */
  		DWORD Compression;     /* Compression methods used */
  		DWORD SizeOfBitmap;    /* Size of bitmap in bytes */
  		LONG  HorzResolution;  /* Horizontal resolution in pixels per meter */
  		LONG  VertResolution;  /* Vertical resolution in pixels per meter */
  		DWORD ColorsUsed;      /* Number of colors in the image */
  		DWORD ColorsImportant; /* Minimum number of important colors */
  							   /* Fields added for Windows 4.x follow this line */
  
  		DWORD RedMask;       /* Mask identifying bits of red component */
  		DWORD GreenMask;     /* Mask identifying bits of green component */
  		DWORD BlueMask;      /* Mask identifying bits of blue component */
  		DWORD AlphaMask;     /* Mask identifying bits of alpha component */
  		DWORD CSType;        /* Color space type */
  		LONG  RedX;          /* X coordinate of red endpoint */
  		LONG  RedY;          /* Y coordinate of red endpoint */
  		LONG  RedZ;          /* Z coordinate of red endpoint */
  		LONG  GreenX;        /* X coordinate of green endpoint */
  		LONG  GreenY;        /* Y coordinate of green endpoint */
  		LONG  GreenZ;        /* Z coordinate of green endpoint */
  		LONG  BlueX;         /* X coordinate of blue endpoint */
  		LONG  BlueY;         /* Y coordinate of blue endpoint */
  		LONG  BlueZ;         /* Z coordinate of blue endpoint */
  		DWORD GammaRed;      /* Gamma red coordinate scale value */
  		DWORD GammaGreen;    /* Gamma green coordinate scale value */
  		DWORD GammaBlue;     /* Gamma blue coordinate scale value */
  	} WIN4XBITMAPHEADER;
  
  	typedef struct {
  		DWORD        bV5Size;
  		LONG         bV5Width;
  		LONG         bV5Height;
  		WORD         bV5Planes;
  		WORD         bV5BitCount;
  		DWORD        bV5Compression;
  		DWORD        bV5SizeImage;
  		LONG         bV5XPelsPerMeter;
  		LONG         bV5YPelsPerMeter;
  		DWORD        bV5ClrUsed;
  		DWORD        bV5ClrImportant;
  		DWORD        bV5RedMask;
  		DWORD        bV5GreenMask;
  		DWORD        bV5BlueMask;
  		DWORD        bV5AlphaMask;
  		DWORD        bV5CSType;
  		LONG		 RedX;          /* X coordinate of red endpoint */
  		LONG		 RedY;          /* Y coordinate of red endpoint */
  		LONG		 RedZ;          /* Z coordinate of red endpoint */
  		LONG		 GreenX;        /* X coordinate of green endpoint */
  		LONG		 GreenY;        /* Y coordinate of green endpoint */
  		LONG		 GreenZ;        /* Z coordinate of green endpoint */
  		LONG		 BlueX;         /* X coordinate of blue endpoint */
  		LONG		 BlueY;         /* Y coordinate of blue endpoint */
  		LONG		 BlueZ;         /* Z coordinate of blue endpoint */
  		DWORD        bV5GammaRed;
  		DWORD        bV5GammaGreen;
  		DWORD        bV5GammaBlue;
  		DWORD        bV5Intent;
  		DWORD        bV5ProfileData;
  		DWORD        bV5ProfileSize;
  		DWORD        bV5Reserved;
  	} BITMAPV5HEADER, *PBITMAPV5HEADER;
  
  	
  	//compression methods
7d01bb90   David Mayerich   matlab matrix sav...
122
123
  	const unsigned int STIM_BI_RGB = 0;
  	const unsigned int STIM_BI_BITFIELDS = 3;
d9b2b2a8   David Mayerich   enabled basic rea...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  
  	class bmp {
  		std::ifstream file;
  	public:
  		unsigned int dib_header_size;
  		size_t bit_pos;					// start position (relative to the beginning of the file) of the bitmap bits
  		size_t total_size;									//total size of the bitmap file (in bytes)
  		size_t width;
  		size_t height;
  		int channels;
  		int bits_per_pixel;
  		unsigned int compression;
  
  		size_t bytes() {
  			return width * height * bits_per_pixel / 8;
  		}
  		void read_bmpFileHeader() {
  			BITMAPFILEHEADER file_header;
  			file.read((char*)&file_header, sizeof(BITMAPFILEHEADER));
  			bit_pos = file_header.bfOffBits;
  			total_size = file_header.bfSize;
  		}
  		void read_bmpCoreHeader() {
  			tagBITMAPCOREHEADER header;
  			file.read((char*)&header, sizeof(tagBITMAPCOREHEADER));
  			width = header.bcWidth;
  			height = header.bcHeight;
  			bits_per_pixel = header.bcBitCount;
  			compression = 0;
  		}
  		void read_bmpInfoHeader() {
  			tagBITMAPINFOHEADER info_header;
  			file.read((char*)&info_header, sizeof(tagBITMAPINFOHEADER));
  			width = info_header.biWidth;
  			height = info_header.biHeight;
  			bits_per_pixel = info_header.biBitCount;
  			compression = info_header.biCompression;
  		}
  		void read_bmpV4Header() {
  			WIN4XBITMAPHEADER header;
  			file.read((char*)&header, sizeof(WIN4XBITMAPHEADER));
  			width = header.Width;
  			height = header.Height;
  			bits_per_pixel = header.BitsPerPixel;
  			compression = header.Compression;
  		}
  		void read_bmpV5Header() {
  			BITMAPV5HEADER header;
  			file.read((char*)&header, sizeof(BITMAPV5HEADER));
  			width = header.bV5Width;
  			height = header.bV5Height;
  			bits_per_pixel = header.bV5BitCount;
  			compression = header.bV5Compression;
  		}
  		void read_dib() {								//read the bitmap DIB information header
929095ab   David Mayerich   removed warnings ...
179
  			std::streamoff header_pos = file.tellg();
d9b2b2a8   David Mayerich   enabled basic rea...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  			file.read((char*)&dib_header_size, sizeof(unsigned int));
  			file.seekg(header_pos);
  			switch (dib_header_size) {
  			case DIB_BITMAPCOREHEADER: read_bmpCoreHeader(); break;
  			case DIB_BITMAPINFOHEADER: read_bmpInfoHeader(); break;
  			case DIB_BITMAPV4HEADER: read_bmpV4Header(); break;
  			case DIB_BITMAPV5HEADER: read_bmpV5Header(); break;
  			default:
  				std::cout << "stim::bmp ERROR: this bitmap header format isn't supported" << std::endl;
  				exit(1);
  			}
  		}
  
  		bool open(std::string filename) {								//open the bitmap file and read the header data
  			file.open(filename, std::ifstream::binary);
  			if (!file) {
  				std::cout << "stim::bmp ERROR: error opening file: " << filename.c_str() << std::endl;
  				return false;
  			}
  			read_bmpFileHeader();										//read the file header
  			read_dib();
7d01bb90   David Mayerich   matlab matrix sav...
201
  			if (compression != STIM_BI_RGB) {								//check for compression
d9b2b2a8   David Mayerich   enabled basic rea...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  				std::cout << "stim::bmp ERROR: this file is compressed, and compression is not supported" << std::endl;
  				return false;
  			}
  			return true;
  		}
  		void close() {
  			file.close();
  		}
  
  		/// Copy the bitmap data into a pre-allocated array
  		bool read(char* dst){
  			file.seekg(bit_pos);						//seek to the beginning of the data array
  			size_t row_bytes = width * bits_per_pixel / 8;	//number of bytes in each row
  			size_t padding = row_bytes % 4;					//calculate the padding on disk for each row (rows must be multiples of 4)
  			
  			if(file){
  				for (size_t h = 0; h < height; h++) {				//for each row in the image
  					file.read(dst + (height - h - 1) * row_bytes, row_bytes);		//read the row of image data
  					file.seekg(padding, std::ios::cur);				//seek to the end of the row on disk
  					if (file.eof())	std::cout << "stim::bmp ERROR: array size incorrect, end of file reached while reading bitmap." << std::endl;
  					else if (file.fail()) std::cout << "stim::bmp ERROR: reading bitmap array failed." << std::endl;
  					else if (file.bad()) std::cout << "stim::bmp ERROR: stream integrity failed while reading bitmap array" << std::endl;
  				}
  				return true;				
  			}
  			else{
  				std::cout<<"stim::bmp ERROR: could not read array from file."<<std::endl;
  				return false;
  			}
  		}
  	};
  
  	bool save_bmp(std::string filename, char* bits, size_t width, size_t height) {
  		size_t bits_per_pixel = 24;
  		size_t row_bytes = width * bits_per_pixel / 8;	//number of bytes in each row
  		size_t padding = row_bytes % 4;					//calculate the padding on disk for each row (rows must be multiples of 4)
  
  		tagBITMAPFILEHEADER file_header;
  		memset(&file_header, 0, sizeof(tagBITMAPFILEHEADER));									//initialize the file header structure to zero
  		file_header.bfOffBits = sizeof(tagBITMAPFILEHEADER) + sizeof(tagBITMAPCOREHEADER);		//the offset includes both the file and DIB header
929095ab   David Mayerich   removed warnings ...
242
243
  		file_header.bfSize = (stim::DWORD)(file_header.bfOffBits + (row_bytes + padding) * height);			//calculate the size of the bitmap file
  		file_header.bfType = (stim::DWORD)0x4D42;
d9b2b2a8   David Mayerich   enabled basic rea...
244
245
246
  
  		tagBITMAPCOREHEADER info_header;
  		memset(&info_header, 0, sizeof(tagBITMAPCOREHEADER));										//initialize the info header to zero
929095ab   David Mayerich   removed warnings ...
247
248
249
  		info_header.bcBitCount = (stim::DWORD)bits_per_pixel;
  		info_header.bcHeight = (stim::WORD)height;
  		info_header.bcWidth = (stim::WORD)width;
d9b2b2a8   David Mayerich   enabled basic rea...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  		info_header.bcSize = sizeof(tagBITMAPCOREHEADER);
  		info_header.bcPlanes = 1;
  
  		std::ofstream outfile(filename, std::ios::binary);										//open the output file for binary writing
  		outfile.write((char*)&file_header, sizeof(tagBITMAPFILEHEADER));						//write the file header
  		outfile.write((char*)&info_header, sizeof(tagBITMAPCOREHEADER));						//write the information header
  		
  		char* pad = (char*)malloc(padding);										//create a buffer that will be written as padding
  		memset(pad, 0, padding);
  		for (size_t h = 0; h < height; h++) {
  			outfile.write((char*)(bits + (height - h - 1) * row_bytes), row_bytes);									//write the bitmap data
  			outfile.write(pad, padding);
  		}
  		free(pad);
  		return true;
  	}
7d01bb90   David Mayerich   matlab matrix sav...
266
267
268
  }
  
  #endif