从C中的文件中提取jpeg文件

时间:2015-07-30 05:14:43

标签: c file-io jpeg

我正在尝试从类似存储卡的文件中提取jpeg文件。程序将一次读取512字节块,如果块以JPEG识别字节开头,我的程序应该将输出文件写入那些字节。它应该继续写入这些字节,直到找到另一个JPEG识别字节序列,此时它应该停止写入.jpg文件并写入新文件。每个文件应命名为00x.jpg,其中x是#。

我的程序编译但不生成所有jpeg。应该有16个JPEG但它只产生7个。

int main(void)
{
    // open file for reading
    FILE* file = fopen("card.raw", "r"); // Open the file for reading

    // target file
    FILE* image;

    // buffer of bytes
    uint8_t buffer[512];        

    // check for NULL file
    if (file == NULL)
    {
        fclose(file);
        printf("Could not open file");
        return 1;
    }

    // Prefixes of a jpeg file
    uint8_t jpeg1[4] = {0xff, 0xd8, 0xff, 0xe0};
    uint8_t jpeg2[4] = {0xff, 0xd8, 0xff, 0xe1};

    // keep track of jpegs opened
    int pic = 0;

    int match = 0;

    // is file open?
    int open = 0;


    // stores first 4 bytes of block
    uint8_t check[4];

    int byteNum;
    byteNum = fread(buffer, 512, 1, file);

    // while there are bytes to be read in the file
    while(fread(buffer,512, 1, file) > 0)
    {
        for (int x=0; x < 4; x++)
        {
            check[x] = buffer[x];
        }

        // compares first 4 bytes of buffer segment to jpeg prefixes to determine match
        if((memcmp(check, jpeg1,4) == 0) || (memcmp(check, jpeg2, 4) == 0))
        {

            match = 1;   
        }
        // if encounter a jpeg and file is open, close the file and set match to false
        if (match == 1 && open == 1)
        {


            fclose(image);
            open = 0;        
            match = 0;
        }

        // if match is true and file is closed, create jpeg output file, increment pic#, set file to open, set match to false, open target file
        if (match == 1 && open == 0)
        {
            // stores name of jpegfile
            char jpegName[8]; 
            // stores the jpeg file name with the # jpeg          
            sprintf(jpegName ,"%03d.jpg" ,pic); 
            pic++;
            open = 1; // signifies target jpeg file is open
            match = 0; // sets match back to 0 (false) so it can detect the next match to signify closing the writing            
            image=fopen(jpegName, "w"); // write to target file image
        }

        // if file target is still open but no match, then keep writing since you're in the middle of a jpeg
        if (match == 0 && open == 1)
        {
            fwrite(buffer, 512, 1, image);
        }

    }

    fclose(file);
    return 0;
}

1 个答案:

答案 0 :(得分:1)

我可能会遗漏一些鲜明的东西,但如果你要做的就是读取一个512字节块的文件,检查每个块的前四个八位字节是否有两个已知的前导码,并且在遇到任何一个时,打开一个图像文件并开始转储,直到下一个匹配的块关闭文件并启动一个新文件,然后大约一半的发布代码不需要。

您可以使用image(null或不是null)的值来指示文件是否被打开。此外,仅在打开文件时写入数据(image != NULL),并在循环到下一个文件之前关闭现有文件。

这样的事情:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

int main(void)
{
    // Prefixes of a jpeg file
    static const uint8_t jpeg1[4] = {0xff, 0xd8, 0xff, 0xe0};
    static const uint8_t jpeg2[4] = {0xff, 0xd8, 0xff, 0xe1};

    // open file for reading
    FILE* file = fopen("card.raw", "r"); // Open the file for reading
    if (file == NULL)
    {
        perror("card.raw");
        return EXIT_FAILURE;
    }

    // target file
    FILE* image = NULL;

    // keep track of jpegs opened
    int pic = 0;

    // while there are bytes to be read in the file
    uint8_t buffer[512];
    size_t n_bytes = 0;
    while( (n_bytes = fread(buffer,1, 512, file)) > sizeof(jpeg1))
    {
        // compares first 4 bytes of buffer segment to jpeg prefixes to determine match
        if( memcmp(buffer, jpeg1, sizeof(jpeg1)) == 0 ||
            memcmp(buffer, jpeg2, sizeof(jpeg2)) == 0)
        {
            // stores the jpeg file name with the # jpeg
            char jpegName[64];
            sprintf(jpegName ,"00%d.jpg" , pic++);

            // match. close current file if present.
            if (image)
                fclose(image);

            // open new image file (sets NULL on failure)
            image = fopen(jpegName, "wb"); // write to target file image
            if (image == NULL)
            {
                perror(jpegName);
                break;
            }
        }

        // write whatever we have for our current bytes
        if (image)
            fwrite(buffer, n_bytes, 1, image);
    }

    // the above loop can exit with a file open (in fact, it is guaranteed
    // if we opened at least one file), so close it if one is active.
    if (image)
        fclose(image);
}

或类似的东西。这也以二进制模式打开和关闭文件,如果它小于偶数512字节,则不会在最后一帧写入无关的垃圾。最后,它会在创建的每个文件上递增pic,并且具有(通常是软的)错误检查量。

无论如何,希望它有所帮助。祝你好运。