c - 使用C从SD卡读取jpeg

标签 c

对于我的 C 课,我必须编写一个程序来查看 SD 卡(或者实际上是 card.raw 文件),并提取意外删除的图像。我遇到的问题是我不断出现段错误,但我不知道为什么。我认为可能是我没有正确使用数据指针,但我不知道还能怎么做。我将在这里提供一些代码,以便您的想法!应该关注的部分是恢复函数,因为它是有问题的部分,老师几乎给了我们其余的代码。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

// Function prototypes. Don't change these.
unsigned char * read_card(char * fname, int *size);
void save_jpeg(unsigned char * data, int size, char * fname);
void recover(unsigned char * data, int size);

int main()
{
    // Read the card.raw file into an array of bytes (unsigned char)
    int card_length;
    unsigned char *card = read_card("card.raw", &card_length);

    // Recover the images
    recover(card, card_length);
}

unsigned char * read_card(char * fname, int * size)
{

    struct stat st;
    if (stat(fname, &st) == -1)
    {
        fprintf(stderr, "Can't get info about %s\n", fname);
        exit(1);
    }
    int len = st.st_size;
    unsigned char *raw = (unsigned char *)malloc(len * sizeof(unsigned 
char));

    FILE *fp = fopen(fname, "rb");
    if (!fp)
    {
        fprintf(stderr, "Can't open %s for reading\n", fname);
        exit(1);
    }

    char buf[512];
    int r = 0;
    while (fread(buf, 1, 512, fp))
    {
        for (int i = 0; i < 512; i++)
    {
        raw[r] = buf[i];
        r++;
    }
    }
    fclose(fp);

    *size = len;
    return raw;
}

void save_jpeg(unsigned char * data, int size, char * fname)
{
    FILE *fp = fopen(fname, "wb");
    if (!fp)
    {
        fprintf(stderr, "Can't write to %s\n", fname);
        exit(1);
    }

    fwrite(data, 1, size, fp);
    fclose(fp);   
}
void recover(unsigned char * data, int size){
    int start=0;
    int length=0;
    int count=0;
    char name[64];

    for( int i = 0; i < size ;i++ ){
        if ((data[i] == 0xff && data[i+1] == 0xd8 && data[i+2] == 0xff && 
data[i+3] == 0xe0) ||
            (data[i] == 0xff && data[i+1] == 0xd8 && data[i+2] == 0xff && 
rmdata[i+3] == 0xe1)){
               start = i;

            }
        if(data[i] == 0xd9){
            length = i - start;
            count++;
            sprintf(name,"pic%d.jpeg",count);
            save_jpeg(data[start], length, name);

        }


    }

}

最佳答案

您的阅读方式有点错误,只有文件大小为 512 的倍数。您必须获取 fread 读取和写入的字节数 只有那个量。因为您正在读取 512 字节的 block ,所以最后一个 block 可能没有那么大,因此您可能会溢出缓冲区,从而导致 段错误。

将您的阅读内容更改为:

unsigned char buf[512];
size_t n;
while ((n = fread(buf, 1, sizeof buf / sizeof buf[0], fp)))
{
    for (int i = 0; i < n; i++) // the i < n is the correct way
    {
        raw[r] = buf[i];
        r++;
    }
}

当函数失败时执行 exit(1) 也是不好的做法,最好这样做 此函数应返回 NULL,并且调用函数应检查 如果返回值为NULL:

unsigned char * read_card(char * fname, int * size)
{

    struct stat st;
    if (stat(fname, &st) == -1)
    {
        fprintf(stderr, "Can't get info about %s\n", fname);
        return NULL; // <-- here do not do exit
    }
    ...

}

int main(void)
{
    int card_length;
    unsigned char *card = read_card("card.raw", &card_length);

    if(card == NULL)
    {
        fprintf(stder, "Error, could not read card.raw\n");
        return 1;
    }

    recover(card, card_length);

    // do not forget to free the memory
    free(card);

    return 0;
}

还有do not cast malloc ,这样做:

unsigned char *raw = malloc(len * sizeof *raw);

并且由于 char 的大小定义为 1,在这种情况下您甚至可以 删除 * sizeof *raw

我不知道jpeg格式是如何工作的,所以我无法评论你的 recover 正在做正确的事情。但有一件事你应该思考 关于:

for( int i = 0; i < size ;i++ ) {
    if ((data[i] == 0xff && data[i+1] == 0xd8 && data[i+2] == 0xff && 
        data[i+3] == 0xe0) ...

}

当你到达最后 2 次迭代时 (i == size - 2),data[i+2]data[i+3] 将超出范围,因此您应该在访问之前检查一下 数据[i+2]数据[i+3]。最后一次迭代也是如此, data[i+1] 也会出界。就像我说的,我不知道 jpeg 是如何工作的 所以我不知道所有这些值的含义(例如 0xff0xd8)。但是我 认为在 save_jpeg(data[start], length, name); 之后您可能需要 进行返回

关于c - 使用C从SD卡读取jpeg,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49268015/

相关文章:

C - alignas 没有给出预期的结果

c - 为什么 gets 方法没有显示在自动完成中?

c - 段错误(核心转储)

C - 为整数分配动态内存并使用它

c - 关闭字体对话框时窗口失去焦点

c - 在C中是否有充当“实例方法”的功能的术语?

c - 为什么从 TCP 套接字读取整数数组时会得到奇怪的结果?

c - 强制函数只接受特定定义?

iphone - 如何使用 iPhone OpenGL ES 绘制抗锯齿圆圈

c - 堆栈上的结构 - 字段已初始化?