def verticalLine(self, size, color): width = size height = size textureImage = QImage(width, height, QImage.Format_ARGB32) # Transparent background for row in range(height): for column in range(width): textureImage.setPixelColor(column, row, Qt.transparent) # Vertical line for row in range(height): column = int(width / 2) textureImage.setPixelColor(column, row, color) brush = QBrush() brush.setTextureImage(textureImage) return brush
def __init__(self, radius): super().__init__() self.setFixedSize(2*radius, 2*radius) self.qc_Color = QColor(0, 0, 0, 255) self.radius = radius self.qpm_Image = QPixmap() #Create the image qi_image = QImage(self.width(), self.height(), QImage.Format_RGB32) for i in range(self.width()): for j in range(self.height()): color = QColor(0, 0, 0, 255) h = (np.arctan2(i - self.radius, j - self.radius) + np.pi) / (2. * np.pi) s = np.sqrt(np.power(i - self.radius, 2) + np.power(j - self.radius, 2)) / self.radius v = 1.0 if s < 1.0: color.setHsvF(h, s, v, 1.0) qi_image.setPixelColor(i, j, color) self.qpm_Image.convertFromImage(qi_image) self.setPixmap(self.qpm_Image)
class RetroDrawWidget(QWidget): """ Defines widget for displaying and handling all retro drawing. """ def __init__(self, fgIndex, bgIndex, palette, parent=None): super(RetroDrawWidget, self).__init__(parent) self.canvasSize = QSize(256, 192) self.canvasCenter = QPoint(self.canvasSize.width() / 2, self.canvasSize.height() / 2) self.fgIndex = fgIndex self.bgIndex = bgIndex self.palette = palette self.scale = 4 self.screenSize = self.canvasSize * self.scale self.screenCenter = self.canvasCenter * self.scale self.grid = QImage(self.screenSize, QImage.Format_RGBA8888) self.grid.fill(QColor(0, 0, 0, 0)) for y in range(0, self.screenSize.height()): for x in range(0, self.screenSize.width(), 8 * self.scale): self.grid.setPixelColor(x, y, QColor(0, 0, 0, 255)) for x in range(0, self.screenSize.width()): for y in range(0, self.screenSize.height(), 8 * self.scale): self.grid.setPixelColor(x, y, QColor(0, 0, 0, 255)) self._gridEnabled = True self._gridOpacity = 0.2 self._guideFilename = None self._guide = None self._guideEnabled = True self._guideOpacity = 0.2 self._guideCoords = QPoint(0, 0) self._guideZoom = 1.0 self._scratch = QImage(self.screenSize, QImage.Format_RGBA8888) self._scratch.fill(QColor(0, 0, 0, 0)) self.drawable = ZXSpectrumBuffer() self.setCursor(Qt.CrossCursor) self._mouseLastPos = self.getLocalMousePos() self._mouseDelta = QPoint(0, 0) self._mousePressed = MouseButton.NONE self._drawMode = DrawingMode.DOTTED self._lineState = None def encodeToJSON(self): rdict = dict() rdict["fg_index"] = self.fgIndex rdict["bg_index"] = self.bgIndex rdict["palette"] = self.palette rdict["grid_enabled"] = self._gridEnabled rdict["grid_opacity"] = self._gridOpacity rdict["guide_filename"] = self._guideFilename rdict["guide_enabled"] = self._guideEnabled rdict["guide_opacity"] = self._guideOpacity rdict["guide_coords_x"] = self._guideCoords.x() rdict["guide_coords_y"] = self._guideCoords.y() rdict["guide_zoom"] = self._guideZoom rdict["drawable"] = self.drawable.encodeToJSON() return rdict def decodeFromJSON(self, json): self.fgIndex = json["fg_index"] self.bgIndex = json["bg_index"] self.palette = json["palette"] self._gridEnabled = json["grid_enabled"] self._gridOpacity = json["grid_opacity"] self._guideFilename = json["guide_filename"] self._guide = QPixmap(self._guideFilename) self._guideEnabled = json["guide_enabled"] self._guideOpacity = json["guide_opacity"] self._guideCoords.setX(json["guide_coords_x"]) self._guideCoords.setY(json["guide_coords_y"]) self._guideZoom = json["guide_zoom"] self.drawable.decodeFromJSON(json["drawable"]) def sizeHint(self): return self.screenSize def minimumSizeHint(self): return self.screenSize def getLocalMousePos(self): return self.mapFromGlobal(QCursor.pos()) def paintEvent(self, event): super(RetroDrawWidget, self).paintEvent(event) painter = QPainter(self) rectTarget = self.rect() rectSource = QRect(QPoint(0, 0), self.canvasSize) painter.drawPixmap(rectTarget, self.drawable.qpixmap, rectSource) if self._guide and self._guideEnabled: painter.setOpacity(self._guideOpacity) self._paintZoomedGuide(painter) if self._gridEnabled: painter.setOpacity(self._gridOpacity) painter.drawImage(rectTarget, self.grid, rectTarget) painter.setOpacity(1.0) painter.drawImage(rectTarget, self._scratch, rectTarget) painter.end() def mousePressEvent(self, event): self._mouseLastPos = self.getLocalMousePos() if event.button() == Qt.LeftButton: self._mousePressed = MouseButton.LEFT elif event.button() == Qt.RightButton: self._mousePressed = MouseButton.RIGHT if self._drawMode == DrawingMode.PEN: if self._mousePressed == MouseButton.LEFT: self.doDraw(event.localPos(), True) elif self._drawMode == DrawingMode.DOTTED: if self._mousePressed == MouseButton.LEFT: self.doDraw(event.localPos(), True) elif self._mousePressed == MouseButton.RIGHT: self.doDraw(event.localPos(), False) elif self._drawMode == DrawingMode.ERASE: if self._mousePressed == MouseButton.LEFT: self.doDraw(event.localPos(), False) elif self._drawMode == DrawingMode.LINE: if self._mousePressed == MouseButton.LEFT: self._lineState = [event.localPos(), event.localPos()] painter = QPainter(self._scratch) painter.setPen(Qt.black) painter.drawLine(self._lineState[0], self._lineState[1]) painter.end() self.update(self.rect()) elif self._drawMode == DrawingMode.ATTR: if self._mousePressed == MouseButton.LEFT: self.doDrawAttr(event.localPos()) def mouseReleaseEvent(self, event): if self._drawMode == DrawingMode.LINE: if self._mousePressed == MouseButton.LEFT and self._lineState: self._lineState[1] = event.localPos() painter = QPainter(self._scratch) painter.setPen(Qt.black) painter.drawLine(self._lineState[0], self._lineState[1]) self.doDrawLine(self._lineState[0], self._lineState[1]) painter.end() self._lineState = None self._scratch.fill(QColor(0, 0, 0, 0)) self.update(self.rect()) self._mousePressed = MouseButton.NONE def mouseMoveEvent(self, event): oldMousePos = self._mouseLastPos newMousePos = self.getLocalMousePos() self._mouseDelta = newMousePos - self._mouseLastPos self._mouseLastPos = newMousePos if self._drawMode == DrawingMode.PEN: if self._mousePressed == MouseButton.LEFT: self.doDrawLine(oldMousePos, newMousePos) if self._drawMode == DrawingMode.DOTTED: if self._mousePressed == MouseButton.LEFT: self.doDraw(newMousePos, True) elif self._mousePressed == MouseButton.RIGHT: self.doDraw(newMousePos, False) elif self._drawMode == DrawingMode.ERASE: if self._mousePressed == MouseButton.LEFT: self.doDraw(newMousePos, False) elif self._drawMode == DrawingMode.GUIDE: if self._mousePressed == MouseButton.LEFT: self._guideCoords += self._mouseDelta self.update(self.rect()) elif self._drawMode == DrawingMode.LINE: if self._mousePressed == MouseButton.LEFT and self._lineState: painter = QPainter(self._scratch) self._scratch.fill(QColor(0, 0, 0, 0)) painter.setPen(Qt.black) self._lineState[1] = event.localPos() painter.drawLine(self._lineState[0], self._lineState[1]) painter.end() self.update(self.rect()) elif self._drawMode == DrawingMode.ATTR: if self._mousePressed == MouseButton.LEFT: self.doDrawAttr(event.localPos()) def wheelEvent(self, event): if self._mousePressed: if self._drawMode == DrawingMode.GUIDE: delta = event.pixelDelta().y() * 0.01 if delta != 0.0: self._guideZoom += delta self._guideZoom = self.clamp(self._guideZoom, 0.1, 8.0) self.update(self.rect()) @staticmethod def clamp(value, min, max): if value < min: return min elif value > max: return max return value def doDraw(self, localPos, setPixel): x = localPos.x() // self.scale y = localPos.y() // self.scale if setPixel: self.drawable.setPixel(x, y, self.fgIndex, self.bgIndex, self.palette) else: self.drawable.erasePixel(x, y, self.fgIndex, self.bgIndex, self.palette) self.update(self.rect()) def doDrawAttr(self, localPos): x = localPos.x() // self.scale y = localPos.y() // self.scale self.drawable.setAttr(x, y, self.fgIndex, self.bgIndex, self.palette) self.update(self.rect()) def doDrawLine(self, localStartPos, localEndPos): x1 = localStartPos.x() // self.scale y1 = localStartPos.y() // self.scale x2 = localEndPos.x() // self.scale y2 = localEndPos.y() // self.scale self.drawable.drawLine(x1, y1, x2, y2, self.fgIndex, self.bgIndex, self.palette) self.update(self.rect()) def setColor(self, fgIndex, bgIndex, palette): self.fgIndex = fgIndex self.bgIndex = bgIndex self.palette = palette def saveImage(self, filename, format=None): self.drawable.saveBuffer(filename) def setGrid(self, checked): self._gridEnabled = checked self.repaint() def setGridOpacity(self, value): self._gridOpacity = value / 100.0 self.repaint() def setGuideImage(self, filename): self._guideFilename = filename self._guide = QPixmap(self._guideFilename) self.repaint() def setGuide(self, checked): self._guideEnabled = checked self.repaint() def setGuideOpacity(self, value): self._guideOpacity = value / 100.0 self.repaint() def setMode(self, mode): self._drawMode = mode def clear(self): self.drawable.clear(self.fgIndex, self.bgIndex, self.palette) self.repaint() def _paintZoomedGuide(self, painter): guideZoom = self._guide.scaled(self._guide.width() * self._guideZoom, self._guide.height() * self._guideZoom, Qt.KeepAspectRatio) pos = QPoint( self._guideCoords.x() + (self.screenCenter.x() - guideZoom.width() / 2), self._guideCoords.y() + (self.screenCenter.y() - guideZoom.height() / 2)) painter.drawPixmap(pos, guideZoom) def copyGuide(self): # This isn't the most efficient way to do this but it just needs to be # reasonably fast self.drawable.clear(self.fgIndex, self.bgIndex, self.palette) guide_copy = QImage(self.screenSize, QImage.Format_RGBA8888) guide_copy.fill(QColor("white")) painter = QPainter(guide_copy) self._paintZoomedGuide(painter) shrunk_guide = guide_copy.smoothScaled(self.canvasSize.width(), self.canvasSize.height()) mono_guide = shrunk_guide.convertToFormat(QImage.Format_Mono) for x in range(0, self.canvasSize.width()): for y in range(0, self.canvasSize.height()): if mono_guide.pixel(x, y) == QColor("black"): self.drawable.setPixel(x, y, self.fgIndex, self.bgIndex, self.palette) painter.end() self.repaint()
class MainWindow(QMainWindow): def __init__(self): # load setting json file with open('setting.json') as f: self.app_setting = json.load(f) # Status of window super().__init__() self.title = 'Image Editor' self.left = 70 self.top = 70 self.width = 800 self.height = 700 # Status of view image self.org_qimg = None self.org_img_width = 0 self.org_img_height = 0 self.layer_pixmap = None self.layer_width = 0 self.layer_height = 0 self.layer_alpha = 50.0 # Prepare color bar data self.colormap_gain = self.app_setting["SoftwareSetting"]["process"][ "colormap"]["gain"] self.colormap_offset_x = self.app_setting["SoftwareSetting"][ "process"]["colormap"]["offset_x"] self.colormap_offset_green = self.app_setting["SoftwareSetting"][ "process"]["colormap"]["offset_green"] self.colormap_data = [ colormap.colorBarRGB(x * 0.001, self.colormap_offset_x, self.colormap_offset_green, self.colormap_gain) for x in range(1000) ] self.img_edit_mode = 'cursor' self.draw_color = QColor(255, 0, 0) self.draw_tool_size = 5 self.eraser_color = QColor(0, 0, 0, 0) # setup user interface components self.setup_ui() # Setup user interface components def setup_ui(self): # Set main window title self.setWindowTitle(self.title) # Set main wiodow initial position self.setGeometry(self.left, self.top, self.width, self.height) # Set up mainWindow's layout self.mainWidget = QWidget(self) # Note not to forget this code. self.main_layout = QVBoxLayout() # Set menu for main window self.main_menu = self.menuBar() self.file_menu = self.main_menu.addMenu('File') self.edit_menu = self.main_menu.addMenu('Edit') self.help_menu = self.main_menu.addMenu('Help') self.main_layout.addWidget(self.main_menu) # Set "Original Image Open" menu self.org_img_open_button = QAction( self.style().standardIcon(getattr(QStyle, 'SP_FileDialogStart')), 'Open Orginal Image', self) self.org_img_open_button.setShortcut('Ctrl+O') self.org_img_open_button.triggered.connect(self.open_org_img_dialog) self.file_menu.addAction(self.org_img_open_button) # Set "Save layer image" menu self.layer_img_save_button = QAction( self.style().standardIcon(getattr(QStyle, 'SP_FileDialogEnd')), 'Save Layer Image', self) self.layer_img_save_button.setShortcut('Ctrl+S') self.layer_img_save_button.triggered.connect(self.save_layer_image) self.file_menu.addAction(self.layer_img_save_button) # Set "Save compose image(original + layer image)" menu self.compose_img_save_button = QAction( self.style().standardIcon(getattr(QStyle, 'SP_FileDialogEnd')), 'Save Compose Image', self) self.compose_img_save_button.setShortcut('Ctrl+D') self.compose_img_save_button.triggered.connect(self.save_compose_image) self.file_menu.addAction(self.compose_img_save_button) # Set "exit software" menu self.exit_button = QAction( self.style().standardIcon(getattr(QStyle, 'SP_DialogCloseButton')), 'Exit', self) self.exit_button.setShortcut('Ctrl-Q') self.exit_button.setStatusTip('Exit software') self.exit_button.triggered.connect(self.close) self.file_menu.addAction(self.exit_button) self.upper_layout = QHBoxLayout() self.main_layout.addLayout(self.upper_layout) # Set image display area self.gview_default_size = 500 self.graphics_view = QGraphicsView() self.graphics_view.setFixedSize(self.gview_default_size, self.gview_default_size) self.graphics_view.setObjectName("imageDisplayArea") self.upper_layout.addWidget(self.graphics_view) # image display area's contents self.scene = GraphicsSceneForMainView(self.graphics_view, self) self.imgs_pixmap = [] self.imgs = [] self.img_status_layout = QVBoxLayout() self.upper_layout.addLayout(self.img_status_layout) # Set tranparency value of layer image self.transparency_title_label = QLabel('layer transparency value') self.img_status_layout.addWidget(self.transparency_title_label) transparency = round((1.0 - self.layer_alpha / 255.0) * 100) self.img_transparency_edit = QLineEdit(str(transparency)) self.img_transparency_sld = QSlider(Qt.Horizontal) self.img_transparency_sld.setFocusPolicy(Qt.NoFocus) self.img_transparency_sld.setRange(0, 100) self.img_transparency_sld.setValue(transparency) self.transparency_layout = QFormLayout() self.transparency_layout.addRow(self.img_transparency_sld, self.img_transparency_edit) self.img_status_layout.addLayout(self.transparency_layout) # Signal of transparency value changed self.img_transparency_sld.valueChanged.connect( self.transparency_change_sld) self.img_transparency_edit.textChanged.connect( self.transparency_change_edit) self.img_editor_layout = QVBoxLayout() self.img_status_layout.addLayout(self.img_editor_layout) # Set layer image editor tool self.img_editor_tool1_layout = QHBoxLayout() self.img_editor_layout.addLayout(self.img_editor_tool1_layout) self.tool_button_size = 64 # Set Mouse cursor self.mouse_cursor_button = QPushButton() self.mouse_cursor_button.setIcon(QIcon('icon/cursor.png')) self.mouse_cursor_button.setCheckable(True) self.mouse_cursor_button.setIconSize( QSize(self.tool_button_size, self.tool_button_size)) self.img_editor_tool1_layout.addWidget(self.mouse_cursor_button) # Set Pen self.pen_button = QPushButton() self.pen_button.setIcon(QIcon('icon/pen.png')) self.pen_button.setCheckable(True) self.pen_button.setIconSize( QSize(self.tool_button_size, self.tool_button_size)) self.img_editor_tool1_layout.addWidget(self.pen_button) # Set Eraser self.eraser_button = QPushButton() self.eraser_button.setIcon(QIcon('icon/eraser.png')) self.eraser_button.setCheckable(True) self.eraser_button.setIconSize( QSize(self.tool_button_size, self.tool_button_size)) self.img_editor_tool1_layout.addWidget(self.eraser_button) # Group button of mouse cursor, pen, eraser self.img_editor_tool1_group1 = QButtonGroup() self.img_editor_tool1_group1.addButton(self.mouse_cursor_button, 1) self.img_editor_tool1_group1.addButton(self.pen_button, 2) self.img_editor_tool1_group1.addButton(self.eraser_button, 3) # Set signal-slot of image editor button self.mouse_cursor_button.toggled.connect( self.mouse_cursor_button_toggled) self.pen_button.toggled.connect(self.pen_button_toggled) self.eraser_button.toggled.connect(self.eraser_button_toggled) # Set color bar self.color_bar_width = 64 self.color_bar_height = 256 self.color_bar_view = QGraphicsView() self.color_bar_view.setFixedSize(self.color_bar_width + 3, self.color_bar_height + 3) self.color_bar_scene = GraphicsSceneForTools() self.color_bar_img = QImage(self.color_bar_width, self.color_bar_height, QImage.Format_RGB888) for i in range(self.color_bar_height): # Set drawing pen for colormap ii = round(i * (1000 / 256)) color = QColor(self.colormap_data[ii][0], self.colormap_data[ii][1], self.colormap_data[ii][2]) pen = QPen(color, 1, Qt.SolidLine, \ Qt.SquareCap, Qt.RoundJoin) self.color_bar_scene.addLine(0, self.color_bar_height - i - 1, self.color_bar_width, self.color_bar_height - i - 1, pen=pen) for j in range(self.color_bar_width): self.color_bar_img.setPixelColor(j, self.color_bar_height - i - 1, color) self.color_bar_scene.set_img_content(self.color_bar_img) self.color_bar_view.setScene(self.color_bar_scene) # Connect signal to slot of color_bar_scene self.color_bar_scene.img_info.connect(self.set_selected_color) self.img_editor_tool1_layout.addWidget(self.color_bar_view) # Set thickness of Pen or Eraser self.draw_status_layout = QVBoxLayout() self.draw_thick_title_label = QLabel('thickness of pen or eraser') self.draw_status_layout.addWidget(self.draw_thick_title_label) self.draw_thick_edit = QLineEdit(str(self.draw_tool_size)) self.draw_thick_sld = QSlider(Qt.Horizontal) self.draw_thick_sld.setFocusPolicy(Qt.NoFocus) self.draw_thick_sld.setRange(1, 30) self.draw_thick_sld.setValue(self.draw_tool_size) self.draw_thick_layout = QFormLayout() self.draw_thick_layout.addRow(self.draw_thick_sld, self.draw_thick_edit) self.draw_status_layout.addLayout(self.draw_thick_layout) self.img_editor_layout.addLayout(self.draw_status_layout) # Signal of draw thickness value changed self.draw_thick_sld.valueChanged.connect(self.draw_thick_change_sld) self.draw_thick_edit.textChanged.connect(self.draw_thick_change_edit) # Set view area of selected color self.select_color_view_size = 64 self.select_color_view = QGraphicsView() self.select_color_view.setFixedSize(self.select_color_view_size + 3, self.select_color_view_size + 3) self.select_color_scene = QGraphicsScene() brush = QBrush(self.draw_color) self.select_color_rect = self.select_color_scene.addRect(QRect(0, 0, self.select_color_view_size, self.select_color_view_size), \ brush=brush) self.select_color_view.setScene(self.select_color_scene) self.select_color_title_label = QLabel('Selected color') self.selected_color_layout = QFormLayout() self.selected_color_layout.addRow(self.select_color_title_label, self.select_color_view) self.img_editor_layout.addLayout(self.selected_color_layout) # Set save button self.save_button_layout = QHBoxLayout() self.img_status_layout.addLayout(self.save_button_layout) self.layer_save_button = QPushButton('Save layer image') self.layer_save_button.setIcon(QIcon('icon/layer_save.png')) self.layer_save_button.setIconSize( QSize(self.tool_button_size, self.tool_button_size)) self.compose_save_button = QPushButton( 'Save composed original and layer image') self.compose_save_button.setIcon(QIcon('icon/compose_save.png')) self.compose_save_button.setIconSize( QSize(self.tool_button_size, self.tool_button_size)) self.save_button_layout.addWidget(self.layer_save_button) self.save_button_layout.addWidget(self.compose_save_button) self.layer_save_button.clicked.connect(self.save_layer_image) self.compose_save_button.clicked.connect(self.save_compose_image) # Set display area of selected file path self.org_img_path_title_label = QLabel('original image file: ') self.org_img_path_label = QLabel('') self.file_path_layout = QFormLayout() self.file_path_layout.addRow(self.org_img_path_title_label, self.org_img_path_label) self.bottom_layout = QVBoxLayout() self.bottom_layout.addLayout(self.file_path_layout) self.main_layout.addLayout(self.bottom_layout) self.mainWidget.setLayout(self.main_layout) self.setCentralWidget(self.mainWidget) # Original image select Function def open_org_img_dialog(self): options = QFileDialog.Options() org_img_default_path = self.app_setting["SoftwareSetting"][ "file_path"]["org_img_dir"] self.org_img_file_path, selected_filter = QFileDialog.getOpenFileName(self, 'Select original image', org_img_default_path, \ 'Image files(*.jpg *jpeg *.png)', options=options) org_img_dir_path, org_img_file = os.path.split(self.org_img_file_path) org_img_bare_name, org_img_ext = os.path.splitext(org_img_file) self.org_img_path_label.setText(self.org_img_file_path) self.set_image_on_viewer() def set_image_on_viewer(self): # Delete existing image item if len(self.imgs_pixmap) != 0: for item in self.imgs_pixmap: self.scene.removeItem(item) self.scene.clear_contents() self.imgs_pixmap.clear() self.imgs.clear() # load original image self.org_qimg = QImage(self.org_img_file_path) self.org_pixmap = QPixmap.fromImage(self.org_qimg) org_img_size = self.org_qimg.size() self.org_img_width = org_img_size.width() self.org_img_height = org_img_size.height() # Set layer image self.layer_qimg = QImage(self.org_img_width, self.org_img_height, QImage.Format_RGBA8888) self.layer_qimg.fill(QColor(0, 0, 0, self.layer_alpha)) self.layer_pixmap = QPixmap.fromImage(self.layer_qimg) self.imgs.append(self.org_qimg) self.imgs.append(self.layer_qimg) # Set image to scene self.imgs_pixmap.append(QGraphicsPixmapItem(self.org_pixmap)) self.scene.addItem(self.imgs_pixmap[-1]) self.imgs_pixmap.append(QGraphicsPixmapItem(self.layer_pixmap)) self.scene.addItem(self.imgs_pixmap[-1]) self.scene.set_img_contents(self.imgs) # Set scene to graphics view self.graphics_view.setScene(self.scene) self.graphics_view.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.show() # Slot function of transparency slider changed def transparency_change_sld(self, value): self.img_transparency_edit.setText(str(value)) self.layer_alpha = int(255 * (1.0 - (value / 100))) # Change layer image's transparency(alpha value) for y in range(self.org_img_height): for x in range(self.org_img_width): self.layer_qimg.setPixelColor( QPoint(x, y), QColor(0, 0, 0, self.layer_alpha)) self.layer_pixmap = QPixmap.fromImage(self.layer_qimg) # remove previous layer image self.scene.removeItem(self.imgs_pixmap[-1]) self.imgs_pixmap.pop(-1) # add new layer image to scene self.imgs_pixmap.append(QGraphicsPixmapItem(self.layer_pixmap)) self.scene.addItem(self.imgs_pixmap[-1]) self.show() # Slot function of transparency text edit changed def transparency_change_edit(self, value): if int(value) < 0 or int(value) > 100: return self.img_transparency_sld.setValue(int(value)) self.layer_alpha = int(255 * (1.0 - (int(value) / 100.0))) # Change layer image's transparency(alpha value) for y in range(self.org_img_height): for x in range(self.org_img_width): self.layer_qimg.setPixelColor( QPoint(x, y), QColor(0, 0, 0, self.layer_alpha)) self.layer_pixmap = QPixmap.fromImage(self.layer_qimg) # remove previous layer image self.scene.removeItem(self.imgs_pixmap[-1]) self.imgs_pixmap.pop(-1) # add new layer image to scene self.imgs_pixmap.append(QGraphicsPixmapItem(self.layer_pixmap)) self.scene.addItem(self.imgs_pixmap[-1]) self.show() # slot(receiver of signal) of mouse_cursor_button toggled def mouse_cursor_button_toggled(self, checked): if checked: self.img_edit_mode = 'cursor' self.scene.set_mode(self.img_edit_mode) self.color_bar_scene.set_mode(self.img_edit_mode) # slot(receiver of signal) of pen_button toggled def pen_button_toggled(self, checked): if checked: self.img_edit_mode = 'pen' self.scene.set_mode(self.img_edit_mode) self.color_bar_scene.set_mode(self.img_edit_mode) # slot(receiver of signal) of eraser_button toggled def eraser_button_toggled(self, checked): if checked: self.img_edit_mode = 'eraser' self.scene.set_mode(self.img_edit_mode) self.color_bar_scene.set_mode(self.img_edit_mode) self.draw_color = self.eraser_color self.select_color_scene.removeItem(self.select_color_rect) brush = QBrush(self.draw_color) self.select_color_rect = self.select_color_scene.addRect(QRect(0, 0, self.select_color_view_size, self.select_color_view_size), \ brush=brush) self.select_color_view.setScene(self.select_color_scene) # Slot of color bar clicked for selection color def set_selected_color(self, color): # Delete existng image item self.select_color_scene.removeItem(self.select_color_rect) self.draw_color = color brush = QBrush(self.draw_color) self.select_color_rect = self.select_color_scene.addRect(QRect(0, 0, self.select_color_view_size, self.select_color_view_size), \ brush=brush) self.select_color_view.setScene(self.select_color_scene) # Slot function of draw thicikeness slider changed def draw_thick_change_sld(self, value): self.draw_thickness_edit.setText(str(value)) self.draw_tool_size = value # Slot function of draw thicikeness text editor changed def draw_thick_change_edit(self, value): if int(value) < 1 or int(value) > 30: return self.draw_thickness_sld.setValue(int(value)) def make_layer_image(self): for i, line in enumerate(self.scene.lines): pen = self.scene.pens[i] pen_size = int(pen.width()) pen_color = pen.color() # start pixel of line x1 = int(line.x1()) y1 = int(line.y1()) # end pixel of line x2 = int(line.x2()) y2 = int(line.y2()) dx = int(line.dx()) dy = int(line.dy()) # When only 1pixl line if dx <= 1 and dy <= 1: draw_pix_x1_s = max(x1 - int(pen_size / 2), 0) draw_pix_x1_e = min(x1 + int(pen_size / 2), self.org_img_width - 1) draw_pix_y1_s = max(y1 - int(pen_size / 2), 0) draw_pix_y1_e = min(y1 + int(pen_size / 2), self.org_img_height - 1) # for Pen's size for y in range(draw_pix_y1_s, draw_pix_y1_e): for x in range(draw_pix_x1_s, draw_pix_x1_e): self.layer_qimg.setPixelColor(x, y, pen_color) draw_pix_x2_s = max(x2 - int(pen_size / 2), 0) draw_pix_x2_e = min(x2 + int(pen_size / 2), self.org_img_width - 1) draw_pix_y2_s = max(y2 - int(pen_size / 2), 0) draw_pix_y2_e = min(y2 + int(pen_size / 2), self.org_img_height - 1) # for Pen's size for y in range(draw_pix_y2_s, draw_pix_y2_e): for x in range(draw_pix_x2_s, draw_pix_x2_e): self.layer_qimg.setPixelColor(x, y, pen_color) else: # For avoid devide by 0 if dx == 0: for y in range(y1, y2 + 1): draw_pix_y_s = y - int(pen_size / 2) draw_pix_y_e = y + int(pen_size / 2) # for Pen's size for yy in range(draw_pix_y_s, draw_pix_y_e): self.layer_qimg.setPixelColor(x1, yy, pen_color) else: grad = dy / dx # Choose coordinates with small slope not to skip pixels if grad >= 1.0: for x in range(dx): y = y1 + int(grad * x + 0.5) draw_pix_x_s = max(x1 + x - int(pen_size / 2), 0) draw_pix_x_e = min(x1 + x + int(pen_size / 2), self.org_img_width - 1) draw_pix_y_s = max(y - int(pen_size / 2), 0) draw_pix_y_e = min(y + int(pen_size / 2), self.org_img_height - 1) # for Pen's size for yy in range(draw_pix_y_s, draw_pix_y_e + 1): for xx in range(draw_pix_x_s, draw_pix_x_e + 1): self.layer_qimg.setPixelColor( xx, yy, pen_color) else: for y in range(dy): x = x1 + int(1 / grad * y + 0.5) draw_pix_y_s = max(y1 + y - int(pen_size / 2), 0) draw_pix_y_e = min(y1 + y + int(pen_size / 2), self.org_img_height - 1) draw_pix_x_s = max(x - int(pen_size / 2), 0) draw_pix_x_e = min(x + int(pen_size / 2), self.org_img_width - 1) # for Pen's size for yy in range(draw_pix_y_s, draw_pix_y_e + 1): for xx in range(draw_pix_x_s, draw_pix_x_e + 1): self.layer_qimg.setPixelColor( xx, yy, pen_color) # Slot function of save layer image button clicked def save_layer_image(self): self.make_layer_image() layer_img_default_path = self.app_setting["SoftwareSetting"][ "file_path"]["layer_img_dir"] options = QFileDialog.Options() file_name, selected_filete = QFileDialog.getSaveFileName(self, 'Save layer image', layer_img_default_path, \ 'image files(*.png, *jpg)', options=options) #print('layer image save name:{file}'.format(file=file_name)) self.layer_qimg.save(file_name) ret = QMessageBox(self, 'Success', 'layer image is saved successfully', QMessageBox.Ok) # Make composed orignal and layered image def make_compose_image(self): self.make_layer_image() self.compose_qimg = QImage(self.org_img_width, self.org_img_height, QImage.Format_RGBA8888) painter = QPainter(self.compose_qimg) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.drawImage(0, 0, self.org_qimg) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.drawImage(0, 0, self.layer_qimg) painter.end() # Slot function of save composer original and layer image button clicked def save_compose_image(self): self.make_compose_image() compose_img_default_path = self.app_setting["SoftwareSetting"][ "file_path"]["compose_img_dir"] options = QFileDialog.Options() file_name, selected_fileter = QFileDialog.getSaveFileName(self, 'Save composed image', compose_img_default_path, \ 'image files(*.png, *jpg)', options=options) #print('compose image save name:{file}'.format(file=file_name)) self.compose_qimg.save(file_name) ret = QMessageBox(self, 'Success', 'compose image is saved successfully', QMessageBox.Ok)
class Bot(QQuickPaintedItem): def __init__(self, parent=None): super(Bot, self).__init__(parent) self._map = None self.image = QImage(300, 300, QImage.Format_RGBA8888) self.image.fill('#000000ff') self.timer = QTimer() self.position = QPoint() self.around = None self.angle = 0 self.last_front = False self.timer.timeout.connect(lambda: self.drawCircle(self.position)) def paint(self, painter): painter.drawImage(QRect(0, 0, self.width(), self.height()), self.image) def setMap(self, map: Map): if not map: return print('Map', map) self._map = map self._map.clicked.connect(self.handleClick) self.image = QImage(self.map.image.width(), self.map.image.height(), QImage.Format_RGBA8888) self.image.fill('#000000ff') def getMap(self) -> Map: return self._map map = Property(Map, getMap, setMap) @Slot(QPoint) def handleClick(self, point: QPoint): self.position = point self.around = False self.drawCircle(point) self.timer.start(100) def mousePressEvent(self, event): a, b = event.pos().x() * self.image.width() / self.width(), event.pos( ).y() * self.image.height() / self.height() def mouseMoveEvent(self, event): a, b = event.pos().x() * self.image.width() / self.width(), event.pos( ).y() * self.image.height() / self.height() @Slot(QPoint) def drawCircle(self, point: QPoint): a = point.x() b = point.y() angle_step_size = 64 radius = 90 initPoint = QPoint(-1, -1) finalPoint = initPoint firstPoint = finalPoint self.image.fill('#000000ff') painter = QPainter(self.image) lidarPoints = [] painter.setPen('#00ff00') painter.drawRect(point.x() - 1, point.y() - 1, 2, 2) front = QPoint(math.cos(self.angle), math.sin(self.angle)) self.image.setPixelColor(point + front, QColor('#0000ff')) painter.setPen('#ff0000') for step in range(0, angle_step_size - 1): angle = 2 * math.pi * step / angle_step_size + self.angle initPoint = finalPoint for r in range(1, radius): x = point.x() + r * math.cos(angle) y = point.y() + r * math.sin(angle) finalPoint = QPoint(x, y) if not self.map.pixel(x, y): break if initPoint != QPoint(-1, -1): painter.drawLine(initPoint, finalPoint) else: firstPoint = finalPoint lidarPoints.append(finalPoint - point) painter.drawLine(finalPoint, firstPoint) painter.end() self.update() self.runObstacleAvoidance(point, lidarPoints) def runObstacleAvoidance(self, point, lidarPoints): # Calculate distance # Target 287, 293 destiny = QPoint(287, 293) ao = destiny - point rcoli = 2 # Get only the front, right, back and left values lpoints = [ lidarPoints[int(i * (len(lidarPoints) + 1) / 4)] for i in range(4) ] dist = lambda d: (d.x()**2 + d.y()**2)**0.5 dist2 = lambda d, d2: ((d.x() - d2.x())**2 + (d.y() - d2.y())**2)**0.5 dists = [dist(p) for p in lpoints] # Calculate next point nextPoint = point if dists[0] < rcoli and not self.around: self.around_point = copy.copy(point) self.around = dists[0] < rcoli or self.around # Bug algorithm if not self.around: if abs(ao.x()) > abs(ao.y()): if ao.x() > 0: nextPoint += QPoint(1, 0) self.angle = 0 else: nextPoint += QPoint(-1, 0) self.angle = math.pi else: if ao.y() > 0: nextPoint += QPoint(0, 1) self.angle = math.pi / 2 else: nextPoint += QPoint(0, -1) self.angle = 3 * math.pi / 2 else: if dist2(self.around_point, point) + dist2(destiny, point) - dist2( destiny, self.around_point) < 3 and dist2( self.around_point, point) > 3: self.around = False elif dists[3] < rcoli: if dists[0] > rcoli: self.position += QPoint(math.cos(self.angle), math.sin(self.angle)) else: self.angle += math.pi / 2 elif dists[0] < rcoli: self.position += QPoint(math.cos(self.angle), math.sin(self.angle)) self.angle += math.pi / 2 elif dists[1] < rcoli: self.angle += math.pi else: self.position += QPoint(math.cos(self.angle - math.pi / 2), math.sin(self.angle - math.pi / 2)) self.angle -= math.pi / 2
class GraphicsWindow(QGraphicsView): def __init__(self, parent=None): super().__init__(parent) print('you in the GraphicsWindow') self.count = 0 self.scene_class = Graphics_scene() self.setScene(self.scene_class) self.update_view() self.table = self.scene_class.spreadsheet.table self.table.cellClicked.connect(self.cellClicked) def update_view(self): if self.count < self.scene_class.Imagelimit: #print(self.count) self.count_UP() self.Show_Image() def prev_view(self): if self.count > 1: self.count_DOWN() self.Show_Image() def Show_Image(self): print('show_Image') self.imgpass = '******'.format(self.count) self.Image = QImage(self.imgpass) color = QColor() color.setRgb(0, 0, 255, a=255) joint_list = self.take_joint() if joint_list: #print('joint_listは存在する', joint_list) for joint in joint_list: if joint != '': jointx, jointy = joint.split(',') jointx, jointy = int(float(jointx)), int(float(jointy)) for x in range(jointx - 4, jointx + 5): self.Image.setPixelColor(x, jointy - 1, color) self.Image.setPixelColor(x, jointy, color) self.Image.setPixelColor(x, jointy + 1, color) for y in range(jointy - 4, jointy + 5): self.Image.setPixelColor(jointx - 1, y, color) self.Image.setPixelColor(jointx, y, color) self.Image.setPixelColor(jointx + 1, y, color) else: continue else: pass self.image_item = QGraphicsPixmapItem(QPixmap(self.Image)) self.scene().clear() self.scene().addItem(self.image_item) self.height, self.width, _ = (cv2.imread(self.imgpass)).shape self.setFixedSize(self.width, self.height) #print('width, height', self.width, self.height) return self def count_UP(self): self.count += 1 def count_DOWN(self): self.count -= 1 def take_joint(self): #print('take_joint') joint_list = [] print('next_csv is ', self.scene_class.spreadsheet.next_csv) for row in range(100): for column in range(18): #print('text is ', self.scene_class.spreadsheet.table.item(row, column).text()) try: joint_list.append( self.scene_class.spreadsheet.table.item(row, column).text()) except AttributeError: joint_list.append('') # print(joint_list) return joint_list def mouseReleaseEvent(self, event): print('view の中でクリックを検知しました') print(type(event)) self.scene_class.mouseReleaseEvent(event) self.Show_Image() def cellClicked(self): print('cell is clicked') self.tableRow, self.tableColumn = self.table.currentRow( ), self.table.currentColumn() print('row, column', self.tableRow, self.tableColumn) self.scene_class.spreadsheet.control.humancombo.setCurrentIndex( self.tableRow) self.scene_class.spreadsheet.control.jointcombo.setCurrentIndex( self.tableColumn) self.Show_Image() coord = self.table.currentItem().text() print('coord is ', coord) color = QColor() color.setRgb(255, 0, 0, a=255) if coord: jointx, jointy = coord.split(',') jointx, jointy = int(jointx), int(jointy) for x in range(jointx - 6, jointx + 7): self.Image.setPixelColor(x, jointy - 1, color) self.Image.setPixelColor(x, jointy, color) self.Image.setPixelColor(x, jointy + 1, color) for y in range(jointy - 6, jointy + 7): self.Image.setPixelColor(jointx - 1, y, color) self.Image.setPixelColor(jointx, y, color) self.Image.setPixelColor(jointx + 1, y, color) self.image_item = QGraphicsPixmapItem(QPixmap(self.Image)) self.scene().addItem(self.image_item)