首页 文章

逐字节读取jpeg文件

提问于
浏览
-3

对于cs50类,我必须从存储卡中逐字节读取jpeg文件,以便查看 Headers 信息 . 该文件编译得很好,但每当我执行该文件时,它都会返回“分段错误(核心转储)”消息 .

编辑)好的,现在我知道为什么我必须使用“unsigned char”而不是“int *” . 有人能告诉我如何将信息存储到此特定代码范围内的文件中吗?现在,我试图在if()条件之外存储信息,我不认为fread函数实际上是访问我打开的“图像”文件 .

#include <stdio.h>
#include <string.h>
#include <math.h>

FILE * image = NULL;

int main(int argc, char* argv[])
{
    FILE* infile = fopen("card.raw", "r");
    if (infile == NULL)
    {
        printf("Could not open.\n");
        fclose(infile);
        return 1;
    }
    unsigned char storage[512]; 
    int number = 0;
    int b = floor((number) / 100);
    int c = floor(((number) - (b * 100))/ 10);
    int d = floor(((number) - (b * 100) - (c * 10)));
    int writing = 0;
    char string[5];
    char* extension = ".jpg";

    while (fread(&storage, sizeof(storage), 1, infile))
    {

        if (storage == NULL)
        {
            break;
        }

        if (storage[0] == 0xff && storage[1] == 0xd8 && storage[2] == 0xff)
        {
            if (storage[3] == 0xe0 || storage[3] == 0xe1)
            {

                if (image != NULL)
                {
                    fclose(image);
                }
                sprintf(string, "%d%d%d%s", b, c, d, extension);
                image = fopen(string, "w");
                number++;
                writing = 1;
                if (writing == 1 && storage != NULL)
                {
                    fwrite(storage, sizeof(storage), 1, image);
                }
            }
        } 

        if (writing == 1 && storage != NULL)
        {
            fwrite(storage, sizeof(storage), 1, image);
        }

        if (storage == NULL)
        {
            fclose(image);
        }

    }

    fclose(image);
    fclose(infile);

    return 0;
}

这是问题集,以防我的解释不清楚 .

恢复由于预期会出现这个问题,过去几天我花了很多时间拍摄我认识的人的照片,所有这些都是我的数码相机在1GB CompactFlash(CF)卡上以JPEG格式保存的 . (实际上,我有可能在Facebook上度过了这么多天 . )不幸的是,我对计算机不太满意,而且我不知何故将它们全部删除了!值得庆幸的是,在计算机世界中,“删除”往往不是“被删除”而是“被遗忘” . 我的电脑坚持认为CF卡现在是空白的,但我很确定这对我说谎 . 在〜/ Dropbox / pset4 / jpg / recover.c中写入一个可以恢复这些照片的程序 . 嗯 . 好的,这就是事情 . 尽管JPEG比BMP更复杂,但JPEG具有“签名”字节模式,可将它们与其他文件格式区分开来 . 事实上,大多数JPEG都以两个字节序列之一开头 . 具体来说,大多数JPEG的前四个字节是从第一个字节到第四个字节从左到右的0xff 0xd8 0xff 0xe0或0xff 0xd8 0xff 0xe1 . 如果您在已知存储照片的磁盘(例如,我的CF卡)上找到这些字节模式之一,则它们会标记JPEG的开头 . (可以肯定的是,你可能会在某些磁盘上偶然遇到这些模式,因此数据恢复并不是一门精确的科学 . )幸运的是,数码相机往往会在CF卡上连续存储照片,因此每张照片都会在之前的照片后立即存储拍照 . 因此,JPEG的开头通常标志着另一个的结束 . 然而,数码相机通常用FAT文件系统初始化CF卡,其“块大小”是512字节(B) . 这意味着这些摄像机只能以512 B为单位写入这些卡 . 因此,1 MB(即1,048,576 B)的照片在CF卡上占用1048576÷512 = 2048“块” . 但是,例如,一个字节更小(即1,048,575 B)的照片也是如此!磁盘上浪费的空间称为“松弛空间” . 法医调查人员经常查看遗留空间以查找可疑数据的遗留物 . 所有这些细节的含义是,你,研究者,可能会编写一个程序,迭代我的CF卡副本,寻找JPEG的签名 . 每次找到签名时,都可以打开一个新文件进行写入,然后从我的CF卡中用字节开始填充该文件,只有在遇到其他签名时才关闭该文件 . 此外,为了提高效率,您不是一次只读取一张CF卡的字节,而是一次读取其中的512个 . 感谢FAT,您可以相信JPEG的签名将是“块对齐的” . 也就是说,您只需要在块的前四个字节中查找这些签名 . 当然,要意识到JPEG可以跨越连续的块 . 否则,JPEG不能大于512 B.但JPEG的最后一个字节可能不会落在块的最后 . 回想一下松弛空间的可能性 . 但不要担心 . 因为当我开始拍摄照片时这张CF卡是全新的,因此制造商已经将其归零(即填充0),在这种情况下,任何松弛空间都将填充0 . 如果那些尾随的0结束于你恢复的JPEG中,那也没关系;它们应该仍然可见 . 现在,我只有一张CF卡,但你们中有很多人!所以我继续前进并创建了卡的“取证图像”,将其内容逐字节存储在名为card.raw的文件中 . 因此,您不必浪费时间不必要地迭代数百万个0,我只会对CF卡的前几兆字节进行成像 . 但是你应该最终发现该图像包含16个JPEG . 像往常一样,您可以使用fopen以编程方式打开文件,如下所示 . FILE * file = fopen(“card.raw”,“r”);顺便提一下,〜/ Dropbox / pset4 / jpg仅包含recover.c,但它没有任何代码 . (我们留给你决定如何实现并编译恢复!)为简单起见,您应该在程序中硬编码“card.raw”;您的程序不需要接受任何命令行参数 . 但是,执行时,您的程序应该从card.raw中恢复每个JPEG,将每个JPEG作为单独的文件存储在当前工作目录中 . 你的程序应该通过命名每个文件对它输出的文件进行编号,### . jpg其中###是从000开始的三位十进制数 . (befriend sprintf . )您无需尝试恢复JPEG的原始名称 . 要检查程序吐出的JPEG是否正确,只需双击并查看即可!如果每张照片都完好无损,那么您的操作可能会成功!但是,你的代码的第一稿吐出的JPEG值可能不正确 . (如果打开它们并且看不到任何内容,它们可能不正确!)执行以下命令删除当前工作目录中的所有JPEG . rm * .jpg如果您不想提示确认每次删除,请执行以下命令 . rm -f * .jpg请小心使用-f开关,因为它会“强制”删除而不会提示您 .

2 回答

  • 3
    int* storage[512];
    

    您可以定义一个指向512内存的内存位置的指针,但实际上并没有保留空间(只有指针 .

    我怀疑你只是想要

    int storage[512];
    

    在此之后,存储仍然是一个指针,但现在它实际上指向512 int s . 虽然我仍然认为你不是't want this. You need ' bytes'而不是 int . 最近的C是 unsigned char . 所以最后的声明是:

    unsigned char storage[512];
    

    为什么?因为 read 读入连续的字节 . 如果你读入 int s,那么你将读入每个 int 的4个字节(因为一个int占用4个字节) .

  • 0

    您的计划中存在许多问题 . 首先是您没有以二进制模式打开文件 .

    第二个是你正在做不必要的指针算术 . 为什么不-

    char buffer [BUFFERSIZE] ;
    
     ....
    
     if (buffer [ii] == WHATEVER)
    

相关问题