def image(self): if self._index < 0: return QImage() data = self.test_data[self._index] data *= 255 img = QImage(data.astype(np.uint8), 28, 28, QImage.Format_Grayscale8) img.invertPixels() return img
def proper_display(window: FullscreenWindow): mat = Matrix(window.staticZoom, window.staticZoom) page_pix = return_page(window.file, window.currentPage).getPixmap( matrix=mat, alpha=False) fmt = QImage.Format_RGBA8888 if page_pix.alpha else QImage.Format_RGB888 qt_img = QImage(page_pix.samples, page_pix.width, page_pix.height, page_pix.stride, fmt) if window.invertImage: qt_img.invertPixels(QImage.InvertRgba) pixmap = QPixmap(QPixmap.fromImage(qt_img)) window.mainLabel.setPixmap(pixmap)
def proper_display(window: ReaderWindowInteractivity): mat = Matrix(window.static_zoom, window.static_zoom) page_pix = return_page(window.file, window.current_page).getPixmap(matrix=mat, alpha=False) fmt = QImage.Format_RGBA8888 if page_pix.alpha else QImage.Format_RGB888 qt_img = QImage(page_pix.samples, page_pix.width, page_pix.height, page_pix.stride, fmt) if window.invert_image: qt_img.invertPixels(QImage.InvertRgba) pixmap = QPixmap(QPixmap.fromImage(qt_img)) window.content.setPixmap(pixmap)
def zoom_out(self, window: FullscreenWindow): if self.currentMatrixZoom > self.minMatrixZoom: self.currentMatrixZoom -= 0.1 page_pix = return_page(window.file, window.currentPage).getPixmap( matrix=Matrix(self.currentMatrixZoom, self.currentMatrixZoom)) fmt = QImage.Format_RGBA8888 if page_pix.alpha else QImage.Format_RGB888 qt_img = QImage(page_pix.samples, page_pix.width, page_pix.height, page_pix.stride, fmt) if window.invertImage: qt_img.invertPixels(QImage.InvertRgba) pixmap = QPixmap(QPixmap.fromImage(qt_img)) window.mainLabel.setPixmap(pixmap) window.staticZoom = self.currentMatrixZoom
def zoom_out(self, window: ReaderWindowInteractivity): if self.currentMatrixZoom > self.minMatrixZoom: self.currentMatrixZoom -= 0.25 page_pix = return_page(window.file, window.current_page).getPixmap( matrix=Matrix(self.currentMatrixZoom, self.currentMatrixZoom)) fmt = QImage.Format_RGBA8888 if page_pix.alpha else QImage.Format_RGB888 qt_img = QImage(page_pix.samples, page_pix.width, page_pix.height, page_pix.stride, fmt) if window.invert_image: qt_img.invertPixels(QImage.InvertRgba) pixmap = QPixmap(QPixmap.fromImage(qt_img)) window.content.setPixmap(pixmap) window.static_zoom = self.currentMatrixZoom
class PopupPaletteFrame(QDialog): def __init__(self, parent=None, f=Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint): super(PopupPaletteFrame, self).__init__(parent) self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setAttribute(Qt.WA_NoSystemBackground, True) self.setAttribute(Qt.WA_TranslucentBackground, True) self.setGeometry(0, 0, 512, 512) self.offset = QPoint(0, 0) self.local_image = QImage(512, 512, QImage.Format_ARGB32) self.fgcolor = '#FFFFFF' self.bgcolor = '#000000' # This is how to load the merged image from a .kra file. ## import zipfile ## archive = zipfile.ZipFile(gImgDir + os.sep + 'myPopupPaletteWorkshop.kra', 'r') ## img_data = archive.read('mergedimage.png') ## img = QImage() ## img.loadFromData(img_data) ## self.texture = img self.texture = QImage(gImgDir + os.sep + 'colorwheel_pixel_palette.png') self.defaultblackwhiteImg = QImage(gImgDir + os.sep + 'defaultblackwhite10.png') self.switcharrowsImg = QImage(gImgDir + os.sep + 'switcharrows16.png') self.colorboxImg = QImage(gImgDir + os.sep + 'colorbox28.png') lHiColorDir = gShareDir + os.sep + 'icons' + os.sep + 'hicolor' # Text box. self.textbox = QTextEdit("Test QTextEdit", parent=self) self.textbox.move(192, 160) self.textbox.setGeometry(192, 160, 128, 32) # Big Button in middle. self.btnImage = btnImage = QImage(lHiColorDir + os.sep + '128x128' + os.sep + 'apps' + os.sep + 'calligrakrita.png') self.button = ImageButton(btnImage, btnImage, btnImage, self) self.button.move(256 - 64, 256 - 64) self.button.pressed.connect(self.buttonPressed) self.button.released.connect(self.buttonReleased) self.button.setToolTip('Right Click for Context Menu') self.button.setContextMenuPolicy(Qt.CustomContextMenu) self.button.customContextMenuRequested.connect(self.show_context_menu) # Create popup context menu. self._context_menu = QMenu(self) self._context_menu.addAction('Invert', self.invertTexture) self._context_menu.addAction('Mirror Horizontal', self.mirrorTextureHorizontal) self._context_menu.addAction('Mirror Vertical', self.mirrorTextureVertical) # 4 smaller buttons. self.btnImage1 = btnImage1 = QImage(lHiColorDir + os.sep + '32x32' + os.sep + 'apps' + os.sep + 'calligrakrita.png') self.button1 = ImageButton(btnImage1, btnImage1, btnImage1, self) self.button1.move(192, 320) self.button1.released.connect(self.button1Released) self.button1.setToolTip('test button') self.btnImage2 = btnImage2 = QImage(lHiColorDir + os.sep + '32x32' + os.sep + 'apps' + os.sep + 'calligrakrita.png') self.button2 = ImageButton(btnImage2, btnImage2, btnImage2, self) self.button2.move(224, 320) self.button2.released.connect(self.button2Released) self.button2.setToolTip('rotate_canvas_left') self.btnImage3 = btnImage3 = QImage(lHiColorDir + os.sep + '32x32' + os.sep + 'apps' + os.sep + 'calligrakrita.png') self.button3 = ImageButton(btnImage3, btnImage3, btnImage3, self) self.button3.move(256, 320) self.button3.released.connect(self.button3Released) self.button3.setToolTip('rotate_canvas_right') self.btnImage4 = btnImage4 = QImage(lHiColorDir + os.sep + '32x32' + os.sep + 'apps' + os.sep + 'calligrakrita.png') self.button4 = ImageButton(btnImage4, btnImage4, btnImage4, self) self.button4.move(288, 320) self.button4.released.connect(self.button4Released) self.button4.setToolTip('Im a painter button') # Fore/Back color stuff self.arrowsBtn = ImageButton(self.switcharrowsImg, self.switcharrowsImg, self.switcharrowsImg, parent=self) self.arrowsBtn.move(464, 453) self.arrowsBtn.pressed.connect(self.swapFG_BG_Colors) self.defblackwhiteBtn = ImageButton(self.defaultblackwhiteImg, self.defaultblackwhiteImg, self.defaultblackwhiteImg, parent=self) self.defblackwhiteBtn.move(436, 486) self.defblackwhiteBtn.pressed.connect(self.defaultFG_BG_Colors) if not krita: quitAction = QAction("E&xit", self, shortcut="Z", triggered=self.close) self.button.addAction(quitAction) self.button.setContextMenuPolicy(Qt.ActionsContextMenu) # Mask - Anything not black (0, 0, 0, 0-255) in this image will not be shown when drawn out. self.setMask(QBitmap(gImgDir + os.sep + "pixel_palette_mask512.png")) self.drawGUI() self.setFocusPolicy(Qt.StrongFocus) self.setFocus() self.setMouseTracking(True) def __del__(self): print('__del__ %s' % self.__class__.__name__) def mirrorTextureHorizontal(self): self.texture = self.texture.mirrored(horizontal=True, vertical=False) self.drawGUI() self.update() def mirrorTextureVertical(self): self.texture = self.texture.mirrored(horizontal=False, vertical=True) self.drawGUI() self.update() def invertTexture(self): self.texture.invertPixels() self.drawGUI() self.update() def swapFG_BG_Colors(self): self.fgcolor, self.bgcolor = self.bgcolor, self.fgcolor self.drawGUI() self.update() def defaultFG_BG_Colors(self): self.fgcolor = '#FFFFFF' self.bgcolor = '#000000' self.drawGUI() self.update() def show_context_menu(self, point): self._context_menu.exec_(self.button.mapToGlobal(point)) def buttonPressed(self): pass def buttonReleased(self): QApplication.beep() def button1Released(self): QMessageBox.information( QWidget(self), i18n("Test Btn1"), i18n("Hello! This is Krita version %s\n\nwidth %s height %s") % (Application.version(), self.width(), self.height())) def button2Released(self): krita.Krita.instance().action('rotate_canvas_left').trigger() def button3Released(self): krita.Krita.instance().action('rotate_canvas_right').trigger() def button4Released(self): QMessageBox.information( QWidget(self), i18n("Test Btn4"), i18n( '"The position of the artist is humble. He is essentially a channel." Piet Mondrian' )) def saveData(self): with open(gFileDir + os.sep + 'test.txt', 'w') as f: f.write('I Closed Cleanly and wrote out some data') def closeEvent(self, event): self.saveData() event.accept() def sizeHint(self): return QSize(512, 512) def drawGUI(self): # Draw everything to an image first so we can have a local copy # available for pixel RGBA access. qimage = QImage(QSize(512, 512), QImage.Format_ARGB32) qp = QPainter(qimage) qp.setRenderHint(QPainter.Antialiasing) qp.setPen(Qt.NoPen) # Draw the texture. qp.drawImage(0, 0, self.texture) # Draw the graydient bar myQRect = QRect(497, 1, 14, 510) gradient = QLinearGradient(0, 0, 0, 512) gradient.setColorAt(0, QColor(self.fgcolor)) gradient.setColorAt(1, QColor(self.bgcolor)) qp.fillRect(myQRect, gradient) qp.setPen(QPen(QColor(0, 0, 0, 255), 1)) qp.setBrush(QBrush(QColor(0, 0, 0, 0))) qp.drawRect(497, 1, 14, 510) # Draw the fore/back color boxes qp.setPen(Qt.NoPen) qp.drawImage(464, 453, self.switcharrowsImg) qp.drawImage(436, 486, self.defaultblackwhiteImg) qp.setBrush(QColor(self.bgcolor)) qp.drawRect(452, 468, 28, 28) qp.drawImage(452, 468, self.colorboxImg) qp.setBrush(QColor(self.fgcolor)) qp.drawRect(436, 452, 28, 28) qp.drawImage(436, 452, self.colorboxImg) # Save a copy of the finished image locally. self.local_image = qimage def paintEvent(self, event): # Draw the completed image to the widget/window frame. qp = QPainter() qp.begin(self) qp.drawImage(0, 0, self.local_image) qp.end() def updateKritaForeGroundColor(self, color): instance = krita.Krita.instance() views = instance.views() view0 = views[0] managedColor = krita.ManagedColor("RGBA", "U8", "") colorComponents = managedColor.components() colorComponents[0] = color.blueF() # b colorComponents[1] = color.greenF() # g colorComponents[2] = color.redF() # r colorComponents[3] = color.alphaF() # a managedColor.setComponents(colorComponents) view0.setForeGroundColor(managedColor) def updateKritaBackGroundColor(self, color): instance = krita.Krita.instance() views = instance.views() view0 = views[0] managedColor = krita.ManagedColor("RGBA", "U8", "") colorComponents = managedColor.components() colorComponents[0] = color.blueF() # b colorComponents[1] = color.greenF() # g colorComponents[2] = color.redF() # r colorComponents[3] = color.alphaF() # a managedColor.setComponents(colorComponents) view0.setBackGroundColor(managedColor) def mousePressEvent(self, event): if event.button() == Qt.MiddleButton: self.offset = event.globalPos() - self.frameGeometry().topLeft() ## print(self.offset) elif event.button() == Qt.LeftButton: position = QPoint(event.pos().x(), event.pos().y()) color = QColor.fromRgb(self.local_image.pixel(position)) self.fgcolor = color ## print(color.redF(), color.greenF(), color.blueF(), color.alphaF()) # print values from a QColor if krita: self.updateKritaForeGroundColor(color) self.drawGUI() self.update() # Refresh the drawn colors. elif event.button() == Qt.RightButton: position = QPoint(event.pos().x(), event.pos().y()) color = QColor.fromRgb(self.local_image.pixel(position)) self.bgcolor = color ## print(color.redF(), color.greenF(), color.blueF(), color.alphaF()) # print values from a QColor if krita: self.updateKritaBackGroundColor(color) self.drawGUI() self.update() # Refresh the drawn colors. elif event.buttons() == Qt.XButton1: QApplication.beep() # Do something here... Change a texture/mask/page, call a function, etc.... elif event.buttons() == Qt.XButton2: QApplication.beep() # Do something here... Change a texture/mask/page, call a function, etc.... def mouseMoveEvent(self, event): if event.buttons() == Qt.MiddleButton: self.move(event.globalPos() - self.offset) event.accept() self.textbox.setPlainText('x = %s, y = %s' % (event.x(), event.y())) ## def wheelEvent(self, event): ## event.accept() def enterEvent(self, event): self.update() ## QApplication.setOverrideCursor(QCursor(Qt.ArrowCursor)) QApplication.setOverrideCursor( QCursor(QPixmap(gImgDir + os.sep + 'paperairplane_arrow_white24.png'), hotX=0, hotY=0)) def leaveEvent(self, event): self.update() QApplication.restoreOverrideCursor() def event(self, event): if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab: ## print("Tab pressed") if krita: krita.Krita.instance().action( 'view_show_canvas_only').trigger() return False return QWidget.event(self, event)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() # self.image = QImage() self.dirty = True self.filename = None self.recentFiles = [] self.image = None self.image_hist = None self.cv_img = None self.cv_img_gray = None self.cv_blur0 = None self.cv_blur1 = None self.cv_blur2 = None self.cv_blur3 = None self.cv_blur4 = None self.cv_blur5 = None self.cv_blur6 = None self.vhf = None self.hf = None self.mhf = None self.mf = None self.mlf = None self.lf = None self.vlf = None self.vhf_n = None self.hf_n = None self.mhf_n = None self.mf_n = None self.mlf_n = None self.lf_n = None self.mirroredvertically = False self.mirroredhorizontally = False self.image_label = QLabel() self.image_label.setMinimumSize(200, 200) self.image_label.setAlignment(Qt.AlignCenter) self.image_label.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.image_label) hist_dock_widget = QDockWidget("Histogram", self) hist_dock_widget.setObjectName("histDockWidget") hist_dock_widget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.hist_label = QLabel() hist_dock_widget.setWidget(self.hist_label) self.addDockWidget(Qt.RightDockWidgetArea, hist_dock_widget) # setup normal adjustment sliders self.Normal_Dialog = QDialog() self.n_dlg = Ui_NormalDialog() self.n_dlg.setupUi(self.Normal_Dialog) self.n_dlg.hs_vhf.valueChanged.connect(self.normal_change_value) self.n_dlg.hs_hf.valueChanged.connect(self.normal_change_value) self.n_dlg.hs_mhf.valueChanged.connect(self.normal_change_value) self.n_dlg.hs_mf.valueChanged.connect(self.normal_change_value) self.n_dlg.hs_mlf.valueChanged.connect(self.normal_change_value) self.n_dlg.hs_lf.valueChanged.connect(self.normal_change_value) self.n_dlg.hs_vlf.valueChanged.connect(self.normal_change_value) self.printer = None self.size_label = QLabel() self.size_label.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) status = self.statusBar() status.setSizeGripEnabled(False) status.addPermanentWidget(self.size_label) status.showMessage("Ready", 5000) # file menu actionNew = self.createAction("&New", "self.file_new", QKeySequence.New, "filenew", "Create a new image") actionOpen = self.createAction("&Open", "self.file_open", QKeySequence.Open, "fileopen", "Open an existing image") actionSave = self.createAction("&Save", "self.file_save", QKeySequence.Save, "filesave", "Open an existing image") actionSaveAs = self.createAction("Save &As", "self.file_save_as", "Ctrl+Shift+S", "filesaveas", "Save image under a different name") actionPrint = self.createAction("&Print", "self.file_print", QKeySequence.Print, "fileprint", "Print the image") actionExit = self.createAction("&Exit", "self.close", "Ctrl+Q", "filequit", "Exit the program") # edit menu actionInvert = self.createAction("&Invert", "self.edit_invert", "Ctrl+I", "editinvert", "Invert the image", True, "toggled") actionSwap = self.createAction("&Swap", "self.edit_swap", "Ctrl+A", "editswap", "Swap Red and Blue", True, "toggled") actionZoom = self.createAction("&Zoom", "self.edit_zoom", "Alt+Z", "editzoom", "zoom image") actionUnmirror = self.createAction("&UnMirror", "self.edit_un_mirror", "Ctrl+U", "editunmirror", "Un-mirror the image", True, "toggled") actionUnmirror.setChecked(True) actionMirrorH = self.createAction("Mirror &Horizontally", "self.edit_mirror_h", "Ctrl+H", "editmirrorhoriz", "Mirror the image horizontally", True, "toggled") actionMirrorV = self.createAction("Mirror &Vertically", "self.edit_mirror_v", "Ctrl+V", "editmirrorvert", "Mirror the image vertically", True, "toggled") actionBlur = self.createAction("Blur Image", "self.edit_blur", "Ctrl+B", "editblur", "Create four levels of frequency", False) # Help menu actionAbout = self.createAction("&About", "self.help_about", None, None, "About this program") actionHelp = self.createAction("&Help", "self.help_help", None, None, "About editing commands") # normal menu actionNormal = self.createAction("&Make", "self.normal_make", "Ctrl+M", "", "Make normal for image") actionAdjust = self.createAction("&Adjust", "self.normal_adjust", "Ctrl+A", "", "Adjust frequencies") # actionSwap = self.createAction("&Swap", "self.edit_swap", "Ctrl+A", "editswap", "Swap Red and Blue", # True, "toggled") # actionZoom = self.createAction("&Zoom", "self.edit_zoom", "Alt+Z", "editzoom", "zoom image") # actionUnmirror = self.createAction("&UnMirror", "self.edit_un_mirror", "Ctrl+U", "editunmirror", # "Un-mirror the image", True, "toggled") # actionUnmirror.setChecked(True) # actionMirrorH = self.createAction("Mirror &Horizontally", "self.edit_mirror_h", "Ctrl+H", "editmirrorhoriz", # "Mirror the image horizontally", True, "toggled") # actionMirrorV = self.createAction("Mirror &Vertically", "self.edit_mirror_v", "Ctrl+V", "editmirrorvert", # "Mirror the image vertically", True, "toggled") # # actionBlur = self.createAction("Blur Image", "self.edit_blur", "Ctrl+B", "editblur", # "Create four levels of frequency", False) # setup menus self.menuFile = self.menuBar().addMenu("&File") self.menuFileActions = (actionNew, actionOpen, actionSave, actionSaveAs, None, actionPrint, None, actionExit) self.addActions(self.menuFile, self.menuFileActions) menuEdit = self.menuBar().addMenu("&Edit") self.addActions(menuEdit, (actionInvert, actionSwap, actionBlur, actionZoom)) mirror_group = QActionGroup(self) mirror_group.addAction(actionUnmirror) mirror_group.addAction(actionMirrorH) mirror_group.addAction(actionMirrorV) mirrorMenu = menuEdit.addMenu(QIcon(":/editmirror.png"), "&Mirror") self.addActions(mirrorMenu, (actionUnmirror, actionMirrorH, actionMirrorV)) # Normal menu self.menuNormal = self.menuBar().addMenu("&Normal") self.addActions(self.menuNormal, (actionNormal, )) self.addActions(self.menuNormal, (actionAdjust, )) # Help menu menuHelp = self.menuBar().addMenu("&Help") self.addActions(menuHelp, (actionAbout, actionHelp)) # toolbars fileToolbar = self.addToolBar("File") fileToolbar.setObjectName("FileToolBar") self.addActions(fileToolbar, (actionNew, actionOpen, actionSaveAs)) editToolbar = self.addToolBar("Edit") editToolbar.setObjectName("EditToolBar") self.addActions(editToolbar, (actionInvert, actionSwap, None, actionUnmirror, actionMirrorH, actionMirrorV)) self.zoomSpinBox = QSpinBox() self.zoomSpinBox.setRange(1, 400) self.zoomSpinBox.setSuffix(" %") self.zoomSpinBox.setValue(100) self.zoomSpinBox.setToolTip("Zoom the image") self.zoomSpinBox.setStatusTip(self.zoomSpinBox.toolTip()) self.zoomSpinBox.setFocusPolicy(Qt.NoFocus) self.zoomSpinBox.valueChanged.connect(self.show_image) editToolbar.addWidget(self.zoomSpinBox) # setup context menu for image separator = QAction(self) separator.setSeparator(True) self.addActions(self.image_label, (actionInvert, actionSwap, separator, actionUnmirror, actionMirrorH, actionMirrorV)) # setup reset-able actions self.resetableActions = ((actionInvert, False), (actionSwap, False), (actionUnmirror, True)) self.settings = QSettings("Kerr & Associates", "Image Changer") self.restoreGeometry(self.settings.value("geometry", "")) self.restoreState(self.settings.value("windowState", "")) self.recentFiles = self.settings.value("RecentFiles", []) print(self.recentFiles) self.setWindowTitle("Image Changer") self.update_file_menu() QTimer.singleShot(0, self.load_initial_file) # ------------------------------------------------------------------- def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered"): print("inside createAction") """ Helper method to create actions """ action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: slot_string = "action." + signal + ".connect(" + slot + ")" exec(slot_string) if checkable: action.setCheckable(True) return action def addActions(self, target, actions): """ Helper method to add list of actions to menus """ for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def update_file_menu(self): print("inside update_file_menu") self.menuFile.clear() self.addActions(self.menuFile, self.menuFileActions[:-1]) current = self.filename if self.filename is not None else None recent_files = [] print("self.recentFiles: ", self.recentFiles, "\ncurrent:", current) for fname in self.recentFiles: if fname != current and QFile.exists(fname): recent_files.append(fname) if recent_files: self.menuFile.addSeparator() for i, fname in enumerate(recent_files): action = QAction( QIcon(":/icon.png"), "&%s %s" % (str(i + 1), QFileInfo(fname).fileName()), self) action.setData(fname) action.triggered.connect(self.load_file) self.menuFile.addAction(action) self.menuFile.addSeparator() self.menuFile.addAction(self.menuFileActions[-1]) def file_new(self): print("inside file new") if not self.ok_continue(): return dialog = QDialog() dialog_ui = Ui_new_image_dlg() dialog_ui.setupUi(dialog) col = QColor(64, 64, 64) dialog_ui.color_label_pic.pixmap = QImage().fill(col) dialog_ui.color_pushButton.clicked.connect(self.show_color_dlg) dialog.show() dialog.exec_() if dialog.exec_(): print("we got here!!!") self.add_recent_file(self.filename) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) dialog_ui.color_label_pic = QImage() dialog_ui.color_label_pic.fill(QColor(255, 15, 15)) self.image = dialog_ui.color_label_pic self.filename = None self.dirty = True self.show_image() self.size_label.setText( "%d x %d" % (self.image.width(), self.image.height())) self.update_status("Created new image") def file_open(self): """ Select the file name to be opened """ if not self.ok_continue(): return dir = os.path.dirname(self.filename)\ if self.filename is not None else "../images" formats = [ "Images PNG (*.png);;Jpeg (*.jpg *.jpeg);;Targa (*.tga);;SVG (*.svg)" ] options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fname, mask = QFileDialog.getOpenFileName( self, caption="Choose image file to open", directory=dir, filter=formats[0], options=options) if fname: self.load_file(fname=fname) def file_save(self): """ if named, save the file, otherwise get a name then save """ if self.image.isNull(): return if self.filename is None: self.file_save_as() else: if self.image.save(self.filename, None): self.update_status(f"Saved as {self.filename}") self.dirty = False else: self.update_status(f"Failed to save {self.filename}") return def file_save_as(self): """ assign a new filename to save under. """ if self.image.isNull(): return fname = self.filename if self.filename is not None else "." # formats = ['*.bmp', '*.cur', '*.icns', '*.ico', '*.jpeg', '*.jpg', '*.pbm', '*.pgm', # '*.png', '*.ppm', '*.tif', '*.tiff', '*.wbmp', '*.webp', '*.xbm', '*.xpm'] formats = [ "Images PNG (*.png);;Jpeg (*.jpg *.jpeg);;Targa (*.tga);;SVG (*.svg)" ] options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fname, mask = QFileDialog.getSaveFileName( None, caption="Choose name to save as", directory=fname, filter=formats[0], options=options) print(fname, mask) if fname: if "." not in fname: fname += ".png" self.add_recent_file(fname) self.filename = fname self.file_save() def file_print(self): print("filePrint - Not Implemented yet") return def edit_invert(self, on): """ inverts the image channels""" if self.image.isNull(): return self.image.invertPixels() self.show_image() self.dirty = True self.update_status("Inverted" if on else "Un-inverted") print("Invert image") def edit_swap(self, swapped): """ swaps red and blue channels""" if self.image.isNull(): return self.image = self.image.rgbSwapped() self.show_image() self.dirty = True self.update_status( "Blue, Green, Red" if swapped else "Red, Green, Blue") print("editSwap not implemented") def edit_zoom(self): if self.image.isNull(): return percent, ok = QInputDialog.getInt(None, "Image Changer - Zoom", "Percent: ", self.zoomSpinBox.value(), 1, 400) if ok: self.zoomSpinBox.setValue(percent) print("OK: ", ok) return def edit_un_mirror(self, on): print(on, "On") print("edit_un_mirror called") print(self.mirroredhorizontally) print('vertically', self.mirroredvertically) return # if self.image.isNull(): # return # if self.mirroredhorizontally: # self.edit_mirror_h(False) # if self.mirroredvertically: # self.edit_mirror_v(False) def edit_mirror_h(self, on): if self.image.isNull(): return self.image = self.image.mirrored(True, False) self.show_image() self.mirroredhorizontally = not self.mirroredhorizontally print("h", self.mirroredhorizontally) self.dirty = True self.update_status( "Mirrored Horizontally" if on else "Un-mirrored Horizontally") def edit_mirror_v(self, on): if self.image.isNull(): return self.image = self.image.mirrored(False, True) self.show_image() self.mirroredvertically = not self.mirroredvertically print("v", self.mirroredvertically) self.dirty = True self.update_status( "Mirrored Vertically" if on else "Un-mirrored Vertically") def edit_blur(self): self.cv_blur0 = self.cv_img.copy() print(self.cv_blur0.shape) i = 149 cv2.bilateralFilter(self.cv_img, i, i * 2, i / 2, self.cv_blur0, cv2.BORDER_WRAP) # create a Contrast Limited Adaptive Histogram Equalization object # clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(4, 4)) # cl1 = clahe.apply(self.cv_blur0) # # cv2.imshow('clahe_2.jpg', cl1) cv2.imwrite("..\\images\\blurred_normal.png", self.cv_blur0) cv2.imshow('blurred image', self.cv_blur0) # cv2.imshow('equalized', cl1) cv2.waitKey(0) cv2.destroyAllWindows() def normal_adjust(self): if self.image.isNull(): return self.Normal_Dialog.show() self.Normal_Dialog.exec_() pass # QInputDialog.getInt(None, "Image Changer - Zoom", # "Percent: ", # self.zoomSpinBox.value(), 1, 400) # if ok: # self.zoomSpinBox.setValue(percent) # print("OK: ", ok) # return def normal_change_value(self): print("normal_change_value: not implemented") pass def help_about(self): QMessageBox.about( self, "About Image Changer", """<b>Image Changer</b> v %s <p>Copyright © 2019. All rights reserved. <p>This application can be used to perform simple image manipulations. <p>Python %s - Qt %s - PyQt %s on %s """ % (__version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) print("about not yet implemented") return def help_help(self): print("Help not yet implemented") return def load_initial_file(self): print("inside loadInitialFile") settings = QSettings("Kerr & Associates", "Image Changer") files = settings.value('RecentFiles', []) fname = '' if files: fname = files[0] if fname and QFile.exists(fname): self.load_file(fname) print("fname: ", fname) print("loadInitialFile implemented") def load_file(self, fname=None): """ method to actually load the file """ if fname is None: # coming from a recent file action - need to get full file name action = self.sender() print("filename is None - action: ", action, action.data()) if isinstance(action, QAction): fname = action.data() if not self.ok_continue(): return else: return if fname: self.filename = None print(fname) image = QImage(fname) if image.isNull(): print("image is null") message = "Failed to read %s" % fname else: self.add_recent_file(fname) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) print(action, check) self.image = image self.filename = fname self.create_histogram(self.filename) print("calling show_image") self.show_image() print("returned from show_image") self.dirty = False self.size_label.setText("%d x %d" % (image.width(), image.height())) print("%d x %d" % (image.width(), image.height()), self.dirty) message = "Loaded %s" % os.path.basename(fname) self.update_status(message) print("exiting loadFile") def create_histogram(self, fname): self.cv_img = cv2.imread(fname) self.cv_img_gray = cv2.imread(fname, 0) cv2.imshow('cv image', self.cv_img_gray) hist_pics = hist_lines_split(self.cv_img) hist_pics[3] = hist_lines(self.cv_img_gray) res = np.vstack( (hist_pics[0], hist_pics[1], hist_pics[2], hist_pics[3])) # cv2.imshow('histogram', res) # cv2.imshow('image', self.cv_img) self.image_hist = self.convert_cv_to_q_image(res) cv2.waitKey() cv2.destroyAllWindows() def convert_cv_to_q_image(self, cv_image): height, width, channel = cv_image.shape bytes_per_line = width * 3 q_image = QImage(cv_image.data, width, height, bytes_per_line, QImage.Format_RGB888).rgbSwapped() return q_image def add_recent_file(self, fname): if fname is None: print("no filename - returning") return print("self.recentFiles: ", self.recentFiles) print("\n\nfname: ", fname) if fname not in self.recentFiles: self.recentFiles.insert(0, fname) # don't allow list to contain more than 9 file names while len(self.recentFiles) > 9: self.recentFiles.pop(-1) print("final list of recent files: ", self.recentFiles) def update_status(self, message): """ shows status message and updates filename in screen title""" self.statusBar().showMessage(message, 5000) self.hist_label.setText(message) self.hist_label.setPixmap(QPixmap.fromImage(self.image_hist)) if self.filename is not None: self.setWindowTitle("Image Changer - %s[*]" % os.path.basename(self.filename)) elif not self.image.isNull(): self.setWindowTitle("Image Changer - Unnamed[*]") else: self.setWindowTitle("Image Changer[*]") self.setWindowModified(self.dirty) def show_color_dlg(self): print("inside show_color_dlg") col = QColorDialog.getColor() if col.isValid(): self.dialog.setStyleSheet("QWidget | background-color: %s" % col.name()) self.dialog.color_label_pic.pixmap = QImage().fill(col) print("color is valid") def show_image(self, percent=None): print("inside show_image") if self.image.isNull(): print(self.image) return if percent is None: percent = self.zoomSpinBox.value() print("percent: ", percent) factor = percent / 100 print("factor: ", factor) width = self.image.width() * factor height = self.image.height() * factor image = self.image.scaled(width, height, Qt.KeepAspectRatio) self.image_label.setPixmap(QPixmap.fromImage(image)) def closeEvent(self, event): print("inside closeEvent") if self.ok_continue(): self.settings = QSettings("Kerr & Associates", "Image Changer") self.settings.setValue("geometry", self.saveGeometry()) self.settings.setValue("windowState", self.saveState()) self.settings.setValue("RecentFiles", self.recentFiles) QMainWindow.closeEvent(self, event) else: event.ignore() def normal_make(self): """ Create a series of normals """ print("initializing") biblurs.initialize_blurs(self) print("blurring images - may take a while") biblurs.blurs(self) print("creating normals") freq_list = [ self.vhf, self.hf, self.mhf, self.mf, self.mlf, self.lf, self.vlf ] norm_list = [] k_list = [3, 5, 7, 11, 25, 55, 75] for i, freq in enumerate(freq_list): print(type(freq)) print("i:", i) channels = cn.process_image(freq) norm_list.append(channels) n_img_out = cn.display_normal_image(channels) cv2.imwrite("..\\images\\part_norm" + str(i) + ".png", n_img_out) n_img_out_blur = n_img_out.copy() cv2.GaussianBlur(n_img_out, (k_list[i], k_list[i]), k_list[i], n_img_out_blur, 0) # cv2.bilateralFilter(n_img_out, s, s, s, n_img_out_blur, cv2.BORDER_WRAP) cv2.imwrite("..\\images\\a_blur" + str(i) + ".png", n_img_out_blur) return norm_list def ok_continue(self): print("inside ok_continue") if self.dirty: reply = QMessageBox.question( self, "Image Changer - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if reply == QMessageBox.Cancel: return False elif reply == QMessageBox.Yes: self.file_save() print("Dirty: ", self.dirty) new_image = self.image.convertToFormat(4) return True
class MainWindow(QMainWindow): """docstring for MainWindow""" def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.image = QImage() self.dirty = False self.filename = None self.mirroredVertically = False self.mirroredHorizontally = False #Central Widgets self.imageLabel = QLabel() self.imageLabel.setMinimumSize(200, 200) self.imageLabel.setAlignment(Qt.AlignCenter) self.imageLabel.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.imageLabel) #Docks at side logDockWidget =QDockWidget('Log', self) logDockWidget.setObjectName('LogDockWidget') logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea|Qt.RightDockWidgetArea) self.listWidget = QListWidget() logDockWidget.setWidget(self.listWidget) self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) self.printer = None #Status bar below self.sizeLabel = QLabel() self.sizeLabel.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken) status = self.statusBar() status.setSizeGripEnabled(False) status.addPermanentWidget(self.sizeLabel) status.showMessage('Ready', 5000) #file Menu Options fileNewAction = self.createAction('&New...', self.fileNew, QKeySequence.New, 'filenew', 'Create a new Image File' ) fileQuitAction = self.createAction('&Quit...', self.close, 'Ctrl + Q', 'filequit', 'Close the Application' ) fileOpenAction = self.createAction('&Open...', self.fileOpen, QKeySequence.Open, 'fileopen', 'open an existing image file') fileSaveAction = self.createAction('&Save...', self.fileSave, QKeySequence.Save, 'filesave', 'save image file') fileSaveAsAction = self.createAction('Save &As...', self.fileSaveAs, QKeySequence.SaveAs, 'filesaveas', 'save image file using a new name') filePrintAction = self.createAction('&Print...', self.filePrint, QKeySequence.Print, 'fileprint', 'print image') #Edit Menu options editZoomAction = self.createAction('&Zoom', self.editZoom, 'Alt + Z', 'editzoom','zoom the image') editInvertAction = self.createAction('&Invert', self.editInvert, 'Ctrl + I', 'editinvert','Invert the images Color', True, 'toggled') editSwapRedAndBlueAction = self.createAction('S&wap red and blue', self.editSwapRedAndBlue, 'Ctrl + W', 'editswap','swap the images red and blue components', True, 'toggled') editResizeAction = self.createAction('&Resize', self.editResize, 'Ctrl + R', 'editresize', 'resizes the image') #Mirror Groups mirrorGroup = QActionGroup(self) editUnMirrorAction = self.createAction('&Unmirror', self.editUnMirror, 'Ctrl + U', 'editunmirror', 'Unmirror the image', True, 'toggled') mirrorGroup.addAction(editUnMirrorAction) editMirrorHorizontalAction = self.createAction('Mirror &Horizontally', self.editMirrorHorizontal, 'Ctrl + H', 'editmirrorhoriz', 'Horizontally Mirror the image', True, 'toggled') mirrorGroup.addAction(editMirrorHorizontalAction) editMirrorVerticalAction = self.createAction('Mirror &Vertically', self.editMirrorVertical, 'Ctrl + V', 'editmirrorvert', 'Vertically Mirror the image', True, 'toggled') mirrorGroup.addAction(editMirrorVerticalAction) editUnMirrorAction.setChecked(True) #help Menu Options helpAboutAction = self.createAction('&About Image Editor', self.helpAbout) helpHelpAction = self.createAction('&Help', self.helpHelp, QKeySequence.HelpContents) #add Menus to menu bar #fileMenu self.fileMenu = self.menuBar().addMenu('&File') self.fileMenuActions = (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction, None, filePrintAction, fileQuitAction) self.fileMenu.aboutToShow.connect(self.updateFileMenu) #edit Menu editMenu = self.menuBar().addMenu('&Edit') self.addActions(editMenu, (editZoomAction, editInvertAction, editSwapRedAndBlueAction, editResizeAction)) mirrorMenu = editMenu.addMenu(QIcon(':/editmirror.png'), '&Mirror') self.addActions(mirrorMenu, (editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) #help Menu helpMenu = self.menuBar().addMenu('&Help') self.addActions(helpMenu, (helpAboutAction, helpHelpAction)) #Tool bars #File Tool Bars fileToolBar = self.addToolBar('File') fileToolBar.setObjectName('FileToolBar') self.addActions(fileToolBar, (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction)) #Edit Tool Bars editToolBar = self.addToolBar('Edit') editToolBar.setObjectName('EditToolBar') self.addActions(editToolBar, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction, editResizeAction)) self.zoomSpinBox = QSpinBox() self.zoomSpinBox.setRange(1, 400) self.zoomSpinBox.setSuffix(' %') self.zoomSpinBox.setValue(100) self.zoomSpinBox.setToolTip('Zoom the Image') self.zoomSpinBox.setStatusTip(self.zoomSpinBox.toolTip()) self.zoomSpinBox.setFocusPolicy(Qt.NoFocus) self.zoomSpinBox.valueChanged.connect(self.showImage) editToolBar.addWidget(self.zoomSpinBox) self.addActions(self.imageLabel, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction, editResizeAction)) self.resettableActions = ((editInvertAction, False), (editSwapRedAndBlueAction, False), (editUnMirrorAction, True)) settings = QSettings() if settings.value('recentFiles') is not None: self.recentFiles = settings.value('recentFiles') self.restoreGeometry(settings.value('Geometry')) self.restoreState(settings.value('MainWindow/State')) else: self.recentFiles = list() self.updateFileMenu() self.setWindowTitle('Image Editor') QTimer.singleShot(0, self.loadInitialFile) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal='triggered'): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(':/%s.png' % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) return action def addActions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def loadInitialFile(self): settings = QSettings() if settings.value('LastFile'): fname = str(settings.value('LastFile')) if fname and QFile.exists(fname): self.loadFile(fname) def closeEvent(self, event): if self.okToContinue(): settings = QSettings() filename = QVariant(str(self.filename)) if self.filename is not None else QVariant() settings.setValue('LastFile', filename) recentFiles = QVariant(self.recentFiles) if self.recentFiles else QVariant() settings.setValue('recentFiles', recentFiles) settings.setValue('Geometry', QVariant(self.saveGeometry())) settings.setValue('MainWindow/State', QVariant(self.saveState())) else: event.ignore() def okToContinue(self): if self.dirty: reply = QMessageBox.question(self, 'Image Editor - Unsaved Changes', 'Save Unsaved Changes?', QMessageBox.Save|QMessageBox.Discard|QMessageBox.Cancel) if reply == QMessageBox.Cancel: return False elif reply == QMessageBox.Yes: self.fileSave() return True def updateFileMenu(self): self.fileMenu.clear() self.addActions(self.fileMenu, self.fileMenuActions[:-1]) current = str(self.filename) if self.filename is not None else None recentFiles = [] if self.recentFiles: for fname in self.recentFiles: if fname != current and QFile.exists(fname): recentFiles.append(fname) if recentFiles: self.fileMenu.addSeparator() for i, fname in enumerate(recentFiles): action = QAction(QIcon(":/icon.png"), '&%d %s' % (i + 1, QFileInfo(fname).fileName()), self) action.setData(QVariant(fname)) action.triggered.connect(self.loadFile) self.fileMenu.addAction(action) self.fileMenu.addSeparator() self.fileMenu.addAction(self.fileMenuActions[-1]) @pyqtSlot(str) def on_Select_file(self, value): self.loadFile(value) def addRecentFiles(self, fname): if fname is None: return if self.recentFiles is not None: if not fname in self.recentFiles: self.recentFiles.insert(0, fname) while len(self.recentFiles) > 9: self.recentFiles.pop(len(self.recentFiles)-1) def fileNew(self): if not self.okToContinue(): return dialog = newImageDlg.NewImageDlg(self) if dialog.exec_(): self.addRecentFiles(self.filename) self.image = QImage() for action, check in self.resettableActions: action.setChecked(check) self.image = dialog.image() self.filename = None self.dirty = True self.showImage() self.sizeLabel.setText('{0} {1}'.format(self.image.width(), self.image.height())) self.updateStatus('Created New Image') def updateStatus(self, message): self.statusBar().showMessage(message, 5000) self.listWidget.addItem(message) if self.filename is not None: self.setWindowTitle('Image Editor - {0}[*]'.format(os.path.basename(self.filename))) elif not self.image.isNull(): self.setWindowTitle('Image Editor - Unnamed[*]') else: self.setWindowTitle('Image Editor[*]') self.setWindowModified(self.dirty) def fileOpen(self): if not self.okToContinue(): return dir = os.path.dirname(self.filename) if self.filename is not None else '.' formats = ['{0}'.format(str(format).lower()) for format in QImageReader.supportedImageFormats()] formats = ['*.{0}'.format(format[2:5]) for format in formats] fname,_ = QFileDialog.getOpenFileName(self, 'Image Editor - Choose Image', dir, 'Image File ({0})'.format(" ".join(formats))) if fname: self.loadFile(fname) def loadFile(self, fname): #print(fname) if fname is None: action = self.sender() if isinstance(action, QAction): fname = str(action.data().toString) if not self.okToContinue(): return else: return if fname: self.filename = None image = QImage(fname) if image.isNull(): message = 'failed to read {0}'.format(fname) else: self.addRecentFiles(fname) self.image = QImage() for action, check in self.resettableActions: action.setChecked(check) self.image = image self.filename = fname self.showImage() self.dirty = False self.sizeLabel.setText('{0} x {1}'.format(image.width(), image.height())) message = 'Loaded {0}'.format(os.path.basename(fname)) self.updateStatus(message) def fileSave(self): if self.image.isNull(): return if self.filename is None: self.fileSaveAs() else: if self.image.save(self.filename, None): self.updateStatus('Saved as {0}'.format(self.filename)) self.dirty = False else: self.updateStatus('Failed to save {0}'.format(self.filename)) def fileSaveAs(self): if self.image.isNull(): return fname = self.filename if self.filename else '.' formats = ['{0}'.format(str(format).lower()) for format in QImageWriter.supportedImageFormats()] formats = ['*.{0}'.format(format[2:5]) for format in formats] fname,_ = QFileDialog.getSaveFileName(self, 'Image Editor - Save Image', fname, 'Image files ({0})'.format(' '.join(formats))) if fname: if '.' not in fname: fname += '.png' self.addRecentFiles(fname) self.filename = fname self.fileSave() def filePrint(self): pass def editZoom(self): if self.image.isNull(): return percent, ok = QInputDialog.getInt(self, 'Image Editor - Zoom', 'Percent', self.zoomSpinBox.value(), 1, 400) if ok: self.zoomSpinBox.setValue(percent) def editInvert(self, on): if self.image.isNull(): return self.image.invertPixels() self.showImage() self.dirty = True self.updateStatus('Inverted' if on else 'UnInverted') def editUnMirror(self): if self.image.isNull(): return if self.mirroredHorizontally: self.editMirrorHorizontal(False) if self.mirroredVertically: self.editMirrorVertical(False) def editMirrorVertical(self, on): if self.image.isNull(): return self.image = self.image.mirrored(False, True) self.showImage() self.mirroredVertically = not self.mirroredVertically self.dirty = True self.updateStatus('Mirrorred Vertically' if on else 'Unmirrored Vertically') def editMirrorHorizontal(self, on): if self.image.isNull(): return self.image = self.image.mirrored(True, False) self.showImage() self.mirroredHorizontally = not self.mirroredHorizontally self.dirty = True self.updateStatus('Mirrorred Horizontally' if on else 'Unmirrored Horizontally') def editSwapRedAndBlue(self, on): if self.image.isNull(): return self.image = self.image.rgbSwapped() self.showImage() self.dirty = True self.updateStatus('Swapped Red and Blue' if on else 'Unswapped Red and Blue') def editResize(self): if self.image.isNull(): return form = resizeDlg.ResizeDialog(self.image.width(), self.image.height(), self) if form.exec_(): width, height = form.result() if (width == self.image.width() and height == self.image.height()): self.updateStatus('Resized to the same Size') else: self.image = self.image.scaled(width, height) self.showImage() self.dirty = True size = '{0} x {1}'.format(self.image.width(), self.image.height()) self.sizeLabel.setText(size) self.updateStatus('Resized to {0}'.format(size)) def helpAbout(self): QMessageBox.about(self, 'About Image Editor', '''<b>Image Editor v %s <p>Copyright © 2018 Qtrac Ltd. All rights reserved <p>This is an application used to perform simple image manipulations <p>Python %s - Qt %s - PyQt %s on %s''' % (__version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) def helpHelp(self): form = hp.HelpForm('index.html', self) form.show() def showImage(self, percent=None): if self.image.isNull(): return if percent is None: percent = self.zoomSpinBox.value() factor = percent/100.0 width = self.image.width() * factor height = self.image.height() * factor image = self.image.scaled(width, height, Qt.KeepAspectRatio) self.imageLabel.setPixmap(QPixmap.fromImage(image))
class MainWindow(QMainWindow): """ Class documentation goes here. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget @type QWidget """ super(MainWindow, self).__init__(parent) self.image = QImage() self.dirty = False self.filename = None self.mirroredvertically = False self.mirroredhorizontally = False self.imageLabel = QLabel() self.imageLabel.setMinimumSize(200, 200) self.imageLabel.setAlignment(Qt.AlignCenter) self.imageLabel.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.imageLabel) logDockWidget = QDockWidget("Log", self) logDockWidget.setObjectName("LogDockWidget") logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.listWidget = QListWidget() logDockWidget.setWidget(self.listWidget) self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) self.printer = None self.sizeLabel = QLabel() self.sizeLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) status = self.statusBar() status.setSizeGripEnabled(False) status.addPermanentWidget(self.sizeLabel) status.showMessage("Ready", 5000) # clearMessage() fileNewAction = self.createAction("&New...", self.fileNew, QKeySequence.New, "filenew", "Create an image file") fileOpenAction = self.createAction("&Open...", self.fileOpen, QKeySequence.Open, "fileopen", "Open an existing image file") fileSaveAction = self.createAction("&Save", self.fileSave, QKeySequence.Save, "filesave", "Save the image") fileSaveAsAction = self.createAction( "Save &As...", self.fileSaveAs, icon="filesaveas", tip="Save the image using a new name") filePrintAction = self.createAction("&Print", self.filePrint, QKeySequence.Print, "fileprint", "Print the image") fileQuitAction = self.createAction("&Quit", self.close, "Ctrl+Q", "filequit", "Close the application") editInvertAction = self.createAction("&Invert", self.editInvert, "Ctrl+I", "editinvert", "Invert the image's colors", True, "toggled(bool)") editSwapRedAndBlueAction = self.createAction( "Sw&ap Red and Blue", self.editSwapRedAndBlue, "Ctrl+A", "editswap", "Swap the image's red and blue color components", True, "toggled(bool)") editZoomAction = self.createAction("&Zoom...", self.editZoom, "Alt+Z", "editzoom", "Zoom the image") editResizeAction = self.createAction("&Resize...", self.editResize, "Ctrl+R", "editresize", "Resize the image") mirrorGroup = QActionGroup(self) editUnMirrorAction = self.createAction("&Unmirror", self.editUnMirror, "Ctrl+U", "editunmirror", "Unmirror the image", True, "toggled(bool)") mirrorGroup.addAction(editUnMirrorAction) editMirrorHorizontalAction = self.createAction( "Mirror &Horizontally", self.editMirrorHorizontal, "Ctrl+H", "editmirrorhoriz", "Horizontally mirror the image", True, "toggled(bool)") mirrorGroup.addAction(editMirrorHorizontalAction) editMirrorVerticalAction = self.createAction( "Mirror &Vertically", self.editMirrorVertical, "Ctrl+V", "editmirrorvert", "Vertically mirror the image", True, "toggled(bool)") mirrorGroup.addAction(editMirrorVerticalAction) editUnMirrorAction.setChecked(True) helpAboutAction = self.createAction("&About Image Changer", self.helpAbout) helpHelpAction = self.createAction("&Help", self.helpHelp, QKeySequence.HelpContents) # file Menu self.fileMenu = self.menuBar().addMenu("&File") self.fileMenuActions = (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction, None, filePrintAction, fileQuitAction) self.fileMenu.aboutToShow.connect(self.updateFileMenu) # edit Menu editMenu = self.menuBar().addMenu("&Edit") self.addActions(editMenu, (editInvertAction, editSwapRedAndBlueAction, editZoomAction, editResizeAction)) # mirrorMenu mirrorMenu = editMenu.addMenu(QIcon(":/editmirror.png"), "&Mirror") self.addActions(mirrorMenu, (editUnMirrorAction, editMirrorHorizontalAction, editMirrorVerticalAction)) # help Menu helpMenu = self.menuBar().addMenu("&Help") self.addActions(helpMenu, (helpAboutAction, helpHelpAction)) # tool bar fileToolbar = self.addToolBar("File") fileToolbar.setObjectName("FileToolBar") self.addActions(fileToolbar, (fileNewAction, fileOpenAction, fileSaveAsAction)) editToolbar = self.addToolBar("Edit") editToolbar.setObjectName("EditToolBar") self.addActions( editToolbar, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.zoomSpinBox = QSpinBox() self.zoomSpinBox.setRange(1, 400) self.zoomSpinBox.setSuffix(" %") self.zoomSpinBox.setValue(100) self.zoomSpinBox.setToolTip("Zoom the image") self.zoomSpinBox.setStatusTip(self.zoomSpinBox.toolTip()) self.zoomSpinBox.setFocusPolicy(Qt.NoFocus) self.zoomSpinBox.valueChanged[int].connect(self.showImage) editToolbar.addWidget(self.zoomSpinBox) self.addActions( self.imageLabel, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.resetableActions = ((editInvertAction, False), (editSwapRedAndBlueAction, False), (editUnMirrorAction, True)) settings = QSettings("MyCompany", "MyApp") self.recentFiles = settings.value("RecentFiles") # self.recentFiles = [] self.restoreGeometry(QByteArray(settings.value("MainWindow/Geometry"))) self.restoreState(QByteArray(settings.value("MainWindow/State"))) self.setWindowTitle("Image Changer") self.updateFileMenu() QTimer.singleShot(0, self.loadInitialFile) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/{0}.png".format(icon))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None and signal == "triggered()": action.triggered.connect(slot) if slot is not None and signal == "toggled(bool)": action.toggled[bool].connect(slot) if checkable: action.setCheckable(True) return action def addActions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def updateFileMenu(self): self.fileMenu.clear() self.addActions(self.fileMenu, self.fileMenuActions[:-1]) current = self.filename recentFiles = [] # self.recentFiles=[] for fname in self.recentFiles: if fname != current and QFile.exists(fname): # recentFiles.insert(0,fname) recentFiles.append(fname) if recentFiles: self.fileMenu.addSeparator() for i, fname in enumerate(recentFiles): action = QAction( QIcon(":/icon.png"), "&{0} {1}".format(i + 1, QFileInfo(fname).fileName()), self) action.setData(QVariant(fname)) action.triggered[bool].connect(self.loadFile) self.fileMenu.addAction(action) self.fileMenu.addSeparator() self.fileMenu.addAction(self.fileMenuActions[-1]) def okToContinue(self): if self.dirty: reply = QMessageBox.question( self, "Image Changer - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if reply == QMessageBox.Cancel: return False elif reply == QMessageBox.Yes: return self.fileSave() return True def fileNew(self): if not self.okToContinue(): return dialog = newimagedlg.NewImageDlg(self) if dialog.exec_(): self.addRecentFile(self.filename) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = dialog.image() self.filename = None self.dirty = True self.showImage() self.sizeLabel.setText("{0} x {1}".format(self.image.width(), self.image.height())) self.updateStatus("Created new image") def fileOpen(self): if not self.okToContinue(): return dir = (os.path.dirname(self.filename) if self.filename is not None else ".") formats = ([ "*.{0}".format(format.data().decode("ascii").lower()) for format in QImageReader.supportedImageFormats() ]) fname, tpye = QFileDialog.getOpenFileName( self, "Image Changer - Choose Image", dir, "Image files ({0})".format(" ".join(formats))) if fname: self.loadFile(True, fname) def fileSave(self): if self.image.isNull(): return True if self.filename is None: return self.fileSaveAs() else: if self.image.save(self.filename, None): self.updateStatus("Saved as {0}".format(self.filename)) self.dirty = False return True else: self.updateStatus("Failed to save {0}".format(self.filename)) return False def fileSaveAs(self): if self.image.isNull(): return True fname = self.filename if self.filename is not None else "." formats = ([ "*.{0}".format(format.data().decode("ascii").lower()) for format in QImageWriter.supportedImageFormats() ]) fname, tpye = QFileDialog.getSaveFileName( self, "Image Changer - Save Image", fname, "Image files ({0})".format(" ".join(formats))) if fname: if "." not in fname: fname += ".png" self.addRecentFile(fname) self.filename = fname return self.fileSave() return False def filePrint(self): if self.image.isNull(): return if self.printer is None: self.printer = QPrinter(QPrinter.HighResolution) self.printer.setPageSize(QPrinter.Letter) form = QPrintDialog(self.printer, self) if form.exec_(): painter = QPainter(self.printer) rect = painter.viewport() size = self.image.size() size.scale(rect.size(), Qt.KeepAspectRatio) painter.setViewport(rect.x(), rect.y(), size.width(), size.height()) painter.drawImage(0, 0, self.image) def loadFile(self, actiontrigger=False, fname=None): if fname is None: action = self.sender() if isinstance(action, QAction): fname = str(action.data()) if not self.okToContinue(): return else: return print(fname) if fname: self.filename = None image = QImage(fname) if image.isNull(): message = "Failed to read {0}".format(fname) else: self.addRecentFile(fname) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = image self.filename = fname self.showImage() self.dirty = False self.sizeLabel.setText("{0} x {1}".format( image.width(), image.height())) message = "Loaded {0}".format(os.path.basename(fname)) self.updateStatus(message) def loadInitialFile(self): settings = QSettings() fname = str(settings.value("LastFile")) if fname and QFile.exists(fname): self.loadFile(fname) def addRecentFile(self, fname): if fname is None: return if fname not in self.recentFiles: self.recentFiles.insert(0, fname) while len(self.recentFiles) > 9: self.recentFiles.pop() def updateStatus(self, message): self.statusBar().showMessage(message, 5000) self.listWidget.addItem(message) if self.filename is not None: self.setWindowTitle("Image Changer - {0}[*]".format( os.path.basename(self.filename))) elif not self.image.isNull(): self.setWindowTitle("Image Changer - Unnamed[*]") else: self.setWindowTitle("Image Changer[*]") self.setWindowModified(self.dirty) def editInvert(self, on): if self.image.isNull(): return self.image.invertPixels() self.showImage() self.dirty = True self.updateStatus("Inverted" if on else "Uninverted") def editSwapRedAndBlue(self, on): if self.image.isNull(): return self.image = self.image.rgbSwapped() self.showImage() self.dirty = True self.updateStatus( ("Swapped Red and Blue" if on else "Unswapped Red and Blue")) def editZoom(self): if self.image.isNull(): return percent, ok = QInputDialog.getInt(self, "Image Changer - Zoom", "Percent:", self.zoomSpinBox.value(), 1, 400) if ok: self.zoomSpinBox.setValue(percent) def editUnMirror(self, on): if self.image.isNull(): return if self.mirroredhorizontally: self.editMirrorHorizontal(False) if self.mirroredvertically: self.editMirrorVertical(False) def editMirrorHorizontal(self, on): if self.image.isNull(): return self.image = self.image.mirrored(True, False) self.showImage() self.mirroredhorizontally = not self.mirroredhorizontally self.dirty = True self.updateStatus( ("Mirrored Horizontally" if on else "Unmirrored Horizontally")) def editMirrorVertical(self, on): if self.image.isNull(): return self.image = self.image.mirrored(False, True) self.showImage() self.mirroredvertically = not self.mirroredvertically self.dirty = True self.updateStatus( ("Mirrored Vertically" if on else "Unmirrored Vertically")) def editResize(self): if self.image.isNull(): return form = resizedlg.ResizeDlg(self.image.width(), self.image.height(), self) if form.exec_(): width, height = form.result() if (width == self.image.width() and height == self.image.height()): self.statusBar().showMessage("Resized to the same size", 5000) else: self.image = self.image.scaled(width, height) self.showImage() self.dirty = True size = "{0} x {1}".format(self.image.width(), self.image.height()) self.sizeLabel.setText(size) self.updateStatus("Resized to {0}".format(size)) def helpAbout(self): QMessageBox.about( self, "About Image Changer", """Image Changer v {0} Copyright © 2008-9 Qtrac Ltd. All rights reserved. This application can be used to perform simple image manipulations. Python {1} - Qt {2} - PyQt {3} on {4}""".format( __version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) def helpHelp(self): form = helpform.HelpForm("index.html", self) form.show() def showImage(self, percent=None): if self.image.isNull(): return if percent is None: percent = self.zoomSpinBox.value() factor = percent / 100.0 width = self.image.width() * factor height = self.image.height() * factor image = self.image.scaled(width, height, Qt.KeepAspectRatio) self.imageLabel.setPixmap(QPixmap.fromImage(image)) def closeEvent(self, event): if self.okToContinue(): settings = QSettings("MyCompany", "MyApp") settings.setValue("LastFile", self.filename) settings.setValue("RecentFiles", self.recentFiles) settings.setValue("MainWindow/Geometry", self.saveGeometry()) settings.setValue("MainWindow/State", self.saveState()) else: event.ignore()
class VideoWidgetSurface(QAbstractVideoSurface): def __init__(self, widget, parent=None): ''' Constructor ''' super(VideoWidgetSurface, self).__init__(parent) self.widget = widget self.imageFormat = QImage.Format_Invalid self.image = None def supportedPixelFormats(self, handleType=QAbstractVideoBuffer.NoHandle): ''' Available Frames Format ''' formats = [QVideoFrame.PixelFormat()] if handleType == QAbstractVideoBuffer.NoHandle: for f in [ QVideoFrame.Format_RGB32, QVideoFrame.Format_ARGB32, QVideoFrame.Format_ARGB32_Premultiplied, QVideoFrame.Format_RGB565, QVideoFrame.Format_RGB555 ]: formats.append(f) return formats def isFormatSupported(self, _format): ''' Check if is supported VideFrame format ''' imageFormat = QVideoFrame.imageFormatFromPixelFormat( _format.pixelFormat()) size = _format.frameSize() _bool = False if (imageFormat != QImage.Format_Invalid and not size.isEmpty() and _format.handleType() == QAbstractVideoBuffer.NoHandle): _bool = True return _bool def start(self, _format): ''' Start QAbstractVideoSurface ''' imageFormat = QVideoFrame.imageFormatFromPixelFormat( _format.pixelFormat()) size = _format.frameSize() if (imageFormat != QImage.Format_Invalid and not size.isEmpty()): self.sourceRect = _format.viewport() QAbstractVideoSurface.start(self, _format) self.imageFormat = imageFormat self.imageSize = size self.widget.updateGeometry() self.updateVideoRect() return True else: return False def stop(self): ''' Stop Video ''' self.currentFrame = QVideoFrame() self.targetRect = QRect() QAbstractVideoSurface.stop(self) self.widget.update() def present(self, frame): ''' Present Frame ''' if (self.surfaceFormat().pixelFormat() != frame.pixelFormat() or self.surfaceFormat().frameSize() != frame.size()): self.setError(QAbstractVideoSurface.IncorrectFormatError) self.stop() return False else: self.currentFrame = frame self.widget.repaint(self.targetRect) return True def videoRect(self): ''' Get Video Rectangle ''' return self.targetRect def GetsourceRect(self): ''' Get Source Rectangle ''' return self.sourceRect def updateVideoRect(self): ''' Update video rectangle ''' size = self.surfaceFormat().sizeHint() size.scale(self.widget.size().boundedTo(size), Qt.KeepAspectRatio) self.targetRect = QRect(QPoint(0, 0), size) self.targetRect.moveCenter(self.widget.rect().center()) def paint(self, painter): ''' Paint Frame''' if (self.currentFrame.map(QAbstractVideoBuffer.ReadOnly)): oldTransform = painter.transform() if (self.surfaceFormat().scanLineDirection() == QVideoSurfaceFormat.BottomToTop): painter.scale(1, -1) painter.translate(0, -self.widget.height()) self.image = QImage(self.currentFrame.bits(), self.currentFrame.width(), self.currentFrame.height(), self.currentFrame.bytesPerLine(), self.imageFormat) if self.widget._filterSatate.grayColorFilter: self.image = filter.GrayFilter(self.image) if self.widget._filterSatate.MirroredHFilter: self.image = filter.MirrredFilter(self.image) if self.widget._filterSatate.monoFilter: self.image = filter.MonoFilter(self.image) # TODO : Probar en un thread distinto if self.widget._filterSatate.edgeDetectionFilter: try: self.image = filter.EdgeFilter(self.image) except Exception: None # TODO : Probar en un thread distinto if self.widget._filterSatate.contrastFilter: try: self.image = filter.AutoContrastFilter(self.image) except Exception: None if self.widget._filterSatate.invertColorFilter: self.image.invertPixels() painter.drawImage(self.targetRect, self.image, self.sourceRect) if self._interaction.objectTracking and self.widget._isinit: frame = convertQImageToMat(self.image) # Update tracker ok, bbox = self.widget.tracker.update(frame) # Draw bounding box if ok: # qgsu.showUserAndLogMessage( # "bbox : ", str(bbox), level=QGis.Warning) painter.setPen(Qt.blue) painter.drawRect( QRect(int(bbox[0]), int(bbox[1]), int(bbox[2]), int(bbox[3]))) else: qgsu.showUserAndLogMessage("Tracking failure detected ", "", level=QGis.Warning) painter.setTransform(oldTransform) self.currentFrame.unmap() return self.painter
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent=parent) self.image = QImage() self.dirty = False self.filename = None self.mirroredvertically = False self.mirroredhorizonlly = False self.imageLabel = QLabel() self.imageLabel.setMinimumSize(200, 200) self.imageLabel.setAlignment(Qt.AlignCenter) self.imageLabel.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.imageLabel) # 停靠窗体 # 停靠窗体不能放在布局中,所以在创建的时候除了需要提供窗体标题外,还要对其给定父对象 # 通过父对象的设置可以保证停靠窗体不会超出作用域 logDockWidget = QDockWidget('log', self) # 每一个Pyqt对象都有一个对象名,对象名称在调试的时候非常有用 logDockWidget.setObjectName('LogDockWidget') # 默认情况下停靠窗体可以移动,停靠,浮动,关闭,并且可以拖拽的任何区域 # 由于这里的停靠窗体打算保留一个列表,使用setAllowedAreas来限制停靠区域 # 还有一个setFeatures() 可以控制窗口是否可以移动,浮动,关闭等特性。 logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) # 停靠窗体创建好了之后就可以创建窗体需要包含的部件了 # 创建列表窗口部件 self.listWidget = QListWidget() logDockWidget.setWidget(self.listWidget) self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) # 打印图片,首先创建一个printer(打印机实例变量) self.printer = None self.sizeLable = QLabel() self.sizeLable.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) # 创建状态栏,调用showMessage方法显示内容 status = self.statusBar() status.setSizeGripEnabled(False) status.addPermanentWidget(self.sizeLable) status.showMessage("Ready", 5000) # 新建action # 显示名称,槽,快捷键,图标名称,显示status内容 fileNewAction = self.createAction("&New...", self.fileNew, QKeySequence.New, "filenew", "Create an image file") # 打开文件action # 显示名称,槽,快捷键,图标名称,显示status内容 fileOpenAction = self.createAction("&Open...", self.fileOpen, QKeySequence.Open, "fileopen", "Open an existing image file") # 保存action # 显示名称,槽,快捷键,图标显示,显示status内容 fileSaveAction = self.createAction("&Save", self.fileSave, QKeySequence.Save, "filesave", "Save the image") # 另存为action # 显示名称,槽,快捷键,图标显示,显示satus内容 fileSaveAsAction = self.createAction( "&Save as", self.fileSaveAs, QKeySequence.SaveAs, "filesaveas", "Save the image using a new name") # 打印action # 显示名称,槽,快捷键,图标显示,显示status内容 filePrintAction = self.createAction("&Print", self.filePrint, QKeySequence.Print, "fileprint", "print the image") fileQuitAction = self.createAction("&Quit", self.close, "Ctrl+Q", "filequit", "Close the application") # editInvertAction = self.createAction("&Invert", self.editInvert, "Ctrl+I", "editinvert", "Invert the Image's colors", True, True) editSwapRedAndBlueAction = self.createAction( "&Sw&ap Ren and Blue", self.editSwapRedAndBlue, "Ctrl+A", "editswap", "Swap the image's red and blue color components", True, True) editZoomAction = self.createAction("&Zoom...", self.editZoom, "Alt+Z", "editzoom", "Zoom the image") mirrorGroup = QActionGroup(self) editUnMirrorAction = self.createAction("&Unmirror", self.edidUnMirror, "Ctrl+U", "editunmirror", "Unmirror the image", True, True) mirrorGroup.addAction(editUnMirrorAction) editMirrorHorizontalAction = self.createAction( "Mirror &Horizontally", self.editMirrorHorizontal, "Ctrl+H", "editmirrorhoriz", "Horizontally mirror the image", True, True) mirrorGroup.addAction(editMirrorHorizontalAction) editMIrrorVerticalAction = self.createAction( "Mirror &Vertically", self.editMirrorVertical, "Ctrl+V", "editmirrorvert", "Vertically mirror the image", True, True) mirrorGroup.addAction(editMIrrorVerticalAction) helpAboutAction = self.createAction("&About", self.about) helpHelpAction = self.createAction("&Help", self.help) menuBar = self.menuBar() newfile = menuBar.addMenu("&File") self.addActions(newfile, (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction, filePrintAction, fileQuitAction)) editMenu = menuBar.addMenu("&Edit") self.addActions( editMenu, (editInvertAction, editSwapRedAndBlueAction, editZoomAction)) mirrMenu = menuBar.addMenu(QIcon("images/editmirror.png"), "&mirror") self.addActions(mirrMenu, (editUnMirrorAction, editMirrorHorizontalAction, editMIrrorVerticalAction)) helpMenu = menuBar.addMenu("&Help") self.addActions(helpMenu, (helpAboutAction, helpHelpAction)) fileToolBar = self.addToolBar("File") fileToolBar.setObjectName("FileToolBar") self.addActions(fileToolBar, (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction, filePrintAction)) editToolBar = self.addToolBar("Edit") editToolBar.setObjectName("EditToolBar") self.addActions(editToolBar, (editInvertAction, editSwapRedAndBlueAction, editZoomAction, editUnMirrorAction, editMirrorHorizontalAction, editMIrrorVerticalAction)) self.zoomSpinBox = QSpinBox() self.zoomSpinBox.setRange(1, 400) self.zoomSpinBox.setValue(100) self.zoomSpinBox.setSuffix(" %") self.zoomSpinBox.setStatusTip(self.zoomSpinBox.toolTip()) self.zoomSpinBox.setFocusPolicy(Qt.NoFocus) self.zoomSpinBox.valueChanged.connect(self.showImage) editToolBar.addSeparator() editToolBar.addWidget(self.zoomSpinBox) settings = QSettings() # self.recentFiles = settings.value("RecentFiles").toStringList() def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=None, togglesigle=False): """ text:显示内容 """ action = QAction(text, self) if icon is not None: action.setIcon(QIcon("images/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: if togglesigle: action.toggled[bool].connect(slot) else: action.triggered.connect(slot) if checkable is not None: action.setCheckable(True) return action def addActions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def updateStatus(self, message): statusBar = self.statusBar() statusBar.showMessage(message, 5000) self.listWidget.addItem(message) if self.filename is not None: self.setWindowTitle("Image Changer - {0}".format( os.path.basename(self.filename))) elif not self.image.isNull(): self.setWindowTitle("Image Changer - Unnamed") else: self.setWindowTitle("Image Changer[*]") self.setWindowModality(self.dirty) def okToContiune(self): """ 判断图片是否修改没有保存 """ if self.dirty: replay = QMessageBox.question( self, "ImageChanger - Unsaved Changed", "Save unsaved changes", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) # 取消操作 if replay == QMessageBox.Cancel: return # 确定保存 elif replay == QMessageBox.Yes: self.fileSave() return True def fileNew(self): pass def fileOpen(self): dir = os.path.dirname( self.filename) if self.filename is not None else "." # 构建所有QImageReader支持的图片类型列表 formats = [ '*.{0}'.format(format.data().decode("ascii").lower()) for format in QImageReader.supportedImageFormats() ] # getOpenFileName返回 fname, type = QFileDialog.getOpenFileName( self, "Image Changer - Choose Image", dir, "Image files (%s)" % " ".join(formats)) # 如果选中了图片,加载图片 if fname: self.loadFile(fname) def loadFile(self, fname=None): if fname is None: action = self.render() if isinstance(action, QAction): fname = str(action.data()) if fname: self.filename = None try: image = QImage(fname) except Exception as e: print(e) if image.isNull(): message = "Failed to read {0}".format(fname) else: # self.addRecentFile(fname) self.image = QImage() # for action, check in self.resetableActions: # action.setChecked(check) self.image = image self.filename = fname self.showImage() self.dirty = False def addRecentFile(self, fname): if fname is None: return if not self.recentFiles.contains(fname): self.recentFiles.prepend(fname) while self.recentFiles.count() > 9: self.recentFiles.takeLast() def fileSave(self): """ 保存文件 :return: """ if self.image.isNull(): return if self.filename is None: self.fileSaveAs() else: if self.image.save(self.filename, None): self.dirty = False self.updateStatus("Save as {0}".format(self.filename)) else: self.updateStatus("Failed to save {0}".format(self.filename)) def fileSaveAs(self): if self.image.isNull(): return fname = self.filename if self.filename is not None else "." formats = [ "*.{0}".format(format.data().decode("ascii").lower()) for format in QImageWriter.supportedImageFormats() ] fname, type = QFileDialog.getSaveFileName( self, "Image Changer - Save Image", fname, "Image files ({0})".format(" ".join(formats))) if fname: if "." not in fname: fname += ".png" self.filename = fname self.fileSave() def filePrint(self): if self.image.isNull(): return if self.printer is None: self.printer = QPrinter(QPrinter.HighResolution) self.printer.setPageSize(QPrinter.Letter) form = QPrintDialog(self.printer, self) if form.exec_(): painter = QPainter(self.printer) rect = painter.viewport() size = self.image.size() size.scale(rect.size(), Qt.KeepAspectRatio) painter.setViewport(rect.x(), rect.y(), size.width(), size.height()) painter.drawImage(0, 0, self.image) def editInvert(self, on): if self.image.isNull(): return self.image.invertPixels() self.showImage() self.dirty = True def editSwapRedAndBlue(self): if self.image.isNull(): return self.image = self.image.rgbSwapped() self.showImage() self.dirty = True def editZoom(self): if self.image.isNull(): return percent, ok = QInputDialog.getInt(self, "Image Changer - Zoom", "Percent:", self.zoomSpinBox.value(), 1, 400) if ok: self.zoomSpinBox.setValue(percent) def edidUnMirror(self): if self.image.isNull(): return if self.mirroredhorizonlly: self.editMirrorHorizontal(False) if self.mirroredvertically: self.editMirrorVertical(False) def editMirrorHorizontal(self, on): if self.image.isNull(): return self.image = self.image.mirrored(False, True) self.showImage() self.mirroredhorizonlly = not self.mirroredhorizonlly self.dirty = True def editMirrorVertical(self, on): if self.image.isNull(): return self.image = self.image.mirrored(True, False) self.showImage() self.mirroredvertically = not self.mirroredvertically self.dirty = True def showImage(self, parcent=None): if self.image.isNull(): return if parcent is None: parcent = self.zoomSpinBox.value() factor = parcent / 100.0 width = self.image.width() * factor height = self.image.height() * factor image = self.image.scaled(width, height, Qt.KeepAspectRatio) self.imageLabel.setPixmap(QPixmap.fromImage(image)) def about(self): QMessageBox.about( self, "about image changer", """<b>Image Changer</b> v {0} <p>Copyright © 2007 Qtrac Ltd. All rights reserved. <p>This application can be used to perform simple image manipulations. <p>Python {1} - Qt {2} - PyQt {3} on {4}""".format( __version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) def help(self): print("跳转到网页界面!")
class VideoWidgetSurface(QAbstractVideoSurface): def __init__(self, widget, parent=None): ''' Constructor ''' super(VideoWidgetSurface, self).__init__(parent) self.widget = widget self.imageFormat = QImage.Format_Invalid self.image = None self.zoomedrect = None def supportedPixelFormats(self, handleType=QAbstractVideoBuffer.NoHandle): ''' Available Frames Format ''' formats = [QVideoFrame.PixelFormat()] if handleType == QAbstractVideoBuffer.NoHandle: for f in [ QVideoFrame.Format_RGB32, QVideoFrame.Format_ARGB32, QVideoFrame.Format_ARGB32_Premultiplied, QVideoFrame.Format_RGB565, QVideoFrame.Format_RGB555 ]: formats.append(f) return formats def isFormatSupported(self, _format): ''' Check if is supported VideFrame format ''' imageFormat = QVideoFrame.imageFormatFromPixelFormat( _format.pixelFormat()) size = _format.frameSize() _bool = False if (imageFormat != QImage.Format_Invalid and not size.isEmpty() and _format.handleType() == QAbstractVideoBuffer.NoHandle): _bool = True return _bool def start(self, _format): ''' Start QAbstractVideoSurface ''' imageFormat = QVideoFrame.imageFormatFromPixelFormat( _format.pixelFormat()) size = _format.frameSize() if (imageFormat != QImage.Format_Invalid and not size.isEmpty()): self.imageFormat = imageFormat self.imageSize = size self.sourceRect = _format.viewport() QAbstractVideoSurface.start(self, _format) self.widget.updateGeometry() self.updateVideoRect() return True else: return False def stop(self): ''' Stop Video ''' self.currentFrame = QVideoFrame() self.targetRect = QRect() QAbstractVideoSurface.stop(self) self.widget.update() def present(self, frame): ''' Present Frame ''' if (self.surfaceFormat().pixelFormat() != frame.pixelFormat() or self.surfaceFormat().frameSize() != frame.size()): self.setError(QAbstractVideoSurface.IncorrectFormatError) self.stop() return False else: self.currentFrame = frame self.widget.repaint(self.targetRect) qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsVideo", 'Video : '), "Repaint Video", onlyLog=True) return True def videoRect(self): ''' Get Video Rectangle ''' return self.targetRect def GetsourceRect(self): ''' Get Source Rectangle ''' return self.sourceRect def updateVideoRect(self): ''' Update video rectangle ''' size = self.surfaceFormat().sizeHint() size.scale(self.widget.size().boundedTo(size), Qt.KeepAspectRatio) self.targetRect = QRect(QPoint(0, 0), size) self.targetRect.moveCenter(self.widget.rect().center()) def updateVideoZoomRect(self, rect): # TODO : Make this function size = self.surfaceFormat().sizeHint() size.scale(rect.width(), rect.height(), Qt.KeepAspectRatio) self.zoomedrect = rect self.zoomedrect.moveCenter(rect.center()) self.widget.update() def updatetest(self): return def paint(self, painter): ''' Paint Frame''' if (self.currentFrame.map(QAbstractVideoBuffer.ReadOnly)): oldTransform = painter.transform() if (self.surfaceFormat().scanLineDirection() == QVideoSurfaceFormat.BottomToTop): painter.scale(1, -1) painter.translate(0, -self.widget.height()) self.image = QImage(self.currentFrame.bits(), self.currentFrame.width(), self.currentFrame.height(), self.currentFrame.bytesPerLine(), self.imageFormat) if grayColorFilter: self.image = filter.GrayFilter(self.image) if monoFilter: self.image = filter.MonoFilter(self.image) if edgeDetectionFilter: self.image = filter.EdgeFilter(self.image) if contrastFilter: self.image = filter.AutoContrastFilter(self.image) if invertColorFilter: self.image.invertPixels() if zoomRect and self.zoomedrect is not None: painter.drawImage(self.sourceRect, self.image, self.zoomedrect) painter.setTransform(oldTransform) self.currentFrame.unmap() return painter.drawImage(self.targetRect, self.image, self.sourceRect) painter.setTransform(oldTransform) self.currentFrame.unmap() self.currentFrame.release()
class DrawingBox(QWidget): """ Allows to draw an image of a letter. After drawing, sends signal containing image rescaled to the input size of the neural network. """ # signal emitted when user releases mouse after drawing newImage = pyqtSignal(QImage) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.imageSize = GUI_IMAGE_SIZE self.setFixedSize(self.imageSize) self.inverted = False self.pen = QPen(Qt.white if self.inverted else Qt.black, int(np.mean(PEN_WIDTH_RANGE)), Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) self.image = QImage(self.imageSize, QImage.Format_Grayscale8) self.clearImage() self.last_pos = None self.drawing = False @pyqtSlot(int) def setPenWidth(self, pen_width): self.pen.setWidth(pen_width) @pyqtSlot() def invert(self): self.inverted = not self.inverted self.pen.setColor(Qt.white if self.inverted else Qt.black) self.image.invertPixels() self.update() self.pushImage() def pushImage(self): image = self.image.scaled(NET_IMAGE_SIZE, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) self.newImage.emit(image) @pyqtSlot() def clearImage(self): self.image.fill(0 if self.inverted else 255) self.update() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.last_pos = event.pos() self.drawing = True def mouseMoveEvent(self, event): dist = (event.pos() - self.last_pos).manhattanLength() if (event.buttons() & Qt.LeftButton) and self.drawing and dist > 3: self.drawLineTo(event.pos()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.drawing: self.drawLineTo(event.pos()) self.drawing = False self.pushImage() def paintEvent(self, event): "Paints changes in the image on the widget." painter = QPainter(self) dirty_rect = event.rect() painter.drawImage(dirty_rect, self.image, dirty_rect) def drawLineTo(self, end_pos): "Draws line on the image and signals which part is dirty." painter = QPainter(self.image) painter.setPen(self.pen) painter.drawLine(self.last_pos, end_pos) radius = int((self.pen.widthF() / 2) + 2) self.update(QRect(self.last_pos, end_pos).normalized().adjusted( -radius, -radius, radius, radius)) self.last_pos = end_pos
class Spectrogram(QWidget): mouseOver = pyqtSignal(float, float) def __init__(self, fname, parent, config): super().__init__(parent) print(f' INFO: processing {fname}') self.conf = config self.setMouseTracking(True) self.setGeometry(parent.contentsRect()) self.setAttribute(Qt.WA_DeleteOnClose) self.data = { 'name': os.path.basename(fname), 'path': fname, 'pex': 0.0, 'tex': 0.0, 'fex': 0.0, 'notes': '' } self.stored = False self.init_fft() if self.amp is None: parent.next_spectrogram() self.close() return self.init_calculations() self.init_image() self.fit() self.eraser = self.init_eraser(10, 200) self.eraser.maxheight = 200 self.cursorX = self.init_cursor(1, self.height() * 4) self.cursorY = self.init_cursor(self.width() * 4, 1) self.show() def init_fft(self): fft = self.conf['fft'] try: with wave.open(self.data['path'], 'rb') as song: channels, bs, samprate, nsamp, comp, compnam = song.getparams() data = fromstring(song.readframes(nsamp), dtype=uint16) except wave.Error: print(f' WARN: skipping \"{self.data["path"]}\": not a wave file.') return None f, t, amp = spectrogram(data, samprate, fft['window-function'], fft['window'], fft['overlap'], detrend=False, mode='psd') self.freq = f self.time = t self.amp = amp def init_calculations(self): calc = self.conf['calculations'] bot = argmax(self.freq > calc['high-pass']) top = argmin(self.freq < calc['low-pass']) self.freq = self.freq[bot:top] self.amp = self.amp[bot:top, :] self.thresh = self.amp.max() / 10**(calc['threshold'] / 10.0) self.thresh = 255.0 - self.thresh * 255.0 / self.amp.max() self.amp = 255.0 - self.amp * 255.0 / self.amp.max() arr = asarray(self.amp.flat) per = 100 * (arr <= self.thresh).sum() / len(arr) msg = f'{per:.2}%% of signal is above the threshold.' if per > 35.0: print(f' WARN: {msg} Consider using a lower threshold.') elif per < 5.0: print(f' WARN: {msg} Consider using a higher threshold.') else: print(f' INFO: {msg}') def init_image(self): colors = self.conf['colors'] self.amp = flipud(self.amp) self.amp_back = copy(self.amp) self.freq = flipud(self.freq) self.imgdata = array(self.amp, uint8) h, w = self.imgdata.shape self.freq /= 1000.0 self.image = QImage(self.imgdata.tobytes(), w, h, w, QImage.Format_Grayscale8) if colors['invert']: self.image.invertPixels() def init_cursor(self, w, h): cursor = QWidget(self) cursor.setAttribute(Qt.WA_TransparentForMouseEvents) effect = QGraphicsOpacityEffect(cursor) effect.setOpacity(0.4) cursor.setGraphicsEffect(effect) cursor.setGeometry(0, 0, w, h) cursor.setAutoFillBackground(True) p = cursor.palette() p.setColor(cursor.backgroundRole(), QColor(self.conf['colors']['cursor'])) cursor.setPalette(p) cursor.hide() return cursor def init_eraser(self, w, h): eraser = QWidget(self) eraser.setAttribute(Qt.WA_TransparentForMouseEvents) effect = QGraphicsOpacityEffect(eraser) effect.setOpacity(0.4) eraser.setGraphicsEffect(effect) eraser.setGeometry(0, 0, w, h) eraser.setAutoFillBackground(True) p = eraser.palette() p.setColor(eraser.backgroundRole(), QColor(self.conf['colors']['eraser'])) eraser.setPalette(p) eraser.hide() return eraser def fit(self): s = self.image.size() asp = s.width() / (s.height() * self.conf['scale-ratio']) if self.size().height() * asp > self.size().width(): self.resize(self.width(), self.width() / asp) else: self.resize(self.height() * asp, self.height()) def mode_normal(self): self.unsetCursor() self.eraser.hide() self.cursorX.hide() self.cursorY.hide() def mode_cursor(self): self.setCursor(Qt.BlankCursor) self.eraser.hide() self.cursorX.show() self.cursorY.show() def mode_eraser(self): self.setCursor(Qt.BlankCursor) self.cursorX.hide() self.cursorY.hide() self.eraser.show() def undo(self): copyto(self.amp, self.amp_back) self.update() def paintEvent(self, e): # TODO refactor this rats nest qp = QPainter(self) qp.setRenderHints(QPainter.SmoothPixmapTransform | QPainter.Antialiasing) qp.drawImage(self.contentsRect(), self.image, self.image.rect()) r = QRect(0, 0, self.width() - 1, self.height() - 1) qp.setPen(QColor(self.conf['colors']['border'])) qp.drawRect(r) path = QPainterPath() pfreq, ptime, pex, tex = 0.0, 0.0, 0.0, 0.0 qp.setPen(QColor(self.conf['colors']['line'])) for x, y in enumerate(argmin(self.amp, 0)): if self.amp[y, x] > self.thresh: continue t, f = self.time[x], self.freq[y] if self.conf['calculations']['log10-freq']: f = log10(f) if pfreq == 0.0: path.moveTo(x * self.sx, y * self.sy) else: path.lineTo(x * self.sx, y * self.sy) pex += sqrt((f - pfreq)**2 + (t - ptime)**2) tex += t - ptime ptime, pfreq = t, f qp.drawPath(path) self.data['pex'] = pex self.data['tex'] = tex try: self.data['fex'] = pex / tex except ZeroDivisionError: self.data['fex'] = 0.0 #self.fexChanged.emit() # TODO replace this? def resizeEvent(self, e): self.sx = self.width() / self.image.width() self.sy = self.height() / self.image.height() def mousePressEvent(self, e): if self.cursorX.isVisible(): pass elif self.eraser.isVisible(): copyto(self.amp_back, self.amp) pass elif e.button() == Qt.MiddleButton: self.fit() else: self.__pos = self.pos() self.__size = self.size() self.__epos = self.mapToParent(e.pos()) def mouseMoveEvent(self, e): # TODO refactor this rats nest # TODO add eraser size changes y = e.pos().y() if y < self.eraser.maxheight / 2.0: fixed = y * 2.0 elif y > self.height() - self.eraser.maxheight / 2.0: fixed = (self.height() - y) * 2.0 else: fixed = self.eraser.maxheight self.eraser.setFixedHeight(int(clip(fixed, 0, self.eraser.maxheight))) x = e.pos().x() - self.eraser.width() / 2.0 y = e.pos().y() - self.eraser.height() / 2.0 self.eraser.move(x, y) x = e.pos().x() y = e.pos().y() self.cursorX.move(x, 0) self.cursorY.move(0, y) s = self.imgdata.shape x = clip(int(s[1] * e.pos().x() / self.width()), 0, self.time.size) y = clip(int(s[0] * e.pos().y() / self.height()), 0, self.freq.size) self.mouseOver.emit(self.time[x], self.time[y]) if e.buttons() and self.cursorX.isVisible(): self.mouseCursorEvent(e) elif e.buttons() and self.eraser.isVisible(): self.mouseEraseEvent(e) elif e.buttons(): self.mouseNormalEvent(e) def mouseCursorEvent(self, e): pass def mapToImgdata(self, x, y): s = self.imgdata.shape x *= s[1] / self.width() y *= s[0] / self.height() x = int(clip(x, 0, s[1])) y = int(clip(y, 0, s[0])) return x, y def mouseEraseEvent(self, e): w = self.eraser.width() h = self.eraser.height() x = e.pos().x() - w / 2.0 y = e.pos().y() - h / 2.0 x1, y1 = self.mapToImgdata(x, y) x2, y2 = self.mapToImgdata(x + w, y + h) self.amp[y1:y2, x1:x2] = 255.0 self.update(x, 0, w, self.height()) self.stored = False def mouseNormalEvent(self, e): if e.buttons() == Qt.LeftButton: diff = self.mapToParent(e.pos()) - self.__epos + self.__pos self.move(diff) elif e.buttons() == Qt.RightButton: diff = self.mapToParent(e.pos()) - self.__epos w = self.__size.width() + diff.x() h = self.__size.height() + diff.y() self.resize(w, h) def mouseReleaseEvent(self, e): self.cursorX.resize(1, self.height() * 4) self.cursorY.resize(self.width() * 4, 1) self.update(self.contentsRect())