Thread: Recovering jpeg images from a .raw file

  1. #1
    Noobin to the max
    Join Date
    Mar 2013
    Posts
    73

    Recovering jpeg images from a .raw file

    Hi again,

    I am working on a HOMEWORK assignment to recover jpg images from a .raw file. As this is something that I will be graded on, I am NOT asking you do "do it all for me" I am asking for hints and help so that I may continue to learn (and get a good grade at the same timehttp://im.cprogramming.com/images/smilies/wink.png).

    The assignment I am currently working on involves recovering a jpg image by looking for the start of a jpeg, and then copying 512 byte chunks to an image file until the start of the next image is seen. I believe I am close to having a fully working program, The part I am stuck on is when I run the program I get a Segmentation fault.

    If you could look over my program (below) and give me your opinion on what is wrong; that would be GREAT!!!


    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    #define false 0
    #define true 1
    
    
    typedef int bool;
    typedef unsigned char BYTE;
    
    
    int main(void)  {
    
    
    FILE*outptr;
    
    
    // open input file 
    FILE* inptr = fopen("card.raw", "r");
    if (inptr == NULL)
    {
        printf("Sorry, me noes able to open the file!!!\n");
        return 2;
    }
    
    
    bool jpegfoundbefore = false;
    
    
    int number = 0;
    
    
    int block_size = 512;
    
    
    BYTE buffer [512];
    
    
    char image_name[8];
    
    
    // untill eof is reached
    while (! feof(inptr) == 0)
    {
         //copy 512 bytes into buffer
         fread(buffer, block_size, 1, inptr);
         
    
    
         {
            // if a previous jpeg was found close file 
                if (jpegfoundbefore == true)
                {
                    fclose(outptr);
                }
    
    
                jpegfoundbefore = true;
     
                // name the image
                sprintf(image_name, "%.3d.jpg", number);
                number++; 
                
                // create the new jpg image file
                outptr = fopen (image_name, "w");
                if (outptr == NULL)
                {
                    printf("could not create jpeg file\n");
                    return 2;
                }     
                
                // write 512 byte block to current jpeg file 
                fwrite(buffer, block_size, 1, outptr);        
          }
    
    
          // continue writing parts of a jpg to file on disk 
          if (jpegfoundbefore == true)
          {
              fwrite(buffer, block_size, 1, outptr);        
          } 
     
     
    }
    
    
    // close card.raw 
    fclose(inptr);
    
    
    // close last jpg
    fclose(outptr);
    
    
    }

  2. #2
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    You don't check the return value of "fread()", which is the amount of blocks it actually read. Also check Why it's bad to use feof() to control a loop
    Devoted my life to programming...

  3. #3
    Noobin to the max
    Join Date
    Mar 2013
    Posts
    73
    How would I check the return value of fread() and would it fix my problem??? Also, I see why it might be bad to use feof, but wont it work???

  4. #4
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Quote Originally Posted by Dude22 View Post
    How would I check the return value of fread() and would it fix my problem???
    Code:
    if (fread(/* stuff in here */) != amountExpected)
    {
        /* Couldn't read data. THIS is a good time to check feof().
           Either the end of file is reached or a read error occurred */
    }
    It's a step towards the right direction...
    Devoted my life to programming...

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Using fread with this open is not usually valid on Windows; best to use binary mode for fread in windows; note using binary mode is not normally needed under Linux; but, it is safe to use it.

    Code:
    FILE* inptr = fopen("card.raw", "r");
    http://www.cplusplus.com/reference/cstdio/fopen/

    Tim S.
    Last edited by stahta01; 03-02-2013 at 08:03 PM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Glad you got your hard disk fixed....

    > The part I am stuck on is when I run the program I get a Segmentation fault.
    Then run it in the debugger, and find out where and why.

    1. Compile with debug
    Eg
    gcc -g prog.c

    2. Load it in the debugger
    Eg
    gdb ./a.out

    3. Run it
    Eg
    (gdb) run

    4. Wait for the inevitable crash.

    5. Use the following commands
    bt - to display the stack trace (tells you where you are - no more guessing)
    frame n - to jump between stack frames of interest. The most interesting is probably the innermost function you've written.
    print x - to print x (or any other variable name or expression)
    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.

  7. #7
    Noobin to the max
    Join Date
    Mar 2013
    Posts
    73
    Ok, so I ran it through gdb and this is what I got:

    Program received signal SIGSEGV, Segmentation fault.
    0xb7e5700e in _IO_new_fclose (fp=0xb7fa0ff4) at iofclose.c:66
    66 _IO_FINISH (fp);




    So the problem is (or at-least starts on) line 66 which is : outptr = fopen (image_name, "w");

    I am not sure what is wrong, although I at-least know where the problem is. If you could take a look at it and give me your opinion that would be great!

    Also, a few people gave me advice about checking the return value of fread... Is this something that I need to do? If so, how would I do it, I seem to have gotten conflicting answers from other people, so I am asking again.

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Well if you use the 'bt' command, you'll find out which particular fclose() in your code is the originating call.

    From there, use the frame command and print command to find out more.

    Since you don't seem to be actually checking for a start of a JPEG, it seems that you're creating new files on every iteration of the loop.

    So perhaps this
    Code:
                sprintf(image_name, "%.3d.jpg", number);
                number++;
    has overflowed the 8 chars (7 + 1 for the \0) allowed.
    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.

  9. #9
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by Dude22 View Post
    Ok, so I ran it through gdb and this is what I got:

    Program received signal SIGSEGV, Segmentation fault.
    0xb7e5700e in _IO_new_fclose (fp=0xb7fa0ff4) at iofclose.c:66
    66 _IO_FINISH (fp);
    Is your file named "iofclose.c"? That's where your program finally crashes but I'm pretty sure that's a library file and not yours.

    Salem told you already about the bt command (for backtracing). This will show you all frames which are active at the time of the crash. You have to find the frame where your program called the library function.

    Here are some links:
    GDB, The GNU Debugger, By Example - Cprogramming.com
    Tutorials - An Introduction to GDB - Cprogramming.com
    RMS's gdb Tutorial: Segmentation Fault Example

    Also, a few people gave me advice about checking the return value of fread... Is this something that I need to do? If so, how would I do it, I seem to have gotten conflicting answers from other people, so I am asking again.
    Yes it is very important to check the return value of fread()
    Recovering jpeg images from a .raw file

    Bye, Andreas

  10. #10
    Noobin to the max
    Join Date
    Mar 2013
    Posts
    73
    Ok, so I am working on rewriting the program with what I have learned, and my question is, what should I do with the return value of fread.... I know that It returns the number of successfully read elements, but how and where would that help???

    Also, if you have any other recommendations for improvement on my old version, let me know!

    Josh

  11. #11
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    You are supposed to only fwrite the number of bytes fread!

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  12. #12
    Registered User
    Join Date
    Mar 2012
    Location
    the c - side
    Posts
    373
    The 2nd and 3rd parameters of both the fwrite and fread should be swapped about.

  13. #13
    Noobin to the max
    Join Date
    Mar 2013
    Posts
    73
    Quote Originally Posted by stahta01 View Post
    You are supposed to only fwrite the number of bytes fread!

    Tim S.
    In the course instructions they say that:

    "The implication of all these details is that you, the investigator, can probably write a program that iterates over a copy of my CF card, looking for JPEGs' signatures. Each time you find a signature, you can open a new file for writing and start filling that file with bytes from my CF card, closing that file only once you encounter another signature. Moreover, rather than read my CF card's bytes one at a time, you can read 512 of them at a time into a buffer for efficiency's sake. Thanks to FAT, you can trust that JPEGs' signatures will be "block-aligned." That is, you need only look for those signatures in a block's first four bytes.

    Realize, of course, that JPEGs can span contiguous blocks. Otherwise, no JPEG could be larger than 512 B. But the last byte of a JPEG might not fall at the very end of a block. Recall the possibility of slack space. But not to worry. Because this CF card was brand-new when I started snapping photos, odds are it'd been "zeroed" (i.e., filled with 0s) by the manufacturer, in which case any slack space will be filled with 0s. It's okay if those trailing 0s end up in the JPEGs you recover; they should still be viewable."


    If I am not mistaken, the only advantage to using the return value of fread to only fwrite the number of bytes read would be that if the extra area at the end of the 512 chunk contained something other then 0's it wouldn't cause any issue. But as they state that the extra space will be all 0's and they say that it wont cause any problems if that is in the recovered images. Is there still a need to : "only fwrite the number of bytes fread"

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Perhaps you'd better post your latest code, including something which actually checks for JPEG headers.

    Because as posted, you end up with a directory full of 512 byte files.
    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.

  15. #15
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by Dude22 View Post
    If I am not mistaken, the only advantage to using the return value of fread to only fwrite the number of bytes read would be that if the extra area at the end of the 512 chunk contained something other then 0's it wouldn't cause any issue. But as they state that the extra space will be all 0's and they say that it wont cause any problems if that is in the recovered images. Is there still a need to : "only fwrite the number of bytes fread"
    Yes, because it is correct thing to do. You HAVE NO IDEA what bytes are going to be written if YOU DO NOT read them.
    They will be junk values left over from the last read. If you do what you say YOU MUST set the buffer to all zeros between each call of fread!!

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. loading jpeg images in picture boxes
    By new_in_c++ in forum Windows Programming
    Replies: 3
    Last Post: 03-13-2011, 07:45 PM
  2. creating/accessing jpeg images
    By JCML in forum C++ Programming
    Replies: 1
    Last Post: 10-02-2010, 12:21 AM
  3. Char [] to Image File (JPEG)
    By TranT in forum C Programming
    Replies: 33
    Last Post: 07-06-2009, 11:38 AM
  4. Help reading a jpeg file into frames of 100 bytes!! :S
    By rodiannef in forum C Programming
    Replies: 4
    Last Post: 12-10-2008, 12:12 AM
  5. Newbie: Displaying jpeg images in C++
    By C2beginner in forum Windows Programming
    Replies: 7
    Last Post: 10-30-2006, 01:05 AM