C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 01-31-2006, 12:09 PM   #1
Registered User
 
Mortissus's Avatar
 
Join Date: Dec 2004
Location: Brazil, Porto Alegre
Posts: 152
Problem reading BMP

Hi! I was trying to read, manipulate and save some BMP files. My program simlpy reads a bmp file then prints the size of the file (present inside the bmp file itself). The problem is that the size remains zero. I have used xxd to see the first bytes of the file and the size is there, and it is different from zero.

Here is the code of bitmap.h:
Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#define BMP_TYPE 19778

typedef struct{
    unsigned short type;                 /* Magic identifier            */
    unsigned int size;                       /* File size in bytes          */
    unsigned short int reserved1, reserved2;
    unsigned int offset;                     /* Offset to image data, bytes */
    unsigned int hsize;               /* Header size in bytes      */
    int width,height;                /* Width and height of image */
    unsigned short int planes;       /* Number of colour planes   */
    unsigned short int bits;         /* Bits per pixel            */
    unsigned int compression;        /* Compression type          */
    unsigned int imagesize;          /* Image size in bytes       */
    int xresolution,yresolution;     /* Pixels per meter          */
    unsigned int ncolours;           /* Number of colours         */
    unsigned int importantcolours;   /* Important colours         */
} HEADER;

typedef struct{
    HEADER header;
    char* data;
} BMP;


void loadFile( char* fileName, BMP** bmp  );
void writeFile( char* fileName, BMP* bmp  );
And here is the code of bitmap.c:

Code:
#include "bitmap.h"

void loadFile( char* filenName, BMP** pbmp  ){

    struct stat stat_file; 
    FILE* file; 
    BMP* bmp;

    // recover file statistics
    stat( filenName, &stat_file );

    *pbmp = (BMP*) malloc( stat_file.st_size );
    if( !(*pbmp) ){
	fprintf(stderr, "It was not possible to allocate some memory.\n");
	exit(1);
    }
    
    // to ease manipulation
    bmp = *pbmp;

    // open bitmap file
    file = fopen( filenName, "r" );

    // read all the file into pbmp structure
    fread( bmp, 1, stat_file.st_size, file );
    
    // we must convert from little-endian to big-endian
    // the error is here, inspection of the file 
    // shows that size is non zero
    //  printf("File size is %d\n", ntohl(bmp->header.size) );
    printf("File size is %d\n",  (((char*)bmp)[2]));
}

void writeFile( char* filenName, BMP* bmp  ){

    struct stat stat_file;

    int file = open( filenName, O_RDWR );
    if( write( file, bmp, stat_file.st_size ) < stat_file.st_size ){
	
	perror( "Error saving file.\n" );
	exit(1);
    }
}
Thanks any help!
Mortissus is offline   Reply With Quote
Old 01-31-2006, 02:53 PM   #2
Registered User
 
Join Date: Aug 2001
Location: Newport, South Wales, UK
Posts: 1,094
Mam-ma mi-a! You-a crazziee keeed!

First, look at this page, where Microsoft has kindly illustrated the structure of a BMP file. Note in particular the presence of an unspecified number of RGBQUAD structures. This is where palette information is stored, and thus where your code's gonna fall over in all sorts of personally amusing ways when you actually get round to testing this thing.

Unfortunately you can't just pack x RGBQUADs into the massive struct you've defined, so you're gonna have to do yourself a favour and stick a little bit closer to the way MS do it, i.e.
Code:
typedef struct{
    HEADER header;
    RGBQUAD *palette;
    char* data;
} BMP;
Then determine how many colours are in the palette by examining "bits" and knowing that 8 means 256 RGBQUADs, 4 means 16, etc.
Code:
*pbmp = (BMP*) malloc( stat_file.st_size );
NEIN! Das ist nicht casten sie malloc im C!
Code:
file = fopen( filenName, "r" );
It's not a text file. "rb" please.

As for your so-called endian problem, your bizarre little cast at the end of that printf statement there serves no one and nothing. Also ntohl converts from network byte order (which if you read the spec is big endian) to host byte order, which for you would appear to be... you guessed it, big endian!.

If you really want to change the byte order, try this cheap little function for size:-
Code:
void SwapDword(unsigned long *ulIn)
{
    unsigned char *ucIn, ucTemp;

    ucIn = (unsigned char *)ulIn;
    ucTemp = *ucIn;
    *ucIn = *(ucIn + 3);
    *(ucIn + 3) = ucTemp;
    ucTemp = *(ucIn + 1);
    *(ucIn + 1) = *(ucIn + 2);
    *(ucIn + 2) = ucTemp;
}
Bon appetit.
SMurf is offline   Reply With Quote
Old 01-31-2006, 06:51 PM   #3
Registered User
 
Mortissus's Avatar
 
Join Date: Dec 2004
Location: Brazil, Porto Alegre
Posts: 152
First, thanks for all answers. Two answers does not appear here, but I have read them in my e-mail. Second, I have changed the open statment to open the file as binary. Also, I have removed the ntohl (i swear it worked). I didnt added the RGBQUAD structure yet, SMurf, since my problem is before I reach this point. I am sorry SMurf, but I dont speak german, what is wrong with my malloc? Just in case you were speaking about the *pbmp, it is because the functions receives a BMP**. Sorry my bad english. After all these modifications I still have the same problem, the size (second field of header) is zero.

Thanks again.
Mortissus is offline   Reply With Quote
Old 02-01-2006, 12:52 AM   #4
old man
 
Join Date: Dec 2005
Posts: 90
I also don't think that your struct will work very well ... for example, you're inviting padding problems with shorts intermixed in the header. Depending on your compiler, the struct will very possibly lose sync with your data.

As for malloc, it makes no sense to cast it to anything, since it only cares about the size argument, and your pointer is already declared -- your pointer is the only tool that matters when it come to accessing the data.

Here's an example of getting that bmp size field. It solves your problem with endianness (which was likely your main problem all along).

Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


void
die (char *s)
{
  perror (s);
  printf ("\n");
  exit (EXIT_FAILURE);
}


unsigned int
get_dw (char *b)
{
  return ((((((b[3]  << 8) 
             | b[2]) << 8) 
             | b[1]) << 8)
             | b[0]);
}


void
load_bmp (char *fn)
{
  struct stat fs;  char *buf;  FILE *fp;

  if ((stat (fn, &fs)) == -1)
    die ("stat");

  buf = malloc (fs.st_size);
  if (buf == NULL)
    die ("malloc");

  fp = fopen (fn, "rb");
  if (fp == NULL)
    die ("fopen");

  fread (buf, 1, fs.st_size, fp);
  if (buf[0] != 'B' || buf[1] != 'M')
    printf ("This seems not to be a bmp file ...\n\n");
  else
    printf ("bmp size: %u bytes\n\n", get_dw (buf+2));

  fclose (fp);
  free (buf);
}


int
main (int argc, char **argv)
{
  if (argc != 2)
  {
    printf ("I need a (single) bmp file ...\n\n");
    exit (EXIT_FAILURE);
  }

  load_bmp (argv[1]);
  exit (EXIT_SUCCESS);
}
When you get further along with this, of course you'll want to access parts of the file with structs ... all you have to do is assign to the struct pointer the address of the appropriate part in the buffer. This will work better than the monolithic struct you're using now.

Last edited by eerok; 02-01-2006 at 12:55 AM.
eerok is offline   Reply With Quote
Old 02-02-2006, 06:32 AM   #5
Registered User
 
Mortissus's Avatar
 
Join Date: Dec 2004
Location: Brazil, Porto Alegre
Posts: 152
It worked! I understand my errors. I was just trying to do the work in a lazy way.

Thanks a lot for the help, I will respect more these details (i have work ed with c++ for 4 years, but I never worked with shorts ints and such).
Mortissus is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
problem with reading struct from file generated by hexdump wollek C Programming 22 12-23-2008 01:53 PM
Problem reading data from file and record it for use in program timmer C Programming 20 06-12-2005 11:53 PM
Problem with reading strings goron350 C++ Programming 8 06-05-2005 12:05 AM
a weird problem with my code on writing & reading from file goldfish C Programming 6 05-12-2005 03:39 AM


All times are GMT -6. The time now is 06:02 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22