我正在尝试从类似存储卡的文件中提取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;
}
答案 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
,并且具有(通常是软的)错误检查量。
无论如何,希望它有所帮助。祝你好运。