用c语言读取24位位图bmp文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用c语言读取24位位图bmp文件相关的知识,希望对你有一定的参考价值。

源代码:
#include <windows.h>
#include <stdio.h>

#define BMP_SIZE_OFFSET 18
#define BMP_DATA_OFFSET 54

int main(void)


//定义操作位图的变量
int w; //图像宽度
int h; //图像高度
char *buf, *p; //图像数据
int r,g,b,pix; //像素颜色
int x,y,x0,y0; //平面坐标
FILE *fp; //文件指针
int i,j;

//定义窗口和绘图设备的变量
HWND wnd; //窗口句柄
HDC dc; //绘图设备环境句柄

if((fp=fopen("b_0.bmp","rb"))==NULL)
printf("文件未找到\n");
return-1;

fseek(fp,18L,SEEK_SET);
fread(&w,4,1,fp); //取图像宽度
fread(&h,4,1,fp); //取图像高度
buf=(char *)malloc(w*h*3);
fseek(fp,54L,SEEK_SET); //定位到数据处
fread(buf,1,w*h*3,fp); //读取像素数据
fclose(fp);

wnd=GetForegroundWindow(); //获取窗口句柄
dc=GetDC(wnd); //获取绘图设备

x0=40; y0=40;
p=buf;
for(j=0;j<h;j++)
for(i=0;i<w;i++)
b=*p++; g=*p++; r=*p++;
pix=RGB(r,g,b); //合成像素颜色值
//pix=(r&0xFF)<<16|(g&0xFF)<<8|b&0xFF; //与上一句邓加
SetPixel(dc,x0+i, y0+h-j, pix); //画像素点


free(buf);
getchar();
return 0;

经过测试此程序可以在vc6下正常运行;
不过出现了一个很诡异的事:
图片正常显示:

================================================================
图片非正常显示:
原图

经过程序读取后显示的(非正常):

以上图片已经过反复确定为24位bmp位图!
求解出现问题的原因!
谢谢!

可以使用C语言标准函数库中的fopen、fseek、fclose等系列函数来打开bmp位图文件,以及进行相应的处理,下面是一个demo,仅供参考。以下代码在vc6.0中编译通过。


#include <stdio.h>
#include <stdlib.h>
#define BITMAPFILEHEADERLENGTH 14   // The bmp FileHeader length is 14
#define BM 19778                    // The ASCII code for BM
/* Test the file is bmp file or not */
void bmpFileTest(FILE* fpbmp);
/* To get the OffSet of header to data part */
void bmpHeaderPartLength(FILE* fpbmp);
/* To get the width and height of the bmp file */
void BmpWidthHeight(FILE* fpbmp);
//get r,g,b data
void bmpDataPart(FILE* fpbmp);
// output data to corresponding txt file
void bmpoutput(FILE *fpout);
unsigned int OffSet = 0;    // OffSet from Header part to Data Part
long width ;          // The Width of the Data Part
long height ;         // The Height of the Data Part
unsigned char r[2000][2000],output_r[2000][2000];
unsigned char g[2000][2000],output_g[2000][2000];
unsigned char b[2000][2000],output_b[2000][2000];
int main(int argc, char* argv[])

     /* Open bmp file */
unsigned char *fp_temp;
     FILE *fpbmp;
     FILE *fpout;
     fpbmp= fopen("1.bmp", "rb");
     if (fpbmp == NULL)
     
 printf("Open bmp failed!!!\\n");
 return 1;
     
     fpout= fopen("out.bmp", "wb+");
     if (fpout == NULL)
     
 printf("Open out.bmp failed!!!\\n");
 return 1;
     
     
     bmpFileTest(fpbmp);                //Test the file is bmp file or not
     bmpHeaderPartLength(fpbmp);        //Get the length of Header Part
     BmpWidthHeight(fpbmp);             //Get the width and width of the Data Part
     
     
//
fseek(fpbmp, 0L, SEEK_SET);
fseek(fpout, 0L, SEEK_SET);
 
fp_temp=(unsigned char *)malloc(OffSet);
         fread(fp_temp, 1, OffSet, fpbmp);
fwrite(fp_temp,1,OffSet,fpout);
     
bmpDataPart(fpbmp);                //Reserve the data to file 
     
/*
 
 
 如果您想对图片进行处理,请您再这里插入处理函数!!!!!!!!!!!!!!!!!!
 
*/
bmpoutput(fpout);
fclose(fpbmp);
fclose(fpout);
         return 0;

void bmpoutput(FILE* fpout)

         int i, j=0;
         int stride;
unsigned char* pixout=NULL;
   
stride=(24*width+31)/8;
stride=stride/4*4;
pixout=(unsigned char *)malloc(stride);
 
fseek(fpout, OffSet, SEEK_SET);
for(j=0;j<height;j++)

   for(i=0;i<width;i++)
        
            pixout[i*3+2]=output_r[height-1-j][i];
            pixout[i*3+1]=output_g[height-1-j][i];
            pixout[i*3]  =output_b[height-1-j][i];
        
fwrite(pixout, 1, stride, fpout);


void bmpDataPart(FILE* fpbmp)

         int i, j=0;
int stride;
unsigned char* pix=NULL;
FILE* fpr;
         FILE* fpg;
FILE* fpb;
     
     if((fpr=fopen("bmpr.txt","w+")) == NULL)
     
    printf("Failed to construct file bmpr.txt.!!!");
exit(1);
     
     if((fpg=fopen("bmpg.txt","w+")) == NULL)
     
 printf("Failed to construct file bmpg.txt.!!!");
 exit(1);
     
if((fpb=fopen("bmpb.txt","w+")) == NULL)
     
printf("Failed to construct file bmpb.txt.!!!");
exit(1);
     
 
     fseek(fpbmp, OffSet, SEEK_SET);
stride=(24*width+31)/8;
stride=stride/4*4;
pix=(unsigned char *)malloc(stride);
 
for(j=0;j<height;j++)

fread(pix, 1, stride, fpbmp);
   for(i=0;i<width;i++)
        
            r[height-1-j][i]   =pix[i*3+2];
            g[height-1-j][i]   =pix[i*3+1];
            b[height-1-j][i]   =pix[i*3];
output_r[height-1-j][i]   =pix[i*3+2];
            output_g[height-1-j][i]   =pix[i*3+1];
            output_b[height-1-j][i]   =pix[i*3];
        

 for(i =0; i < height; i++)
     
for(j = 0; j < width-1; j++)
   
fprintf(fpb,"%4d",b[i][j]);
fprintf(fpg,"%4d",g[i][j]);
fprintf(fpr,"%4d",r[i][j]);

fprintf(fpb,"%4d\\n",b[i][j]);
fprintf(fpg,"%4d\\n",g[i][j]);
fprintf(fpr,"%4d\\n",r[i][j]);
 
  
fclose(fpr);
fclose(fpg);
fclose(fpb);
 

void bmpFileTest(FILE* fpbmp)
     
     unsigned short bfType = 0;
 
     fseek(fpbmp, 0L, SEEK_SET);//seek_set 起始位置
     fread(&bfType, sizeof(char), 2, fpbmp);
     if (BM != bfType)
     
 printf("This file is not bmp file.!!!\\n");
 exit(1);
     

/* To get the OffSet of header to data part */
void bmpHeaderPartLength(FILE* fpbmp)

     fseek(fpbmp, 10L, SEEK_SET);
     fread(&OffSet, sizeof(char), 4, fpbmp);  
     printf("The Header Part is of length %d.\\n", OffSet);

/* To get the width and height of the bmp file */
void BmpWidthHeight(FILE* fpbmp)

     fseek(fpbmp, 18L, SEEK_SET);
     fread(&width, sizeof(char), 4, fpbmp);
     fseek(fpbmp, 22L, SEEK_SET);
     fread(&height, sizeof(char), 4, fpbmp);
     printf("The Width of the bmp file is %ld.\\n", width);
     printf("The Height of the bmp file is %ld.\\n", height);
参考技术A 如果横向的一行叫做一个“扫描线”的话
那么每条扫描线的第一个字节一定是对齐到4字节边界的
就比如,假设一条扫描线21个像素,那么一条扫描线就是21*3=63字节
实际上每条扫描线会占用64字节,因为下一条扫描线的第一个字节要对齐到4字节边界
(所谓对齐到边界,就是 除4余0)

注意:以上是凭印象说的。文件里保存和内存里保存是不是一样的不太确定……

最简单的解决方案,你要加载的BMP都确定宽是4的倍数就可以了本回答被提问者采纳
参考技术B 行像素错了一位,导致图像倾斜了。

在 C 中解析/读取位图文件

【中文标题】在 C 中解析/读取位图文件【英文标题】:Parse/Read Bitmap file in C 【发布时间】:2013-07-31 10:07:13 【问题描述】:

我正在尝试编写一个程序来从位图文件(.bmp,Windows 文件格式,8 位)中读取数据。现在我一直在阅读图像数据之前的标题。

我使用我找到的 here 的 bmp 规范来制作这些结构来保存 bmp 的文件头、信息头和图像数据:

typedef struct                                                                                                                                                                                                                              
    unsigned char fileMarker1;                                                                                                                                                                                              
    unsigned char fileMarker2;                                                                                                                                                                                               
    unsigned int   bfSize;                                                                                                                                                                                                                   
    uint16_t unused1;                                                                                                                                                                                                                        
    uint16_t unused2;                                                                                                                                                                                                                        
    unsigned int   imageDataOffset;                                                                                                                                                            
 FILEHEADER;                                                                                                                                                                                                                                

typedef struct                                                                                                                                                                                                                              
    unsigned int   biSize;                                                                                                                                                                                                                   
    int            width;                                                                                                                                                                
    int            height;                                                                                                                                                                     
    uint16_t planes;                                                                                                                                                                                                                         
    uint16_t bitPix;                                                                                                                                                                                                                         
    unsigned int   biCompression;                                                                                                                                                                                                            
    unsigned int   biSizeImage;                                                                                                                                                                                                              
    int            biXPelsPerMeter;                                                                                                                                                                                                          
    int            biYPelsPerMeter;                                                                                                                                                                                                          
    unsigned int   biClrUsed;                                                                                                                                                                                                                
    unsigned int   biClrImportant;                                                                                                                                                                                                           
 INFOHEADER;                                                                                                                                                                                                                                

typedef struct                                                                                                                                                                                                                              
    unsigned char  b;                                                                                                                                                                                                                        
    unsigned char  g;                                                                                                                                                                                                                        
    unsigned char  r;                                                                                                                                                                                                                        
 IMAGE;  

我真的看不出这些有什么问题(除非我的规范来源是错误的,但我在别处看过,在我看来没问题)。

我正在使用以下代码来测试它是否被正确解析:

int main(void)                                                                                                                                                                                                                              
    FILEHEADER fh;                                                                                                                                                                                                                           
    INFOHEADER ih;                                                                                                                                                                                                                           
    FILE *img = fopen("img.bmp", "rb");
    fread(&fh, sizeof(unsigned char), sizeof(FILEHEADER), img);
    fread(&ih, sizeof(unsigned char), sizeof(INFOHEADER), img);
    printf("fM1 = %c, fM2 = %c, bfS = %u, un1 = %hu, un2 = %hu, iDO = %u\n", fh.fileMarker1, fh.fileMarker2, fh.bfSize, fh.unused1, fh.unused2, fh.imageDataOffset);                                                                         
    printf("w = %d, h = %d\n", ih.width, ih.height);
    return 0;

不幸的是,当我运行它时,我得到了错误的结果:

User$ ./images 
fM1 = B, fM2 = M, bfS = 0, un1 = 0, un2 = 118, iDO = 2621440
w = 3276800, h = 65536

根据该链接,未使用的 1 和 2 应始终为 0。此外,宽度和高度完全错误(这是 16x16 图像)。

似乎结构存在某种对齐问题。有人对这个有经验么? (我不想使用任何图像/位图库,我想自己做这一切)。

感谢您的帮助!

【问题讨论】:

如果您直接读取这些结构,请检查结构上的填充以确保您将文件中的数据与结构的布局对齐。 See here 呃,这太愚蠢了。谢谢! 【参考方案1】:

是的,我忘了打包结构。这可以解决问题。哎呀:

typedef struct __attribute__((__packed__))                                                                                                                                                                                                                              
    unsigned char fileMarker1;                                                                                                                                                                                              
    unsigned char fileMarker2;                                                                                                                                                                                               
    unsigned int   bfSize;                                                                                                                                                                                                                   
    uint16_t unused1;                                                                                                                                                                                                                        
    uint16_t unused2;                                                                                                                                                                                                                        
    unsigned int   imageDataOffset;                                                                                                                                                            
 FILEHEADER;                                                                                                                                                                                                                                

typedef struct __attribute__((__packed__))                                                                                                                                                                                                                              
    unsigned int   biSize;                                                                                                                                                                                                                   
    int            width;                                                                                                                                                                
    int            height;                                                                                                                                                                     
    uint16_t planes;                                                                                                                                                                                                                         
    uint16_t bitPix;                                                                                                                                                                                                                         
    unsigned int   biCompression;                                                                                                                                                                                                            
    unsigned int   biSizeImage;                                                                                                                                                                                                              
    int            biXPelsPerMeter;                                                                                                                                                                                                          
    int            biYPelsPerMeter;                                                                                                                                                                                                          
    unsigned int   biClrUsed;                                                                                                                                                                                                                
    unsigned int   biClrImportant;                                                                                                                                                                                                           
 INFOHEADER;                                                                                                                                                                                                                                

typedef struct __attribute__((__packed__))                                                                                                                                                                                                                              
    unsigned char  b;                                                                                                                                                                                                                        
    unsigned char  g;                                                                                                                                                                                                                        
    unsigned char  r;                                                                                                                                                                                                                        
 IMAGE;

【讨论】:

以上是关于用c语言读取24位位图bmp文件的主要内容,如果未能解决你的问题,请参考以下文章

C语言读取1位的BMP图

数字图像C++8位和24位BMP位图的平滑锐化二值化处理,以及24位真彩图的灰度化

西电C语言程序设计实验之位图图像文件缩放

用C语言编写程序处理图片bmp文件 1.读取图片的宽度,高度,每个像素所需的位数,水平分辨率,垂直

用标准c读取bmp文件的长宽?

如何用c语言printf输出bmp图片的像素信息。