【问题标题】:Write a JPG image file in C用C写一个JPG图像文件
【发布时间】:2012-05-18 21:36:56
【问题描述】:

我读取 JPEG 图像文件并将其位存储到文本文件中。现在我想使用文本文件中的这些位转换回有效的 JPEG 图像。我试过写一个二进制文件,但它没有检索到图像文件。

请引导我走向正确的方向。这几天我一直在努力解决这个问题,但到目前为止还没有运气。

这是我编写 JPG 文件的代码:

int length;
unsigned char *inData;  
char Buffer[9];
int c = 0, x;
/* file.txt has single bit per line. */
FILE *reader = fopen(file.txt, "r"); 
FILE *writer = fopen("output.JPG","wb");

fseek(reader, 0, SEEK_END);
length=ftell(reader);
fseek(reader, 0, SEEK_SET);

for(x=0; x < length; x++){
    fscanf(reader, "%d", &inData);
    if(c <= 8){       /*  reading 8-bits  */
        Buffer[c] = inData;
    } else {
        fwrite(&Buffer, sizeof(Buffer), 1, writer);
        c = 0;
    }
    c++;
}

fclose(reader);
fclose(writer);

这里是读取 input.JPG 并将其位写入 file.txt 的代码 sn-p

    char *buffer;
int fileLen;
FILE *file = fopen("inputIM.JPG", "rb");

fseek(file, 0, SEEK_END);
fileLen=ftell(file);
fseek(file, 0, SEEK_SET);

buffer=(char *)malloc(fileLen+1);
fread(buffer, fileLen, 1, file);
fclose(file);
convertToBit(&buffer, fileLen);
free(buffer);
}

// convert buffer data to bits and write them to a text file   
convertToBit(void *buffer, int length)
{
int c=0;
int SIZE = length * 8;
unsigned char bits[SIZE + 1];
unsigned char mask = 1;
unsigned char byte ;
int i = 0;
FILE *bitWRT = fopen("file.txt", "w");

for (c=0;c<length;c++)
{
    byte = ((char *)&buffer)[c];

    for(i = 0; i < 8; i++){
        bits[i] = (byte >> i) & mask;
        fprintf(bitWRT, "%d\n", bits[i]);
    }
}
fclose(bitWRT);
}

谢谢,

-山姆

【问题讨论】:

  • “存储它的位”是什么意思?您能否向我们展示您在哪里读取 jpeg 图像并将其写入文本文件的代码?
  • 没有看到您的代码,我们无法告诉您您做错了什么。我的建议是比较原始输入文件和输出文件,找出差异所在。
  • 我添加了代码 sn-p。 output.JPG 是损坏的图像文件。我哪里错了。
  • 你确定你写的是位而不是字符?
  • 实际上你写的是 9 个字符,而不是 8 位(参见 fwrite),并且在将它设置为 0 后增加 c 变量。此外您使用字节数读取,但即使是换行符也被计为字节。有点乱……

标签: c image image-processing jpeg file-handling


【解决方案1】:

必须考虑一件重要的事情,每个文件的开头都有一个页眉,最后有一个页脚。 jpeg头是FF D8,所以如果你只是写文件,你可以破坏这个头,文件就会被破坏。

另一件重要的事情,如果你想读取一个 imagem 文件,你有没有尝试过使用 fread()/fwrite 以二进制模式来做到这一点,而不是尝试使用最初设计为读/写的函数来读取它的内容字符? (我不知道,也许我在这里说一些愚蠢的话,但我会试一试)

对不起,我的英语不好顺便说一句......

【讨论】:

    【解决方案2】:

    尝试如下重写(请注意,这是一个非常幼稚且未经测试的实现):

    FILE* pInput = fopen("file.txt", "r"); 
    FILE* pOutput = fopen("output.JPG","wb");
    
    unsigned char index = 0, byte = 0;
    char line[32]; // Arbitrary, few characters should be enough
    while (fgets(line, sizeof(line), pInput))
    {
        if (line[0] == '1')
            byte = (unsigned char)(byte | (1 << index));
    
        if (++index == 8)
        {
            fwrite(&byte, 1, 1, pOutput);
    
            index = 0;
            byte = 0;
        }
    }
    
    fclose(pInput);
    fclose(pOutput);
    

    假设:输入文件的每一 都是原始文件的单个 (这意味着如果原始文件是,例如,1024 字节,那么您将在文本文件中有 1024 * 8 = 8192 行)。请注意,由于行终止符和(可能)不同的编码,文件的总长度会更大(至少加倍)。

    编辑 写你可以使用这样的东西:

    void convertToBit(void* pBuffer, size_t length)
    {
        FILE* pOutput = fopen("file.txt", "w");
        for (size_t i=0; i < length; ++i)
        {
            unsigned char byte = (unsigned char)pBuffer[i];
            for (int bitIndex=0; bitIndex < 8; ++bitIndex)
            {
                if ((byte & (1 << bitIndex)) != 0)
                    fputs("1\n", pOutput);
                else
                    fputs("0\n", pOutput);
            }
        }
    
        fclose(pOutput);
    }
    

    【讨论】:

    • 谢谢阿德里亚诺。但不幸的是,我仍然没有有效的图像文件。
    • @Sam 你能提供你用来编写文本文件的代码吗?
    • 我添加了代码 sn-p 用于读取输入图像文件并转换为位。请帮帮我
    • @Sam 目前你不是在写你的 JPEG 文件,而是随机的工作人员,请看这一行:byte = ((char *)&buffer)[c];
    • @Sam 更新了我的答案(但我没有尝试,所以如果它不起作用,您可以尝试使用几个字节的输入文件进行调试 - 不是 JPEG - 填充已知值,如 0x55 0xAA )
    猜你喜欢
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多