C. CS50恢复分配,恢复Jpg图像

时间:2014-08-31 18:03:57

标签: c jpeg recover file-recovery cs50

我有一个关于如何恢复jpg图像的问题(它是CS50的一项任务)。 我的代码大部分都是有效的(我相信),但是当我打开我发现的jpg时,我只得到一堆缩略图。

我一直试图解决这个问题很长一段时间,但我似乎无法弄清楚它为什么不起作用。有人能帮我推动正确的方向。

这是我的代码(也可在http://pastebin.com/U2pwJd5e处获得):

#include <stdio.h>
#include <stdlib.h>

#include "bmp.h"


int main(int argc, char* argv[])
{

    //get input file
    char* infile = "card.raw";
    // open card file
    FILE* inptr;
    inptr = fopen("card.raw", "r");


    // error checking (copied from copy.c)
    if (inptr == NULL)
    {
        printf("Could not open %s.\n", infile);
        return 2;
    }

    // initialize buffer
    BYTE buffer[512];

    //initialize jpg variables:
    int increment = 0;
    char outfilename[8];

    // while the end of the file is not reached, continue process & write to buffer next block of 512 bytes
    while (fread(buffer, 512, 1, inptr) != 0)
    {
        // if the inpointer is not empty
        if(inptr != NULL)
        {
            // If the block of 512 bytes starts with markers
            if(buffer[0] == 0xff  && buffer[1] == 0xd8  && buffer[2] == 0xff && (buffer[3]== 0xe1 || buffer[3]== 0xe0))
            {
                // increase file number by 1
                sprintf(outfilename,"%.3d.jpg", ++increment);

                // open new file
                FILE* outptr;
                outptr = fopen(outfilename, "a");

                // write first block of 512 bytes, then read next block
                fwrite(buffer, 512, 1, outptr);

                if(fread(buffer, 512, 1, inptr) == 0)
                       break;

                // copy all information from inpointer to buffer to jpg
                while((buffer[0] != 0xff  && buffer[1] != 0xd8  && buffer[2] != 0xff && (buffer[3]!= 0xe1 || buffer[3]!= 0xe0) ))
                {
                    // if next byte is NULL break
                    if(fread(buffer, 512, 1, inptr) == 0)
                        break;

                    fread(buffer, 512, 1, inptr);

                    //copies jpg file 1 byte at a time
                    fwrite(buffer, 512, 1, outptr);

                }

                // close file
                fclose(outptr);
            }  
        }

    }
    return 0;
}

1 个答案:

答案 0 :(得分:4)

您的问题中有很多缺失的信息,但我可以看到一些潜在的问题:

  1. 您只在每个512字节块的开头检查JPEG文件。除非保证是这种情况,否则您应该检查整个内存块中JPEG文件的开始。
  2. 您只能检查FFD8FFE1或FFD8FFE0启动的JPEG文件。如果JPEG中的第二个块不是FFE1 / FFE0怎么办?
  3. 第二个if块中的以下检查不正确:

    (buffer[3] != 0xe1 || buffer[3] != 0xe0)
    

    这始终是正确的,因为buffer[3]不能同时是0xE1和0xE0。这应该是:

    (buffer[3] != 0xe1 && buffer[3] != 0xe0)
    
  4. 您检查JPEG图像的结尾可能并不符合您的要求:

    while ( buffer[0] != 0xff && buffer[1] != 0xd8 &&
            buffer[2] != 0xff && buffer[3] != 0xe1 && buffer[3]!= 0xe0 )
    

    当您在512字节块的开头找到任何的值时,这将结束JPEG。例如,字节01DB0203将结束JPEG,因为buffer[1] != 0xd8为假,即使这不是JPEG块标记。

  5. 我认为找到JPEG文件的结尾会要求您在整个内存块中搜索FFD9字节标记,这标志着JPEG file的结束。如果我理解JPEG格式正确,则FFD9字节组合只能出现在有效JPEG文件的末尾。
  6. 如果您仍然遇到问题,我会创建一个由几个已知的JPEG文件和其他数据组成的测试文件。然后,您可以直接比较输出的内容与您应该输出的内容,以缩小导致问题的位置/原因。