基于Qt仿QQ效果实现图片查看器

主要提供两个类,第一个类显示静态图片,第二个类显示动态图片
两个类都包含图片缩小放大以及图片移动功能。

最后自己封装一个类,根据判断图片是动态还是静态去调用对应的类显示图片

效果展示:

判断图片类型

int showImage::getImageFormat(const QString & fileName)
{
	//BMP格式特征码
	unsigned char BMP_Format[] = { 0x42, 0x4d };
	//JPG,JPEG格式特征码
	unsigned char JPG_Format1[] = { 0xff, 0xd8, 0xff, 0xdb };
	unsigned char JPG_Format2[] = { 0xff, 0xd8, 0xff, 0xe0 };
	unsigned char JPG_Format3[] = { 0xff, 0xd8, 0xff, 0xe1 };
	unsigned char JPG_Format4[] = { 0xff, 0xd8, 0xff, 0xe2 };
	unsigned char JPG_Format5[] = { 0xff, 0xd8, 0xff, 0xe3 };
	unsigned char JPG_Format6[] = { 0xff, 0xd8, 0xff, 0xe8 };
	//GIF格式特征码
	unsigned char GIF_Format1[] = { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 };
	unsigned char GIF_Format2[] = { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 };
	//PNG格式特征码
	unsigned char PNG_Format[] = { 0x89, 0x50, 0x4E, 0x47 };

	int count = 0;
	int step = 2;
	//以二进制方式打开文件并读取前几个字节
	unsigned char header[16];
	std::ifstream readf(fileName.toStdString().c_str(), std::ios::binary);
	if (!readf.is_open()) {
		return E_Error;
	}

	//先读两个,判断是否BMP格式
	for (int i = 0; i < step; i++) {
		readf >> header[count + i];
	}
	count = count + step;
	if (memcmp(header, BMP_Format, count) == 0) {
		return E_Image;
	}
	//再读两个,判断是否JPG格式、PNG格式
	for (int i = 0; i < step; i++) {
		readf >> header[count + i];
	}
	count = count + step;
	
	if ((memcmp(header, JPG_Format1, count) == 0)
		|| (memcmp(header, JPG_Format2, count) == 0)
		|| (memcmp(header, JPG_Format3, count) == 0)
		|| (memcmp(header, JPG_Format4, count) == 0)
		|| (memcmp(header, JPG_Format5, count) == 0)
		|| (memcmp(header, JPG_Format6, count) == 0)) {
		return E_Image;
	}
	else if (memcmp(header, PNG_Format, count) == 0) {
		return E_Image;
	}
	//再读两个,判断是否GIF格式
	for (int i = 0; i < step; i++) {
		readf >> header[count + i];
	}
	count = count + step;
	if ((memcmp(header, GIF_Format1, count) == 0)
		|| (memcmp(header, GIF_Format2, count) == 0)) {
		return E_GifImage;
	}
	return E_Error;
}

获取非动态图片尺寸

QSize showImage::getImageSize(const QString & fileName)
{
	QImage image;
	image.load(fileName);
	int width = image.width();
	int height = image.height();
	return QSize(width, height);
}

获取动态图片尺寸

QSize showImage::getGifSize(const QString & fileName)
{
	std::ifstream fp(fileName.toStdString().c_str(), std::ios::binary);
	if (!fp) {
		std::cout << "Can not open this file." << std::endl;
		return QSize(0, 0);
	}
	char s1[2] = { 0 }, s2[2] = { 0 };
	fp.seekg(6);
	fp.read(s1, 2);
	fp.read(s2, 2);
	int width = (unsigned int)(s1[1]) << 8 | (unsigned int)(s1[0]);
	int height = (unsigned int)(s2[1]) << 8 | (unsigned int)(s2[0]);
	fp.close();
	return QSize(width, height);
}

非动态图片显示类

模仿qq图片查看效果
根据图片尺寸自适应显示图片,尺寸过大则会等比例优化显示
具有图片缩小放大功能,可移动图片

ImageView::ImageView(QWidget *parent)
{

}

ImageView::~ImageView()
{

}
void ImageView::toSetImageValue(QImage image)
{
	m_image = image;
	int height = qMax(image.height(), this->height());
	int width = qMax(image.width(), this->width());
	if (image.height() < image.width()) {
		height = this->height();
		width = image.width();
		//width = height * 1.0 * (image.width() * 1.0 / image.height());
	}
	else {
		width = this->width();
		height = image.height();
		//height = width * 1.0 / (image.width() * 1.0 / image.height());
	}

	m_image = image.scaled(width, height, Qt::KeepAspectRatio);
	m_pixmap = QPixmap::fromImage(m_image);
	m_imageSize = m_pixmap.size();

	m_minImageSize = QSize(m_imageSize.width() / 10, m_imageSize.height() / 10);;
	m_maxImageSize = QSize(m_imageSize.width() * 3, m_imageSize.height() * 3);
}

void ImageView::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);

	int NowW = m_imageSize.width();//现在的宽
	int NowH = m_imageSize.height();

	xPoint = width() / 2 - m_imageSize.width() / 2;
	yPoint = height() / 2 - m_imageSize.height() / 2;

	if (m_action == ImageView::Move)                    //移动
	{
		int offsetx = m_Alloffset.x() + m_offset.x();
		m_Alloffset.setX(offsetx);//总偏移 x

		int offsety = m_Alloffset.y() + m_offset.y();
		m_Alloffset.setY(offsety); //总偏移 y
		m_action = ImageView::None;
	}

	if (abs(m_Alloffset.x()) >= abs(xPoint))    //限制X偏移值
	{
		if (m_Alloffset.x() > 0)//右移
			m_Alloffset.setX(abs(xPoint));//最大值
		else//左移
			m_Alloffset.setX(-abs(xPoint));
	}

	if (abs(m_Alloffset.y()) >= abs(yPoint))    //限制X偏移值
	{
		if (m_Alloffset.y() > 0)//右移
			m_Alloffset.setY(abs(yPoint));//最大值
		else//左移
			m_Alloffset.setY(-abs(yPoint));
	}

	int x = width() / 2 + m_Alloffset.x() - m_imageSize.width() / 2;
	if (x < 0)x = 0;

	int y = height() / 2 + m_Alloffset.y() - m_imageSize.height() / 2;
	if (y < 0)y = 0;

	int  sx = m_imageSize.width() / 2 - width() / 2 - m_Alloffset.x();
	if (sx < 0)sx = 0;

	int  sy = m_imageSize.height() / 2 - height() / 2 - m_Alloffset.y();
	if (sy < 0)sy = 0;

	int w = (m_imageSize.width() - sx) > width() ? width() : (m_imageSize.width() - sx);
	if (w > (width() - x))
		w = width() - x;

	int h = (m_imageSize.height() - sy) > height() ? height() : (m_imageSize.height() - sy);
	if (h > (height() - y))
		h = height() - y;

	if ((xPoint > 0) && (yPoint > 0)) {
		//这里清零,可以保证,放大以后拖动到其他位置后缩小,不会改变处于中下位置.
		int offSetX = xPoint;
		int offSetY = yPoint;
		painter.drawPixmap(offSetX, offSetY, m_pixmap);
	}
	else {
		painter.drawPixmap(x, y, w, h, m_pixmap, sx, sy, w, h);             
	}
}

void ImageView::wheelEvent(QWheelEvent *event)
{
	QImage imgScaled;
	
	int numDegrees = event->delta();
	int numSteps = numDegrees;

	if (m_imageSize == QSize(0, 0)) {
		m_imageSize = m_image.size();
	}
	if ((m_imageSize.width() <= m_maxImageSize.width()) && \
		(m_imageSize.height() <= m_maxImageSize.height()) && \
		(m_imageSize.width() >= m_minImageSize.width()) && \
		(m_imageSize.height() >= m_minImageSize.height())) {
		if (numSteps > 0) {//向上滚动
			imgScaled = m_image.scaled(m_imageSize.width() * 12 / 11, m_imageSize.height() * 12 / 11, Qt::KeepAspectRatio);
		}
		else {
			imgScaled = m_image.scaled(m_imageSize.width() * 11 / 12, m_imageSize.height() * 11 / 12, Qt::KeepAspectRatio);
		}
		//给painter绘制图片
		m_pixmap = QPixmap::fromImage(imgScaled);
		m_imageSize = m_pixmap.size();
		update();
		//大于最大 只能缩小
	}
	else if ((m_imageSize.width() >= m_maxImageSize.width()) && \
		(m_imageSize.height() >= m_maxImageSize.height()) && \
		(numSteps < 0)) {
		if (numSteps > 0) {//向上滚动
			imgScaled = m_image.scaled(m_imageSize.width() * 12 / 11, m_imageSize.height() * 12 / 11, Qt::KeepAspectRatio);
		}
		else {
			imgScaled = m_image.scaled(m_imageSize.width() * 11 / 12, m_imageSize.height() * 11 / 12, Qt::KeepAspectRatio);
		}
		//给painter绘制图片
		m_pixmap = QPixmap::fromImage(imgScaled);
		m_imageSize = m_pixmap.size();
		update();
		//小于最小,只能放大
	}
	else if ((m_imageSize.width() <= m_minImageSize.width()) && \
		(m_imageSize.height() <= m_minImageSize.height() && \
		(numSteps > 0))) {
		if (numSteps > 0) {//向上滚动
			imgScaled = m_image.scaled(m_imageSize.width() * 12 / 11, m_imageSize.height() * 12 / 11, Qt::KeepAspectRatio);
		}
		else {
			imgScaled = m_image.scaled(m_imageSize.width() * 11 / 12, m_imageSize.height() * 11 / 12, Qt::KeepAspectRatio);
		}
		//给painter绘制图片
		m_pixmap = QPixmap::fromImage(imgScaled);
		m_imageSize = m_pixmap.size();
		update();
	}
}

void ImageView::mousePressEvent(QMouseEvent *event)
{
	if (Qt::LeftButton == event->button()) {
		m_bPressed = true;
		m_preDotPos = event->pos();
	}
	QWidget::mousePressEvent(event);
}

void ImageView::mouseMoveEvent(QMouseEvent *event)
{
	if ((event->buttons() & Qt::LeftButton) && m_bPressed && ((yPoint < 0) || (xPoint < 0))) {
		this->setCursor(Qt::SizeAllCursor);
		m_offset.setX(event->pos().x() - m_preDotPos.x());//偏移量 x
		m_offset.setY(event->pos().y() - m_preDotPos.y());//偏移量 y
		m_preDotPos = event->pos();//改变 前点
		m_action = ImageView::Move;
		event->accept();
		update();
	}
	QWidget::mouseMoveEvent(event);
}

void ImageView::mouseReleaseEvent(QMouseEvent *event)
{
	m_bPressed = false;
	this->setCursor(Qt::ArrowCursor);
}

动态图片显示类

模仿qq图片查看效果
根据图片尺寸自适应显示图片,尺寸过大则会等比例优化显示
具有图片缩小放大功能,可移动图片

LabelGIF::LabelGIF(QWidget *parent)
	: QLabel(parent)
{
	setAlignment(Qt::AlignCenter);
	setMovie(&m_movie);
}

LabelGIF::~LabelGIF()
{
}

void LabelGIF::setResource(const QString & path)
{
	if (m_movie.state() == QMovie::Running) {
		return;
	}
	m_movie.setFileName(path);
	m_movie.start();
}

void LabelGIF::setScaledSize(const QSize & size)
{
	setFixedSize(size);
	m_movie.setScaledSize(size);
	m_pSize = size;
}

void LabelGIF::setScaledSize(int w, int h)
{
	QSize size(w, h);
	setFixedSize(size);
	m_movie.setScaledSize(size);
	m_pSize = size;
}

void LabelGIF::mouseDoubleClickEvent(QMouseEvent *e)
{
	emit sigMouseDoubleClick();
}

void LabelGIF::getPsize(int w, int h)
{
	posWidth = w;
	posHeight = h;
}

void LabelGIF::wheelEvent(QWheelEvent * event)
{
	int value = event->delta();
	double poxWidth = m_pSize.width();
	double poxHeight = m_pSize.height();

	if (value > 0)
	{
		if (m_pSize.width() > m_pSize.height()) {
			poxWidth = m_pSize.width() + 10;
			if (posWidth <= m_pSize.width())
				poxWidth = posWidth;
			poxHeight = poxWidth * ((float)m_pSize.height() / (float)m_pSize.width());
		}
		else
		{
			poxHeight = m_pSize.height() + 10;
			if (posHeight <= m_pSize.height())
				poxHeight = posHeight;
			poxWidth = poxHeight * ((float)m_pSize.width() / (float)m_pSize.height());
		}
	//	qInfo() << QStringLiteral("放大操作") << "poxHeight = " << poxHeight << "poxWidth = " << poxWidth;
	}
	else
	{	
		if (m_pSize.width() > m_pSize.height()) {
			poxWidth = m_pSize.width() - 10;
			if (120 >= m_pSize.width())
				poxWidth = 120;
			poxHeight = poxWidth * ((float)m_pSize.height() / (float)m_pSize.width());
		}
		else
		{
			poxHeight = m_pSize.height() - 10;
			if (120 >= m_pSize.height())
				poxHeight = 120;
			poxWidth = poxHeight * ((float)m_pSize.width() / (float)m_pSize.height());
		}
	//	qInfo() << QStringLiteral("缩小操作") << "poxHeight = " << poxHeight << "poxWidth = " << poxWidth;
	}

	m_pSize = QSize(poxWidth, poxHeight);
	setScaledSize(m_pSize);
}

void LabelGIF::mousePressEvent(QMouseEvent * event)
{
	m_OldPos = event->pos();
	m_Pressed = true;
}

void LabelGIF::mouseMoveEvent(QMouseEvent * event)
{
	if (!m_Pressed)
		return QWidget::mouseMoveEvent(event);

	this->setCursor(Qt::SizeAllCursor);
	QPoint pos = event->pos();
	int xPtInterval = pos.x() - m_OldPos.x();
	int yPtInterval = pos.y() - m_OldPos.y();
	m_XPtInterval += xPtInterval;
	m_YPtInterval += yPtInterval;
	int moveX = this->x() + m_XPtInterval;
	int moveY = this->y() + m_YPtInterval;
	if (moveX < 0)
		moveX = 0;
	if (moveY < 0)
		moveY = 0;
	if ((moveX + m_pSize.width()) > posWidth)
		moveX = posWidth - m_pSize.width();
	if ((moveY + m_pSize.height()) > posHeight)
		moveY = posHeight - m_pSize.height();
	move(moveX, moveY);
	m_OldPos = pos;
	repaint();
}

void LabelGIF::mouseReleaseEvent(QMouseEvent * event)
{
	m_Pressed = false;
	this->setCursor(Qt::ArrowCursor);
}

你可能感兴趣的:(Qt,C/C++)