zoukankan      html  css  js  c++  java
  • 一步步实现看图工具(二)

    1. 控件在对话框中的适配。

    2. 图像和显示控件的适配。

    3. 以鼠标点为中心, 滚轮缩放图片(类似于手机图库)

    4. 鼠标拖动图片。(类似于手机图库)

    5。双击100%显示图片, 再次双击显示全图(类似于手机图库)

    6. 图像任意角度旋转。



    1. 控件在对话框中的适配。

       可以先参考我这篇文章: 

       http://blog.csdn.net/fallingstar08/article/details/5182830

         现在的控件不多我就这么写了

    void CEasyImageDlg::OnSize(UINT, int w, int h)
    {
    	if(m_player.GetSafeHwnd())
    	{
    		Move(&m_player, 0, 0, w, h, 0, 0, 800, 1000);
    		Move(&xyPos, 0, 0, w, h, 840,  130,100, 30);
    		Move(&textRGB, 0, 0, w, h, 840,  170,100, 30);
    		Move(&textYUV, 0, 0, w, h, 840,  210, 100,30);
    		Move(&imageInfo, 0, 0, w, h, 840,  50,100, 30);
    		Move(&scaleInfo, 0, 0, w, h, 840,  90, 100,30);
    		Move(GetDlgItem(IDC_BAR1), 0, 0, w, h, 801,  0, 2,1000);
    		Move(GetDlgItem(IDC_BAR2), 0, 0, w, h, 803,  250, 197,2);
    		m_player.Invalidate(FALSE);
    	}
    }

    2. 图像和显示控件的适配。

       图像要尽量大的显示在控件上面, 并保持宽高比。

     

     这里分为两种情况:

      一: 图像宽高都比控件小。

           直接在控件中心位置显示图像。

      二: 图像的宽或高比控件大。

           分别计算图像宽度/控件宽度,  图像高度/控件高度。 取一个最大值,作为缩放比例。

           然后在控件中心位置显示图像。


    void CImageView::CalcImageShowRect(const CRect& rc, const CRect& rcImage, CRect& rcShow)
    {
    	double dw= rcImage.Width()/(1.0*rc.Width());
    	double dh= rcImage.Height()/(1.0*rc.Height());
    	int cx = rc.Width()/2;
    	int cy = rc.Height()/2;
    	rcShow = rc;
    	if(dw< 1.0 && dh < 1.0)
    	{
    		rcShow.left = cx - rcImage.Width()/2;
    		rcShow.top = cy - rcImage.Height()/2;
    		rcShow.right = rcShow.left + rcImage.Width();
    		rcShow.bottom = rcShow.top + rcImage.Height();
    		scale = 1.0;
    	}
    	else 
    	{
    		double s = max(dw, dh);
    		double fw = rcImage.Width()/s;
    		double fh = rcImage.Height()/s;
    		rcShow.left = cx - fw/2;
    		rcShow.right = cx + fw/2;
    		rcShow.top = cy - fh/2;
    		rcShow.bottom = cy + fh/2;
    
    	}
    }


    3. 以鼠标点为中心, 滚轮缩放图片。

    4. 鼠标拖动图片。

    5。双击100%显示图片, 再次双击显示全图

       对话框响应滚轮事件然后传给控件。

       上面计算过的控件显示区域, 是不变的。 我们修改图像的显示区域来实现缩放功能。



    先把坐标点从屏幕坐标系 映射到图像坐标系。

    void CImagePlayer::ScreenToImage(CPoint& pt)
    {
    	CPoint ret;
    	ret.x = rcImage.left + rcImage.Width()*(pt.x-rcShow.left)/rcShow.Width();
    	ret.y = rcImage.top + rcImage.Height()*(pt.y-rcShow.top)/rcShow.Height();
    	pt = ret;
    }


    定义一个scale变量来记录缩放倍数。

    比如scale=2,那么 新的显示宽度=图像宽度/2.

    由于缩放前后, 图像坐标系里的鼠标点离左右显示边界的距离是不变的。

    推出

      (鼠标点横坐标-新的左边界)/新的宽度 = ((鼠标点横坐标-旧的左边界)/旧的宽度。


    我们要求的是新的左边界, 其他参数已知。


    void CImagePlayer::Scale(CPoint pt)
    {
    	if(scale == 1.0)
    	{
    		rcImage = CRect(0, 0, w, h);
    	}
    	else
    	{
    		ScreenToImage(pt);
    		double dw = w/scale;
    		double dh = h/scale;
    		double ds = dw/rcImage.Width();
    		rcImage.left = pt.x - ds*(pt.x-rcImage.left);
    		rcImage.right = rcImage.left + dw;
    		rcImage.top = pt.y - ds*(pt.y-rcImage.top);
    		rcImage.bottom = rcImage.top + dh;
    		if(rcImage.left < 0) rcImage.left = 0;
    		if(rcImage.top < 0) rcImage.top = 0;
    		if(rcImage.bottom > h) rcImage.bottom = h;
    		if(rcImage.right > w) rcImage.right = w;
    	}
    	SendScaleInfo();
    	Invalidate(FALSE);
    
    }

    效果图:





    6. 图像任意角度旋转。

       图像旋转其实是很普通的几何问题。

       旋转矩阵:

       

        


    OPENCV提供了计算旋转矩阵的函数, 和仿射变换函数

    //! warps the image using affine transformation
    CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst,
                                  InputArray M, Size dsize,
                                  int flags=INTER_LINEAR,
                                  int borderMode=BORDER_CONSTANT,
                                  const Scalar& borderValue=Scalar());

    我的实现如下:

    void rotateImage(Mat& img, double degree, int &w, int &h)
    {
    	double angle = degree  * CV_PI / 180.;
    	double a = sin(angle), b = cos(angle);   
    	int width = img.cols;    
    	int height = img.rows;    
    	w= int(height * fabs(a) + width * fabs(b));    
    	h= int(width * fabs(a) + height * fabs(b));   
    
    	w = ALIGN_UP(w, 4);
    	h = ALIGN_UP(h, 4);
    	float map[6];  
    	CvMat map_matrix = cvMat(2, 3, CV_32F, map);    
    
    	CvPoint2D32f center = cvPoint2D32f(width / 2, height / 2);    
    	cv2DRotationMatrix(center, degree, 1.0, &map_matrix);    
    	map[2] += (w - width) / 2;    
    	map[5] += (h - height) / 2;
    	warpAffine(img, img, Mat(&map_matrix), Size(w, h),
    		CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS,BORDER_CONSTANT, Scalar::all(0));
    
    }


  • 相关阅读:
    SAP OPEN UI5 Step 8: Translatable Texts
    SAP OPEN UI5 Step7 JSON Model
    SAP OPEN UI5 Step6 Modules
    SAP OPEN UI5 Step5 Controllers
    SAP OPEN UI5 Step4 Xml View
    SAP OPEN UI5 Step3 Controls
    SAP OPEN UI5 Step2 Bootstrap
    SAP OPEN UI5 Step1 环境安装和hello world
    2021php最新composer的使用攻略
    Php使用gzdeflate和ZLIB_ENCODING_DEFLATE结果gzinflate报data error
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3177825.html
Copyright © 2011-2022 走看看