无法在C中读/写.bmp文件

时间:2017-06-20 21:56:09

标签: c image-processing

我的程序需要能够读取.bmp图像,在其中写入一些数据,然后创建另一个.bmp图像。首先,我开始编写一些东西来读取图像并在另一个文件中重写相同的图像,但我遇到了一些问题。 这是我的代码:

bmp.h:

#ifndef _BMP_H_
#define _BMP_H_


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>

#pragma pack(push, 1)
typedef struct {
  uint16_t type;
  uint32_t fileSize;
  uint16_t reserved1;
  uint16_t reserved2;
  uint32_t offset;
} BMP_File_Header;

typedef struct {
  BMP_File_Header fileHeader;
  uint32_t bSize;
  int32_t width;
  int32_t height;
  uint16_t planes;
  uint16_t bitCount;
  uint32_t compression;
  uint32_t imageSize;
  int32_t xPixelsPerMeter;
  int32_t yPixelsPerMeter;
  uint32_t colorUsed;
  uint32_t importantColor;
} BMP_Info_Header;
#pragma pack(pop)

BMP_Info_Header* loadBMP(const char *filename, char *data);
void writeBMP(BMP_Info_Header *infoHeader, char *data);

#endif

bmp.c:

#include "bmp.h"


BMP_Info_Header* loadBMP(const char *file_name, char *data) {
  FILE *file;
  BMP_Info_Header *infoHeader;
  int n;

  //Open the file
  file = fopen(file_name, "rb");
  if (!file) {
    fprintf(stderr, "Failed to read file %s.\n", file_name);
    exit(1);
  }

  //Alloc and read the headers
  infoHeader = (BMP_Info_Header *) malloc (sizeof(BMP_Info_Header));

  n = fread(infoHeader, sizeof(BMP_Info_Header), 1, file);

  //Check format
  if (infoHeader->fileHeader.type != 0x4D42) {
    fclose(file);
    fprintf(stderr, "Invalid image");
    exit(1);
  }

  //-------------------------Checking the image--------------------------
  if (infoHeader->bSize != 40) {
    fclose(file);
    fprintf(stderr, "Couldn't load image correctly");
    exit(1);
  }

  if ((infoHeader->planes != 1) || (infoHeader->bitCount != 24)) {
    fclose(file);
    fprintf(stderr, "Invalid image");
    exit(1);
  }

  if (infoHeader->compression != 0) {
    fclose(file);
    fprintf(stderr, "This software currently does not support compressed BMP files.\n");
    exit(1);
  }

  //Move the file through the offset until the beginning of the data itself
  fseek(file, sizeof(char) * infoHeader->fileHeader.offset, SEEK_SET);

  //Allocate the char array to the needed size to hold the data
  data = (char *) malloc (sizeof(char) * infoHeader->imageSize);

  //Actually read the image data
  fread(data, sizeof(char), infoHeader->imageSize, file);
  printf("%s", data);

  //Verify the data
  if (!data) {
    fclose(file);
    fprintf(stderr, "Couldn't load image data correctly\n");
    exit(1);
  }

  fclose(file);
  return infoHeader;

}

void writeBMP(BMP_Info_Header *header, char *data){

  FILE *fp;
  fp = fopen("output.bmp", "wb");
  int n;

  if (!fp) {
    fclose(fp);
    fprintf(stderr, "Unable to create output file\n");
    exit(1);
  }

  //-----------------------WRITE THE IMAGE------------------------
  //Header
  n = fwrite(header, sizeof(char), sizeof(BMP_Info_Header), fp);
  if (n < 1) {
    fclose(fp);
    fprintf(stderr, "Couldn't write the image header.\n");
    exit(1);
  }

  //Offset
  fseek(fp, sizeof(char) * header->fileHeader.offset, SEEK_SET);

  //Data
  n = fwrite(data, sizeof(char), header->imageSize, fp);
  if (n < 1) {
    fclose(fp);
    fprintf(stderr, "Couldn't write the image data.\n");
    exit(1);
  }

  fclose(fp);
  fprintf(stdout, "Image written successfully!\n");
}

似乎总是在“无法写入图像数据”错误时掉线。有人能帮助我吗?我对编程很新,无法自己解决。

2 个答案:

答案 0 :(得分:1)

所以,我确实找到了解决问题的方法。麻烦的是,当未压缩BMP文件时,imageSize结构中找到的BMP_Info_Header变量中的值等于0,所以当我调用fread和{{1}时函数,他们不会读或写任何东西,因为fwrite的值为0.我找到的解决方案是用header->imageSize调用header->imageSize来代替,这样我就可以得到真实的图像分辨率,我乘以3,这样我就可以得到精确的像素值。顺便说一句,谢谢你的帮助!欣赏它!

答案 1 :(得分:0)

可能问题在于fseek,您不会检查返回值。

  fwrite(header, sizeof(char), sizeof(BMP_Info_Header), fp);
  fseek(fp, sizeof(char) * header->fileHeader.offset, SEEK_SET);
  fwrite(data, sizeof(char), header->imageSize, fp);

请注意,如果您在撰写标题后的当前位置小于fileHeader.offset,,您预计会发生什么?用随机值填充剩余的字节?零?在任何情况下,您都应该显式写入这些字节。