By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,549 Members | 1,077 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,549 IT Pros & Developers. It's quick & easy.

writing BITMAP header

P: 1
hi,
i am attempting to split a BITMAP file into 4 parts
in that process we have to write header for each part
how to write the header
please help me
i am in deadly need
Apr 26 '07 #1
Share this Question
Share on Google+
25 Replies


gpraghuram
Expert 100+
P: 1,275
HI,
Tell me what you have attempted on this and where r u stuck?
Then people here can hep u...
Thanks
Raghuram
Apr 26 '07 #2

P: 16
Hi Guys,

hopefully you can help me. I have an array of number from 0-255 and I would like to create a bmp file, but only grey colors so 0 = schwarz , 255 = white.

I am already able to write into the file with the following method: (c++)
[PHP]
fstream data(filename, ios::'out' | ios::binary | ios::trunc);

if(!data.is_open() || data.bad())
{
cout << "error: cannot open file" << endl;
exit(-1);
}

writeBin(data, 'B');
writeBin(data, 'M');
writeBin(data, (long) height*width*3+52);
writeBin(data, (long) 0);
writeBin(data, (long) 52);

writeBin(data, (long) 40);
writeBin(data, width);
writeBin(data, height);
writeBin(data, (short) 1);
writeBin(data, (short) 8);
writeBin(data, (long) 0);
writeBin(data, (long) 0);
writeBin(data, (long) 0);
writeBin(data, (long) 0);
writeBin(data, (long) 0);
writeBin(data, (long) 0);

std::vector< pix >::iterator pixIterator = grauwert.begin();
for (pixIterator;pixIterator != grauwert.end();pixIterator++)
{
printf("%i test",(*pixIterator).grauwert);
writeBin(data, (*pixIterator).grauwert);
}
data.close();
[/PHP]

[PHP]
struct pix
{
pix():grauwert( 0 ),x(0),y(0) {}
int grauwert;
int x;
int y;
};

//the writing method:
template <class T>
void writeBin(fstream &Out, T data)
{
Out.write(reinterpret_cast<char*> (&data), sizeof(T));
}
[/PHP]
So my question is how can I edit my header, that I can use the numbers of my vector as numbers which indicate a grayvalue?

If you have any suggestions, please feel free to answer :-)

bye
May 16 '07 #3

AdrianH
Expert 100+
P: 1,251
I'll answer this tomorrow (or maybe later tonight).


Adrian
May 16 '07 #4

P: 16
Would be cool thanks

I'll answer this tomorrow (or maybe later tonight).


Adrian
May 18 '07 #5

AdrianH
Expert 100+
P: 1,251
Would be cool thanks
Oops, sorry. I forgot. :o :blush: So here is my response.

In the method you are describing, you have a bunch of pix objects. Can they can be in any order? If so, you will have to generate the image array prior to writing it to disk or you will have to seek around the file as you write the pixels in.

On a stylistic (and perhaps personal) note, I would recommend using BITMAPINFO and BITMAPFILEHEADER structures, filling them in and writing these structures out to disk. This can make it easier to read and understand your code. For more information on these you can look here. The following is your code with the names of the fields put in as comments to the right:
Expand|Select|Wrap|Line Numbers
  1. writeBin(data, 'B');    // bfType
  2. writeBin(data, 'M');    
  3. writeBin(data, (long) height*width*3+52);    // bfSize 
  4. writeBin(data, (long) 0);    // bfReserved0
  5. writeBin(data, (long) 52);    // bfReserved1
  6.     // bfOffBits
  7.  
  8. writeBin(data, (long) 40);    // blSize
  9. writeBin(data, width);    // biWidth
  10. writeBin(data, height);    // biHight
  11. writeBin(data, (short) 1);    // biPlains
  12. writeBin(data, (short) 8);    // biBitCount
  13. writeBin(data, (long) 0);    // biCompression
  14. writeBin(data, (long) 0);    // biSizeImage
  15. writeBin(data, (long) 0);    // biXPelsPerMeter
  16. writeBin(data, (long) 0);    // biYPelsPerMeter
  17. writeBin(data, (long) 0);    // biClrUsed
  18. writeBin(data, (long) 0);     // biClrImportant
  19.  
There are a few errors here. You are not supposed to fill in reserved areas. You image size is not defined. I would not use (long)40 for blSize but instead use sizeof(BITMAPINFOHEADER). You haven’t specified bfOffBits. The list goes on.

Follow the link I provided for more information.


Adrian
May 18 '07 #6

P: 16
Hi thanks,

I resolved almost all everything, but I still have a header error (I guess). Windows says not defined bmp.

so here is my header
[PHP]
ofstream os(filename.c_str(), ios::out | ios::trunc | ios::binary);
if (!os.is_open()) return false;

BITMAPINFOHEADER bmpinfo;
bmpinfo.biSize = 40;
bmpinfo.biWidth = width;
bmpinfo.biHeight = height;
bmpinfo.biPlanes = 1;
bmpinfo.biBitCount = 24;
bmpinfo.biCompression = 0;
bmpinfo.biSizeImage = width * height * 3;
bmpinfo.biXPelsPerMeter = 0;
bmpinfo.biYPelsPerMeter = 0;
bmpinfo.biClrUsed = 0;
bmpinfo.biClrImportant = 0;

BITMAPFILEHEADER bmpfile;
bmpfile.bfType = 0x4D42;
bmpfile.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGB) * (width*height));
bmpfile.bfReserved1 = 0;
bmpfile.bfReserved2 = 0;
bmpfile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

os.write((char*)&bmpfile, sizeof(bmpfile));
os.write((char*)&bmpinfo, sizeof(bmpinfo));
[/PHP]

!!Just a tipp!! for newbies like me :-): For saving a grayscale bmp file set RGB on the same values. For example: grayscalenumber = 55 so R = 55 G = 55 B = 55

If somebody see's an error in my header please let me know

thanks so far Gomanza
May 21 '07 #7

P: 16
And another thing

Check this out:

http://www.wotsit.org/list.asp?al=B
May 21 '07 #8

AdrianH
Expert 100+
P: 1,251
Hi thanks,

I resolved almost all everything, but I still have a header error (I guess). Windows says not defined bmp.

so here is my header
Expand|Select|Wrap|Line Numbers
  1. ofstream os(filename.c_str(), ios::out | ios::trunc | ios::binary);
  2.     if (!os.is_open()) return false;
  3.  
  4.     BITMAPINFOHEADER bmpinfo;
  5.     bmpinfo.biSize = 40;
  6.     bmpinfo.biWidth = width;
  7.     bmpinfo.biHeight = height;
  8.     bmpinfo.biPlanes = 1;
  9.     bmpinfo.biBitCount = 24;
  10.     bmpinfo.biCompression = 0;
  11.     bmpinfo.biSizeImage = width * height * 3;
  12.     bmpinfo.biXPelsPerMeter = 0;
  13.     bmpinfo.biYPelsPerMeter = 0;
  14.     bmpinfo.biClrUsed = 0;
  15.     bmpinfo.biClrImportant = 0;
  16.  
  17.     BITMAPFILEHEADER bmpfile;
  18.     bmpfile.bfType = 0x4D42;
  19.     bmpfile.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGB) * (width*height));
  20.     bmpfile.bfReserved1 = 0;
  21.     bmpfile.bfReserved2 = 0;
  22.     bmpfile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  23.  
  24.     os.write((char*)&bmpfile, sizeof(bmpfile));
  25.     os.write((char*)&bmpinfo, sizeof(bmpinfo));
  26.  
!!Just a tipp!! for newbies like me :-): For saving a grayscale bmp file set RGB on the same values. For example: grayscalenumber = 55 so R = 55 G = 55 B = 55

If somebody see's an error in my header please let me know

thanks so far Gomanza
Sorry that I haven't responded to this earlier. Having problems loosing threads every so often. Please bump the thead by posting something to it if you don't get a responce after a while.

You don't have to set the grayscale value using R = 55, G=55 and B=55, just declare the bitmap as a 8 bit instead of a 24 bit bitmap. Of course, I've not used this in a while so I could be wrong. ;)

Also, include the Windows.h header file to fix the error you are referring to (unless I have misinterpreted, if so, post the message as it is outputted by the compiler).


Adrian
May 21 '07 #9

P: 16
8bit didn't work very well anyway 24bit and RGB = same number works somehow. :-)

So here is my Class
[PHP]

//Grafikfunctions.h:
#pragma once

#include <windows.h>
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <ctime>

using namespace std;

struct RGB
{
BYTE blue;
BYTE green;
BYTE red;
};


class Graficfunctions
{
private:
long width;
long height;
vector<RGB> colors;
vector<RGB> tempColor;

public:
Graficfunctions();
~Graficfunctions();

void arrayReorder();
void setPixelColor(long x, long y, BYTE red, BYTE green, BYTE blue);
void setPixelColor(long x, long y, RGB newColor);
void setWidth(long nwidth);
void setHeight(long nheight);

bool to8Bmp(std::string filename,int height, int width);

};

//Grafikfunctions.cpp:
#include "Graficfunctions.h"

using namespace std;

Graficfunctions::Graficfunctions() {
}

Graficfunctions::~Graficfunctions() {

}

void Graficfunctions::setPixelColor(long x, long y, BYTE red, BYTE green, BYTE blue)
{
RGB newCol;
newCol.red = red;
newCol.green = green;
newCol.blue = blue;
colors.push_back(newCol);
}

void Graficfunctions::setPixelColor(long x, long y, RGB newColor)
{
colors.push_back(newColor);
}

void Graficfunctions::arrayReorder() {

}

void Graficfunctions::setWidth(long nwidth) {
width = nwidth;
}

void Graficfunctions::setHeight(long nheight){
height = nheight;
}

bool Graficfunctions::to8Bmp(string filename,int height,int width)
{
//unsigned register long i;
ofstream os(filename.c_str(), ios::out | ios::trunc | ios::binary);
if (!os.is_open()) return false;

BITMAPINFOHEADER bmpinfo;
bmpinfo.biSize = 40;
bmpinfo.biWidth = width;
bmpinfo.biHeight = height;
bmpinfo.biPlanes = 1;
bmpinfo.biBitCount = 24;
bmpinfo.biCompression = 0;
bmpinfo.biSizeImage = width * height * 3+52;
bmpinfo.biXPelsPerMeter = 0;
bmpinfo.biYPelsPerMeter = 0;
bmpinfo.biClrUsed = 0;
bmpinfo.biClrImportant = 0;

BITMAPFILEHEADER bmpfile;
bmpfile.bfType = 0x4D42;
bmpfile.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGB) * (width*height));
bmpfile.bfReserved1 = 0;
bmpfile.bfReserved2 = 0;
bmpfile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

os.write((char*)&bmpfile, sizeof(bmpfile));
os.write((char*)&bmpinfo, sizeof(bmpinfo));

//Bilddaten einfügen:
int i=0;
vector<RGB>::iterator myiteratorColor;
for(myiteratorColor = colors.begin(); myiteratorColor != colors.end(); myiteratorColor++){
os.write((char*)&(*(myiteratorColor)), sizeof(RGB));
i++;
}

os.close();
printf("File created\n");
return true;
}

[/PHP]

The compiler does not bring any error it works until I try to open a file with the Windows picture viewer. Can I send you such a image file?

Sorry have to leave work now I'll be back tomorrow
May 21 '07 #10

AdrianH
Expert 100+
P: 1,251
8bit didn't work very well anyway 24bit and RGB = same number works somehow. :-)
Hmmm, dunno. I've just dumpped entire 256 grey scale images before, but its been a while (few years). If you don't mind using 24bit colour, then I'll leave it at that. ;)

The compiler does not bring any error it works until I try to open a file with the Windows picture viewer. Can I send you such a image file?
Sure, umm, not sure. I am not aware of any method for you to send it to me. I don't post my email due to spam reasons. Maybe you can find a place to host the file for a short time?

Sorry have to leave work now I'll be back tomorrow
No prob. Its late anyway. ;)


Adrian
May 22 '07 #11

P: 16
Hi Adrian,

ok here you can download 2 of my files.
The interesting file is Graficfunctions.cpp

http://www.home.hs-karlsruhe.de/~sest0024/greyscale/

I guess 24bit are ok. You can also find a 24bit bmp and a picture that shows what my programm produces if the header is on 8bit.

gomanza
May 22 '07 #12

P: 16
I just found another possibility do you know how this works?

http://msdn2.microsoft.com/en-us/library/ms532305.aspx
May 22 '07 #13

P: 16
Sorry couldn't edit my message:

I just found another possibility do you know how this works?

http://msdn2.microsoft.com/en-us/library/ms532305.aspx

edit: ok its not that difficult, haven't tried it yet cause of time.

Another interesting thing about my putput pictures: I cannot load them with openCV. I guess it is the same problem as windows has.

I also player a little with my header configuration:
[PHP]
BITMAPINFOHEADER bmpinfo;
bmpinfo.biSize = sizeof(BITMAPINFOHEADER);
bmpinfo.biWidth = width;
bmpinfo.biHeight = -height; //minus just to mirror the picture
bmpinfo.biPlanes = 1;
bmpinfo.biBitCount = 24;
bmpinfo.biCompression = BI_RGB; //BI_RGB is 0
bmpinfo.biSizeImage = ((((width * bmpinfo.biBitCount) + 31) & ~31) >> 3) * height; //width * height * 3; //width = 64 height = 48
bmpinfo.biXPelsPerMeter = 0;
bmpinfo.biYPelsPerMeter = 0;
bmpinfo.biClrUsed = 0;
bmpinfo.biClrImportant = 0;

BITMAPFILEHEADER bmpfile;
bmpfile.bfType = 0x4D42;
bmpfile.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGB) * (width*height));
bmpfile.bfReserved1 = 0;
bmpfile.bfReserved2 = 0;
bmpfile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

[/PHP]
May 22 '07 #14

P: 16
problem half solved:

preknowledge: grayscale picture R & G & B same number!!

Yippi I just figured out by comparing the hex files of a incorrupt and a corrupt bmp file that there is a 00 after every RGB numbers:

[PHP]
// incorrupt file
4b 4b 4b 00 ff ff ff 00 ....
//corrupt file
4b 4b 4b ff ff ff
[/PHP]
-> I miss something in between :-)

so I just added another BYTE to my struct RGB. By definition this byte is 0
[PHP]
struct RGB
{
BYTE blue;
BYTE green;
BYTE red;
BYTE zero;
};
[/PHP]

The result is no longer a grayscale picture:
http://www.home.hs-karlsruhe.de/~ses...le/strange.bmp

let's see what I can figure out

gomanza
May 22 '07 #15

AdrianH
Expert 100+
P: 1,251
problem half solved:

preknowledge: grayscale picture R & G & B same number!!

Yippi I just figured out by comparing the hex files of a incorrupt and a corrupt bmp file that there is a 00 after every RGB numbers:

[PHP]
// incorrupt file
4b 4b 4b 00 ff ff ff 00 ....
//corrupt file
4b 4b 4b ff ff ff
[/PHP]
-> I miss something in between :-)

so I just added another BYTE to my struct RGB. By definition this byte is 0
[PHP]
struct RGB
{
BYTE blue;
BYTE green;
BYTE red;
BYTE zero;
};
[/PHP]

The result is no longer a grayscale picture:
http://www.home.hs-karlsruhe.de/~ses...le/strange.bmp

let's see what I can figure out

gomanza
Yeah, there is actually a struct already defined. See here for a general colour reference and here for the struct actually used. The forth byte is sometimes used as an alpha channel.

As for the reason why it looks weird, it is probably because you've set up the bytes wrong. Use the macros shown in the first link.


Adrian
May 23 '07 #16

P: 16
I found the windows error. After writing BITMAPFILEHEADER and
BITMAPINFOHEADER into my file I need to create a table the
(i am not shure about the name) Palette. it is just like this:
[PHP]
struct WinColorTable
{
BYTE blue;
BYTE green;
BYTE red;
BYTE zero;
};

WinColorTable temp;
for(int r=0;r<= 255; r++) {
temp.blue=r;
temp.green = r;
temp.red = r;
temp.zero=0;
//writing directly to the file:
os.write((char*)&(temp.blue), sizeof(temp.blue));
os.write((char*)&(temp.green), sizeof(temp.green));
os.write((char*)&(temp.red), sizeof(temp.red));
os.write((char*)&(temp.zero), sizeof(temp.zero));
}
[/PHP]

and after this is done just dump the RGB vector to the file
[PHP]
//insert picture data:
vector<RGB>::iterator myRGBiteratorColor;
for(myRGBiteratorColor = colors.begin();
myRGBiteratorColor != colors.end(); myRGBiteratorColor++){
os.write((char*)&(*(myRGBiteratorColor)), sizeof(RGB));
}
[/PHP]

So I kind of recreated the Macros you suggested to use. They are identical.

So far my windows opens the files I create, but still with a funny effect :-)
see picture here

yeah could be that I have the wrong order of Blue Green Red. Let's see......
Ok PALETTERGB as shown in one of your links has a different order,
but I read somewhere, that BGR is the right order to write into files.
Anyway I'll try it. :-)

I am running out of ideas :-)

thanks
Gomanza
May 23 '07 #17

P: 16
Gosh another milestone :-D

So i forgot to extend the bfOffbits with the PALETTERGB which I mentioned in the previous post.
bmpfile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+ sizeof(WinColorTable)*256;

But still openCV is not loading my images
damn it ...

gomanza

1. Edit:
K didn't realize before, that the old windows problem is back. So any ideas.
"old windows problem" = cannot load the files with openCv and Windows ImageViewer.
May 23 '07 #18

AdrianH
Expert 100+
P: 1,251
Gosh another milestone :-D

So i forgot to extend the bfOffbits with the PALETTERGB which I mentioned in the previous post.
bmpfile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+ sizeof(WinColorTable)*256;

But still openCV is not loading my images
damn it ...

gomanza

1. Edit:
K didn't realize before, that the old windows problem is back. So any ideas.
"old windows problem" = cannot load the files with openCv and Windows ImageViewer.
What old windows problem?

Adrian
May 23 '07 #19

P: 16
I can load/open the created files with irfanView, but any other programm has problems with loading the file.
Ok sorry windows problem was the wrong name, its just that the file is somehow not correct. I have no clue why and where i shall start searching for the propably wrong header information.

gomanza
May 23 '07 #20

AdrianH
Expert 100+
P: 1,251
I can load/open the created files with irfanView, but any other programm has problems with loading the file.
Ok sorry windows problem was the wrong name, its just that the file is somehow not correct. I have no clue why and where i shall start searching for the propably wrong header information.

gomanza
You may be interested in CreateDIBSection().

Also, look at "BMP FILE FORMATS", in the very first link I gave you. It could be that the deceprency between the definition and the documentation is what is causing your problem.


Adrian
May 23 '07 #21

P: 16
K thanks.

I guess my programming or better experience in reading and using the docu is not good, Its hard to understand what they want me to do for using the functions. Can you please just show how to use for example createBitmap(). I guess a hint is enough to then I can figure out how to use the rest.

1. Edit: Never mind I can search with google :-)

And by the way thanks for your help. I hope this post also helps lost programmers like me in the future.
I'll be back as soon as I have news :-)

bye gomanza
May 23 '07 #22

P: 16
Hey everybody I totally changed my code so here is my method:

[PHP]
int Graficfunctions::dc2bitmap(int width, int height, const char *filename)
{
BITMAPINFO bi;
HANDLE fileHandle;

BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
DWORD bytes_write;
DWORD bytes_written;

//hdc2=CreateCompatibleDC(hdc);

ZeroMemory(&bmih,sizeof(BITMAPINFOHEADER));
bmih.biSize=sizeof(BITMAPINFOHEADER);
bmih.biHeight=height;
bmih.biWidth=width;
bmih.biPlanes=1;
bmih.biBitCount=24;
bmih.biCompression=BI_RGB;
bmih.biSizeImage = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3) * bmih.biHeight;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrImportant = 0;

bi.bmiHeader=bmih;

ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BIT MAPINFOHEADER);
bmfh.bfSize=(3*bmih.biHeight*bmih.biWidth)+sizeof( BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
bmfh.bfType=0x4d42;
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;

fileHandle=CreateFile(filename,GENERIC_READ | GENERIC_WRITE,(DWORD)0,NULL,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL);

if (fileHandle==INVALID_HANDLE_VALUE)
{
OutputDebugString("CreateFile failed!\n");
return 0;
}

// Write the BITMAPFILEHEADER
bytes_write=sizeof(BITMAPFILEHEADER);
if (!WriteFile(fileHandle,(void*)&bmfh,bytes_write,&b ytes_written,NULL))
{
printf("ERROR writing file");
return 0;
}


//Write the BITMAPINFOHEADER
bytes_write=sizeof(BITMAPINFOHEADER);
if (!WriteFile(fileHandle,(void*)&bmih,bytes_write,&b ytes_written,NULL))
{
printf("ERROR writing file");
return 0;
}

vector<RGB>::iterator myRGBiteratorColor;

RGB *tmp = new RGB[width*height];
int i=0;
for(myRGBiteratorColor = colors.end(); myRGBiteratorColor != colors.begin(); myRGBiteratorColor--){
tmp[i].blue = (*myRGBiteratorColor).blue;
tmp[i].green = (*myRGBiteratorColor).green;
tmp[i].red = (*myRGBiteratorColor).red;
i++;
}

//Write the Color Index Array???
bytes_write=bmih.biSizeImage;//3*bmih.biHeight*bmih.biWidth;
if (!WriteFile(fileHandle,/*(void*)dibvalues*/(void*)tmp,bytes_write,&bytes_written,NULL))
{
printf("ERROR writing file");
return 0;
}

CloseHandle(fileHandle);

return 1;
}


[/PHP]

gomanza
May 24 '07 #23

P: 16
Adrian Thx for your help, cause of your ideas and links I was able to figure out what to do.

Gomanza
May 25 '07 #24

AdrianH
Expert 100+
P: 1,251
Adrian Thx for your help, cause of your ideas and links I was able to figure out what to do.

Gomanza
Good to hear. Were you able to get it working with only 256 gray scale? Or you doing 24bit colour? I just googled for it again and I came up with this, just in case it is of any use to you.


Adrian
May 25 '07 #25

P: 16
Hi,

I found this earlier page, but it is questinable how usefull it was/is.

My programm creates 24bit bitmaps.

Right now I am satisfied. Maybe in terms of performance 8bit are better, but its future musik.
If I will do this I keep you updated here

Bye gomanza
May 30 '07 #26

Post your reply

Sign in to post your reply or Sign up for a free account.