Thread: reading bitmap file

  1. #1
    Registered User
    Join Date
    Feb 2003
    Posts
    596

    reading bitmap file

    I'm writing this program to read in bitmap files (in Linux). It's not finished, but it does seem to read in the header info correctly so it'll be easy enough to do the rest. I'm just worried that I'm making this harder than it needs to be. Is there an easier or more elegant way to go about this?

    What about this code, stylewise & so on -- my C++ is pretty rusty & it was never very brilliant to begin with -- any suggestions on aspects that need improvement?

    Finally: at the end of main() I print out the bytes one at a time to check the data that I saved in Header. When I run it on the file TEST.bmp here:
    http://www.geocities.com/velocide/index.html
    the third byte is printing as ffffffc6 instead of just c6. I guess thats because of the leading 1 in the binary 11010110, but there must be a way to print it as just "c6". How?

    Thanks for looking.

    Here's the code:
    Code:
    #include <iostream>
    #include <fstream>
    #include "Header.h"
    
    using namespace std;
    
    int main(int argc, char* argv[]) {
    	ifstream infile(argv[1], ios::in|ios::binary);
    	Header *myHeader = new Header();
    	char c;
    	char *pc = &c;
    	unsigned short s = 0;
    	char *ps = (char*)&s;
    	unsigned long l = 0;
    	char *pl = (char*)&l;
    	if(infile.is_open()) {
    		infile.read(pc,1);
    		myHeader->setSig1(c);
    		infile.read(pc,1);
    		myHeader->setSig2(c);
    		infile.read(pl, 4);
    		myHeader->setFileSize(l);
    		infile.read(ps, 2);
    		if(s) {
    			cout << "Invalid data: filler1 = " << s << endl;
    			return 0;
    		}
    		infile.read(ps, 2);
    		if(s) {
    			cout << "Invalid data: filler2 = " << s << endl;
    			return 0;
    		}
    		infile.read(pl, 4);
    		myHeader->setPixDatOffset(l);
    		infile.read(pl, 4);
    		if(l != 40) {
    			cout << "Invalid data: headerSize = " << l << endl;
    			return 0;
    		}
    
    //		infile.close();
    	}else {
    		cout << "readBinFile: Unable to open file " << argv[1] << endl;
    		return 0;
    	}
    	
    	cout << "Finished reading header." << endl;
    	cout << "File signature: " << myHeader->getSig1() << myHeader->getSig2() << endl;
    	cout << "File size: " << myHeader->getFileSize() << endl;
    	cout << "Pixel data offset: " << myHeader->getPixDatOffset() << endl;
    
    	infile.seekg(0);
    	cout << endl;
    	cout << "First 18 bytes of file " << argv[1] << ":" << endl;
    	for (int i=0; i<18; i++) {
    		infile.read(pc, 1);
    		cout << hex << (unsigned int)c << endl;
    	}
    	return 0;
    }
    Code:
    class Header
    {
    public:
    	Header() {
    		filler1 = 0;
    		filler2 = 0;
    		headerSize = 40;
    	}
    	virtual ~Header(){}
    
    	void setSig1(char& c) {sig1 = c;}
    	void setSig2(char& c) {sig2 = c;}
    	void setFileSize(unsigned long s) {fileSize = s;}
    	void setPixDatOffset(unsigned long s) {pixDatOffset = s;}
    	char getSig1() {return sig1;}
    	char getSig2() {return sig2;}
    	unsigned long getFileSize() {return fileSize;}
    	unsigned long getPixDatOffset() {return pixDatOffset;}
    
    
    private:
    	char sig1;
    	char sig2;
    	unsigned long fileSize;
    	unsigned short filler1;
    	unsigned short filler2;
    	unsigned long pixDatOffset;
    	unsigned long headerSize;
    
    };
    and the test output:
    Code:
    Finished reading header.
    File signature: BM
    File size: 1478
    Pixel data offset: 1078
    
    First 18 bytes of file TEST.bmp:
    42
    4d
    ffffffc6
    5
    0
    0
    0
    0
    0
    0
    36
    4
    0
    0
    28
    0
    0
    0

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    cast to unsigned char first - then there will be no filling
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Registered User
    Join Date
    Feb 2003
    Posts
    16
    [QUOTE=R.Stiltskin]
    Code:
    	char c;
    	char *pc = &c;
    	unsigned short s = 0;
    	char *ps = (char*)&s;
    	unsigned long l = 0;
    	char *pl = (char*)&l;
    	if(infile.is_open()) {
    		infile.read(pc,1);
    		myHeader->setSig1(c);
    		infile.read(pc,1);
    		myHeader->setSig2(c);
    		infile.read(pl, 4);
    		myHeader->setFileSize(l);
    		infile.read(ps, 2);
    The above can be changed as
    Code:
            
    	unsigned char pc;
    	unsigned short int ps;
    	unsigned long pl;
    	if(infile.is_open()) {
    		infile.read( &pc,1);
    		myHeader->setSig1(c);
    		infile.read(&pc,1);
    		myHeader->setSig2(c);
    		infile.read((unsigned char * ) &pl, 4);
    		myHeader->setFileSize(l);
    		infile.read((unsigned char *) &ps, 2);
    Code:
        
    	for (int i=0; i<18; i++) {
    		infile.read(&pc, 1);
    		cout << hex << (unsigned int)c << endl;
    	}
    	return 0;
    }

  4. #4
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Thanks for your suggestions.

    One more question: in the class Header file (post #1), what difference, if any, does it make whether I write a function member as (for example)
    Code:
    	void setSig1(char& c) {sig1 = c;}
    or as
    Code:
    	void setSig1(char c) {sig1 = c;}
    In general, does it matter whether primitive type parameters are passed to a function like setSig1 by reference or by value? Is one or the other method preferable?

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    In general, does it matter whether primitive type parameters are passed to a function like setSig1 by reference or by value? Is one or the other method preferable?
    Typically, primitive type arguments would be passed by value unless the function may change their values (upon which they would be passed by reference).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Quote Originally Posted by laserlight
    ...unless the function may change their values (upon which they would be passed by reference).
    Do you mean a situation in which I want the called function to be able to change the parameter's value in the calling function?

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by R.Stiltskin
    Do you mean a situation in which I want the called function to be able to change the parameter's value in the calling function?
    yes-yes
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Formatting a text file...
    By dagorsul in forum C Programming
    Replies: 12
    Last Post: 05-02-2008, 03:53 AM
  2. Inventory records
    By jsbeckton in forum C Programming
    Replies: 23
    Last Post: 06-28-2007, 04:14 AM
  3. Basic text file encoder
    By Abda92 in forum C Programming
    Replies: 15
    Last Post: 05-22-2007, 01:19 PM
  4. Simple File encryption
    By caroundw5h in forum C Programming
    Replies: 2
    Last Post: 10-13-2004, 10:51 PM
  5. System
    By drdroid in forum C++ Programming
    Replies: 3
    Last Post: 06-28-2002, 10:12 PM