以前做嵌入式开发时,在裸奔的单片机、arm7或stm32上,显示图片时方式往是将一张图片通过ImagetoLcd等软件,转换成数据烧录在flash中,显示时调出数据,刷到屏上。但对于后来移植了文件系统,这种做法在维护更换图片时就不直观了,今天主要讲讲在有文件系统后,如何调出bmp图片解析显示液晶屏上。
由于手头上没有硬件,就用vs或qt的控件作为一个显示单元,方法:不直接调用系统的接口函数显示图片,而且解析bmp文件格式及图像数据,通过描点的方法显示出来。(mfc和qt下本人都作过试验,本例以qt讲解,用QFrame作为液晶屏显示单元)
一、bmp文件格式:这一部分内容可以去百度
bmpformat.h
#ifndef BMPFORMAT_H
#define BMPFORMAT_H
#include
typedef quint16 UINT16;
typedef quint32 DWORD;
typedef quint32 LONG;
typedef quint16 WORD;
typedef quint8 BYTE;
#pragma pack(push,1)
typedef struct tagBITMAPFILEHEADER
{
UINT16 bfType;
DWORD bfSize;
UINT16 bfReserved1;
UINT16 bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
typedef struct _tagBMP_INFOHEADER
{
DWORD biSize; //4Bytes,INFOHEADER结构体大小,存在其他版本I NFOHEADER,用作区分
LONG biWidth; //4Bytes,图像宽度(以像素为单位)
LONG biHeight; //4Bytes,图像高度,+:图像存储顺序为Bottom2Top,-:Top2Bottom
WORD biPlanes; //2Bytes,图像数据平面,BMP存储RGB数据,因此总为1
WORD biBitCount; //2Bytes,图像像素位数
DWORD biCompression; //4Bytes,0:不压缩,1:RLE8,2:RLE4
DWORD biSizeImage; //4Bytes,4字节对齐的图像数据大小
LONG biXPelsPerMeter; //4 Bytes,用象素/米表示的水平分辨率
LONG biYPelsPerMeter; //4 Bytes,用象素/米表示的垂直分辨率
DWORD biClrUsed; //4 Bytes,实际使用的调色板索引数,0:使用所有的调色板索引
DWORD biClrImportant; //4 Bytes,重要的调色板索引数,0:所有的调色板索引都重要
}BMP_INFOHEADER;
typedef struct _tagRGBQUAD
{
BYTE rgbBlue; //指定蓝色强度
BYTE rgbGreen; //指定绿色强度
BYTE rgbRed; //指定红色强度
BYTE rgbReserved; //保留,设置为0
} RGBQUAD;
#pragma pack(pop)
#endif // BMPFORMAT_H
二、解析并绘制
void Widget::drawBmp(void)
{
char data[1024];
char palette[256][4];
int w,h;
int i,j;
uint8_t r,g,b;
uint8_t index;
BITMAPFILEHEADER *pBITMAPFILEHEADER;
BMP_INFOHEADER *pBMP_INFOHEADER;
if(drawFlag)
{
bmpFile.setFileName(bmpFileName);
bmpFile.open(QIODevice::ReadOnly);
//test
// bmpFile.read(data,512);
// for(int i=0;i<512;i++)
// qDebug("%.2x ",data[i]);
bmpFile.read(data,sizeof(BITMAPFILEHEADER)+sizeof(BMP_INFOHEADER));
pBITMAPFILEHEADER=(BITMAPFILEHEADER*)data;
pBMP_INFOHEADER=(BMP_INFOHEADER*)(data+sizeof(BITMAPFILEHEADER));
qDebug("offset = %d",pBITMAPFILEHEADER->bfOffBits);
qDebug("biSize = %d",pBMP_INFOHEADER->biSize);
qDebug("biWidth = %d biHeight = %d",pBMP_INFOHEADER->biWidth,pBMP_INFOHEADER->biHeight);
qDebug("biPlanes = %d",pBMP_INFOHEADER->biPlanes);
qDebug("biBitCount = %d",pBMP_INFOHEADER->biBitCount);
qDebug("biCompression = %d",pBMP_INFOHEADER->biCompression);
qDebug("biSizeImage = %d",pBMP_INFOHEADER->biSizeImage);
qDebug("biClrUsed = %d",pBMP_INFOHEADER->biClrUsed);
qDebug("biClrImportant = %d",pBMP_INFOHEADER->biClrImportant);
w=pBMP_INFOHEADER->biWidth;
h=pBMP_INFOHEADER->biHeight;
this->resize(w+33,h+52);
ui->bmpFrame->resize(w,h);
ui->loadBmpButton->move(10,h+20);
ui->closeButton->move(100,h+20);
QPainter painter(ui->bmpFrame);
// painter.setPen(Qt::gray);
// painter.setBrush(Qt::green);
// painter.drawRect(10,10,200,200);
// painter.setPen(Qt::red);
// painter.drawLine(0,1,600,1);
// painter.setPen(QColor(0,255,255));
// for(int i=0;i<800;i++)
// painter.drawPoint(300,i);
// 画图
// for(i=0; i < h; i++)
// {
// for(j=0;jbfOffBits);
for(i=h; i >0; --i)
{
bmpFile.read(data,w);
for(j=0;j
从bmp文件开始读出信息头 bmpFile.read(data,sizeof(BITMAPFILEHEADER)+sizeof(BMP_INFOHEADER)); pBITMAPFILEHEADER=(BITMAPFILEHEADER*)data; pBMP_INFOHEADER=(BMP_INFOHEADER*)(data+sizeof(BITMAPFILEHEADER)); 打印信息,验证解析是否和文件属性是否一致。 qDebug("offset = %d",pBITMAPFILEHEADER->bfOffBits); qDebug("biSize = %d",pBMP_INFOHEADER->biSize); qDebug("biWidth = %d biHeight = %d",pBMP_INFOHEADER->biWidth,pBMP_INFOHEADER->biHeight); qDebug("biPlanes = %d",pBMP_INFOHEADER->biPlanes); qDebug("biBitCount = %d",pBMP_INFOHEADER->biBitCount); qDebug("biCompression = %d",pBMP_INFOHEADER->biCompression); qDebug("biSizeImage = %d",pBMP_INFOHEADER->biSizeImage); qDebug("biClrUsed = %d",pBMP_INFOHEADER->biClrUsed); qDebug("biClrImportant = %d",pBMP_INFOHEADER->biClrImportant);
初始化显示区域宽和高
w=pBMP_INFOHEADER->biWidth; h=pBMP_INFOHEADER->biHeight; this->resize(w+33,h+52); ui->bmpFrame->resize(w,h); ui->loadBmpButton->move(10,h+20); ui->closeButton->move(100,h+20);
QPainter painter(ui->bmpFrame); 注释部分为测试画图区 区域确定。调i,j的描点方向 // painter.setPen(Qt::gray); // painter.setBrush(Qt::green); // painter.drawRect(10,10,200,200); // painter.setPen(Qt::red); // painter.drawLine(0,1,600,1); // painter.setPen(QColor(0,255,255)); // for(int i=0;i<800;i++) // painter.drawPoint(300,i); // 画图 // for(i=0; i < h; i++) // { // for(j=0;j开始读数据 画图, 如果是16、24、32位真色图片,没有调色板区,直接拿图像数据根据像素位深绘图就行了,
bmpFile.seek(pBITMAPFILEHEADER->bfOffBits); for(i=h; i >0; --i){ bmpFile.read(data,w);//读一行像素数据。 for(j=0;j