1

这是代码:

#include <stdio.h> 
#include <stdlib.h> 

void main(void) 
{ 
  char path_bmp [100]; 
  char path_txt [100]; 
  int w; //width 
  int h; //height 
  int wc; //width counter 
  int hc; //height counter 
  FILE *bfp; //BMP pointer 
  FILE *tfp; //TXT pointer 

  puts("BMP path"); 
  gets(path_bmp); 
  puts("Resulting TXT path"); 
  gets(path_txt); 

  bfp = fopen(path_bmp, "r"); 
  tfp = fopen(path_txt, "w"); 

  fseek(bfp, 18, SEEK_SET); 
  fscanf(bfp, "%i", &w); 
  fseek(bfp, 4, SEEK_CUR); 
  fscanf(bfp, "%i", &h); 
  printf("%i x %i", w, h); 

  char mat [w][h]; 
  fseek(bfp, 54, SEEK_SET); 

  for(hc=0; hc < h; hc++)
      fread(mat, 1, w, bfp); 

  for(hc=0; hc < h; hc++) 
      for(wc=0; wc < w; wc++) 
      { 
          if (mat [wc][hc] == 0) 
              fprintf(tfp, " "); 
          else
              fprintf(tfp, "o"); 
      } 

  fprintf(tfp, "\n"); 
} 

它的用途:它将.bmp 转换为ASCII-art,不是很复杂,只是非常简单的黑白图片。它应该读取.bmp,从标题中获取高度和宽度,将所有像素逐字节读取到矩阵(mat数组)中,然后如果像素是白色则将空间写入文本文件,如果像素是除白色之外的任何颜色,则写入“0”。

它实际上做了什么:它正在从某个错误的地方读取 w 和 h。在printf("%i x %i", w, h);它上面打印出一些大数字(我使用小图片进行测试,比如 10x6 像素)然后崩溃,进程返回更大的数字。据我所见,该程序显然是从一些垃圾中读取而不是从应该读取的位置读取,我不明白为什么(花了很多时间试图弄清楚)。

另外,我觉得在读取数组/从数组写入时我做错了,因此将不胜感激指出这些缺陷。

UPD:谢谢你们,你们帮了我很大的忙!

4

2 回答 2

2

您的代码似乎有一些问题,包括一些关于 C 的基本内容。我评论了一些我乍一看发现的错误,但可能还有更多。我还建议您查看位图格式,特别是在描述添加到每行末尾的填充的部分。

#include <stdio.h> 
#include <stdlib.h> 

void main(void) 
{ 
    char path_bmp [100]; 
    char path_txt [100]; 
    int w; //width 
    int h; //height 
    int wc; //width counter 
    int hc; //height counter 
    FILE *bfp; //BMP pointer 
    FILE *tfp; //TXT pointer 

    puts("BMP path"); 
    gets(path_bmp); 
    puts("Resulting TXT path"); 
    gets(path_txt); 

    bfp = fopen(path_bmp, "r"); 
    tfp = fopen(path_txt, "w"); 

    fseek(bfp, 18, SEEK_SET); 
    fread(&w, sizeof(int), 1, bfp); // Read the width in binary format (signed integer)
    fread(&h, sizeof(int), 1, bfp); // The position indicator of the stream is advanced by the total amount of bytes read (sizeof(int)).

    printf("%i x %i", w, h); 

    pixel mat [w][h]; //This can be a packed structure or a union, so you can read all 3 color components with one fread() call

    fseek(bfp, 54, SEEK_SET); 

    for(hc=0; hc < h; hc++)
    {
        for(wc=0; wc < w; wc++) 
        { 
            /* Note that you have to read three bytes, since every pixel has 3 color components*/
            fread(mat[wc][hc].red, sizeof(char), 1, bfp);
            fread(mat[wc][hc].green, sizeof(char), 1, bfp);
            fread(mat[wc][hc].blue, sizeof(char), 1, bfp);
        }
        // you need to do a fseek() here, in order to advance the padding added to the end of each line defined in .BMP format
        fprintf(tfp, "\n"); 
    }
} 
于 2013-10-15T19:15:19.867 回答
1

fscanfwith%i将整数读取为 ASCII 数字序列,但 BMP 的宽度和高度存储在原始二进制文件中。改为fread阅读它们:

fread(&w, 1, 4, bfp); 
fread(&h, 1, 4, bfp);

fseek在读取高度之前没有必要,因为前面fread已经推进了流指针。这也是这种情况fscanf

由于宽度和高度被指定为 4 个字节,因此建议使用它来int32_t代替int类型,以确保它始终完全适合。

于 2013-10-15T19:17:08.247 回答