问题描述:
现在想用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)
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)