Saving a 24bit bitmap?

Started by
11 comments, last by Toolmaker 20 years ago
Ok, this might be a stupid question which, but I can't seem to get it right. I have been trying to save a 24bit BMP file friday, but it didn't work. So, I created the structs for the header, infoheader, even the RGBQUAD, although I don't use it(No palette). First I start out with filling the 2 headers up and write them to the file. However, there is a little problem that arises here. If I want to save a 50 * 50 pixel BMP, to what do I set the width? 50? or 3 * 50(because 1 pixel needs 3 bytes, right?). To check things, this is my code, any help is appreciated, since it didn't work friday.

struct BMPFILEHEADER
{
    WORD  bfType;
    DWORD bfSize;
    WORD  bfReserved1;
    WORD  bfReserved2;
    DWORD bfOffbits;
};

struct BMPINFOHEADER
{
  DWORD  biSize; 
  LONG   biWidth; 
  LONG   biHeight; 
  WORD   biPlanes; 
  WORD   biBitCount; 
  DWORD  biCompression; 
  DWORD  biSizeImage; 
  LONG   biXPelsPerMeter; 
  LONG   biYPelsPerMeter; 
  DWORD  biClrUsed; 
  DWORD  biClrImportant; 
};

//struct RGBQUAD

//{

//    BYTE Blue;

//    BYTE Green;

//    BYTE Red;

//    BYTE Reserved;

//};


BOOL WriteBitmap24(const char *szFile, BYTE *Surface, DWORD dwWidth, DWORD dwHeight)
{
    BMPFILEHEADER FileHeader;
    BMPINFOHEADER InfoHeader;
    BYTE V = 0;

    FileHeader.bfType      = 0x4D42; // It's a bitmap!

    FileHeader.bfSize      = sizeof(BMPFILEHEADER) + sizeof(BMPINFOHEADER) + (3 * dwWidth) * dwHeight;
    FileHeader.bfReserved1 = 0;
    FileHeader.bfReserved2 = 0;
    FileHeader.bfOffbits   = sizeof(BMPFILEHEADER) + sizeof(BMPINFOHEADER);

    InfoHeader.biSize          = sizeof(BMPINFOHEADER);
    InfoHeader.biWidth         = (long)dwWidth;
    InfoHeader.biHeight        = (long)dwHeight;
    InfoHeader.biPlanes        = 1;
    InfoHeader.biBitCount      = 24;
    InfoHeader.biCompression   = 0;
    InfoHeader.biSizeImage     = 3 * dwWidth * dwHeight;
    InfoHeader.biXPelsPerMeter = 0;
    InfoHeader.biYPelsPerMeter = 0;
    InfoHeader.biClrUsed       = 0;
    InfoHeader.biClrImportant  = 0;

    long dwPadWidth = dwWidth * 3;
    while ((dwWidth % 4) != 0)
        ++dwWidth;

    ofstream File(szFile, ios::binary);
    if (!File.is_open())
        return (FALSE);

    File.write((char *)&FileHeader, sizeof(BMPFILEHEADER));
    File.write((char *)&InfoHeader, sizeof(BMPINFOHEADER));
    for (int Vert = 0; Vert < dwHeight; ++Vert)
    {
        for (int Horz = 0; Horz < dwPadWidth; ++Horz)
        {
            if (Horz < dwPadWidth - dwWidth)
                File.write((char *)&Surface[Vert * dwHeight + Horz], sizeof(BYTE));
            else
                File.write((char *)&V, sizeof(BYTE));
        }
    }
    File.close();

    return (TRUE);
}
-Earth is 98% full. Please delete anybody you can. [edited by - toolmaker on April 5, 2004 9:16:39 AM]

Advertisement
Shouldn''t this:

File.write((char *)Surface[Vert * dwHeight + Horz], sizeof(BYTE));

be this:

File.write((char *)&Surface[Vert * dwHeight + Horz], sizeof(BYTE));


"C lets you shoot yourself in the foot rather easily. C++ allows you to reuse the bullet!"
"C lets you shoot yourself in the foot rather easily. C++ allows you to reuse the bullet!"
Dont forget to write file in binary mode, as in windows you''ll get 2 chars when outputing ''/n'' otherwise.

______________________________
Madman
______________________________Madman
quote:Original post by CPPMaster Poppet
Shouldn''t this:

File.write((char *)Surface[Vert * dwHeight + Horz], sizeof(BYTE));

be this:

File.write((char *)&Surface[Vert * dwHeight + Horz], sizeof(BYTE));


I don''t think so, Surface is already a BYTE ptr. A pointer to pointer would get me weird output(I assume).

quote:
Dont forget to write file in binary mode, as in windows you''ll get 2 chars when outputing ''/n'' otherwise.


I won''t be writing \n characters to a bitmap file. But as you mentioned it, I saw I forgot it. So it was assuming I was writing in text mode(I think it''s text mode by default).

Other then that, are there logic errors in my code?

Toolmaker


-Earth is 98% full. Please delete anybody you can.

quote:Original post by Toolmaker I don''t think so, Surface is already a BYTE ptr.


yes, but you dereference it with []
Good thinking

[EDIT]
I updated the above code. For some reason, I can''t write my BMP image to file. Can anyone find out why I doesn''t show up as a working bitmap? The above code is my entire header+source.

Toolmaker


-Earth is 98% full. Please delete anybody you can.

I wrote a program based on a tutorial before for creating a 24 bit bitmap, throwing in some random pixels and writing it to a file and then counting how many unique 24 bit color values there were. The counting part I am sure was done really bad but you're welcome to the source code. Just email me if you are interested and you can have a look. I think that I used bits from This tutorial but leaving out the directdraw stuff.

[edit]
After looking at that tutorial, I don't think I used that one but for some reason it is in my bookmarks under bitmap stuff. Maybe I just used Big Sassy's tutorial on loading them but reversed the concepts. That seems to fit better since I prefer to use fopen instead of streams.

Evillive2
E-Mail

[edited by - evillive2 on April 5, 2004 7:33:43 PM]
Evillive2
Did you check the struct alignment/packing for you header?
I noticed the file is 2 bytes bigger then when I save it from paint using the same size. How do I prevent MSVC from aligning on DWORDs?

Toolmaker


-Earth is 98% full. Please delete anybody you can.

quote:Original post by Toolmaker
I noticed the file is 2 bytes bigger then when I save it from paint using the same size. How do I prevent MSVC from aligning on DWORDs?


Here''s my code for the BMP header. Note the pragmas..

	#pragma pack( push, BMP_Header )	#pragma pack(1)	struct BMP_Header	{		char B;		char M;		int SizeOfFile;		int Reserved;		int ImageOffset;		int SizeOfImageHeader;		int ImageWidth;		int ImageHeight;		short NumberOfPlanes;		short BitsPerPixel;		int CompressionType;		int CompressedImageSize;		int HorizontalResolution;		int VerticalResolution;		int NumberOfColoursInPalette;		int NumberOfMostImportantColours;					};	#pragma pack( pop, BMP_Header ) 


This topic is closed to new replies.

Advertisement