我有一个关于如何恢复 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;
}
最佳答案
您的问题中缺少很多信息,但我可以看到一些潜在的问题:
- 您仅在每个 512 字节 block 的开头检查 JPEG 文件。除非您能保证确实如此,否则您可能应该检查整个内存块中是否有 JPEG 文件的开头。
- 您仅检查以 FFD8FFE1 或 FFD8FFE0 开头的 JPEG 文件。如果 JPEG 中的第二个 block 不是 FFE1/FFE0 怎么办?
第二个
if
block 中的以下检查不正确:(buffer[3] != 0xe1 || buffer[3] != 0xe0)
这始终是正确的,因为
buffer[3]
不能同时为 0xE1 和 0xE0。这应该是:(buffer[3] != 0xe1 && buffer[3] != 0xe0)
您对 JPEG 图像结尾的检查可能没有达到您想要的效果:
while ( buffer[0] != 0xff && buffer[1] != 0xd8 && buffer[2] != 0xff && buffer[3] != 0xe1 && buffer[3]!= 0xe0 )
当您在 512 字节 block 的开头找到任何这些值时,JPEG 就会结束。例如,字节 01DB0203 将结束 JPEG,因为
buffer[1] != 0xd8
为 false,即使这不是 JPEG block 标记。- 我认为找到 JPEG 文件的结尾需要您在整个内存块中搜索 FFD9 字节标记,该标记表示 JPEG file 的结尾。如果我理解 JPEG 格式正确,FFD9 字节组合只能出现在有效 JPEG 文件的末尾。
- 如果您仍然遇到问题,我将创建一个由多个已知 JPEG 文件和其他数据组成的测试文件。然后,您可以直接将正在输出的内容与您知道应该输出的内容进行比较,以缩小导致问题的位置/原因。
关于C. CS50恢复作业,恢复Jpg图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25594775/