使用C从SD卡读取jpeg

时间:2018-03-14 00:30:55

标签: 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);

        }


    }

}

1 个答案:

答案 0 :(得分:1)

您阅读的方式有点不对,只有在文件大小合适时才会有效 512的倍数。您必须获得读取和写入的字节数fread 只有这个数额。因为您正在读取512字节的块,最后一块 可能不会那么大,因此你可能溢出缓冲区,导致a 段错误。

将您的阅读更改为:

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]将超出界限,因此您应该在访问之前检查它 data[i+2]data[i+3]。对于最后一次迭代也是如此, data[i+1]也将超出范围。就像我说的,我不知道jpeg是如何工作的 所以我不知道所有这些值的含义(例如0xff0xd8)。但是我 认为在你可能需要的save_jpeg(data[start], length, name);之后 做return