增强深度看图,记录查看状态!苦战好几天了,成功。
Tofloor
poster avatar
137******41
deepin
2017-10-10 09:55
Author
本帖最后由 hykjfc 于 2017-10-10 02:08 编辑

我在windows上使用2345看图王很久了,感觉有2个功能非常不错,一是他能在一次会话中,记住每张浏览过的图片的位移、缩放历史,再次返回看过的图片时,能保持刚才的查看状态,这点尤其是在需要对比多张图片的局部细节时非常有用!二是只需要移动鼠标到某个位置,不需要点击就是默认以鼠标悬停位置作为缩放中心点(深度看图需要点击一次,不习惯,刚开始还以为没有设定缩放中心的功能呢!)于是我想在深度看图中实现此功能!!战斗开始了……
ps:电信网络访问github非常慢,而且网页打开不全,无法直接git提交,源代码都是在手机上用uc下载的(貌似uc有代理?很快)

然而,我是从大学毕业后,自学了几个月c++就因为工作原因,转战php、java阵营,c++那些复杂的指针、地址什么的已经忘得差不多了,需要重新捡起来,还需要熟悉qtcreator。
麻烦的过程¥%#%%%
大致查看代码后,发现图像缩放、平移等核心功能都是依托了QGraphicsView来实现的。于是想要取巧,单纯采用模拟鼠标点击的方式实现所有功能,结果只是成功实现了不用点击鼠标设定缩放中心。
imageview.cpp:
  1. void ImageView::mouseMoveEvent(QMouseEvent *e)
  2. {

  3.     if (! (e->buttons() | Qt::NoButton)) {
  4.         if (! items().isEmpty()) {
  5.             items().first()->setCursor(Qt::ArrowCursor);
  6.         }
  7.         // auto set click point as scale center

  8.         QGraphicsView::mousePressEvent(e);
  9.         QGraphicsView::mouseReleaseEvent(e);
  10.         //        end auto set
  11.         emit mouseHoverMoved();
  12.     }
  13. ……
  14. }
Copy the Code

为了实现记录缩放、平移图片的历史记录,新增了一个viewHistory类记录操作历史,主要包括缩放值、图像scene坐标系的中心x,y。在imageview中增加了一个map对象QMap<QString,viewHistory*> m_history    作为历史记录hash表。
  1. #ifndef VIEWHISTORY_H
  2. #define VIEWHISTORY_H
  3. #include
  4. #include

  5. class viewHistory: public QObject{
  6.     Q_OBJECT
  7. public:
  8.     explicit viewHistory();
  9.     int *getCenterXY();
  10.     bool setCenterXY(int x,int y);
  11.     ~viewHistory();
  12.     void setScale(double scale);
  13.     double getScale();
  14.     void setRelativeScale(double scale);
  15.     double getRelativeScale();
  16. private:
  17.     double m_scale=1;
  18.     double m_relativeScale=1;
  19.     int XY[2]={0,0};

  20. };

  21. #endif // VIEWHISTORY_H
Copy the Code

记录历史:在wheelEvent、mouseReleaseEvent事件处理函数中使用setHistoryCenter()记录图像的scene坐标系中心(查看文档+测试,好久才搞清楚view、scene、image的坐标转换的正确方式,scene的大小是个坑,一直以为会随着items的布局和大小而变化,结果是固定值!
  1. void ImageView::setHistoryCenter(){
  2.     qreal sw= scene()-> width();
  3.     qreal sh= scene()-> height();
  4.     QPoint offsetPoint= mapFromScene(0, 0);
  5.     int ox=offsetPoint.x();
  6.     int oy=offsetPoint.y();
  7.     int viewWidth= width();
  8.     int viewHeight=height();
  9.     int viewcx=-ox+viewWidth/2;
  10.     int viewcy=-oy+viewHeight/2;
  11.     qreal iw=imageRect().width();
  12.     qreal ih=imageRect().height();
  13.     m_history[m_path]->setCenterXY(viewcx/iw*sw,viewcy/ih*sh);
  14. }
Copy the Code
然后修改resetImageGeometry
  1. void ViewPanel::resetImageGeometry()
  2. {
  3.     // If image's size is smaller than window's size, set to 1:1 size
  4.     if (m_viewB->windowRelativeScale() > 1) {
  5.         m_viewB->fitImage();
  6.     }
  7.     else {
  8.         m_viewB->setToHistoryState();
  9. //        m_viewB->fitWindow();
  10.     }
  11. }
Copy the Code


  1. void ImageView::setToHistoryState(){
  2.     int *e= m_history[m_path]->getCenterXY();
  3.     setScaleValue( m_history[m_path]->getScale());
  4.     if(e[0]!=0 && e[1]!=0)
  5.         centerOn(e[0],e[1]);
  6. }
Copy the Code
setScaleValue也做了修改,通过判断相对缩放值是否与历史记录相同来确定是否为需要叠加缩放值(不太靠谱,需要优化,特殊情况可能误判
  1. void ImageView::setScaleValue(qreal v)
  2. {
  3.     const qreal rs=imageRelativeScale();
  4.     if(rs==m_history[m_path]->getRelativeScale()){
  5.         qreal o_scale= m_history[m_path]->getScale();
  6.         m_history[m_path]->setScale(o_scale*v);
  7.     }else {
  8.         m_history[m_path]->setScale(v);
  9.     }
  10.     scale(v, v);
  11.     const qreal irs = imageRelativeScale();
  12.     // Rollback
  13.     if ((v < 1 && irs <= MIN_SCALE_FACTOR)) {
  14.         const qreal minv = MIN_SCALE_FACTOR / irs;
  15.         scale(minv, minv);
  16.     }
  17.     else if (v > 1 && irs >= MAX_SCALE_FACTOR) {
  18.         const qreal maxv = MAX_SCALE_FACTOR / irs;
  19.         scale(maxv, maxv);
  20.     }
  21.     else {
  22.         m_isFitImage = false;
  23.         m_isFitWindow = false;
  24.     }
  25.     m_history[m_path]->setRelativeScale(imageRelativeScale());
  26.     emit scaled(imageRelativeScale() * 100);
  27.     emit showScaleLabel();
  28.     emit transformChanged();
  29. }
Copy the Code




终于成功实现了我想要的功能。希望官方能继续完善并加上这2个功能!

sourceCode.zip

sourceCode.zip



Reply Favorite View the author
All Replies
avatar
wtz
deepin
2017-10-10 11:01
#1
支持一下。
随手编译了一遍,发现两个小问题:
1、view/module/view/view.pri文件没有修改,需要分别在HEADERS和SOURCES两个区域增加上新的文件名;
2、viewer/module/view/scen/imageview.h文件的第23行,相对路径有误(可能是编译环境问题?)。
此外,打开一幅图片并缩放,然后查看其他图片,之前的缩放值并没有被保留。所以想问问楼主应当如何测试此功能?
Reply View the author
avatar
137******41
deepin
2017-10-10 15:16
#2
https://bbs.deepin.org/post/146496
支持一下。
随手编译了一遍,发现两个小问题:
1、view/module/view/view.pri文件没有修改,需要分别在HEAD ...

那是路径问题,我把viewhistory放在上一级文件夹里面了。重新传整个项目
Reply View the author
avatar
jingle
deepin
2017-10-10 16:40
#3
https://bbs.deepin.org/post/146496
那是路径问题,我把viewhistory放在上一级文件夹里面了。重新传整个项目

我转给开发人员看看,谢谢
Reply View the author
avatar
137******41
deepin
2017-10-11 05:58
#4
https://bbs.deepin.org/post/146496
支持一下。
随手编译了一遍,发现两个小问题:
1、view/module/view/view.pri文件没有修改,需要分别在HEAD ...

history类的存放路径:deepin-image-viewer-master/viewer/module/view/viewHistory.cpp
在scen上一层文件夹中。整个项目压缩包过大,无法上传,就只能告诉你路径了。
Reply View the author
avatar
137******41
deepin
2017-10-11 06:20
#5
https://bbs.deepin.org/post/146496
支持一下。
随手编译了一遍,发现两个小问题:
1、view/module/view/view.pri文件没有修改,需要分别在HEAD ...

效果是有的,但是不排除可能第一幅图处理过程有小bug,另外我只记录了放大,缩小仍然是用的老代码的fitImage,缩小原图没有记录。
此外,测试过程中我发现,可能是由于scene的大小设置(我看到似乎一直是1024*768?),对于高度明显大于宽度的那种图,好像图像定位会有偏差。
Reply View the author
avatar
rekols
deepin
2017-10-11 06:23
#6
先赞赞。
Reply View the author
avatar
180******28
deepin
2017-10-11 06:27
#7
C++大佬!
Reply View the author
avatar
wtz
deepin
2017-10-11 11:59
#8
https://bbs.deepin.org/post/146496
history类的存放路径:deepin-image-viewer-master/viewer/module/view/viewHistory.cpp
在scen上一层文件 ...

了解。建议同时更新 viewer/module/view/view.pri。
放大数值还是无法保存,不知道是不是和发行版有关。目前我只在其他发行版上做了测试,有空我切换到deepin下再编译看看。
Reply View the author
avatar
moriwuhen
deepin
2017-10-11 15:23
#9
本帖最后由 moriwuhen 于 2017-10-11 07:25 编辑

2345看图在win下简直看图软件的神器。能优化到那种程度,基本不用安装其他同类软件了。支持原创。
Reply View the author