如何使用QT显示bmp图片(24位)

1、了解bmp图片

2、此网站可以查看bmp图片的二进制信息

3、QT建立工程(MainWindow)和(Widget)都可以

1、了解bmp图片格式后,首先我们需要建立两个结构体BITMAPFILEHEADER BITMAPINFOHEADER  存储该bmp图片的信息(宽、高等)

2、用类将bmp的操作进行封装:bmpGet.h 代码如下:

#ifndef BMPGET_H
#define BMPGET_H

#include <QFile>
#include <qDebug>
#include <QRgb>
#include <QImage>
typedef char         CHAR;
typedef short        SHORT;
typedef int          BOOL;//4
typedef float        FLOAT;
typedef uint         LONG;//4
typedef quint8       BYTE;//1
typedef quint16      WORD;//2
typedef quint32      DWORD;//4

typedef struct tagBITMAPINFOHEADER {
    DWORD      biSize;
    LONG       biWidth;                //图像宽
    LONG       biHeight;               //图像高
    WORD       biPlanes;
    WORD       biBitCount;             //每个像素有多少位
    DWORD      biCompression;
    DWORD      biSizeImage;
    LONG       biXPelsPerMeter;
    LONG       biYPelsPerMeter;
    DWORD      biClrUsed;
    DWORD      biClrImportant;
} BITMAPINFOHEADER;                     //40字节

typedef struct tagBITMAPFILEHEADER {
    WORD    bfType;                     //文件类型:表示bmp的固定值
    DWORD   bfSize;                     //文件大小
    WORD    bfReserved1;                //保留字:0
    WORD    bfReserved2;                //保留字:0
    DWORD   bfOffBits;                  //从文件头到位图数据的偏移量
} BITMAPFILEHEADER;                     //14个字节

//封装
class bmpGet
{
public:
    BITMAPFILEHEADER headBmp;                           //位图头信息
    BITMAPINFOHEADER tailBmp;                           //位图中间信息
    QString          bmpPath;                           //文件路径
    char            *img_R    = NULL;                   //new char[1024 * 1024];
    char            *img_G    = NULL;                   //new char[1024 * 1024];
    char            *img_B    = NULL;                   //new char[1024 * 1024];
    char            *img_data = NULL;
    int              bmpWidth;
    int              bmpHeight;
    int              lineByte;

    QImage           img;
public:
    bool readRgb();                         //读数据
    bool separateRGB();                     //分离RGB
    void printImageBmp(int offX, int offY); //保存IMG

    bmpGet(QString bmpPath);
    ~bmpGet();
};
//--------------------->x
//|
//|
//|
//|
//|
//|
//↓
//y

#endif // BMPGET_H

相应的.cpp文件:在readRgb()这个方法里面尤其要注意设置小端排序

#include "bmpget.h"

bmpGet::bmpGet(QString bmpPath):bmpPath(bmpPath)
    {

    img_R    = new char[1024 * 1024];
    img_G    = new char[1024 * 1024];
    img_B    = new char[1024 * 1024];
    img_data = new char[1024 * 1024 * 3];
    };

bool bmpGet::readRgb()
{
    QFile bmpFile(this->bmpPath);
    if(!bmpFile.open(QIODevice::ReadOnly))
        qDebug()<<"error";                      //debug
    QDataStream in(&bmpFile);                   //read barry stream;建立二进制的流文件对象,从流里面读取二进制数据。如果需要,seek函数可以改变流的起始位置。
    in.setByteOrder(QDataStream::LittleEndian); //小端排序:这一步非常重要

    in>>this->headBmp.bfType;
    in>>this->headBmp.bfSize;
    in>>this->headBmp.bfReserved1;
    in>>this->headBmp.bfReserved2;
    in>>this->headBmp.bfOffBits;

    in>>this->tailBmp.biSize;
    in>>this->tailBmp.biWidth;
    in>>this->tailBmp.biHeight;
    in>>this->tailBmp.biPlanes;
    in>>this->tailBmp.biBitCount;
    in>>this->tailBmp.biCompression;
    in>>this->tailBmp.biSizeImage;
    in>>this->tailBmp.biXPelsPerMeter;
    in>>this->tailBmp.biYPelsPerMeter;
    in>>this->tailBmp.biClrUsed;
    in>>this->tailBmp.biClrImportant;
    this->lineByte    = (this->tailBmp.biWidth * this->tailBmp.biBitCount / 8 + 3) / 4 * 4; //4字节补齐,不补齐会出现图像偏差的问题
    char *tempByteData=new char[this->lineByte * this->tailBmp.biHeight];

    if ((unsigned int)in.readRawData(tempByteData,(this->lineByte * this->tailBmp.biHeight))<(unsigned int)this->lineByte * this->tailBmp.biHeight)
    {
        qDebug() << "get bmp err";
    }
    memcpy(this->img_data,tempByteData,this->lineByte * this->tailBmp.biHeight);            //not strycpy

    this->bmpHeight  =this->tailBmp.biHeight;
    this->bmpWidth   =this->tailBmp.biWidth;

    delete [] tempByteData;//不要忘记释放内存
    bmpFile.close();
    return true;
}


bool bmpGet::separateRGB()
{
    char *temp=this->img_data;
    int t=0;
    for (int i = 0; i < this->bmpHeight; i++) {
        for (int k = 0; k < this->bmpWidth; k++)
        {
            this->img_R[t] = temp[3 * k + 0];
            this->img_G[t] = temp[3 * k + 1];
            this->img_B[t] = temp[3 * k + 2];
            t++;
        }
        temp += lineByte;//跳过lineByte个地址而不是this->bmpWidth个地址:这可以查查bmp图片的位图数据的格式对齐:要不然输出的图像是倾斜的。
    }
    return true;
}


void  bmpGet::printImageBmp(int offX, int offY)
{
    this->readRgb();
    this->separateRGB();
    unsigned char R, G, B = 0;
    QImage img(this->bmpWidth+offX,this->bmpHeight+offY,QImage::Format_RGB32);

    for (int i = 0 ; i < this->bmpHeight; i++)
        for (int k = 0; k < this->bmpWidth; k++)
        {
            R = (unsigned char)this->img_R[i * this->bmpWidth + k];
            G = (unsigned char)this->img_G[i * this->bmpWidth + k];
            B = (unsigned char)this->img_B[i * this->bmpWidth + k];
            img.setPixel(k + offX, this->bmpHeight - i - 1+offY, qRgb(B,G,R));//为什么是this->bmpHeight - i - 1+offY,因为bmp位图像素数据是图片从下往上,从左往右一一排序的。同时要注意img的坐标,分别是向右和向左为xy轴。
        }
    this->img=img;
}


bmpGet::~bmpGet()//在构造函数里面new 就需要在析构函数里面delete
{
    delete [] img_R;
    delete [] img_G;
    delete [] img_B;
    delete [] img_data;
}











3、界面文件调用封装的类:widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
//#include <QWheelEvent>通过鼠标缩放用的头文件(建立鼠标滚轮角度事件)
#include <QFile>
#include <qDebug>
#include "bmpget.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);

    void showBmp(int offX, int offY);

    ~Widget();

private:
    QImage     img;
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "bmpget.h"
#include <QMessageBox>
#include <fstream>
#include<iostream>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    showBmp(0,0);
}

void  Widget::showBmp(int offX, int offY)
{
    bmpGet bmp("C:\\Users\\32652\\Pictures\\2.bmp");//这里改成自己放bmp图片的位置。
    bmp.printImageBmp(offX,offY);
    ui->label->setPixmap(QPixmap::fromImage(bmp.img));
}

Widget::~Widget()
{
    delete ui;
}







4、要记得在ui里面托一个组件:QLabel

4、总的工程结构

运行效果:

最后!不懂的可以私信我。同时,后续我会优化UI界面和添加各种图片缩放算法的示例。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值