在C中读取/写入.bmp文件时出现问题
我的程序需要能够读取.bmp图像,在其中写入一些数据,然后创建另一个.bmp图像。首先,我开始编写一些东西来读取图像,然后在另一个文件中重写相同的图像,但我遇到了一些问题。 这是我的密码: bmp.h:在C中读取/写入.bmp文件时出现问题,c,image-processing,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> #inclu
#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
\ifndef\u BMP\u H_
#定义_
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#pragma包(推送,1)
类型定义结构{
uint16_t型;
uint32_t文件大小;
uint16保留1;
uint16_t储备2;
uint32_t偏移量;
}BMP_文件_头;
类型定义结构{
BMP_文件头文件头;
uint32_t b尺寸;
int32_t宽度;
int32_t高度;
uint16_t平面;
uint16_t比特计数;
uint32_t压缩;
uint32_t图像大小;
int32_t xPixelsPerMeter;
int32_t型验光仪;
使用uint32_t颜色;
uint32_t重要颜色;
}BMP_信息_标题;
#布拉格语包(流行语)
BMP_Info_Header*loadBMP(常量字符*文件名,字符*数据);
void writeBMP(BMP\u Info\u Header*infoHeader,char*data);
#恩迪夫
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");
}
#包括“bmp.h”
BMP_Info_Header*loadBMP(常量字符*文件名,字符*数据){
文件*文件;
BMP_Info_Header*infoHeader;
int n;
//打开文件
file=fopen(文件名,“rb”);
如果(!文件){
fprintf(stderr,“读取文件%s失败。\n”,文件名);
出口(1);
}
//Alloc并读取标题
infoHeader=(BMP_Info_Header*)malloc(sizeof(BMP_Info_Header));
n=fread(infoHeader,sizeof(BMP\u Info\u Header),1,文件);
//检查格式
if(infoHeader->fileHeader.type!=0x4D42){
fclose(文件);
fprintf(标准格式,“无效图像”);
出口(1);
}
//-------------------------检查图像--------------------------
如果(infoHeader->bSize!=40){
fclose(文件);
fprintf(stderr,“无法正确加载图像”);
出口(1);
}
如果((信息头->平面!=1)| |(信息头->比特数!=24)){
fclose(文件);
fprintf(标准格式,“无效图像”);
出口(1);
}
如果(信息头->压缩!=0){
fclose(文件);
fprintf(stderr,“此软件当前不支持压缩的BMP文件。\n”);
出口(1);
}
//通过偏移量移动文件,直到数据本身开始
fseek(文件,sizeof(char)*infoHeader->fileHeader.offset,SEEK\u SET);
//将字符数组分配到所需的大小以保存数据
数据=(char*)malloc(sizeof(char)*infoHeader->imageSize);
//实际读取图像数据
fread(数据,大小(字符),信息头->图像大小,文件);
printf(“%s”,数据);
//验证数据
如果(!数据){
fclose(文件);
fprintf(stderr,“无法正确加载图像数据\n”);
出口(1);
}
fclose(文件);
返回信息头;
}
void writeBMP(BMP\u Info\u头*头,字符*数据){
文件*fp;
fp=fopen(“output.bmp”、“wb”);
int n;
如果(!fp){
fclose(fp);
fprintf(stderr,“无法创建输出文件”\n);
出口(1);
}
//-----------------------写下图像------------------------
//标题
n=fwrite(头,sizeof(char),sizeof(BMP\u Info\u头),fp);
if(n<1){
fclose(fp);
fprintf(stderr,“无法写入图像头。\n”);
出口(1);
}
//抵消
fseek(fp,sizeof(char)*header->fileHeader.offset,SEEK\u SET);
//资料
n=fwrite(数据,大小(字符),标题->图像大小,fp);
if(n<1){
fclose(fp);
fprintf(stderr,“无法写入图像数据。\n”);
出口(1);
}
fclose(fp);
fprintf(标准输出,“图像写入成功!\n”);
}
它似乎总是在“无法写入图像数据”错误时下降。有人能帮我吗?我对编程相当陌生,无法自己解决它。问题可能在于
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,
,您预计会发生什么情况?用随机值填充剩余的字节?零?在任何情况下,您都应该显式地写入这些字节。因此,我确实找到了解决问题的方法。问题是,当BMP文件未压缩时,在BMP\u Info\u Header
结构中找到的imageSize
变量中的值等于0,因此当我调用fread
和fwrite
函数时,它们不会读取或写入任何内容,因为Header->imageSize
值为0。我找到的解决方案是用header->imageSize
调用3*header->width*header->height
,这样我就可以得到真正的图像分辨率,然后将其乘以3,这样我就可以得到准确的像素值。顺便说一下,谢谢你们的帮助!谢谢你 使用调试器并找出原因。应使用windows中定义的位图标题。h@MichaëlRoy使用的标题(unistd.h
)表明该代码是用于*nix的。@EugeneSh。是的,我在一台MacYou电脑上,你输出的字符串(以null结尾)不是以null结尾的字符串。对printf的调用只显示第一个null之前的随机垃圾。