C++ bmp位图读取

来源:互联网 发布:知几学生密码是什么 编辑:程序博客网 时间:2024/06/07 16:37

如何用C++读取  bmp图片格式颜色矩阵 以及显示

首先   简单解释一下bmp文件格式                在 http://paulbourke.net/dataformats/bmp/  有官方详细解释

                                                                       


bmp 格式文件  分为四个部分    

header                   文件格式,大小

infoheader            图像的高,宽,位数

optional palette    可选调色板:使用索引来表示图像是的 索引与颜色的映射 并非一定包含

image data            图像像素信息的数据


其中24位bmp文件不使用索引 所以不需要optional palette 部分

header C结构体typedef struct {   unsigned short int type;                 /* Magic identifier   文件格式*/   unsigned int size;                       /* File size in bytes 文件大小*/   unsigned short int reserved1, reserved2; /* 保留区 默认设置为0          */   unsigned int offset;                     /* Offset to image data, bytes文件头到图像数据信息便宜字节 */} HEADER;infoheader 结构体typedef struct {   unsigned int size;               /* Header size in bytes   infoheader文件部分size大小   */   int width,height;                /* Width and height of image  图像宽,高   */   unsigned short int planes;       /* Number of colour planes    位面数 总为1 */   unsigned short int bits;         /* Bits per pixel             像素位深     */   unsigned int compression;        /* Compression type       压缩类型     */   unsigned int imagesize;          /* Image size in bytes    图像大小(字节)    */   int xresolution,yresolution;     /* Pixels per meter       分辨率(水平,垂直) */   unsigned int ncolours;           /* Number of colours      实际所用颜色索引数目   */   unsigned int importantcolours;   /* Important colours      对图像显示有重要影响的颜色索引数   */} INFOHEADER;



读取方法

windows 默认最小扫描字节为4字节

bmp图像 记录每行像素 单位是字节,bmp图像每行像素最后位要进行补齐 与4字节对齐 根据补齐规则 算出用于补充的字符长度为

int nBytesPerRow = infoHeader.width * 3;                      //每行的的字节数 int nPaddingByresPerRow = 4 - (nBytesPerRow % 4);             //用于补齐的字节数,也就是读取时需要跳过的字节数
#include"bitmap.h"#include<stdio.h>#include<assert.h>void LoadBmp(D3DCOLOR *surface)                   //d3d9.h头文件支持 surface为像存取像素地址 {FILE  *bmpFile = fopen("C://Users//inkycherry//Desktop//C++forbmp//bmpSource//4.bmp", "rb");  //以二进制形式读入char signature[2];fread(&signature, sizeof(char), 2, bmpFile);   //读取前两位 表示type字节BitmapFileHeader fileHeader;fread(&fileHeader, sizeof(fileHeader), 1, bmpFile);   //读取header部分BitmapInfoHeader infoHeader;fread(&infoHeader, sizeof(infoHeader), 1, bmpFile);   //读取infoheader部分fseek(bmpFile, fileHeader.offset, SEEK_SET);int nPixels = infoHeader.width*infoHeader.height;        //图像的像素数int nBytesPerRow = infoHeader.width * 3;            int nPaddingByresPerRow = 4 - (nBytesPerRow % 4);     for (int y = infoHeader.height-1; y >=0; y--)       //bmp文件是自底向上存储像素信息{for (int x = 0; x < infoHeader.width; x++){Piexl24 pixel;                         //Piexl24为 3个unsigned char变量的结构体fread(&pixel, sizeof(pixel), 1, bmpFile);//surface[x+y*infoHeader.width] = D3DCOLOR_XRGB(pixel.red, pixel.green, pixel.blue);surface[x+y*infoHeader.width] = D3DCOLOR_XRGB(pixel.red, pixel.green, pixel.blue);}fseek(bmpFile, nPaddingByresPerRow, SEEK_CUR);  }fclose(bmpFile);


这样完成了读取工作,像素矩阵存到surface数组中

然后用directx打印,两个函数如下(因为directx还是菜鸟,现在还是用别人写的框架)

当然也可以存个一般的结构体数组 ,包含三个uint就可以了,通过其他输出像素的方式打印也可

void D3DGraphics::DrawSurface(int xoff, int yoff, int width, int height, const D3DCOLOR *xsurf){for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){PutPixel(x + xoff, y + yoff, xsurf[x + y*width]);}}}void PutPixel(int x, int y, D3DCOLOR c)     {IDirect3DSurface9* pBackBuffer = NULL;D3DLOCKED_RECT rect;D3DGraphics::pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);pBackBuffer->LockRect(&rect, NULL, NULL);((D3DCOLOR*)rect.pBits)[x + (rect.Pitch >> 2) * y] = c;pBackBuffer->UnlockRect();pBackBuffer->Release();}DrawSurface(x,y,inforheader.width,infoheader.height,surface);


还有待完善,下次打印一下矩阵然后注释一下

这个效果图,你能看出打印的什么吗:)

————————————————————————————————————

上边的例子是24位的  基本也是用的最多的 

struct Piexl24
{
unsigned char blue;
unsigned char green;
unsigned char red;

};

读取32位的方法 比24位简单一些 他的结构体多了一个 alpha 的8位变量

struct Piexl32
{
unsigned char blue;
unsigned char green;
unsigned char red;
unsigned char alpha;
};

并且 32位的读取 肯定是4的倍数  不需要填充字符 文件读取不需要位移

读取只需要修改 填充部分 和 结构体类型即可


#include"bitmap.h"#include<stdio.h>#include<assert.h>#include<math.h>void LoadBmp(D3DCOLOR *surface)  //d3d9.h头文件支持;{FILE  *bmpFile = fopen("C://Users//inkycherry//Desktop//directxpratice//C++fortank//bmpSource//4.bmp", "rb");char signature[2];fread(&signature, sizeof(char), 2, bmpFile);BitmapFileHeader fileHeader;fread(&fileHeader, sizeof(fileHeader), 1, bmpFile);BitmapInfoHeader infoHeader;fread(&infoHeader, sizeof(infoHeader), 1, bmpFile);fseek(bmpFile, fileHeader.offset, SEEK_SET);infoHeader.width = abs(infoHeader.width);infoHeader.height = abs(infoHeader.height);int nPixels = infoHeader.width*infoHeader.height;  //图像的像素数/*int nBytesPerRow = infoHeader.width * 3;          int nPaddingByresPerRow = 4 - (nBytesPerRow % 4);*/for (int y = infoHeader.height-1; y >=0; y--){for (int x = 0; x < infoHeader.width; x++){Piexl32 pixel;fread(&pixel, sizeof(pixel), 1, bmpFile);//surface[x+y*infoHeader.width] = D3DCOLOR_XRGB(pixel.red, pixel.green, pixel.blue);surface[x+y*infoHeader.width] = D3DCOLOR_ARGB(pixel.alpha,pixel.red, pixel.green, pixel.blue);}/*fseek(bmpFile, nPaddingByresPerRow, SEEK_CUR);*/}fclose(bmpFile);}

另外还发现一个问题,刚测试的时候 都不到东西 调试发现height为负值 绝对值正确

查询得到 bmp 图像 width height 值正数为像素数组与图像逆向 负数则为正向  

根据需要自己调一下循环就好了


原创粉丝点击