使用C转换图像--->二进制--->图像

时间:2015-09-11 15:46:48

标签: c image image-processing image-conversion

我们正在尝试使用C编程将图像转换为二进制数据,反之亦然。我们在网上找到的所有其他解决方案都是C ++或Java。以下是我们尝试的方法:

  1. 将图像转换为包含二进制数据的文本文件。每个8个字符对应于使用文本编辑器打开图像时的字符字节。

  2. 然后我们尝试使用C程序将二进制数据重新转换为各自的字符。

  3. 然后我们使用Picasa Photoviewer打开结果。我们得到的图片无效。

  4. 我们如何取回原始图片?以下是我们用于将图像转换为文本文件的代码:

    #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文件时,我们得到的图像无效。当我们使用文本编辑器打开这个新文件,并使用文本编辑器打开图像文件时,我们会得到相同的字符。

3 个答案:

答案 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是实现者(例如编译器供应商)选择的signedunsigned

如果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;
}