convert image to bitstream (binary digits)

Discussion in 'C' started by xero43, Oct 8, 2009.

  1. xero43

    xero43 New Member

    Joined:
    Oct 8, 2009
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    Hi all,
    I'm an engineering student from Italy and i'd be very glad if you help me in solving a very big problem.
    First of all, i'm not expert at all in programming so, please don't insult me if i write something stupid ;)
    I'm doing my research thesis regarding optimal trasmission of image from a deep-space link; in order to do this i have to compress a raw image 8 bitperpixel (that is a matrix composed by numbers,no header, whose values go from 0 to 255) in an other format, in particular in JPEG2000, that is a .jpc file. This format has is own header, but we're not interested in this right now.
    After the compression i have to protect the image witha parity check coder, in particular a LDPC coder. This coder already exist, and the problem is that, in input, it ONLY accepts a text file composed by a stream of '0' an '1', that is a bitstream.
    The only way to make my testbed works is to take the jpc image, composed by a complex header and by data image, convert it into a bitstream, so in a binary stream composed only by '0' and '1' and save it in a text file.
    is this problem solvable?? i'm desperate!
    please somebody help me!
    thank you all.

    p.s. i posted this thread in the c++ topics because it's the only language that i know, but if anyone has other ideas, it would be very welcome.

    Francesco
     
  2. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    Yes, it's quite easy to do in C++, just read the file one character at a time, each will be 8 bits, and then you loop over each bit testing if it's 1 or not, and output '1' or '0' accordingly. Here's a simple function to convert a text string to binary:
    Code:
    void conv1010()
    {
    	char *str="abc";
    	for (int i=0; str[i]; i++)
    	{
    		char c=str[i];
    		for (unsigned char bitmask=0x80; bitmask; bitmask>>=1)
    		{
    			putchar((c & bitmask) ? '1' : '0');
    		}
    		putchar(' ');
    	}
    	putchar('\n');
    }
    
    To convert this for your needs, read characters from the .jpc file instead of str (fgetc()), and output (fputc()) the 1s and 0s to the file to be encoded with LDPC. The spaces and newline are just there to make the screen output clearer; you wouldn't output these. You'll need fopen and fclose as well.
     
  3. xero43

    xero43 New Member

    Joined:
    Oct 8, 2009
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    thank you very much,
    sorry but i was abroad and i couldn't answer.
    can you write the example with the fgetc() and fputc() functions please?
    assume that i have to read e.g. a file called "image.jpc", so how should i change the program? thanks a lot,
    francesco.

    noreover, do i have to verify if the "image.jpc" is coded with the big or little endian mode?
    because if i wrong, i think that the content of the file can be misled
     
  4. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    No, you can do that; it's easy enough. If you get stuck post what you've got and we'll give you a hint how to continue. Start by RTFM to understand how the functions work.

    I don't know if endianness will make any difference, but you'll need to check if the LDPC coder takes that into account.
     
  5. xero43

    xero43 New Member

    Joined:
    Oct 8, 2009
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    hi,
    i made some progress but i need your help again; i post the code that i wrote but before to do that, i wanted to
    verify that the results were good, so i opened some file jpc, but also raw (that is the original image without any header) with an hex editor, where i could see the values of the byte written in hexadecimal format.
    Code:
    #include <stdio.h>
    
    void ShowByte( char b , FILE * im)
    {    
        
        for(int i = 7; i >= 0; --i)
        {
            if ( b & (1 << i) )
            {
                  fputc('1', im);
            }
            else
            {
                  fputc('0', im);
            }
        
        }
      
    }
    
    int main ()
    {
      FILE * pFile;
      FILE * image;
      char c;
      pFile=fopen ("image.raw","r");
      image=fopen ("bitstream.txt","w");
      if (pFile==NULL) perror ("Error opening file");
      else
      {
    
        do {
          c = fgetc (pFile); 
          ShowByte(c, image);
        
        } while (c != EOF);
    	    
    	fclose (pFile);
         
      }
      return 0;
    }
    
    first thing strange (for me): if i declare the variable c as an unsigned char and if in the function ShowByte i declare b as unsigned char, the program never stops (infinite loop?)

    secondly: i compare a very big file of 1 MB called image.raw and it seems that the program works, but the file txt generated (4 MB) contains less bytes than the original; the program i wrote cut a very huge amount data at some point that i cannot find.
    for example, i create a file with 20 random values with an hex editor, and my program print (correctly) only the first 7 bytes of this file.

    finally, if i use in input the file that i have to test, the image.jpc file, my program prints only the first byte!!

    please can somebody help me??
     
    Last edited by a moderator: Oct 12, 2009
  6. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    EOF is an integer and is equal to -1. So if c is unsigned char, when you read at EOF it will be set to 0xff, which when upcast to an integer for the comparison with EOF will be converted to 0x000000ff and so the comparison will never evaluate FALSE, hence the infinite loop. However, when it is a (signed) char, upcasting 0xff will be sign-extended and result in 0xffffffff, which will equal EOF.

    At a guess, the program bails out when it encounters an 0xff character, which is not the same thing as EOF. So it's better to use the feof() function that tests whether or not you are really at the end of the file.

    Also as the file is binary you should open it in mode "rb" otherwise it defaults to text-mode, which means you might get some funky (and unwanted) conversions with values 10 and 13.
     
  7. xero43

    xero43 New Member

    Joined:
    Oct 8, 2009
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    ok i solved with this code:
    Code:
    #include <stdio.h>
    
    void ShowByte( char b , FILE * im)
    {    
        
        for(int i = 7; i >= 0; --i)
        {
            if ( b & (1 << i) )
            {
                  fputc('1', im);
            }
            else
            {
                  fputc('0', im);
            }
        
        }
    
    }
    
    int main ()
    {
      FILE * pFile;
      FILE * image;
      int c;
      pFile=fopen ("image.jpc","r");
      image=fopen ("bitstream.txt","w");
      if (pFile==NULL) perror ("Error opening file");
      else
      {
        
          c = fgetc(pFile); 
          while (c != EOF)
        {
                  ShowByte((char)c, image);
             c = fgetc(pFile); 
        
        } 
            }
        fclose (pFile);
            fclose (image);
      
      return 0;
    }
    
    now it works perfectly!
    but i have the dual problem now, and so, starting from text, recover the jpc file.
    i tried with this code but i get a segmentation fault:
    #include <stdio.h>
    
    // text points to 8 bytes string containing 0 and 1 symbols
    
    unsigned char ByteFromText(char* text, FILE * im)
    {
        unsigned char result = 0;
        for (int i = 0; i < 8; i++)
        {
            if (text[i] == '1') 
            {
                 result &= ( 1 << (7-i) );
             fputc(result, im);
            }
        }
        return result;
    }
    
    
    
    int main ()
    {
      FILE * pFile;
      FILE * image;
      int c;
      pFile=fopen ("bitstream.txt","r");
      image=fopen ("image.jpc","w");
      if (pFile==NULL) perror ("Error opening file");
      else
      {
        
          c = fgetc(pFile); 
          while (c != EOF)
        {
                  ByteFromText((char*)c, image);
             c = fgetc(pFile); 
        
        } 
            }
        fclose (pFile);
            fclose (image);
    
      
      return 0;
    }
    any suggestions? thanks,
    Fra
     
    Last edited by a moderator: Oct 12, 2009
  8. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    Please use code blocks when you post code.

    What happens if you don't use a cast?
    How many characters does fgetc return from the file?
     
  9. xero43

    xero43 New Member

    Joined:
    Oct 8, 2009
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    ok, if i don't use a cast, i modify the main in this way:
    Code:
    int main ()
    {
      FILE * pFile;
      FILE * image;
      int c;
      pFile=fopen ("bitstream.txt","r");
      image=fopen ("image.jpc","w");
      if (pFile==NULL) perror ("Error opening file");
      else
      {
        
          c = fgetc(pFile); 
    
          while (c != EOF)
        {
                  ByteFromText(c, image);
             c = fgetc(pFile); 
        
        } 
            }
        fclose (pFile);
            fclose (image);
    
      
      return 0;
    }
    and the program doesn't compile. g++ outputs this message:

    error: invalid conversion from ‘int’ to ‘char*’
    error: initializing argument 1 of ‘char ByteFromText(char*, FILE*)’.

    concerning the result of fgetc, i don't know how to answer :(
    how can i measure the number of characters output? the only thing i can see is that a file named image.jpc empty is generated
     
  10. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    OK. fgetc() returns a single char from the file. It does not return a string, and you cannot cast a char to a char*. Casts are tricky business, and you shouldn't use them unless you know EXACTLY what you're doing. If the compiler complains then there's a good chance that a cast won't fix the problem, or will create a new problem or make the problem worse (in this case, it changes a compiler error to a program crash).

    ByteFromText seems OK, but what you need to do is read 8 characters from the file before calling it. Put those characters into a temporary buffer that is at least 9 bytes long, add a NULL terminator (a zero byte), and call ByteFromText with the buffer.
     
  11. xero43

    xero43 New Member

    Joined:
    Oct 8, 2009
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    i wrote this code
    Code:
    #include <stdio.h>
    #include <iostream>
    using namespace std;
    
    // text points to 8 bytes string containing 0 and 1 symbols
    
    char ByteFromText(char* text, FILE * im)
    {
        unsigned char result = 0;
        for (int i = 0; i < 8; i++)
        {
            if (text[i] == '1') 
            {
                 result &= ( 1 << (7-i) );
    	     fputc(result, im);
            }
        }
        return result;
    }
    
    
    
    int main ()
    {
      FILE * pFile;
      FILE * image;
      char buf[9];
      char c;
      int j=0;
      pFile=fopen ("image.txt","r");
      image=fopen ("/home/fra1985/Scrivania/c++/image.jpc","w");
      if (pFile==NULL) perror ("Error opening file");
      else
      {
        
           
    
          while (c != EOF )
    	{      
                   for (j=0; j<9; j++) {
                   c = fgetc(pFile);
                   buf[j]=c;
                    
                                        }
                  
                   ByteFromText(buf, image); 		 
       
        } 
    	    }
    	fclose (pFile);
            fclose (image);
    
      
      return 0;
    }
    and it creates a jpc file whose dimension are more than 660 kbyte, while the original image was only 64 byte; besides, if i open the jpc file with the hex editor, all of the byte are 0..
    where do i wrong?
    thanks
     
  12. xero43

    xero43 New Member

    Joined:
    Oct 8, 2009
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    edit, the new file has dimension equal to 277 kbyte, but the content is 0 anywhere
     
  13. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    Try calling ByteFromText in a small test program that passes known strings of bits to ByteFromText to create results (on the screen) that you expect. So for example my original conv1010 function displayed 01100001 01100010 01100011, which we can confirm from an ASCII table, so we could call ByteFromText("01100001"); and expect it to display "a". If it doesn't, then we know there's a problem with it.

    The other thing you can try is to read the 8-character strings from the file and display them to the screen as it's working on them (maybe just display the first 20 or so). This will show if there's a problem with any of those.
     
  14. xero43

    xero43 New Member

    Joined:
    Oct 8, 2009
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    ok, this is the corrected code
    Code:
    #include <stdio.h>
    #include <iostream>
    using namespace std;
    
    // text points to 8 bytes string containing 0 and 1 symbols
    
    char ByteFromText(char* text)
    {
        char result = 0;
        for (int i = 0; i < 8; i++)
        {
            if (text[i] == '1') 
            {
                 result &= ( 1 << (7-i) );
            }
        }
        return result;
    }
    
    
    
    int main ()
    {
      FILE * pFile;
      FILE * image;
      char buf[8];
      char c;
      int j=0;
      pFile=fopen ("image.txt","r");
      image=fopen ("/home/fra1985/Scrivania/c++/image.jpc","w");
      if (pFile==NULL) perror ("Error opening file");
      else
      {
          c = fgetc(pFile);
    
          while (c != EOF )
          {      
              buf[j++] = c;
     
              if ( j == 8 )
              {
                   fputc(ByteFromText(buf),  image);
                   j = 0;
               }
               c = fgetc(pFile);
          }
    
          fclose (pFile);
          fclose (image);
      }
     
      return 0;
    }
    now it creates a file whose dimension are right, because the output file is 64 kbyte as the original image, but if i try to open the content with the hex editor, it continues to assume 0 values everywhere....
    it seems that it doesn't save the value in the file.....
     
  15. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    Did you do what I suggested above?
     
  16. xero43

    xero43 New Member

    Joined:
    Oct 8, 2009
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    now it works perfectly, replacing
    result &= ( 1 << (7-i) );
    with result |= ( 1 << (7-i) );

    you can close the thread, thanks
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice