图片浏览器开发日志-13(多风格显示和速度显示的改善)

按:至此,软件的雏形基本形成,可以浏览图片,要求不高基本可用了。

多风格显示

多风格显示可以增加工具的娱乐性,人们看图像一方面是看图的内容,一方面也是从不同风格的显示过程中,得到一点轻松的感觉,这可可能很重要。否则,PPT也不用支持动画显示了。目前本软件已经可以支持十几种风格的显示。如图所示
在这里插入图片描述
UDRL 分别表示Up,Down,Righ 和Left, perspective 风格就是前文介绍的开关门的风格,如图示:
从上到下:
在这里插入图片描述
从左到右:
在这里插入图片描述
利用上一章的开关门代码,连续调用有关函数达到动画效果。

void CImgShape::showPerspectiveImage(CImage &src0, bool bOpenDoor, int times, float interval, CString dir, CWnd *ctrWnd, bool bFixdWHRatio=true)
	{
    
    
		int iTopL;
		CImage dst;
		CRect rect;
		ctrWnd->GetClientRect(&rect);

		if (bFixdWHRatio) {
    
    
			getRectWithFixedAspectRatio(src0, rect);
		}
		CImage src;
		GetStrechIMG(src0, src, rect.Width(), rect.Height());


		CDC* pDC = ctrWnd->GetDC();
		int H, W;

		if (dir == "U" || dir == "D") {
    
    
			W = src.GetWidth();
			H = src.GetHeight();
		}
		else {
    
    
			H = src.GetWidth();
			W = src.GetHeight();
		}

		float maxRotateAngle;
		int tanVal = 6;
		maxRotateAngle = atan(tanVal);
		float viewDistance = W / 2 * tanVal;//tan(maxRotateAngle)

		float step = maxRotateAngle / times;
		int ModeOld = SetStretchBltMode(pDC->m_hDC, COLORONCOLOR);//
// 连续调用perspectiveImage,将输出结果显示,得到动画效果。
		for (int i = 0; i < times; i++) {
    
    
			float rotateAngle = step * i;
			if (!bOpenDoor) {
    
    
				rotateAngle = step * (times - i - 1);
			}
			int th = cos(rotateAngle)*H;
			int tw = sin(rotateAngle)*H;
			iTopL = (viewDistance - tw) / viewDistance * W;
			perspectiveImage(src, th, iTopL, dir, dst);


			dst.Draw(pDC->m_hDC,
				rect.left,
				rect.top,
				rect.Width(),
				rect.Height());
			Sleep(interval);
		}
		src.Draw(pDC->m_hDC,
			rect.left,
			rect.top,
			rect.Width(),
			rect.Height());
		SetStretchBltMode(pDC->m_hDC, ModeOld);

		ctrWnd->ReleaseDC(pDC);

	}

其他效果,将逐步介绍。

显示速度的改善

使用发现,从硬盘load文件需要时间,对图像进行翻转操作也需要时间,这样在连续浏览时,有迟滞的现象,用起来比较卡。为了提高流畅性,采用了多线程技术和缓存技术和图片缩放技术。图片缩放是根据计算机屏幕的大小对原始图片进行缩放,虽然显示的是压缩或者放大的图片,但是这并不影响对图片视觉效果的影响。因为,视窗就那么大,人眼看不到视窗以外的东西。图像操作,针对视窗内的图片操作即可,这样可以大大提高处理速度。(为了编程的简单操作,本软件还是在后台对原始图片进行了操作,抓实际上对于较大图片而言,产生了问题,后面会单独介绍。)
为了简单操作,缓存只做了两个,即上一图片和下一个图片的缓存,经过简单测试,显示速度基本可以接受。
线程有四个
读取buffer主线程,读取前后两个图片的线程和旋转线程。
读缓存线程启动后,等候主线程发送指令是否启动读取图片,并启动旋转线程,判断是否对图片进行旋转。
代码如下:

UINT CseePictureDlg::readBufferThread()
{
    
    
	while (!g_bStopThread)
	{
    
    
		if(g_beginReadBuffer) {
    
    
			g_originalImg0Mutex.Lock();
			if (g_bCopyNext) {
    
    
				m_OriginalImg0.copyImg2(m_nextImg0, m_OriginalImg0);
				m_OriginalImg0.setRotateDegree(m_nextImg0.getRotateDegree());

			}
			else {
    
    
				m_OriginalImg0.copyImg2(m_prevImg0, m_OriginalImg0);
				m_OriginalImg0.setRotateDegree(m_prevImg0.getRotateDegree());

			}
			g_originalImg0Mutex.Unlock();
			g_beginRotate = true;
			g_readBuffMutex.Lock();
			std::thread thr1(&CseePictureDlg::readNextImageThread, this);
			
			std::thread thr2(&CseePictureDlg::readPrevImageThread, this);
			thr1.join();
			thr2.join();
			g_readBuffMutex.Unlock();
			g_beginReadBuffer = false;
		}
	}
	return 0;
}

其中copy2 是图片拷贝函数,图片0 和1,,0 是原始图像,可能很大,1 是根据显示区域大小对图像进行了裁剪,图像的处理和操作在没有进行放大和缩小操作时,都是针对图片1进行操作,这样可以提高速度。
读取下一张图片的线程

UINT CseePictureDlg::readNextImageThread()
{
    
    
	if (m_ImgFilesVct.size() == 0)
		return -1;

	int pos;
	string file;
	CString imgFile;
	CImage bufImg;
	CMyImage myImg;

	//1#read the next one 
	pos = m_Pos +1;
	if (pos >= m_ImgFilesVct.size()) {
    
    
		pos = 0;
	}
	file = m_ImgPath + "\\" + m_ImgFilesVct[pos].getName();
	imgFile = file.c_str();
	if (!m_nextImg0.IsNull()) {
    
    
		m_nextImg0.Destroy();
	}
	m_nextImg0.Load(imgFile);
	if (m_nextImg0.IsNull()) {
    
    
		throw "Load image failed";
	}


	//myImg.GetStrechIMG(m_nextImg0, m_nextImg1, m_ImgRect.Width(), m_ImgRect.Height());
	getSuitableImage(m_nextImg0, m_nextImg1, m_ImgRect);
	if (m_autoUpWard) {
    
    
		CImage tmpImg;
		CExif exif;
		exif.setImage(imgFile);
		int degree;
		degree = exif.getRotateAngle();
		if (degree != 0) {
    
    
			CMsApiRotate rtt;

			rtt.filter(m_nextImg1, degree,tmpImg );
			myImg.copyImg2(tmpImg, m_nextImg1);
			m_nextImg1.setRotateDegree(degree);
			m_nextImg0.setRotateDegree(degree);
		}
	}
	return 0;
}

图像旋转的线程

UINT CseePictureDlg::rotatePrevImageThread()
{
    
    
	if (m_ImgFilesVct.size() == 0)
		return -1;

	int pos;
	string file;
	CString imgFile;
	CImage bufImg;
	CMyImage myImg;

	//2# read the previous one 
	pos = m_Pos - 1;
	if (pos < 0) {
    
    
		pos = m_ImgFilesVct.size() - 1;
	}
	file = m_ImgPath + "\\" + m_ImgFilesVct[pos].getName();
	imgFile = file.c_str();
	//myImg.GetStrechIMG(m_prevImg0, m_prevImg1, m_ImgRect.Width(), m_ImgRect.Height());

	if (m_autoUpWard)
	{
    
    
		CImage tmpImg;
		CExif exif;
		exif.setImage(imgFile);
		int degree;
		degree = exif.getRotateAngle();
		if (degree != 0) {
    
    
			CMsApiRotate rtt;
			rtt.filter(m_prevImg0, degree, tmpImg);
			CMyImage mImg;
			mImg.copyImg(tmpImg, m_prevImg0);
		}
	}
	return 0;
}

考察前面的flag,还有很多功能没有实现
1、按钮扁平化处理:完成
2、鼠标点击处动画水纹效果:没有
3、花样显示效果:完成部分
4、幻灯片效果:没有
5、背景音乐:没有
6、图片说明记录:初步完成
7、相机参数显示:没有
8、简单美图处理:没有
9、对象识别(人,车等):没有

路漫漫其修远兮,还要上下而求索吗?
2020-04-29 于泛五道口地区

猜你喜欢

转载自blog.csdn.net/Uman/article/details/105842296