Qt Gif转字符动画
发布于 10 天前 作者 雨田哥-工作号 57 次浏览 来自 创意与作品

@[toc]

简述

1.今天无意间看到一位网友用Java实现了一个 GIF转字符动画的效果,看起来挺有意思的。然后看了下原理,用Qt也实现了一把。目前缺陷是计算过程中特别耗CPU,后面的网友们,希望你们能优化掉这个问题。

参考地址:【轻松一刻】Java制作字符动画

效果图

1.gif

2.gif

3.gif

核心代码

const int limit_max_pixmap_cache = 5;
char toChar(int g) 
{
	if (g <= 30) {
		return '#';
	}
	else if (g > 30 && g <= 60) {
		return '&';
	}
	else if (g > 60 && g <= 120) {
		return '$';
	}
	else if (g > 120 && g <= 150) {
		return '*';
	}
	else if (g > 150 && g <= 180) {
		return 'o';
	}
	else if (g > 180 && g <= 210) {
		return '!';
	}
	else {
		return ' ';
	}
}

int rgbtoGray(int r, int g, int b)
{
	return (int)((((quint32)((r << 5) + (r << 2) + (r << 1))) + (quint32)((g << 6) + (g << 3) + (g << 1) + g)
		+ (quint32)((b << 4) - b)) >> 7);
}

QPixmap setImage(const QImage &image)
{
	const int ih = image.height();
	const int iw = image.width();

	QPixmap txtImage(iw, ih);
	txtImage.fill(Qt::transparent);
	QPainter painter(&txtImage);
	painter.setBrush(Qt::NoBrush);
	painter.setPen(QColor::fromHsl(rand() % 360, rand() % 256, rand() % 200));
	QFont font = painter.font();
	font.setPixelSize(7);
	font.setFamily("Microsoft YaHei");
	painter.setFont(font);
	
	for (int i = 0; i < iw; i+= 7)
	{
		for (int j = 0; j < ih; j+= 7)
		{
			const QRgb&& pixel = image.pixel(i, j);
			int r = qRed(pixel);
			int g = qGreen(pixel);
			int b = qBlue(pixel);
			int gray = rgbtoGray(r, g, b);
			char c = toChar((int)gray);
			painter.drawText(i, j, QChar(c));
		}
	}
	return txtImage;
}

MainWindow::MainWindow(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	m_movie = getMovie(":/MainWindow/Resources/1.gif");
	m_movieFrameCount = m_movie->frameCount();

	m_curplayFrame = 0;
	m_movie->jumpToFrame(0);
	for (int i = 0; i < limit_max_pixmap_cache; i++){
		m_cachePixmap.insert(i, setImage(m_movie->currentImage()));
		m_srcCachePixmap.insert(i, m_movie->currentPixmap());
		m_movie->jumpToNextFrame();
	}
	updateTextPixmap();
}

MainWindow::~MainWindow()
{
	QThreadPool::globalInstance()->clear();
	QThreadPool::globalInstance()->waitForDone(3000);
}

void MainWindow::updateTextPixmap()
{
	int curNumber = m_movie->currentFrameNumber();
	if (m_cachePixmap.contains(m_curplayFrame)){
		ui.imageLabel->setPixmap(m_cachePixmap.value(m_curplayFrame));
		ui.giflabel->setPixmap(m_srcCachePixmap.value(m_curplayFrame));
		m_cachePixmap.take(m_curplayFrame);
		m_srcCachePixmap.take(m_curplayFrame);
		ThradFunctionTask* task = new ThradFunctionTask;

		int curplayFrame = m_curplayFrame;
		QImage image = m_movie->currentImage();
		task->FNBind([this, curNumber, curplayFrame, image](){
			m_cachePixmap.insert(curNumber, setImage(image));
			m_srcCachePixmap.insert(curNumber, QPixmap::fromImage(image));
		});
		QThreadPoolManager::getInstance()->AddTask(task);
	}
	else{
		qDebug() << "totalframe = " << m_movieFrameCount << " not find = " << m_curplayFrame;
	}
	m_curplayFrame++;
	if (m_curplayFrame >= m_movieFrameCount)
		m_curplayFrame = 0;
	m_movie->jumpToNextFrame();
	QTimer::singleShot(m_movie->speed(), this, &MainWindow::updateTextPixmap);
}

QMovie* MainWindow::getMovie(const QString& path)
{
	if (m_movie == nullptr)
		m_movie = new QMovie(this);
	if (m_movie->state() == QMovie::NotRunning){
		m_movie->setFileName(path);
		m_movie->jumpToFrame(0);
		m_movie->stop();
	}
	return  m_movie;
}

工程文件

Qt交流大会 853086607 (收费群,用于后期群费用) 在这里插入图片描述

结尾

不定期上传新作品,解答群中作品相关问题。相关外,能解答则解答。欢迎大家一起探索Qt世界!相关工程,可以联系博主雨田哥:3246214072

回到顶部