Image height = -16

This is a discussion on Image height = -16 within the C++ Programming forums, part of the General Programming Boards category; I'm reading header info from a bitmap. I can get the image width and bit-depth fine but the height comes ...

  1. #1
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218

    Image height = -16

    I'm reading header info from a bitmap. I can get the image width and bit-depth fine but the height comes out as -16. I am almost certain that this problem is caused by me reading bytes from the file as char type, but I cant work out how to get it to read as Uint8. Aslo the way I am doing this is probably unnecessarily complicated. Heres my code:
    Code:
    int Image::LoadBMP(char* filename)
    {
    	ifstream in;
    	in.open(filename, ios::binary);
    	if(! in.is_open()) return LOAD_IMAGE_INVALID;
    	
    	char i[4];
    
    	in.seekg(18, ios::beg);
    	in.read(i, 4);
    	w=(i[3]<<24)+(i[2]<<16)+(i[1]<<8)+i[0];
    	
    	//in.seekg(22, ios::beg);
    	in.read(i, 4);
    	h=(i[3]<<24)+(i[2]<<16)+(i[1]<<8)+i[0];
    
    	in.seekg(2, ios::cur);
    	in.read(i, 2);
    	bpp=(i[1]<<8)+i[0];
    
    	in.close();
    	return IMAGE_LOAD_SUCCESS;
    }
    Any suggestions on a working/better way to read this data?

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,802
    unsigned char i[4] perhaps?
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Nah, I already tried that but it wont seem to work. I'd get errors when I call in.read() saying:
    Code:
    error C2664: 'std::basic_istream<_Elem,_Traits>::read' : cannot convert parameter 1 from 'unsigned char [4]' to 'char *'

  4. #4
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    Probably the endian ordering. I had a similar problem when reading dimensions for a terrain file. I had to do shifts each time I read a byte until I recieved the proper value.

  5. #5
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Is a BMP really big-endian? Either way, shifting a (signed) char will not give you what you want. Cast the chars to unsigned before you shift them, or make the whole array unsigned and cast it to a regular char * when you call get().

    Personally, I'd write a small inline function which takes a char [4] and returns an unsigned 32-bit integer. Call it "unpack32BitBigEndian" or something. No need to duplicate the same code over and over.

  6. #6
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Hmm, I thought I sorted that out with all the bitshifting I'm doing.

    Also my test image has a height of 240. And -16 as a char would be something like 239 as Uint8.

  7. #7
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Quote Originally Posted by mike_g View Post
    Hmm, I thought I sorted that out with all the bitshifting I'm doing.
    The code you have now is treating the byte sequence as big-endian -- the first byte gets shifted to the MSB. But the real problem is the signed shift.

    EDIT: And the bit patterns for (unsigned char)240 and (signed char)-16 are the same bit pattern, so it's definitely the problem.

  8. #8
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Thanks brewbuck, that fixed it. I'm casting it to Uint8 just before the bitshifting. As in:

    Code:
    w=((Uint8)i[3]<<24)+((Uint8)i[2]<<16)+((Uint8)i[1]<<8)+(Uint8)i[0];
    But would there be a cleaner way to write this? It looks kind of messy.

    [edit]Oh and how do I get if the machine is big endian or not?

    Thanks[/edit]

  9. #9
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Quote Originally Posted by mike_g View Post
    But would there be a cleaner way to write this? It looks kind of messy.
    Like I said, contain the messiness in a function which does this for you.

    Oh and how do I get if the machine is big endian or not?
    It has nothing to do with the endianness of your machine -- the shifting method protects against your MACHINE'S endianness. It has to do with the endianness of the FILE FORMAT.

  10. #10
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Ok cool, i'll just chuck it in a function. and forget about the endian thing then

  11. #11
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Quote Originally Posted by mike_g View Post
    Ok cool, i'll just chuck it in a function. and forget about the endian thing then
    Well I'm kind of concerned that a Microsoft Windows file format would be big-endian. I don't have the BMP spec or know where to get one, so I don't know for sure, but I suspect the format is actually little-endian, like most Windows computers. I COULD BE WRONG THOUGH.

    The difference between reading a big-endian and a little-endian value is simple, the indexes go [3], [2], [1], [0] for big-endian and [0], [1], [2], [3] for little-endian.

    Just to be clear, the shifting method makes sure that you get the right value taking into account your machine's endianness. You still have to deal with the endianness of the data source itself.

  12. #12
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,588
    If your machine is an x86, then endian is unlikely to be the problem.

    BMP files with a positive height load from bottom to top. ISTR from somewhere that a negative height means that the image loads from top to bottom.

    > I don't have the BMP spec or know where to get one
    Almost all file formats can be found by typing "foo file format" into a search engine.
    http://www.wotsit.org/ for example.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    BMP files with a positive height load from bottom to top. ISTR from somewhere that a negative height means that the image loads from top to bottom.
    Yes, that's correct. http://www.mathworks.com/access/help...+Height+Values
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  14. #14
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,246
    Quote Originally Posted by Salem View Post
    Almost all file formats can be found by typing "foo file format" into a search engine.
    http://www.wotsit.org/ for example.
    I'm fairly paranoid about file formats. If I can't prove to myself that what I'm looking at is "THE spec" I don't tend to trust it very much. When you're dealing with an MS spec things get even more... interesting.

  15. #15
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    wotsit.org is very reliable when it comes to file formats.

    I've loaded thousands of BMPs and usually when a value in the header is not reading correctly it is caused by byte alignment in the header structure.

    I've never come across a negative height for a BMP but keep in mind the BMP format has so many variations it's nearly impossible to account for them all w/o writing an entire library. This is why Windows has functions specifically for loading BMPs.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem reading tiff image files?
    By compz in forum C++ Programming
    Replies: 9
    Last Post: 10-30-2009, 04:17 AM
  2. Image rotation - doesn't always work
    By ulillillia in forum C Programming
    Replies: 12
    Last Post: 05-03-2007, 12:46 PM
  3. SSH Hacker Activity!! AAHHH!!
    By Kleid-0 in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 03-06-2005, 02:53 PM
  4. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  5. Replies: 4
    Last Post: 03-02-2003, 08:12 AM

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