函数原型:
bool loadFromData(const uchar * data, uint len, const char * format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor)
bool loadFromData(const QByteArray & data, const char * format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor)
这两个函数是根据内存中的图像数据进行导入的,而图像的数据可以是从本地磁盘上读入的文件。比如读入一张BMP格式的文件到QByteArray对象中,再调用该函数,那么该函数就会根据QByteArray中数据进行解析,分析图像的格式等。BMP文件数据包含:BITMAPFILEHEADER + BITMAPINFOHEADER + [调色板] + 图像数据。因此只要QByteArray对象中包含了这些图形所必须的信息,那么该函数就会导入成功。另外,我们有时也可以不用从磁盘上导入数据,直接在程序中按照指定的图像格式来构造图像数据,并填入QByteArray中,那么用该函数同样可以导入成功!
以下是将截屏数据填入QPixmap对象中:
void MainWindow::on_pushButton_clicked()
{
char * pData = new char[10 * 1024 * 1024];
HWND hWnd = GetDesktopWindow();
HDC hDc, hDcMem;
HBITMAP hBitmap, hOldBitmap;
hDc = GetDC(hWnd);
hDcMem = CreateCompatibleDC(hDc);
RECT rectClient;
GetClientRect(hWnd, &rectClient);
hBitmap = CreateCompatibleBitmap(hDc, rectClient.right - rectClient.left, (rectClient.bottom - rectClient.top));
hOldBitmap = (HBITMAP)SelectObject(hDcMem, hBitmap);
BITMAP bitmap;
GetObject(hBitmap, sizeof(BITMAP), &bitmap);
BITMAPINFOHEADER bitmapInfoHeader;
memset(&bitmapInfoHeader, 0, sizeof(bitmapInfoHeader));
bitmapInfoHeader.biBitCount = bitmap.bmBitsPixel;
bitmapInfoHeader.biWidth = bitmap.bmWidth;
bitmapInfoHeader.biHeight = -bitmap.bmHeight;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biSizeImage = bitmap.bmWidthBytes * bitmap.bmHeight;
bitmapInfoHeader.biCompression = BI_RGB;
BitBlt(hDcMem, 0, 0, rectClient.right - rectClient.left, rectClient.bottom - rectClient.top, hDc, 0, 0, SRCCOPY);
int lines;
lines = GetDIBits(hDcMem, hBitmap, 0, bitmap.bmHeight, pData + sizeof(BITMAP), (LPBITMAPINFO)&bitmapInfoHeader, DIB_RGB_COLORS); //写入图像信息
BITMAPFILEHEADER bitmapFileHeader;
bitmapFileHeader.bfReserved1 = 0;
bitmapFileHeader.bfReserved2 = 0;
bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bitmapInfoHeader.biSizeImage;
bitmapFileHeader.bfType = 0x4d42;
bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
QByteArray byteArray;
byteArray.append((char*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER)); //文件信息头
byteArray.append((char*)&bitmapInfoHeader,sizeof(BITMAPINFOHEADER)); //位图信息头
byteArray.append(pData,bitmapInfoHeader.biSizeImage); //位图信息数据
qDebug()<<byteArray.size();
bool bRet = false;
QPixmap pixmap;
//bRet = pixmap.loadFromData(byteArray); //导入方式1
bRet = pixmap.loadFromData((const uchar*)byteArray.data(),byteArray.size()); //导入方式2
qDebug()<<"LoadFromData:"<<bRet;
m_pixmap = pixmap;
SelectObject(hDcMem, hOldBitmap);
DeleteObject(hDcMem);
ReleaseDC(hWnd, hDc);
DeleteObject(hBitmap);
delete[] pData;
update();
}
void MainWindow::paintEvent(QPaintEvent *)
{
static int i = 0;
qDebug()<<"begin draw"<<i++;
if(!m_pixmap.isNull())
{
QPainter painter(this);
painter.drawPixmap(0,0,m_pixmap);;
qDebug()<<"end draw";
}
}
这样就可以写入将屏幕数据显示在窗口上了,注意,这里只是通过原始数据来导入,并不是为了截屏。如果要想截屏方便,那么可以直接用Qt的截屏函数grabWindow来,而不用Win32的函数!
最后说明一下ARGB数据的具体格式,即是如何排列的,如果颜色用32位表示,那么格式如下:
在本人的电脑上测试,通过截屏获得屏幕数据,biBitCount为32,其ARGB的排列规则见下图:
也可以从DirectX宏函数分析得到:
#define D3DCOLOR_ARGB(a,r,g,b) \
((D3DCOLOR)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))