0

I have just spend hours trying to figure out why my program is giving out only 8 images (correct) instead of 15.Checked on the forums there were similar problems and the solution that I understood was that due to two consecutive freads one block is been skipped but can someone help me understand how the block is skipped in my code? The idea of my code is that freads a block if its end of file it breaks but if not it checks for the header if header is there opens a new file and writes the header to that file, then reads next block and keep on writing and reading blocks until next header comes

/**

* recover.c * * Computer Science 50 * Problem Set 4 * * Recovers JPEGs from a forensic image. */

include

include

include

int main(int argc, char* argv[]) { // open card file FILE* inptr = fopen("card.raw", "r");

// check for errors
if (inptr == NULL)
{
    printf ("could not open card. \n");
    return 1;
}

// declaring a block of 8 bits of Type BYTE and having 512 blocks
typedef uint8_t BYTE;
BYTE block[512];
FILE* picture ;
int counter = 0;
while (true)

{
    fread(&block, 512, 1, inptr);
    // checking for if end of data on card has reached.
    if(feof(inptr))
    {
        break;
    }


    // checking for headers of JPEGs
    if (block[0] == 0xff && block[1] == 0xd8 && block[2] == 0xff && (block[3] == 0xe0 || block[3] == 0xe1))
    {
        char name[9];
        sprintf(name, "%03i.jpg", counter);
         picture = fopen(name, "w");
        fwrite(&block , 512, 1, picture);

        // going on to next block
        fread(&block, 512, 1, inptr);

        //loop for keep on reading blocks by blocks after the header
        while (!(block[0] == 0xff && block[1] == 0xd8 && block[2] == 0xff && (block[3] == 0xe0 || block[3] == 0xe1)))

        {

            fwrite(&block, 512, 1, picture);
            fread(&block, 512, 1, inptr);
        }  



    counter++;
    }


} 

fclose(picture);

}

1 Answer 1

1

Look at the structure of your outer while loop, which I have stripped down to the significant lines:

while (true)
{   
     fread(&block, 512, 1, inptr);
     // most of your code here....

     while (!(signature check))
    {
        fwrite(&block, 512, 1, picture);
        fread(&block, 512, 1, inptr);
    }  
counter++;
}

Now, start by looking at the last fread() call. You read in 512 byte blocks until you hit a signature. When you do detect a signature there, you exit the inner while loop, increment counter, and then go back to the top of the while loop. So far, you haven't done anything with that 512 byte block that has the signature. THe very next thing you do, the first thing you do in the outer while loop, is to read in the next 512 byte block, overwriting the one with the signature. Although they seem to be separated by a bunch of code, the last fread and the first fread in the while loop are back to back. Remember, it's called a while LOOP for a reason.

The reason that you're getting every other file is that after discarding the signature block, you now keep looping through the while loop, discarding the remaining data in that image file until you come to yet another signature and open the second image following the one that was most recently closed - a common problem when attempting to implement this structure.

In the previous question, I said that this could be done with a single read. Think about what your program has to do when it reads in a block. If it has a signature, it needs to close the current output file, if one is open, and then open an output file no matter if one was open or not.

But what else do you do with a data block? What a lot of people miss is that, except for opening a new file, it doesn't matter if a block has a signature or not. There are only two choices. If there's an open output file, you write the block out to it. If there's not an open file, you don't do anything with it. THEN you loop around to the top of the while loop and read the next block. Except for a few details and some housekeeping, that's the whole program in a nutshell.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

1
  • ok did understood how the two freads were coming back to back so is that mean my approch towards this problem is with two while loops is wrong from the start? becasue for some time i have been thinking about as to how to use just a single fread and fwrite in this code and cant seem to come up with a logic Commented Dec 12, 2015 at 14:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .