【问题标题】:Conversion of Image--->binary--->image using C图像的转换--->二进制--->使用C的图像
【发布时间】:2023-03-09 13:30:02
【问题描述】:

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

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

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

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

【问题讨论】:

  • 作为二进制数据处理。
  • 您的代码在处理图像数据方面不正确。位图文件在文件的开头有一个信息头,其中包含有关图像的信息。图像不仅仅是代表图像像素强度的 8 个字节的集合。 en.wikipedia.org/wiki/…。因此,您正在不正确地修改文件的标题,这就是文件无效的原因。您需要跳过标题,修改图像强度,然后使用相同的标题重新保存图像。
  • 顺便说一句,请停止使用conio.h。这被认为是不好的做法:stackoverflow.com/questions/21329485/…
  • @rayryeng 它对像素没有任何作用。它将每个 8 位值转换为 8 个 1 或 0,然后将其转换回来。什么都没有修改,数据是什么都没有关系。
  • @SamiKuhmonen 啊我读源代码太快了。我以为 OP 试图显示二进制像素...没有看到有人尝试使用相同的有缺陷的思维进行重建...所以理论上这应该可行,但在这里使用 fgetc 是错误的。谢谢!

标签: c image image-processing image-conversion


【解决方案1】:

图像到文本文件

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。纯 charsignedunsigned,由实现者(例如编译器供应商)选择。

如果result 中存储的值不能在signed char 中表示(例如1&lt;&lt;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()always 返回 int,您应该返回一个适当的值来指示成功或失败。 (这不适用于独立环境,例如在没有操作系统的情况下运行的 C 程序。)

  • 第二个程序中的注释部分使用反斜杠而不是正斜杠。发布代码时,您应该始终复制/粘贴它以避免引入新的错误。

【讨论】:

    【解决方案2】:

    检查image=fopen("D:\\aa2.bmp","w");的写入模式,它不是二进制的,用“wb”打开。

    【讨论】:

    • 仍然遇到同样的问题!
    • 将 w 更改为 wb 但图像仍然无效
    【解决方案3】:

    这是运行良好的代码。尝试过 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-26
      • 2012-10-16
      • 2014-11-12
      • 1970-01-01
      • 2015-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多