我们正在尝试使用C编程将图像转换为二进制数据,反之亦然。我们在网上找到的所有其他解决方案都是C ++或Java。以下是我们尝试的方法:
将图像转换为包含二进制数据的文本文件。每个8个字符对应于使用文本编辑器打开图像时的字符字节。
然后我们尝试使用C程序将二进制数据重新转换为各自的字符。
然后我们使用Picasa Photoviewer打开结果。我们得到的图片无效。
我们如何取回原始图片?以下是我们用于将图像转换为文本文件的代码:
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
FILE *fptr;
FILE *txt;
int c;
fptr=fopen("D:\\aa.bmp","r");
txt=fopen("D:\\test1.txt","w");
if(fptr==NULL)
{
printf("NOTHING In FILE");
fclose(fptr);
}
else
{
printf("success");
do
{
c=fgetc(fptr);
for(int i=0;i<=7;i++)
{
if(c&(1<<(7-i)))
{
fputc('1',txt);
}
else
{
fputc('0',txt);
}
}
// fprintf(txt,"\t");
}while(c!=EOF);
}
fclose(fptr);
fclose(txt);
printf("writing over");
getch();
}
以下是将生成的文本文件转换为带有二进制字符的图像文件的代码,即只包含1和0的文本文件。
#include<stdio.h>
#include<conio.h>
\\The following function converts the ones and zeroes in the text file into a character.
\\For example the text file may have the 8 consecutive characters '1','0','0','0','1','0','0','0'.
\\This converts it into the character equivalent of the binary \\value 10001000
char bytefromtext(char* text)
{
char result=0;
for(int i=0;i<8;i++)
{
if(text[i]=='1')
{
result |= (1<< (7-i) );
}
}
return result;
}
void main()
{
clrscr();
FILE *pfile;
FILE *image;
char buf[8];
char c;
int j=0;
image=fopen("D:\\aa2.bmp","w"); //open an empty .bmp file to
//write characters from the source image file
pfile=fopen("D:\\test1.txt","r");
if(pfile==NULL)
printf("error");
else
{
c=fgetc(pfile);
while(c!=EOF)
{
buf[j++]=c;
if(j==8)
{
fputc(bytefromtext(buf),image);
j=0;
}
c=fgetc(pfile);
}
fclose(pfile);
fclose(image);
}
getch();
}
当字符写入.bmp文件时,我们得到的图像无效。当我们使用文本编辑器打开这个新文件,并使用文本编辑器打开图像文件时,我们会得到相同的字符。
答案 0 :(得分:2)
fptr=fopen("D:\\aa.bmp","r");
BMP文件必须以二进制模式("rb"
)打开,以确保正确读取字节值。 "r"
模式以文本模式打开文件,这可能导致某些字符被转换,从而导致输出损坏。
例如,在Windows(或至少DOS)上,行结尾将从"\r\n"
转换为"\n"
,而字符"\x1a"
可能会被解释为EOF
指示符并截断您的输入。
另一方面,在类UNIX系统上,没有区别。
do { c=fgetc(fptr); for(int i=0;i<=7;i++) { /* ... */ } // fprintf(txt,"\t"); }while(c!=EOF);
这个循环是完全错误的。您需要检查循环顶部的EOF
。当fgetc()
返回EOF
时,您的代码将采用EOF
值(通常为-1
),并在退出循环之前输出相应的1和0。这也会破坏你的输出。
相反,你应该这样做:
while ((c = fgetc (fptr)) != EOF) {
{
/* ... */
}
如果您对同一表达式中的赋值和比较感到不舒服,可以解决这个问题:
while (1)
{
c = fgetc (fptr);
if (c == EOF)
break;
/* ... */
}
另请注意,fgetc()
在出错时也会返回EOF
。您应对此进行测试(if (ferror (fptr))
)并将问题报告给用户。
fclose(fptr); fclose(txt);
您应该检查fclose()
的返回值,并将任何错误报告给用户,至少在输出流上。在某些文件系统上,最后一个输出在流关闭之前不会写入光盘,编写它的任何错误都将由fclose()
报告。请参阅"What are the reasons to check for error on close()?",了解不这样做可能会发生什么的故事。
image=fopen("D:\\aa2.bmp","w"); //open an empty .bmp file to
您必须使用二进制模式("wb"
),如上所述。
char bytefromtext(char* text) { char result=0; for(int i=0;i<8;i++) { if(text[i]=='1') { result |= (1<< (7-i) ); } } return result; }
在处理二进制数据时,应该使用 unsigned char
。简单char
是实现者(例如编译器供应商)选择的signed
或unsigned
。
如果result
中存储的值无法在signed char
中表示(例如1<<7
),则结果为实现已定义。理论上这可能会破坏你的输出。虽然我认为您的代码在大多数情况下可能会按预期工作,但您仍应使用unsigned char
作为原则。
(当然,这假定char
不大于8位,这通常是这种情况。)
char c; /* ... */ c=fgetc(pfile); while(c!=EOF) { /* ... */ c=fgetc(pfile); }
由于其他原因,这个循环是错误的。如果简单char
恰好是无符号的,则c
永远不会比较等于始终具有负值的EOF
。您应该使用int
变量,针对EOF
进行测试,然后才将该值用作字符值。
fclose(pfile); fclose(image);
您应该检查上面提到的返回值。
我的代码还有其他一些狡辩。
在C中,main()
始终返回int
,您应返回适当的值以指示成功或失败。 (这不适用于独立环境,例如,没有操作系统的C程序。)
第二个程序中的注释部分有反斜杠而不是正斜杠。发布代码时,您应始终复制/粘贴代码以避免引入新错误。
答案 1 :(得分:1)
检查image=fopen("D:\\aa2.bmp","w");
的写入模式是否为二进制,在&#34; wb&#34;中打开。
答案 2 :(得分:0)
这是行之有效的代码。尝试过使用raspberryPi3和gcc。
bmp到文本
#include <stdio.h>
int main(int argc, char*argv[]){
FILE *ptr_bmp_in;
FILE *ptr_text_out;
int c;
ptr_bmp_in=fopen("panda_input.bmp","rb");
ptr_text_out=fopen("panda_to_text.txt","w");
if(!ptr_bmp_in)
{
printf("Unable to open file\n");
return 1;
}
while((c=fgetc(ptr_bmp_in)) != EOF)
{
for(int i=0;i<=7;i++)
{
if(c&(1<<(7-i)))
{
fputc('1',ptr_text_out);
}
else
{
fputc('0',ptr_text_out);
}
}
}
fclose(ptr_bmp_in);
fclose(ptr_text_out);
printf("Writing done\n");
return 0;
}
和文本到bmp
#include <stdio.h>
char bytefromtext(unsigned char* text)
{
char result = 0;
for(int i=0;i<8;i++)
{
if(text[i]=='1')
{
result |= (1 << (7-i));
}
}
return result;
}
int main(int argc, char*argv[]){
FILE *ptr_txt_in;
FILE *ptr_bmp_out;
unsigned char buf[8];
int c;
int j = 0;
ptr_txt_in=fopen("panda_to_text.txt","r");
ptr_bmp_out=fopen("panda_output.bmp","wb");
if(!ptr_txt_in)
{
printf("Unable to open file\n");
return 1;
}
while((c=fgetc(ptr_txt_in)) != EOF)
{
buf[j++] = c;
if(j==8)
{
fputc(bytefromtext(buf),ptr_bmp_out);
j=0;
}
}
fclose(ptr_txt_in);
fclose(ptr_bmp_out);
printf("Writing done\n");
return 0;
}