0

I have been pulling my hair for recover 2 weeks by now. I finally got it to print 50 files at last. However, they are all invalid . Can anyone help me out?

while (fread(&buffer, sizeof(buffer), 1, infile) == 1) // if fread return anything smaller than 1 then it's EOF
    {
        //fread(&buffer, sizeof(buffer), 1, infile); (this line is causing files not reach 49 files, for some reasons)
        //check if block is beginning of jpeg
        if (buffer[0] == 0xff &&
            buffer[1] == 0xd8 &&
            buffer[2] == 0xff &&
            (buffer[3] & 0xf0) == 0xe0)
            {
                //Create new file to store jpg 
                sprintf(filename, "%03i.jpg", count);
                // Here we open the img file
                FILE *img = fopen(filename, "w");
                // if there is a JPEG file already opened
                // close it.
                // then open the next file
                if (img != NULL)
                {
                    fclose(img);
                    img = fopen(filename,"w");
                }
                //write to the new file 512 bytes/block a time while byte is not JPEG beginning
                while  (buffer[0] != 0xff &&
                        buffer[1] != 0xd8 &&
                        buffer[2] != 0xff &&
                        (buffer[3] & 0xf0) != 0xe0)
                {
                    fwrite(&buffer, sizeof(buffer), 1, img);
                }
                count++;
                fclose(img);
            }
    }
    fclose(infile);
}

Thank you in advance.

**** UPDATE I hope it is less a mess now. It recovers all images, not invalid anymore but images return chessboard patterns. Any leads why?

while (fread(&buffer, 512, 1, infile) != 0)
    {
        FILE *img = NULL;
        if (buffer[0] == 0xff &&
            buffer[1] == 0xd8 &&
            buffer[2] == 0xff &&
            (buffer[3] & 0xf0) == 0xe0)
            {
                if (img == NULL)
                {
                    sprintf(filename, "%03i.jpg", count);
                    img = fopen(filename,"w");
                    fwrite(&buffer, 512, 1, img);
                    count++;
                }
                else if (img != NULL)
                {
                    fclose(img);
                    sprintf(filename, "%03i.jpg", count);
                    img = fopen(filename, "w");
                    fwrite(&buffer, 512, 1, img);
                    count++;
                }
            }
        else
        {
            if (img != NULL)
            {
                fwrite(&buffer,512,1,img);
            }
            else if (img == NULL)
            {
                continue;
            }
        }
    }
    fclose(infile);
}

1 Answer 1

1

At first read PSET4 RECOVER Can't Open JPEGS, I Have Tried Everything Please HELP! about sizeof(buffer)

Then, do something with the whole logic of your code. Write it in your language (english or whatever it is) and then try to implement step by step with C. For now, I am sorry, but it is a mess. Just look what you are doing:

  1. You read a block from card.raw. You check if 4 first bytes look like .jpg. Well, it seems correct. (but quite uncommon way to implement. Hope you understand why (buffer[3] & 0xf0) == 0xe0 gives you correct check for 4th byte.).

  2. If true:

    1. You determine filename (correct)

    2. Then, you open a file, create a pointer to it (correct)

    3. Then you close this file.

    4. Then you immediately open it again. (no harm but why??)

    5. Then you loop checking if 4 bytes do not look like .jpg. Of course its immediately false, see step 2. So you write nothing.

    6. Then you count++, close file and back to step 1.

It should look something like that (for all files except of the first, which is a bit tricky)

  1. Read a block from card.raw untill EOF. Check if the first four bites of a block looks like .jpg
  2. If true
    1. Close current file
    2. Determine filename for the next one
    3. Open new file
    4. Update count
    5. Write the block to the file and go to step 1.
  3. If false
    1. Write the block to the file and go to step 1.

Try to think over your logic before coding instead of coding something and change it back and forth. And then code step by step. Like "am I able to find 50 sequences of 4 bytes?" - Yes. "am I able to write one valid file?" - Yes. And so on.

5
  • Hi obesman. Tbh that (buffer[3] & 0xf0) == 0xe0 is something I just found in CS50x 2016 video walkthrough. I don't really understand why it works. If possible can you point me out why this is even correct?
    – Ha Tran
    Commented Jul 14, 2017 at 10:40
  • Hi Ha Tran. My strong recommendation: never ever paste something in your code if you don't understand what it is. About this particular issue: & is bitwise operator that compares bit by bit two variables. According to specification of .jpg, 4th byte is 1110 wxyz where w, x, y, z are either 0 or 1. (stop!! if you don't understand what I'm talking about don't read farther and return to the Lecture or to the Shorts, or forget about it). 0xf0 is 1111 0000. & operator returns 1 only if both bits are 1. So for any 1110 wxyz, (1110 wxyz & 1111 0000) gives 1110 000 that is == 0xe0.
    – obesman
    Commented Jul 14, 2017 at 11:24
  • Hi obesman I took your advice on sizeof and logic and it seems to fix the invalid file problems. But the images return a chessboard pattern, so I am assuming there is missing texture involved?
    – Ha Tran
    Commented Jul 15, 2017 at 10:12
  • Hi Ha Tran. Don't quite understand what do you mean by "missing texture involved". All .jpgs are photos of Harvard students and staff. PS. And yes its less a mess now )) However, still.....
    – obesman
    Commented Jul 15, 2017 at 10:30
  • Look, after reading one block, you do FILE *img = NULL; It means that you kill all that has been done in previous loops. You start from scratch.
    – obesman
    Commented Jul 15, 2017 at 10:39

You must log in to answer this question.

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