| | |
Help with manually creating a BMP image
Thread Solved
![]() |
•
•
Join Date: Jan 2009
Posts: 6
Reputation:
Solved Threads: 0
Hello, im a noob with C++ at the moment and Im trying to create a BMP image from pixel data stored in a array. Everything seems to work except that when i look at the file generated in a hex editor i get an extra '00 00' in between the BM identifier and the bytes reserved for the file size. It is as though the member short BM within the bmp_header struct is taking 4 bytes where i think i it is suppose to take 2 bytes. Could someone please explain why this is happening. Thanks in advance. (there are probably much more efficient ways of doing this but this is the way i want 2 do it at the moment)
Template is from http://en.wikipedia.org/wiki/BMP_file_format (the 2 by 2 pixel example)
Template is from http://en.wikipedia.org/wiki/BMP_file_format (the 2 by 2 pixel example)
C++ Syntax (Toggle Plain Text)
#include <fstream> #include <iostream> using namespace std; #define w_in_pix 2 #define h_in_pix 2 short padding = 0x0000; struct bmp_header { short BM; long size_of_file; long reserve; long offset_of_pixle_data; long size_of_header; long width; long hight; short num_of_colour_plane; short num_of_bit_per_pix; long compression; long size_of_pix_data; long h_resolution; long v_resolution; long num_of_colour_in_palette; long important_colours; } HEADER; // pix array /////////////////////////////////////////////////////////////////////////// // L to R // char BGR [12] = { 0xFF,0x00,0x00, 0x00,0xFF,0x00, 0x00,0x00,0xFF, 0xFF,0xFF,0xFF}; //////////////////////////////////////////////////////////////////////////////////////// int main() { HEADER.BM = 0x4d42; HEADER.size_of_file = sizeof(HEADER) + sizeof(BGR) + sizeof(padding) * h_in_pix; HEADER.reserve = 0000; HEADER.offset_of_pixle_data = 54; HEADER.size_of_header = 40; HEADER.width = w_in_pix; HEADER.hight = h_in_pix; HEADER.num_of_colour_plane = 1; HEADER.num_of_bit_per_pix = 24; HEADER.compression = 0; HEADER.size_of_pix_data = sizeof(BGR) + sizeof(padding) * h_in_pix; HEADER.h_resolution = 2835; HEADER.v_resolution = 2835; HEADER.num_of_colour_in_palette = 0; HEADER.important_colours = 0; // write BMP Header //////////////////////////////////////////////////////////////// ofstream file; file.open ("test.bmp", ios::out | ios::trunc | ios::binary); file.write ((char*)(&HEADER), sizeof(HEADER)); //////////////////////////////////////////////////////////////////////////////////// // write BMP data ////////////////////////////////////////////////////////////////// //file.write ((char*)(&BGR[0]),1); int position = w_in_pix * h_in_pix * 3; while (position != 0) { for (int n = 0; n != w_in_pix * 3; n++) { file.write ((char*)(&BGR[position - w_in_pix * 3 + n]), 1); } file.write ((char*)(&padding), 2); position = position - w_in_pix * 3; } }
The short answer is padding and alignment.
> short BM;
> long size_of_file;
To ensure efficient access to size_of_file, the compiler inserts a pair of padding bytes after BM.
The common way to "fix" this is to use something like
Also look up "endian-ess"
Unfortunately, the only good long-term answer (which is pretty horrible) is to read/write bytes one at a time, and assign them to the struct in the correct order.
> short BM;
> long size_of_file;
To ensure efficient access to size_of_file, the compiler inserts a pair of padding bytes after BM.
The common way to "fix" this is to use something like
#pragma pack(1) , but there is no standard way to tell a compiler how to do this (or indeed how well your request for packing the struct will be met).Also look up "endian-ess"
Unfortunately, the only good long-term answer (which is pretty horrible) is to read/write bytes one at a time, and assign them to the struct in the correct order.
Yet another common and portable approach: use ordinar structures to create BMP info then pack them into the final char buffer (use memcpy(buffer+offset,&member,sizeof member), move offset forward and so on). Of course, it's possible to write data to a file stream directly (no need in current write pos forwarding).
Add some syntax sugar, for example:
A nasty thing but it works
Add some syntax sugar, for example:
c++ Syntax (Toggle Plain Text)
struct bmp_header { short BM; long size_of_file; long reserve; long offset_of_pixle_data; long size_of_header; long width; long hight; short num_of_colour_plane; short num_of_bit_per_pix; long compression; long size_of_pix_data; long h_resolution; long v_resolution; long num_of_colour_in_palette; long important_colours; void* pack(void* pbuf) { char* p = (char*)pbuf; int i = 0; # define PACK(member) {memcpy(p+i,&member,sizeof member);i+=sizeof member;} PACK(BM) PACK(size_of_file) ... PACK(important_colours) # undef PACK return pbuf; } } HEADER; ... HEADER.pack(buffer)
•
•
Join Date: Jan 2009
Posts: 6
Reputation:
Solved Threads: 0
I did what freaky_chris suggested and created the value of BM outside of the bmp_header struct and it seems to work. Final code is now
C++ Syntax (Toggle Plain Text)
#include <fstream> #include <iostream> using namespace std; #define w_in_pix 2 #define h_in_pix 2 short padding = 0x0000; short BM = 0x4d42; struct bmp_header { long size_of_file; long reserve; long offset_of_pixle_data; long size_of_header; long width; long hight; short num_of_colour_plane; short num_of_bit_per_pix; long compression; long size_of_pix_data; long h_resolution; long v_resolution; long num_of_colour_in_palette; long important_colours; } HEADER; // pix array /////////////////////////////////////////////////////////////////////////// // L to R // char BGR [12] = { 0xFF,0x00,0x00, 0x00,0xFF,0x00, 0x00,0x00,0xFF, 0xFF,0xFF,0xFF}; //////////////////////////////////////////////////////////////////////////////////////// int main() { HEADER.size_of_file = sizeof(HEADER) + sizeof(BGR) + sizeof(padding) * h_in_pix + 2; HEADER.reserve = 0000; HEADER.offset_of_pixle_data = 54; HEADER.size_of_header = 40; HEADER.width = w_in_pix; HEADER.hight = h_in_pix; HEADER.num_of_colour_plane = 1; HEADER.num_of_bit_per_pix = 24; HEADER.compression = 0; HEADER.size_of_pix_data = sizeof(BGR) + sizeof(padding) * h_in_pix; HEADER.h_resolution = 2835; HEADER.v_resolution = 2835; HEADER.num_of_colour_in_palette = 0; HEADER.important_colours = 0; // write BMP Header //////////////////////////////////////////////////////////////// ofstream file; file.open ("test.bmp", ios::out | ios::trunc | ios::binary); file.write ((char*)(&BM), 2); file.write ((char*)(&HEADER), sizeof(HEADER)); //////////////////////////////////////////////////////////////////////////////////// // write BMP data ////////////////////////////////////////////////////////////////// //file.write ((char*)(&BGR[0]),1); int position = w_in_pix * h_in_pix * 3; while (position != 0) { for (int n = 0; n != w_in_pix * 3; n++) { file.write ((char*)(&BGR[position - w_in_pix * 3 + n]), 1); } file.write ((char*)(&padding), 2); position = position - w_in_pix * 3; } }
![]() |
Similar Threads
- Cannot find server or DNS Error - please help! (Viruses, Spyware and other Nasties)
- Open In New Window Php (PHP)
Other Threads in the C++ Forum
- Previous Thread: for loop as a macros
- Next Thread: Structures
| Thread Tools | Search this Thread |
api array based binary bitmap business c++ c/c++ char class classes code coding commentinghelp compile console conversion count decide delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez graph guess gui homeworkhelp homeworkhelper iamthwee ifpug ifstream incrementoperators infinite input int integer java lib linkedlist linker loop looping loops map math matrix memory multiple news node number numbertoword output parameter pointer problem proficiency program programming project python random read recursion reference rpg string strings temperature template templates test text text-file tree url variable vector video win32 windows winsock word wordfrequency wxwidgets






