-2

我有一个关于如何恢复 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;
}
4

1 回答 1

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 文件的结尾需要您在整个内存块中搜索表示JPEG 文件结尾的 FFD9 字节标记。如果我理解正确的 JPEG 格式,则 FFD9 字节组合只能出现在有效 JPEG 文件的末尾。
  6. 如果您仍然遇到问题,我将创建一个由几个已知 JPEG 文件和其他数据组成的测试文件。然后,您可以直接将输出的内容与您知道的应该输出的内容进行比较,以缩小导致问题的位置/原因。
于 2014-08-31T18:59:29.300 回答