-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathactions.py
153 lines (129 loc) · 7.45 KB
/
actions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
from PyQt5.QtGui import QImage, QPixmap, QPainter
from PyQt5 import QtCore, QtGui, QtWidgets#, QRect
import numpy as np
__author__ = "Christofel Rio Goenawan"
__license__ = "MIT"
__version__ = "1.0"
__email__ = "christofel.goenawan@kaist.ac.kr"
class ImageViewer:
''' Basic image viewer class to show an image with zoom and pan functionaities.
Requirement: Qt's Qlabel widget name where the image will be drawn/displayed.
'''
def __init__(self, qlabel , image_position = [0,0]):
self.qlabel_image = qlabel # widget/window name where image is displayed (I'm usiing qlabel)
self.qimage_scaled = QImage() # scaled image to fit to the size of qlabel_image
self.qpixmap = QPixmap() # qpixmap to fill the qlabel_image
self.zoomX = 1 # zoom factor w.r.t size of qlabel_image
self.position = image_position # position of top left corner of qimage_label w.r.t. qimage_scaled
self.panFlag = False # to enable or disable pan
self.qlabel_image.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
self.__connectEvents()
# Variable to show where the image is pressed
self.pressed = None
def __connectEvents(self):
# Mouse events
self.qlabel_image.mousePressEvent = self.mousePressAction
self.qlabel_image.mouseMoveEvent = self.mouseMoveAction
self.qlabel_image.mouseReleaseEvent = self.mouseReleaseAction
def onResize(self):
''' things to do when qlabel_image is resized '''
self.qpixmap = QPixmap(self.qlabel_image.size())
self.qpixmap.fill(QtCore.Qt.gray)
self.qimage_scaled = self.qimage.scaled(self.qlabel_image.width() * self.zoomX, self.qlabel_image.height() * self.zoomX, QtCore.Qt.KeepAspectRatio)
self.update()
def loadImage(self, imagePath):
''' To load and display new image.'''
camera_image_crop = QtCore.QRect(0,0,1280,720)
self.qimage = QImage(imagePath).copy( camera_image_crop )
self.qpixmap = QPixmap(self.qlabel_image.size())
#print( "Shape of the image is : " + str( self.qlabel_image.size() ))
if not self.qimage.isNull():
# reset Zoom factor and Pan position
self.zoomX = 1
self.position = [0, 0]
#self.initial_image_size = [ self.qimage.width() , self.qimage.height() ]
self.qimage_scaled = self.qimage.scaled(self.qlabel_image.width(), self.qlabel_image.height(), QtCore.Qt.KeepAspectRatio)
self.update()
else:
self.statusbar.showMessage('Cannot open this image! Try another one.', 5000)
def loadImageFromArray(self, imageArray):
''' To load and display new image.'''
#camera_image_crop = QtCore.QRect(0,0,1280,720)
#self.qimage = QImage(imagePath).copy( camera_image_crop )
self.qimage = QtGui.QImage(imageArray.astype( np.uint8 ), imageArray.shape[1],imageArray.shape[0],QtGui.QImage.Format_RGB888)
self.qpixmap = QPixmap(self.qlabel_image.size())
#print( "Shape of the image is : " + str( self.qlabel_image.size() ))
if not self.qimage.isNull():
# reset Zoom factor and Pan position
self.zoomX = 1
self.position = [0, 0]
#self.initial_image_size = [ self.qimage.width() , self.qimage.height() ]
self.qimage_scaled = self.qimage.scaled(self.qlabel_image.width(), self.qlabel_image.height(), QtCore.Qt.KeepAspectRatio)
self.update()
else:
self.statusbar.showMessage('Cannot open this image! Try another one.', 5000)
def update(self):
''' This function actually draws the scaled image to the qlabel_image.
It will be repeatedly called when zooming or panning.
So, I tried to include only the necessary operations required just for these tasks.
'''
if not self.qimage_scaled.isNull():
# check if position is within limits to prevent unbounded panning.
px, py = self.position
px = px if (px <= self.qimage_scaled.width() - self.qlabel_image.width()) else (self.qimage_scaled.width() - self.qlabel_image.width())
py = py if (py <= self.qimage_scaled.height() - self.qlabel_image.height()) else (self.qimage_scaled.height() - self.qlabel_image.height())
px = px if (px >= 0) else 0
py = py if (py >= 0) else 0
self.position = (px, py)
if self.zoomX == 1:
self.qpixmap.fill(QtCore.Qt.white)
# the act of painting the qpixamp
painter = QPainter()
painter.begin(self.qpixmap)
painter.drawImage(QtCore.QPoint(0, 0), self.qimage_scaled,
QtCore.QRect(self.position[0], self.position[1], self.qlabel_image.width(), self.qlabel_image.height()) )
painter.end()
self.qlabel_image.setPixmap(self.qpixmap)
else:
pass
def mousePressAction(self, QMouseEvent):
x, y = QMouseEvent.pos().x(), QMouseEvent.pos().y()
actual_x_on_image = int( x*self.qimage.width()/self.qimage_scaled.width())
actual_y_on_image = int( y*self.qimage.height()/self.qimage_scaled.height())
#print(x,y)
#print( "Actual point location on x and y is : " + str( actual_x_on_image ) + " " + str( actual_y_on_image ))
if self.panFlag:
self.pressed = QMouseEvent.pos() # starting point of drag vector
self.anchor = self.position # save the pan position when panning starts
def mouseMoveAction(self, QMouseEvent):
x, y = QMouseEvent.pos().x(), QMouseEvent.pos().y()
if self.pressed is not None :
dx, dy = x - self.pressed.x(), y - self.pressed.y() # calculate the drag vector
self.position = self.anchor[0] - dx, self.anchor[1] - dy # update pan position using drag vector
self.update() # show the image with udated pan position
def mouseReleaseAction(self, QMouseEvent):
self.pressed = None # clear the starting point of drag vector
def zoomPlus(self):
self.zoomX += 1
px, py = self.position
px += self.qlabel_image.width()/2
py += self.qlabel_image.height()/2
self.position = (px, py)
self.qimage_scaled = self.qimage.scaled(self.qlabel_image.width() * self.zoomX, self.qlabel_image.height() * self.zoomX, QtCore.Qt.KeepAspectRatio)
self.update()
def zoomMinus(self):
if self.zoomX > 1:
self.zoomX -= 1
px, py = self.position
px -= self.qlabel_image.width()/2
py -= self.qlabel_image.height()/2
self.position = (px, py)
self.qimage_scaled = self.qimage.scaled(self.qlabel_image.width() * self.zoomX, self.qlabel_image.height() * self.zoomX, QtCore.Qt.KeepAspectRatio)
self.update()
def resetZoom(self):
self.zoomX = 1
self.position = [0, 0]
self.qimage_scaled = self.qimage.scaled(self.qlabel_image.width() * self.zoomX, self.qlabel_image.height() * self.zoomX, QtCore.Qt.KeepAspectRatio)
self.update()
def enablePan(self, value):
self.panFlag = value