Thread: Writing BMP file... doesn't work correctly

  1. #1
    Registered User
    Join Date
    Sep 2004
    Posts
    12

    Unhappy Writing BMP file... doesn't work correctly

    I've written up a bit of code based on the BMP file format and it seems to work, except that the image appears to be sheared. I can't seem to figure it out... the 8-bit image of 32x32 shouldn't require any padding for row data since it already fits into a multiple of 4 bytes. Also, the colors seem to be inverted.

    BTW, when I use fwrite(&bh, sizeof(struct bmp_header), 1, file1), it doesn't work correctly so I have to fwrite each element of the struct separately :-( Any logical explanations, anyone?


    Here's the code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct bmp_header {
    	unsigned char Type[2];
    	unsigned long Size;
    	unsigned short Reserved1;
    	unsigned short Reserved2;
    	unsigned long offBits;
    	unsigned long headerSize;
    	unsigned long width;
    	unsigned long height;
    	unsigned short planes;
    	unsigned short bitCount;
    	unsigned long compression;
    	unsigned long img_size;
    	unsigned long xpix;
    	unsigned long ypix;
    	unsigned long colors_used;
    	unsigned long colors_imp;
    };
    
    struct rgb_quad {
    	unsigned char blue;
    	unsigned char green;
    	unsigned char red;
    	unsigned char reserved;
    };
    
    int main() {
    	struct bmp_header bh;
    	struct rgb_quad palette[256];
    	unsigned char imgData[32][32];
    	int i, j;
    	FILE* file1;
    	char nullchar=0;
    
    	file1 = fopen("out.bmp", "wb");
    
    	bh.Type[0]='B';
    	bh.Type[1]='M';
    	bh.Size=2102;
    	bh.Reserved1=0;
    	bh.Reserved2=0;
    	bh.offBits=1078;
    	bh.headerSize=40;
    	bh.width=32;
    	bh.height=32;
    	bh.planes=1;
    	bh.bitCount=8;
    	bh.compression=0;
    	bh.img_size=32*32;
    	bh.xpix=0;
    	bh.ypix=0;
    	bh.colors_used=2;
    	bh.colors_imp=2;
    
    	fwrite(&bh.Type[0], sizeof(bh.Type[0]), 1, file1);
    	fwrite(&bh.Type[1], sizeof(bh.Type[1]), 1, file1);
    	fwrite(&bh.Size, sizeof(bh.Size), 1, file1);
    	fwrite(&bh.Reserved1, sizeof(bh.Reserved1), 1, file1);
    	fwrite(&bh.Reserved2, sizeof(bh.Reserved2), 1, file1);
    	fwrite(&bh.offBits, sizeof(bh.offBits), 1, file1);
    	fwrite(&bh.headerSize, sizeof(bh.headerSize), 1, file1);
    	fwrite(&bh.width, sizeof(bh.width), 1, file1);
    	fwrite(&bh.height, sizeof(bh.height), 1, file1);
    	fwrite(&bh.planes, sizeof(bh.planes), 1, file1);
    	fwrite(&bh.bitCount, sizeof(bh.bitCount), 1, file1);
    	fwrite(&bh.compression, sizeof(bh.compression), 1, file1);
    	fwrite(&bh.img_size, sizeof(bh.img_size), 1, file1);
    	fwrite(&bh.xpix, sizeof(bh.ypix), 1, file1);
    	fwrite(&bh.colors_used, sizeof(bh.colors_used), 1, file1);
    	fwrite(&bh.colors_imp, sizeof(bh.colors_imp), 1, file1);
    
    	palette[0].blue=0;
    	palette[0].green=0;
    	palette[0].red=0;
    	palette[0].reserved=0;
    
    	palette[1].blue=255;
    	palette[1].green=255;
    	palette[1].red=255;
    	palette[1].reserved=255;
    
    	for (i=0; i<256; i++)
    	{
    		fwrite(&palette[i].blue, 1, 1, file1);
    		fwrite(&palette[i].green, 1, 1, file1);
    		fwrite(&palette[i].red, 1, 1, file1);
    		fwrite(&palette[i].reserved, 1, 1, file1);
    	}
    
    	for (i=0; i<32; i++) {
    		for (j=0; j<32; j++) {
    			imgData[i][j]=0;
    		}
    	}
    
    	for (i=0; i<32; i++)
    	{
    		imgData[i][i]=1;
    	}
    
    	for (i=0; i<32; i++)
    	{
    		for (j=0; j<32; j++)
    		{
    			fwrite(&imgData[j][i], 1, 1, file1);
    		}
    	}
    
    	fclose(file1);
    	return 0;
    }
    Thanks for being patient enough to look through my code

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > Any logical explanations, anyone?
    Structures can (and do) contain padding to preserve the alignment of data within the structure (for efficient access).

    Depending on your compiler, you can modify the amount of padding in the structure, at the expense of having more complex code (generated by the compiler, not written by you).
    Eg.
    Code:
    #pragma pack(1)
    struct bmp_header {
    	unsigned char Type[2];
    	unsigned long Size;
    	unsigned short Reserved1;

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    • The pragma that Salem suggests is the only way to correctly load the structure from disk using C I/O.
    • The colors are stored in a bmp in the exact opposite order that the hardware expects.
    • The shearing is probably due to the fact you are not using the width correctly. Make sure you test for value>width instead of value>=width. This will cause shearing. Also make sure your structure size is correct. Since you are not using pragma pack(1) your structure size is not correct and thus the next read will not start at the beginning of the graphic data.
    • BMPs are stored in upside down fashion.
    • Some BMPs use RLE compression - however this is extremely rare but there is a field in the bmp structure to denote compression usage.
    • BMPs color data will use a full DWORD, even though the upper 8 bits are discarded.


    Use this structure for BMPs.
    Code:
    struct RGB
    { 
      BYTE red;
      BYTE green;
      BYTE blue;
      BYTE user;
    };

  4. #4
    Registered User
    Join Date
    Sep 2004
    Posts
    12
    Hi!

    Thanks for the help. That suggestion by Salem really worked for me, and Bubba's explanation of the shearing too.

    I now having a working program that can write a perfectly good 8-bit Bitmap Image.

    Best Regards,
    T.I.N.
    (The Information Need-er... just trying to find a new expansion for every thread )

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Inventory records
    By jsbeckton in forum C Programming
    Replies: 23
    Last Post: 06-28-2007, 04:14 AM
  2. help with text input
    By Alphawaves in forum C Programming
    Replies: 8
    Last Post: 04-08-2007, 04:54 PM
  3. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  4. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM