Bitmasking Problem

This is a discussion on Bitmasking Problem within the C++ Programming forums, part of the General Programming Boards category; I'm making a set of functions to produce console-like output for SDL. The font is made from a binary mask ...

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

    Bitmasking Problem

    I'm making a set of functions to produce console-like output for SDL. The font is made from a binary mask but I am having problems getting it to display properly. Heres an example of it printing the string"0123456789ABCDE" :
    http://i92.photobucket.com/albums/l1...l/deleteme.png

    Its partly readable but somethings definitely wrong. The constructor for the class takes a character map, and the data. This is run here in my prog:
    Code:
    BitText txt(	"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 
    				"mprtxpmckccccmmp`acg~mp`e`pmaeiq~aa~oom`pmego}ppm~``acgomppmppmmppn`ak"
    				"cipp~pp}pp}pp}mpooopm}ppppp}~oo}oo~~oo}ooompoorpnppp~pppmcccccm~aaaqqk"
    				"pqswsqpoooooo~pztppppppxtrppmpppppm}pp}ooomppptrn}pp}sqpmpom`pm~cccccc"
    				"ppppppmpppppicppppttippicipppppiccc~`acgo~" );
    Heres what the constructor does with it:
    Code:
    BitText::BitText(const char* char_map, const char* char_data)
    {
    	int len = (int)strlen(char_map);
    	map = new char[len];
    	strcpy(map, char_map);
    	len = (int)strlen(char_data);
    	data = new char[len];
    	strcpy(data, char_data); 
    	col = 0xFFFFFFFF;
    }
    And heres the function to print text to the screen:
    Code:
    void BitText::Print(Uint16 x_pos, Uint16 y_pos, const char* text)
    {
    	int x, y, bit, pos;
    	char* ptr;
    
    	for(int i=0; i<(int)strlen(text); i++)
    	{
    		//Get the coresponding character in the character map
    		for(ptr=map, pos=0; *ptr; ptr++, pos++)
    			if(*ptr == text[i]) break;
    
    		//Get the characters data start point
    		ptr = data +(pos*7);
    		
    		//Draw character
    		for(y=0; y<7; y++)
    		{		
    			bit=16;
    			for(x=0; x<5; x++, bit >>= 1)
    				if(*ptr & bit) 
    					WritePixel(x_pos+x, y_pos+y, this->col);	 
    			ptr++; //Move to data byte holding next scanline of the character	
    		}
    
    		x_pos+=6;
    	}
    }
    I'm pretty sure the mistake is in this last function. Can someone see whats going wrong here? I can't Hopefully thats all the relevant code here.
    Last edited by mike_g; 11-07-2007 at 12:58 PM.

  2. #2
    Registered User
    Join Date
    Jan 2007
    Location
    Euless, TX
    Posts
    144
    First question --- where does "map" come from in your print function??

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    [edit]
    First question --- where does "map" come from in your print function??
    It's likely a char*, a member of the class BitText. At least that's what I should think.
    Code:
    BitText::BitText(const char* char_map, const char* char_data)
    {
    	int len = (int)strlen(char_map);
    	map = new char[len];  /* +1, right? . . . */
    	strcpy(map, char_map);
    [/edit]

    In BitText::BitText() . . .
    Code:
    map = new char[len];
    len+1 perhaps?
    Code:
    col = 0xFFFFFFFF;
    I like
    Code:
    col = (unsigned long)-1;
    just because.

    Code:
    for(int i=0; i<(int)strlen(text); i++)
    Calculating strlen() is expensive, consider moving the calculation outside of the for loop and storing it in a variable.

    Code:
    		//Get the coresponding character in the character map
    		for(ptr=map, pos=0; *ptr; ptr++, pos++)
    			if(*ptr == text[i]) break;
    
    		//Get the characters data start point
    		ptr = data +(pos*7);
    It seems to me that this is simpler:
    Code:
    for(pos = 0; map[pos]; pos ++)
        if(map[pos] == text[i]) break;
    
    ptr = data + pos * 7;
    Or you could just use pos all the way through. pos and ptr basically hold the same information, so you don't need both of them.
    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.

  4. #4
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Code:
    	map = new char[len];
    .
    .
    	data = new char[len];
    You have to allocate len+1 to make room for the string terminator which is appended by strcpy().
    Code:
    	map = new char[len+1];
    .
    .
    	data = new char[len+1];

  5. #5
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    First question --- where does "map" come from in your print function??
    Sorry heres my class definition:
    Code:
    class BitText
    {
    	private:
    		char* data;
    		char* map;
    		Uint32 col;
    	public:
    		BitText(const char*, const char*); 
    		void Print(Uint16, Uint16, const char*);
    };
    map holds all the characters displayable in order. EG: 0123456789ABCDEF....etc.
    data holds the mask data. EG: "mprtxpm" is the data to display the number 0.

    In BitText::BitText() . . .
    Code:

    map = new char[len];

    len+1 perhaps?
    Yeah forgot about that.

    I like
    Code:

    col = (unsigned long)-1;
    Now youre just showing off

    Calculating strlen() is expensive, consider moving the calculation outside of the for loop and storing it in a variable.
    Oh. I dident think it recalculated it each loop. Best move it out I guess.

    It seems to me that this is simpler:
    Code:

    for(pos = 0; map[pos]; pos ++)
    if(map[pos] == text[i]) break;

    ptr = data + pos * 7;
    But wheres 'i' gone then?

    Cheers.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    What do you mean? i still exists. I'm just saying that you could use my for loop instead of your for loop. Mine makes use of only one counting variable, pos, whilst yours uses pos as well as ptr. You don't need both counters -- one will suffice.
    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.

  7. #7
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    >_< oh yeah. dident realize that. I guess I should take more time to think while i type

    Still looking for an answer to the original problem tho if anyone can spot it.

    Cheers.

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    That buffer overrun could be the source of your problem. Buffer overruns can result in strange things. Fix it and see what happens.

    You are of course aware that there are plenty of text handling libraries available for the SDL? You can get truetype fonts with SDL_ttf; SDL_gfx has simple bitmap font handling capabilities (with embedded data); and I've heard of sfont as well. Search the SDL libraries page if you're interested.

    Code:
    		//Get the coresponding character in the character map
    		for(ptr=map, pos=0; *ptr; ptr++, pos++)
    			if(*ptr == text[i]) break;
    What if the character doesn't exist in the map, for example a space? You'll have another buffer overrun.

    How is your data laid out? Because you seem to be using only the lower-order 4 bits of every byte:
    Code:
    		//Draw character
    		for(y=0; y<7; y++)
    		{		
    			bit=16;
    			for(x=0; x<5; x++, bit >>= 1)
    				if(*ptr & bit) 
    					WritePixel(x_pos+x, y_pos+y, this->col);	 
    			ptr++; //Move to data byte holding next scanline of the character	
    		}
    If data is stored in the upper 4 bits as well, you're not using it.
    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.

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    I think there's a problem with your font map. It appears you have a 7x5 grid for every character, is this correct? I printed out the grid for some of the characters, and it almost looks like in some cases part of the character is missing. The number one looks ok, but most look similar to your deleteme.png file. Maybe the grid is supposed to be wider?

    And Dwks, it's 5 bits, not 4 bits being used.

  10. #10
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Speaking of which do you have a file that you can post that shows what the font looks like for each character?

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    And Dwks, it's 5 bits, not 4 bits being used.
    Oops, you're right. Sigh.

    Actually, a better way to write the loop would perhaps be
    Code:
    for(x=0; bit; x++, bit >>= 1)
    Of course, bit could also be computed inside the loop with
    Code:
    2 << (4 - x)
    but that would likely be slightly less efficient. Maybe.
    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.

  12. #12
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Quote Originally Posted by dwks
    That buffer overrun could be the source of your problem. Buffer overruns can result in strange things. Fix it and see what happens.
    Well I had made most of the changes you suggested, as they were good. However I couldent see any of them changing the output of my prog. Fair enough the string delimeter was missing, but with the test data I was using the end of either strings would never be reached anyway since non-featured characters were never used. Still those parts are all fixed, and my for loops are a bit better now too

    Quote Originally Posted by swoopy
    Speaking of which do you have a file that you can post that shows what the font looks like for each character?
    No sorry dude. I got the font data from some Basic code for drawing fake led displays. Having seen that prog work I know the original data was correct. Just incase you would like it with the characters seperated this was the original Basic source:
    Code:
    Data "mprtxpm"    ; 0
    Data "ckccccm"    ; 1
    Data "mp`acg~"    ; 2
    Data "mp`e`pm"    ; 3
    Data "aeiq~aa"    ; 4 
    Data "~oom`pm"    ; 5
    Data "ego}ppm"    ; 6
    Data "~``acgo"    ; 7
    Data "mppmppm"    ; 8
    Data "mppn`ak"    ; 9
    
    Data "cipp~pp"    ; A
    Data "}pp}pp}"    ; B
    Data "mpooopm"    ; C
    Data "}ppppp}"    ; D
    Data "~oo}oo~"    ; E
    Data "~oo}ooo"    ; F
    Data "mpoorpn"    ; G
    Data "ppp~ppp"    ; H
    Data "mcccccm"    ; I
    Data "~aaaqqk"    ; J
    Data "pqswsqp"    ; K
    Data "oooooo~"    ; L
    Data "pztpppp"    ; M
    Data "ppxtrpp"    ; N
    Data "mpppppm"    ; O
    Data "}pp}ooo"    ; P
    Data "mppptrn"    ; Q
    Data "}pp}sqp"    ; R
    Data "mpom`pm"    ; S
    Data "~cccccc"    ; T
    Data "ppppppm"    ; U
    Data "pppppic"    ; V
    Data "pppptti"    ; W
    Data "ppicipp"    ; X
    Data "pppiccc"    ; Y
    Data "~`acgo~"    ; Z

  13. #13
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Ok I just drew the binary pattern out for the first character and I found it dosent match to what I want. Apparently the prog I got this from used some other method to read the data. >_< That was kind of dumb of me not checking it. Guess I need to come up with some new data.

  14. #14
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    I noticed the map had more than the 5 least significant bits set in some of the chars too, which seemed odd, so maybe somehow it makes use of all 8 bits (or perhaps 7 bits), but as you say, the patterns don't seem to properly map.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 10:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM

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