C语言 读取黑白BMP图

C语言 读取黑白BMP图,第1张

分类: 电脑/网络 >>程序设计 >>其他编程语言

问题描述:

现在想用C语言来读取一个黑白的BMP图. 我已经知道: 图的偏移量是54.以二进制打开BMP图,从54个字节开始便应该是图形码了. 如:"FF FF FF FF FF 00 00 FF FF FF" .

图片大小是320*240.我一个个读入后按一行320个像素,240行来画,画出了原图象的一个稍微重叠的图. 所以我怀疑是不是一个字节并不是代表一个像素? 如"FF"并不是代表一个白色像素? 具体如何? 希望能有高手指点下.我取出来的图形码该如何处理才能显示出正确的图来? 感激不尽!!!

解析:

1. 黑白BMP文件图的像素大多是从62字节(从0数起)开始。具体从哪一字节开始, 决定于文件中第10字节(从0数起)开始处4字节的整形数是多少. 因为文件头后面不是紧接着像素值.

2. 黑白BMP图的一个像素用一个bit表示。一般0表示背景(缺省为白色),1表示前景色(缺省为黑色)。即一个字节代表相邻的8个像素。

3. 320*240的黑白BMP图,每行320个像素用40个字节表示,240行,应占40*240=9600字节。加上前头62字节,文件大小应为9662字节。

4. BMP图像素的存储顺序是自底向上。所以文件最后40个字节表示的是第一行的像素值。

5. 行宽如不是8的倍数,也扩展到8的倍数。如行宽321, 则每行像素需用41个字节存储。你的行宽320,恰好是8的倍数,没有这个问题。

#ifndef IMAGE_H

#define IMAGE_H

void image_info(FILE* file)

void image_save(FILE *file)

void image_gray()

void image_binarization()

void image_opposite()

void image_channel() //抽取RGB通道

void image_bright()//改变图像亮度

typedef struct BMP

{

//14字节

unsigned shortbfType //文件标识 2字节 必须为BM

unsigned int bfSize //文件大小 4字节

unsigned shortbfReserved1 //保留,每字节以"00"填写 2字节

unsigned shortbfReserved2 //同上 2字节

unsigned int bfOffBits //记录图像数据区的起始位置(图象数据相对于文件头字节的偏移量)。 4字节

//40字节

unsigned int biSize //表示本结构的大小 4字节

intbiWidth //位图的宽度 4字节

intbiHeight //位图的高度 4字节

unsigned short biPlanes //永远为1 , 2字节

unsigned short biBitCount //位图的位数 分为1 4 8 16 24 32 2字节

unsigned int biCompression //压缩说明 4字节

unsigned int biSizeImage //表示位图数据区域的大小以字节为单位 4字节

int biXPelsPerMeter //用象素/米表示的水平分辨率 4字节

int biYPelsPerMeter //用象素/米表示的垂直分辨率 4字节

unsigned int biClrUsed //位图使用的颜色索引数 4字节

unsigned int biClrImportant //对图象显示有重要影响的颜色索引的数目 4字节

} BMP

int line_byte

unsigned char *imagedata

extern BMP bmp

extern int line_byte

extern unsigned char *imagedata

#endif

//image_rw.c文件

#include<stdio.h>

#include<stdlib.h>

#include"image.h"

void image_info(FILE *file)

{

int times=3//输入文件名次数。

char bmp_name[10] //文件名

printf("\nplease enter a file name for reading:")

do

{

if (times<3)

{

printf("\nplease enter a file name for reading again:")

}

fflush(stdin)

gets(bmp_name)

//printf("\n%s",bmp_name)

file=fopen(bmp_name,"rb+") //打开一个文件进行读写 *** 作。

--times

if (file==NULL)

{

printf("\nerror opening %s for reading! ",bmp_name)

}

else

{

break

}

}

while(times!=0)

if (times==0)

{

printf("\nsorry, shutdown!")

exit(1)

}

//读取图像信息

fseek(file,0L,0)//读取图像文件类型

fread(&bmp,sizeof(BMP),1,file)

printf("\n bmp tpye:%u",bmp.bfType)

printf("\n bmp size:%u",bmp.bfSize)

printf("\n bmp reserved1:%u",bmp.bfReserved1)

printf("\n bmp reserved2:%u",bmp.bfReserved2)

printf("\n bmp offBits: %u",bmp.bfOffBits)

printf("\n bmp bisize: %u",bmp.biSize)

printf("\n bmp biWidth: %d",bmp.biWidth)

printf("\n bmp biHeight: %d",bmp.biHeight)

printf("\n bmp biplans: %u",bmp.biPlanes)

printf("\n bmp biBitCount: %u",bmp.biBitCount)

printf("\n bmp biCompression: %u",bmp.biCompression)

printf("\n bmp biSizeImage: %u",bmp.biSizeImage)

printf("\n bmp biXPelsPerMeter: %d",bmp.biXPelsPerMeter)

printf("\n bmp biYPelsPerMeter: %d",bmp.biYPelsPerMeter)

printf("\n bmp biClrUsed: %u",bmp.biClrUsed)

printf("\n bmp biClrImportant: %u\n",bmp.biClrImportant)

line_byte=(bmp.biWidth*bmp.biBitCount/8+3)/4*4//获得图像数据每行的数据个数

//printf("dfsa%u",bmp.line_byte)

//bmp.imagedata=NULL

imagedata=(unsigned char*)malloc(bmp.biSizeImage)

fseek(file,(long)bmp.bfOffBits,0)

fread(imagedata,sizeof(unsigned char),bmp.biSizeImage,file)

fclose(file)

}

//保存图像

void image_save(FILE *file)

{

int times=3//输入文件名次数。

char bmp_name[10] //文件名

//int i //记录数据区个数

printf("\nplease enter a file name for writeing:")

do

{

if (times<3)

{

printf("\nplease enter a file name for writeing again:")

}

fflush(stdin)

gets(bmp_name)

printf("\n%s",bmp_name)

file=fopen(bmp_name,"wb+") //打开一个文件进行读写 *** 作。

--times

if (file==NULL)

{

printf("\nerror opening %s for writing",bmp_name)

}

else

{

break

}

}

while(times!=0)

if (times==0)

{

printf("\nsorry, shutdown!")

exit(1)

}

//写文件头

printf("\n%s",bmp_name)

fseek(file,0L,0)//图像文件类型

fwrite(&(bmp.bfType),sizeof(short),1,file)

printf("\n bmp tpye:%d",bmp.bfType)

fseek(file,2L,0)//图像文件大小

fwrite(&(bmp.bfSize),sizeof(int),1,file)

printf("\n bmp size:%d",bmp.bfSize)

fseek(file,6L,0)//图像文件保留字1

fwrite(&(bmp.bfReserved1),sizeof(short),1,file)

printf("\n bmp reserved1:%d",bmp.bfReserved1)

fseek(file,8L,0)//图像文件保留字2

fwrite(&(bmp.bfReserved2),sizeof(short),1,file)

printf("\n bmp reserved2:%d",bmp.bfReserved2)

fseek(file,10L,0)//数据区的偏移量

fwrite(&(bmp.bfOffBits),sizeof(short),1,file)

printf("\n bmp offBits: %d",bmp.bfOffBits)

fseek(file,14L,0)//文件头结构大小

fwrite(&(bmp.biSize),sizeof(int),1,file)

printf("\n bmp bisize: %d",bmp.biSize)

fseek(file,18L,0)//图像的宽度

fwrite(&(bmp.biWidth),sizeof(int),1,file)

printf("\n bmp biWidth: %d",bmp.biWidth)

fseek(file,22L,0)//图像的高度

fwrite(&(bmp.biHeight),sizeof(int),1,file)

printf("\n bmp biHeight: %d",bmp.biHeight)

fseek(file,24L,0)//图像的面数

fwrite(&(bmp.biPlanes),sizeof(short),1,file)

printf("\n bmp biplans: %d",bmp.biPlanes)

fseek(file,28L,0)//图像一个像素的字节数

fwrite(&(bmp.biBitCount),sizeof(short),1,file)

printf("\n bmp biBitCount: %d",bmp.biBitCount)

fseek(file,30L,0)//图像压缩信息

fwrite(&(bmp.biCompression),sizeof(short),1,file)

printf("\n bmp biCompression: %d",bmp.biCompression)

fseek(file,34L,0)//图像数据区的大小

fwrite(&(bmp.biSizeImage),sizeof(int),1,file)

printf("\n bmp biSizeImage: %d",bmp.biSizeImage)

fseek(file,38L,0)//水平分辨率

fwrite(&(bmp.biXPelsPerMeter),sizeof(int),1,file)

printf("\n bmp biXPelsPerMeter: %d",bmp.biXPelsPerMeter)

fseek(file,42L,0)//垂直分辨率

fwrite(&(bmp.biYPelsPerMeter),sizeof(int),1,file)

printf("\n bmp biYPelsPerMeter: %d",bmp.biYPelsPerMeter)

fseek(file,46L,0)//颜色索引数

fwrite(&(bmp.biClrUsed),sizeof(int),1,file)

printf("\n bmp biClrUsed: %d",bmp.biClrUsed)

fseek(file,50L,0)//重要颜色索引数

fwrite(&(bmp.biClrImportant),sizeof(int),1,file)

printf("\n bmp biClrImportant: %d\n",bmp.biClrImportant)

fseek(file,(long)(bmp.bfOffBits),0)

fwrite(imagedata,sizeof(unsigned char),bmp.biSizeImage,file)

fclose(file)

}

//pixProcess.c文件

#include<stdio.h>

#include<stdlib.h>

#include<math.h>

#include"image.h"

//灰度化

void image_gray()

{

int i,j

unsigned char tmp

for (i=0i<bmp.biHeighti++)

{

for (j=0j<line_byte/3j++)

{

tmp=0.11*(*(imagedata+i*line_byte+j*3+0))+0.59*(*(imagedata+i*line_byte+j*3+1))+0.3*(*(imagedata+i*line_byte+j*3+2))

imagedata[i*line_byte+j*3+0]=tmp

imagedata[i*line_byte+j*3+1]=tmp

imagedata[i*line_byte+j*3+2]=tmp

//printf("\nnidsfh%d%d",i,j)

}

}

}

//二值化

void image_binarization()

{

int i,j

for (i=0i<bmp.biHeighti++)

{

for (j=0j<line_bytej++)

{

if ((*(imagedata+i*line_byte+j))<128)

{

imagedata[i*line_byte+j]=0

}

else

{

imagedata[i*line_byte+j]=255

}

}

}

}

void image_opposite() //反相

{

int i,j

for (i=0i<bmp.biHeighti++)

{

for (j=0j<line_bytej++)

{

imagedata[i*line_byte+j]=abs(255-imagedata[i*line_byte+j])

}

}

}

void image_channel() //抽取RGB通道

{

int i,j

char rgb

printf("\nplease enter a char(r/g/b): ")

fflush(stdin)

scanf("%c",&rgb)

if (rgb=='b')

{

for (i=0i<bmp.biHeighti++)

{

for (j=0j<line_byte/3j++)

{

imagedata[i*line_byte+3*j+1]=0

imagedata[i*line_byte+3*j+2]=0

}

}

}

else if(rgb=='g')

{

for (i=0i<bmp.biHeighti++)

{

for (j=0j<line_byte/3j++)

{

imagedata[i*line_byte+3*j]=0

imagedata[i*line_byte+3*j+2]=0

}

}

}

else

{

for (i=0i<bmp.biHeighti++)

{

for (j=0j<line_byte/3j++)

{

imagedata[i*line_byte+3*j]=0

imagedata[i*line_byte+3*j+1]=0

}

}

}

}

void image_bright()//改变图像亮度

{

int level

int i,j

printf("\n please enter the level of brightness[-255 to 255] :")

fflush(stdin)

scanf("%d",&level)

for (i=0i<bmp.biHeighti++)

{

for (j=0j<line_bytej++)

{

if (level>=0)

{

if ((imagedata[i*line_byte+j]+level)>255)

imagedata[i*line_byte+j]=255

else

imagedata[i*line_byte+j]+=level

}

else

{

if ((imagedata[i*line_byte+j]-abs(level))<0)

imagedata[i*line_byte+j]=0

else

imagedata[i*line_byte+j]+=level

}

}

}

}

//void image_create() //创建一幅24位BMP图像文件。

//{

//main.c文件

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<conio.h>

#include"image.h"

BMP bmp

int main()

{

FILE *file=NULL

int choose

char gono

do

{

image_info(file) //imagedata已经分配了动态内存,但是没有释放

printf("\n 1.image_opposite")

printf("\n 2.image_gray")

printf("\n 3.image_binarization")

printf("\n 4.image_channel")

printf("\n 5.image_brightness")

//printf("6.image_opposite")

//printf("7.image_opposite")

printf("\nchoose your options:")

fflush(stdin)

scanf("%d",&choose)

switch(choose)

{

case 1:

image_opposite()

image_save(file)

free(imagedata)

break

case 2:

image_gray()

image_save(file)

free(imagedata)

break

case 3:

image_binarization()

image_save(file)

free(imagedata)

break

case 4:

image_channel()

image_save(file)

free(imagedata)

break

case 5:

image_bright()

image_save(file)

free(imagedata)

break

default:

printf("\n wrong choose!")

}

printf("\nlet's go on?(y/n):")

fflush(stdin)

scanf("%c",&gono)

if (gono=='n')

{

printf("\nbye bye!")

break

}

}

while(1)

return 0

}

可以使用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=0j<heightj++)

{

   for(i=0i<widthi++)

        {

            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=0j<heightj++)

{

fread(pix, 1, stride, fpbmp)

   for(i=0i<widthi++)

        {

            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)

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11591199.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-17
下一篇 2023-05-17

发表评论

登录后才能评论

评论列表(0条)

保存