QT QPixmap QImage内存泄漏

发布时间 2023-09-29 17:16:55作者: 吾非无心

无论是在代码中还是在UI中设置icon都会产生内存泄漏

大概看了下,好像是QPixmap的data_ptr的引用计数,到不了1/0(查看引用计数,释放后,理论上应回到1)

试了下,仅以下两种方式不会产生内存泄漏:

1、从 XPM加载:

img = QPixmap(result);   //result为   static const char *result[] = {。。。。}

ui.label->setPixmap(QPixmap(result));

2、现场绘制:

img = QPixmap(16, 16);
img.fill(Qt::transparent);
QPainter painter(&img);
painter.drawLine(1, 1, 15, 15);

。。。
painter.end();
ui.label->setPixmap(img);

 

但是,使用XPM,图片的质量太差

png 

xpm

所以决定自己绘制。

步骤一、使用代码生成自定义图片的数据文件:

w(ushort)h(ushort)bytesperpixel(uchar)+若干RGBA数据

例:

16(ushort)16(ushort)4(uchar)+{uint32(RGBA)*16*16}

步骤二、加载、显示

CLeeBuffer.h   自定义图片数据的存取类

#include <QByteArray>
class CLeeBuffer
{
public:
	CLeeBuffer() {}
	~CLeeBuffer() {}
	CLeeBuffer& Store(char val) {
		m_data.append(1, val);
		return *this;
	}
	CLeeBuffer& Store(uchar val) {
		m_data.append(1, (char)val);
		return *this;
	}
	CLeeBuffer& Store(ushort val) {
		m_data.append((const char*)&val, 2);
		return *this;
	}
	CLeeBuffer& Store(short val) {
		m_data.append((const char*)&val, 2);
		return *this;
	}
	CLeeBuffer& Store(uint val) {
		m_data.append((const char*)&val, 4);
		return *this;
	}
	CLeeBuffer& Store(int val) {
		m_data.append((const char*)&val, 4);
		return *this;
	}
	CLeeBuffer& Store(void* pBuf, int len) {
		m_data.append((const char*)pBuf, len);
		return *this;
	}

	CLeeBuffer& Store(QByteArray val) {
		m_data.append(val);
		return *this;
	}


	bool Read(int& nPos, char& val) {
		if (nPos + sizeof(val) > m_data.size())
			return false;
		auto pBuf = m_data.constData();
		memcpy(&val, pBuf + nPos, sizeof(val));
		nPos += sizeof(val);
		return true;
	}
	bool Read(int& nPos, uchar& val) {
		if (nPos + sizeof(val) > m_data.size())
			return false;
		auto pBuf = m_data.constData();
		memcpy(&val, pBuf + nPos, sizeof(val));
		nPos += sizeof(val);
		return true;
	}
	bool Read(int& nPos, ushort& val) {
		if (nPos + sizeof(val) > m_data.size())
			return false;
		auto pBuf = m_data.constData();
		memcpy(&val, pBuf + nPos, sizeof(val));
		nPos += sizeof(val);
		return true;
	}
	bool Read(int& nPos, short& val) {
		if (nPos + sizeof(val) > m_data.size())
			return false;
		auto pBuf = m_data.constData();
		memcpy(&val, pBuf + nPos, sizeof(val));
		nPos += sizeof(val);
		return true;
	}
	bool Read(int& nPos, uint& val) {
		if (nPos + sizeof(val) > m_data.size())
			return false;
		auto pBuf = m_data.constData();
		memcpy(&val, pBuf + nPos, sizeof(val));
		nPos += sizeof(val);
		return true;
	}
	bool Read(int& nPos, int& val) {
		if (nPos + sizeof(val) > m_data.size())
			return false;
		auto pBuf = m_data.constData();
		memcpy(&val, pBuf + nPos, sizeof(val));
		nPos += sizeof(val);
		return true;
	}
	bool Read(int& nPos, void* pBuf, int len) {
		if (nPos + len > m_data.size())
			return false;
		auto pBuf_ = m_data.constData();
		memcpy(pBuf, pBuf_ + nPos, len);
		nPos += len;
		return true;
	}
	QByteArray getData() {
		return m_data;
	}
private:
	QByteArray m_data;
};

  

QLeePixmap.h

#include "CLeeBuffer.h"
#include <QPixmap>
#include <QFile>
#include <QString>
#include <QPainter>
#include <QPen>
class QLeePixmap
{
public:
	QLeePixmap() {}
	QLeePixmap(QString sFile) {
		load(sFile);
		
	}
	void	load(QString sFile) {
		union {
			int IntVal;
			struct {
				uchar b, g, r, a;
			}Color;
		}Color32;
		QFile mFile(sFile);
		if (mFile.open(QIODevice::ReadOnly)) {
			CLeeBuffer leeBuf;
			leeBuf.Store(mFile.readAll());
			mFile.close();



			ushort w = 0, h = 0;
			uchar bytesPerPixel = 0;
			int nPos = 0;
			leeBuf.Read(nPos, w);
			leeBuf.Read(nPos, h);
			leeBuf.Read(nPos, bytesPerPixel);

			m_pixmap = QPixmap(w, h);


			m_pixmap.fill(Qt::transparent);
			QPainter painter(&m_pixmap);
			QPen pen;


			for (ushort row = 0; row < h; row++) {
				for (ushort col = 0; col < w; col++) {
					if (!leeBuf.Read(nPos, Color32.IntVal)) {

					}
					pen.setColor(QColor(Color32.Color.r, Color32.Color.g, Color32.Color.b, Color32.Color.a));
					painter.setPen(pen);
					painter.drawPoint(col, row);
				}
			}

			painter.end();
		}
	}
	QPixmap&	getPixmap() {
		return m_pixmap;
	}
private:
	QPixmap		m_pixmap;
};

  

使用:

QLeePixmap m_img;//.h
//.cpp
m_img.load(QString::fromLocal8Bit("。。。。\\img_connected.sim")); ui.label->setPixmap(m_img.getPixmap());