用C语言读取BMP文件的像素数据

fred8619 2008-04-29 05:37:49
请问如何读取BMP文件的像素数据啊?请问有代码吗?要完全用C写出来的。请问用方法用C来显示BMP文件吗?听说有vesa这个类,真的吗?
...全文
2857 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
远方2012 2010-10-26
  • 打赏
  • 举报
回复
直方图均衡化算法是什么呀?哪位大哥给个详细的呀?
梦醒时分xw 2008-06-26
  • 打赏
  • 举报
回复
这个程序有错误!
xzdwfwt111 2008-05-04
  • 打赏
  • 举报
回复
看//纯C代码下读写BMP文件代码,简单易懂。


/**//*************************************************************
** Copyright (c) 2007, Shanghai
**
** 文件名称:read_write_bmp_with_C.c
** 编译: Visual C++ / ANSI C / ISO C++
** 日期: 2007.10.24
**************************************************************/

#include "stdio.h"
#include "stdlib.h"

#define PIXPLINE 320

typedef struct tagRGBQUAD...{ //定义每个像素的数据类型
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
} RGBQUAD;

int bmp_read(unsigned char *image, int xsize, int ysize, char *filename) ...{
char fname_bmp[128];
sprintf(fname_bmp, "%s.bmp", filename);

FILE *fp;
if (!(fp = fopen(fname_bmp, "rb")))
return -1;

unsigned char header[54];
fread(header, sizeof(unsigned char), 54, fp);
fread(image, sizeof(unsigned char), (size_t)(long)xsize * ysize * 3, fp);

fclose(fp);
return 0;
}

int bmp_write(unsigned char *image, int xsize, int ysize, char *filename) ...{
unsigned char header[54] = ...{
0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
54, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};

long file_size = (long)xsize * (long)ysize * 3 + 54;
header[2] = (unsigned char)(file_size &0x000000ff);
header[3] = (file_size >> 8) & 0x000000ff;
header[4] = (file_size >> 16) & 0x000000ff;
header[5] = (file_size >> 24) & 0x000000ff;

long width = xsize;
header[18] = width & 0x000000ff;
header[19] = (width >> 8) &0x000000ff;
header[20] = (width >> 16) &0x000000ff;
header[21] = (width >> 24) &0x000000ff;

long height = ysize;
header[22] = height &0x000000ff;
header[23] = (height >> 8) &0x000000ff;
header[24] = (height >> 16) &0x000000ff;
header[25] = (height >> 24) &0x000000ff;

char fname_bmp[128];
sprintf(fname_bmp, "%s.bmp", filename);

FILE *fp;
if (!(fp = fopen(fname_bmp, "wb")))
return -1;

fwrite(header, sizeof(unsigned char), 54, fp);
fwrite(image, sizeof(unsigned char), (size_t)(long)xsize * ysize * 3, fp);

fclose(fp);
return 0;
}

void clonebmp(unsigned char *image,int xsize,int ysize)
...{
bmp_read(image, xsize, ysize, "orgbmp"); //orgbmp为当前目录下的bmp文件名
bmp_write(image, xsize, ysize, "clone_bmp");//clone_bmp为克隆的bmp文件名
}


/**//****************************************************************************
* 名称:youwritetobmp()
* 功能:写入bmp文件
* 入口参数:RGBQUAD *pixarr ---- 要写入的像素数组指针, int xsize ---- 图像宽度, int ysize ---- 图像高度, char *filename --图像名称
* 出口参数:无
* 返回值:-1:错误 ;0:正确
****************************************************************************/
int youwritetobmp(RGBQUAD *pixarr, int xsize, int ysize, char *filename) ...{
unsigned char header[54] = ...{
0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
54, 0, 0, 0, 40, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 24, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};
int i;
int j;
long file_size = (long)xsize * (long)ysize * 3 + 54;
header[2] = (unsigned char)(file_size &0x000000ff);
header[3] = (file_size >> 8) & 0x000000ff;
header[4] = (file_size >> 16) & 0x000000ff;
header[5] = (file_size >> 24) & 0x000000ff;

long width;
if(!(xsize%4)) width=xsize;
else width= xsize+(4-xsize%4); //如不是4的倍数,则转换成4的倍数
header[18] = width & 0x000000ff;
header[19] = (width >> 8) &0x000000ff;
header[20] = (width >> 16) &0x000000ff;
header[21] = (width >> 24) &0x000000ff;

long height = ysize;
header[22] = height &0x000000ff;
header[23] = (height >> 8) &0x000000ff;
header[24] = (height >> 16) &0x000000ff;
header[25] = (height >> 24) &0x000000ff;

char fname_bmp[128];
sprintf(fname_bmp, "%s.bmp", filename);

FILE *fp;
if (!(fp = fopen(fname_bmp, "wb")))
return -1;

fwrite(header, sizeof(unsigned char), 54, fp);

RGBQUAD zero=...{0,0,0}; //不足字节,用zero填充

for(j=0;j<ysize;j++)...{
if(!(xsize%4))...{
for(i=0;i<xsize;i++)...{
fwrite(pixarr+i, sizeof(RGBQUAD),1, fp);
}
}
else
...{
for(i=0;i<xsize;i++)...{
fwrite(pixarr+i, sizeof(RGBQUAD),1, fp);
}
for(i=xsize;i<xsize+(4-xsize%4);i++)...{
fwrite(&zero, sizeof(RGBQUAD),1, fp);
}
}
}

fclose(fp);
return 0;

}

int main() ...{
unsigned char *image;
int xsize = 320;
int ysize = 163;

RGBQUAD pixarray[PIXPLINE]; //一行像素值数组

image = (unsigned char *)malloc((size_t)xsize * ysize * 3);
if (image == NULL)
return -1;
clonebmp(image,xsize,ysize); //功能一:实现一副图像的拷贝


youwritetobmp(pixarray,xsize,ysize,"yourimage");//功能二:实现像素的精确绘制,像素值在pixarray数组中

free(image);
return -1;
}
fred8619 2008-05-02
  • 打赏
  • 举报
回复
多谢各位,谢谢帮助,在下十分感激
  • 打赏
  • 举报
回复
以下是我之前截取图片信息时候用到的知识点,楼主慢慢研究吧!

1. BMP文件组成
BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。

2. BMP文件头
BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。
其结构定义如下:

程序代码 程序代码

typedef struct tagBITMAPFILEHEADER{
WORD bfType; // 位图文件的类型,必须为BM:2字节
DWORD bfSize; // 位图文件的大小,以字节为单位:4字节
WORD bfReserved1; // 位图文件保留字,必须为0:2字节
WORD bfReserved2; // 位图文件保留字,必须为0:2字节
DWORD bfOffBits; // 位图数据的起始位置,以相对于位图:4字节
} BITMAPFILEHEADER;


3. 位图信息头
BMP位图信息头数据用于说明位图的尺寸等信息。

程序代码 程序代码

typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本结构所占用字节数:4字节
LONG biWidth; // 位图的宽度,以像素为单位:4字节
LONG biHeight; // 位图的高度,以像素为单位:4字节
WORD biPlanes; // 目标设备的级别,必须为1:2字节
WORD biBitCount// 每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一:2字节
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一:4字节
DWORD biSizeImage; // 位图的大小,以字节为单位:4字节
LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数:4字节
LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数:4字节
DWORD biClrUsed; // 位图实际使用的颜色表中的颜色数:4字节
DWORD biClrImportant; // 位图显示过程中重要的颜色数:4字节
} BITMAPINFOHEADER;


4. 颜色表
颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:

程序代码 程序代码

typedef struct tagRGBQUAD {
BYTE rgbBlue;// 蓝色的亮度(值范围为0-255)
BYTE rgbGreen; // 绿色的亮度(值范围为0-255)
BYTE rgbRed; // 红色的亮度(值范围为0-255)
BYTE rgbReserved;// 保留,必须为0
} RGBQUAD;


注意这个顺序是B G R

颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
当biBitCount=1,4,8时,分别有2,16,256个表项;
当biBitCount=24时,没有颜色表项。

位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:

程序代码 程序代码

typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 位图信息头
RGBQUAD bmiColors[1]; // 颜色表
} BITMAPINFO;


5. 位图数据
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:

当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=24时,1个像素占3个字节;(这个也是BGR)

Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充,一个扫描行所占的字节数计算方法:

程序代码 程序代码

DataSizePerLine= (biWidth* biBitCount+31)/8; // 一个扫描行所占的字节数
DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数
DataSize= DataSizePerLine* biHeight; //位图数据的大小(不压缩情况下)
dyron 2008-04-30
  • 打赏
  • 举报
回复
读bmp文件, 很简单, 直接跳过头长, 就可以.
要注意文件的字节序问题!
laolaoliu2002 2008-04-30
  • 打赏
  • 举报
回复
http://topic.csdn.net/u/20080429/20/1bb09c06-d28f-4342-b5ff-42dace8fc9b6.html
Eleve 2008-04-30
  • 打赏
  • 举报
回复
大清早起来学习!~
l999358 2008-04-30
  • 打赏
  • 举报
回复
[Quote=引用楼主 fred8619 的帖子:]
请问如何读取BMP文件的像素数据啊?请问有代码吗?要完全用C写出来的。请问用方法用C来显示BMP文件吗?听说有vesa这个类,真的吗?
[/Quote]
你说什么呢? 又说C,又说类的。。。。。。
C里面哪有类的说法。
jmulxg 2008-04-30
  • 打赏
  • 举报
回复
mark
疯魔症 2008-04-29
  • 打赏
  • 举报
回复
一句话,认真看本图像处理的书就OK了
sailinghz 2008-04-29
  • 打赏
  • 举报
回复
忘了说明,这个代码是读不含调色板信息的BMP文件,也就是16位以上的BMP
sailinghz 2008-04-29
  • 打赏
  • 举报
回复
最近我正好在写读取与显示BMP文件的程序,基于VC6.0

#include <stdio.h>
#include <stdlib.h>

#pragma pack(2)

/*定义WORD为两个字节的类型*/
typedef unsigned short WORD;
/*定义DWORD为e四个字节的类型*/
typedef unsigned long DWORD;

/*位图文件头*/
typedef struct BMP_FILE_HEADER
{
WORD bType; /* 文件标识符 */
DWORD bSize; /* 文件的大小 */
WORD bReserved1; /* 保留值,必须设置为0 */
WORD bReserved2; /* 保留值,必须设置为0 */
DWORD bOffset; /* 文件头的最后到图像数据位开始的偏移量 */
} BMPFILEHEADER;

/*位图信息头*/
typedef struct BMP_INFO
{
DWORD bInfoSize; /* 信息头的大小 */
DWORD bWidth; /* 图像的宽度 */
DWORD bHeight; /* 图像的高度 */
WORD bPlanes; /* 图像的位面数 */
WORD bBitCount; /* 每个像素的位数 */
DWORD bCompression; /* 压缩类型 */
DWORD bmpImageSize; /* 图像的大小,以字节为单位 */
DWORD bXPelsPerMeter; /* 水平分辨率 */
DWORD bYPelsPerMeter; /* 垂直分辨率 */
DWORD bClrUsed; /* 使用的色彩数 */
DWORD bClrImportant; /* 重要的颜色数 */
} BMPINF;

/*彩色表*/
typedef struct RGB_QUAD
{
WORD rgbBlue; /* 蓝色强度 */
WORD rgbGreen; /* 绿色强度 */
WORD rgbRed; /* 红色强度 */
WORD rgbReversed; /* 保留值 */
} RGBQUAD;

int main()
{
FILE *fp;
BMPFILEHEADER fileHeader;
BMPINF infoHeader;
long offset, bmpImageSize, width, height, bytesPerPixel, size, bitCount;
// int i, j;
// unsigned char **p;
WORD c;

if((fp = fopen("5.bmp", "rb")) == NULL)
{
printf("Cann't open the file!\n");
exit(0);
}

fseek(fp, 0, 0);
fread(&fileHeader, sizeof(fileHeader), 1, fp);
fread(&infoHeader, sizeof(infoHeader), 1, fp);

//计算并输出位图数据的偏移量,图像的大小,宽度和高度,每个像素点所占的字节
size = fileHeader.bSize;
offset = fileHeader.bOffset;
bmpImageSize = infoHeader.bmpImageSize;
width = infoHeader.bWidth;
height = infoHeader.bHeight;
bitCount = infoHeader.bBitCount;
bytesPerPixel = infoHeader.bBitCount / 8;

printf("%d %d %d %d %d %d\n", size, offset, bmpImageSize, width, height, bitCount, bytesPerPixel);

//输出每个像素点所占字节中的内容
c = fgetc(fp);
while (!feof(fp))
{
printf("%x ", c);
c = fgetc(fp);
}

printf("\n");

fclose(fp);

return 0;
}
kakaying 2008-04-29
  • 打赏
  • 举报
回复
这是以前写的24位bmp图片读取像素数据的函数,当时只求达到很单一的目的,些的相对简单,给楼主参考一下

BITMAPFILEHEADER m_bmf;
BITMAPINFO m_bmi;

BYTE* m_lpData = NULL;
UINT m_ncbCount = 0;

UINT CBmpWatermark::LoadImage(LPCTSTR lpszFile)
{
FILE* fp = _tfopen(lpszFile, _T("r+b"));
if(!fp)
return 0;

fseek(fp, 0, SEEK_SET);
// 文件头
memset(&m_bmf, 0, sizeof(m_bmf));
fread(&m_bmf, sizeof(m_bmf), 1, fp);
// 位图信息头
memset(&m_bmi, 0, sizeof(m_bmi));
fread(&m_bmi, sizeof(m_bmi), 1, fp);
// 只有回退4BYTE,结果才是对的,估计是因为没有调色盘而多读取了4BYTE的缘故
fseek(fp, -4, SEEK_CUR);
if(m_bmi.bmiHeader.biCompression == BI_RGB)
m_bmi.bmiHeader.biSizeImage = m_bmi.bmiHeader.biWidth * m_bmi.bmiHeader.biHeight * 3;
// 位图数据
m_ncbCount = m_bmi.bmiHeader.biSizeImage;
delete [] m_lpData;
m_lpData = new BYTE[m_ncbCount];
if(!m_lpData)
return 0;
fread(m_lpData, 1, m_ncbCount, fp);
return m_ncbCount;
}

zhangjundriver 2008-04-29
  • 打赏
  • 举报
回复
在windows 程序设计(第5 版)中的与设备无关的位图,那章,讲解得很清楚!
kakaying 2008-04-29
  • 打赏
  • 举报
回复
查一下MSDN里面BITMAPINFO 和 BITMAPHEADER等结构,就基本了解bmp图片文件的格式了
打开图片文件直接read结构就可以了
获取像素数据可以根据调色板的有无情况相应处理,一般24位以上位图不包含调色板,图像素具直接就是RGB像素数据排列的。24位以下的图像数据保存的图像数值在调色板中的索引值,依次查询即可
blh 2008-04-29
  • 打赏
  • 举报
回复
try to search source codes in www.vckbase.com
jxfengzi 2008-04-29
  • 打赏
  • 举报
回复
读一个BMP文件,根据bmp文件的结构,然后读像素点,读一个点,就画一个点,读完整个bmp,就可以显示图片了。

建议先从24(或16位)位图开始玩,

然后玩带调色板的位图。
jxfengzi 2008-04-29
  • 打赏
  • 举报
回复
bmp位图格式:



#ifndef _BITMAP_H_
#define _BITMAP_H_

#define TRUE 1
#define FALSE 0

typedef char S8;
typedef short S16;
typedef int S32;
typedef long long S64;

typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned int U32;
typedef unsigned long long U64;
//typedef unsigned long LONG;

typedef int BOOL;
typedef U8 BYTE; /* 8 bit */
typedef U16 WORD; /* word: 16 bit */
//typedef U32 DWORD; /* dword: 32 bit */

/* 位图信息头:版本3 */
typedef struct _tagBITMAPINFOHEADER{
U32 biSize; /* 信息头长度:识别各种版本的唯一方法 */
U32 biWidth; /* 像素宽度 */
U32 biHeight; /* 像素高度,正:由下向上,负:由上至下 */
U16 biPlanes; /* 位平面,必须为1 */
U16 biBitCount; /* 每个像素的位数,如256色,8bit */
U32 biCompression; /* 压缩方法 */
U32 biSizeImage; /* 图像的像素阵列大小 */
U32 biXPelsPerMeter;
U32 biYPelsPerMeter;
U32 biClrUsed;
U32 biClrImportant;
} _BITMAPINFOHEADER, *_PBITMAPINFOHEADER;

/* 调色板格式:其它格式 */
typedef struct _tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} _RGBQUAD, *_PRGBQUAD;

/* 调色板格式:OS/2 */
typedef struct _tagRGBTRIPLE {
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} _RGBTRIPLE, *PRGBTRIPLE;

/* GDI定义了将信息头和颜色表组合在一起的数据结构 */
typedef struct _tagBITMAPINFO {
_BITMAPINFOHEADER bmiHeader;
_RGBQUAD bmiColors[1];
} _BITMAPINFO, *_PBITMAPINFO;

#endif /* _BITMAP_H_ */
独孤过儿 2008-04-29
  • 打赏
  • 举报
回复
先去搜索下BMP图像的存储格式,然后再考虑怎么读...

70,016

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧