C,麻烦读.bmp

时间:2013-10-15 18:58:25

标签: c bitmap

以下是代码:

#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艺术,不是非常复杂,只是非常简单的黑白图片。 它应该读取.bmp,从标题获取高度和宽度,逐字节读取所有像素到矩阵( mat 数组),然后如果像素是白色则将空间写入文本文件,如果是像素则写入“0”是任何颜色,但白色。

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

另外,我觉得在从数组读取数组/写入时我做错了,所以指出这些缺陷会非常感激。

UPD:谢谢你们,伙计们,你们给了我很大的帮助!

2 个答案:

答案 0 :(得分:2)

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

#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"); 
    }
} 

答案 1 :(得分:1)

fscanf

%i读取一个整数作为ASCII数字序列,但宽度&amp; BMP的高度存储在原始二进制文件中。请改用fread来阅读它们:

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

(在读取高度之前不需要fseek,因为之前的fread已经推进了流指针。fscanf也是如此

作为宽度&amp;高度指定为4个字节,建议使用int32_t而不是int作为类型,以确保它始终完全适合。