Bitmap文件格式通常包含 54(不固定)个字节的文件头 + 数据部分
数据部分存储方式采用 从左到右,从下到上,如下图所示:
即图像的存储方式与显示方式是镜面对称的(上下翻转)
下面的程序只能读取 24(RGB)位真彩色图像
#include <stdio.h>
#pragma comment(lib, "ImageShow.lib")
extern "C" __declspec(dllimport) void ShowImage(unsigned char *data, int rows, int cols);
int rows;
int cols;
unsigned char *buffer = NULL;
void ReadHeader(FILE *fp)
{
unsigned char bytes[4]; //一次读 4 个字节
fseek(fp, 18, SEEK_SET); // 跳过前18个字节,读取Width, Height
//read Width
fread(bytes, 1, 4, fp);
cols = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24);
//read Height
fread(bytes, 1, 4, fp);
rows = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24);
}
//写入一行数组到 图像缓冲区中
void WriteRow(unsigned char *rowBuffer, int idx)
{
int offset = idx * cols * 3; //第 idx 行, 每列3个像素
for (int i = 0; i < cols * 3; i++)
{
buffer[offset + i] = rowBuffer[i];
}
}
unsigned char *OpenImage(const char *fileName)
{
FILE *fp = fopen(fileName, "rb+"); //二进制方式读取
ReadHeader(fp); //读取图片的 Width, Height
buffer = new unsigned char[rows * cols * 3]; // 24位真彩色,3个字节
/* 从文件头开始,偏移54个字节(文件头信息长度) */
fseek(fp, 54, SEEK_SET);
int offset = (cols * 24 + 31) / 32 * 4; // 计算每行存储字节数
unsigned char *rowBuffer = new unsigned char[offset]; //行缓冲区
for (int i = 0; i < rows; i++)
{
fread(rowBuffer, 1, offset, fp); //读取一行
WriteRow(rowBuffer, rows - 1 - i); //写入到缓冲区
}
delete []rowBuffer; //释放行缓冲区
fclose(fp); //关闭文件
return buffer;
}
void CloseImage()
{
delete[] buffer; // 删除文件缓冲区
}
int main(int argc, char *argv[])
{
unsigned char *img = OpenImage(argv[1]); //打开图像文件
ShowImage(img, rows, cols); //显示图像
CloseImage(); //关闭图像
return 0;
}
ImageShow 调用OpenCV -> imshow()方法显示图像:
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
extern "C" __declspec(dllexport) void ShowImage(unsigned char *data, int rows, int cols);
/* @brief Returns a Matrix
*/
static Mat ConvertToMat(unsigned char *data, int rows, int cols)
{
Mat img(rows, cols, CV_8UC3); // create a new matrix
for (int i = 0; i < rows * cols * 3; i++)
{
img.data[i] = data[i];
}
return img;
}
void ShowImage(unsigned char *data, int rows, int cols)
{
Mat img = ConvertToMat(data, rows, cols);
imshow("Bitmap", img);
waitKey();
}
运行示例: