def render_image(self, rgbobj, dst_x, dst_y): """Render the image represented by (rgbobj) at dst_x, dst_y in the pixel space. *** internal method-- do not use *** """ self.logger.debug("redraw surface=%s" % (self.surface)) if self.surface is None: return self.logger.debug("drawing to surface") # Prepare array for rendering # TODO: what are options for high bit depth under Qt? data = rgbobj.get_array(self.rgb_order, dtype=np.uint8) (height, width) = data.shape[:2] daht, dawd, depth = data.shape self.logger.debug("data shape is %dx%dx%d" % (dawd, daht, depth)) # Get qimage for copying pixel data qimage = self._get_qimage(data) drawable = self.surface painter = QPainter(drawable) #painter.setWorldMatrixEnabled(True) # fill surface with background color size = drawable.size() sf_wd, sf_ht = size.width(), size.height() bg = self.viewer.img_bg bgclr = self._get_color(*bg) painter.fillRect(QtCore.QRect(0, 0, sf_wd, sf_ht), bgclr) # draw image data from buffer to offscreen pixmap painter.drawImage(QtCore.QRect(dst_x, dst_y, width, height), qimage, QtCore.QRect(0, 0, width, height))
def _render_offscreen(self, drawable, data, dst_x, dst_y, width, height): # NOTE [A] daht, dawd, depth = data.shape self.logger.debug("data shape is %dx%dx%d" % (dawd, daht, depth)) # Get qimage for copying pixel data qimage = self._get_qimage(data) painter = QtGui.QPainter(drawable) painter.setWorldMatrixEnabled(True) # fill pixmap with background color imgwin_wd, imgwin_ht = self.get_window_size() painter.fillRect(QtCore.QRect(0, 0, imgwin_wd, imgwin_ht), self.img_bg) # draw image data from buffer to offscreen pixmap painter.drawImage(QtCore.QRect(dst_x, dst_y, width, height), qimage, QtCore.QRect(0, 0, width, height)) # Draw a cross in the center of the window in debug mode if self.t_['show_pan_position']: clr = QtGui.QColor() clr.setRgbF(1.0, 0.0, 0.0) painter.setPen(clr) ctr_x, ctr_y = self.get_center() painter.drawLine(ctr_x - 10, ctr_y, ctr_x + 10, ctr_y) painter.drawLine(ctr_x, ctr_y - 10, ctr_x, ctr_y + 10) # render self.message if self.message: self.draw_message(painter, imgwin_wd, imgwin_ht, self.message)
def draw_polygon(self, cpoints): qpoints = list(map(lambda p: QtCore.QPoint(p[0], p[1]), cpoints)) p = cpoints[0] qpoints.append(QtCore.QPoint(p[0], p[1])) qpoly = QPolygon(qpoints) self.cr.drawPolygon(qpoly)
def draw_polygon(self, cpoints): qpoints = [QtCore.QPoint(p[0], p[1]) for p in cpoints] p = cpoints[0] qpoints.append(QtCore.QPoint(p[0], p[1])) qpoly = QPolygon(qpoints) self.cr.drawPolygon(qpoly)
def main(options, args): QtGui.QApplication.setGraphicsSystem('raster') app = QtGui.QApplication(args) app.connect(app, QtCore.SIGNAL('lastWindowClosed()'), app, QtCore.SLOT('quit()')) logger = logging.getLogger("example2") logger.setLevel(options.loglevel) fmt = logging.Formatter(STD_FORMAT) if options.logfile: fileHdlr = logging.handlers.RotatingFileHandler(options.logfile) fileHdlr.setLevel(options.loglevel) fileHdlr.setFormatter(fmt) logger.addHandler(fileHdlr) if options.logstderr: stderrHdlr = logging.StreamHandler() stderrHdlr.setLevel(options.loglevel) stderrHdlr.setFormatter(fmt) logger.addHandler(stderrHdlr) w = FitsViewer(logger) w.resize(524, 540) w.show() app.setActiveWindow(w) if len(args) > 0: w.load_file(args[0]) app.exec_()
def draw_path(self, cp): self.cr.pen().setCapStyle(QtCore.Qt.RoundCap) pts = [ QtCore.QLineF(QtCore.QPointF(cp[i][0], cp[i][1]), QtCore.QPointF(cp[i + 1][0], cp[i + 1][1])) for i in range(len(cp) - 1) ] self.cr.drawLines(pts)
def __init__(self, logger): super(FitsViewer, self).__init__() self.logger = logger fig = Figure() w = FigureCanvas(fig) fi = ImageViewCanvas(logger=self.logger) fi.enable_autocuts('on') fi.set_autocut_params('zscale') fi.enable_auto_orient(True) fi.enable_autozoom('on') #fi.set_callback('drag-drop', self.drop_file) fi.set_callback('none-move', self.motion) fi.set_bg(0.2, 0.2, 0.2) fi.ui_set_active(True) fi.set_figure(fig) self.fitsimage = fi fi.get_bindings().enable_all(True) vbox = QtGui.QVBoxLayout() vbox.setContentsMargins(QtCore.QMargins(2, 2, 2, 2)) vbox.setSpacing(1) vbox.addWidget(w, stretch=1) self.readout = QtGui.QLabel("") vbox.addWidget(self.readout, stretch=0, alignment=QtCore.Qt.AlignCenter) hbox = QtGui.QHBoxLayout() hbox.setContentsMargins(QtCore.QMargins(4, 2, 4, 2)) wopen = QtGui.QPushButton("Open File") wopen.clicked.connect(self.open_file) wquit = QtGui.QPushButton("Quit") wquit.clicked.connect(self.close) hbox.addStretch(1) for w in (wopen, wquit): hbox.addWidget(w, stretch=0) hw = QtGui.QWidget() hw.setLayout(hbox) vbox.addWidget(hw, stretch=0) vw = QtGui.QWidget() self.setCentralWidget(vw) vw.setLayout(vbox) fi.configure(512, 512)
def draw_arrowhead(self, cr, x1, y1, x2, y2): i1, j1, i2, j2 = self.calcVertexes(x1, y1, x2, y2) self.fill(cr, True) cr.pen().setJoinStyle(QtCore.Qt.MiterJoin) cr.drawPolygon( QtGui.QPolygonF([ QtCore.QPointF(x2, y2), QtCore.QPointF(i1, j1), QtCore.QPointF(i2, j2) ])) cr.pen().setJoinStyle(QtCore.Qt.BevelJoin) self.fill(cr, False)
def draw_arrowhead(self, cr, x1, y1, x2, y2): i1, j1, i2, j2 = self.calcVertexes(x1, y1, x2, y2) alpha = getattr(self, 'alpha', 1.0) self.set_fill(cr, True, alpha=alpha) cr.pen().setJoinStyle(QtCore.Qt.MiterJoin) cr.drawPolygon( QPolygonF([ QtCore.QPointF(x2, y2), QtCore.QPointF(i1, j1), QtCore.QPointF(i2, j2) ])) cr.pen().setJoinStyle(QtCore.Qt.BevelJoin) self.set_fill(cr, False)
def __init__(self, logger): super(FitsViewer, self).__init__() self.logger = logger # create the ginga viewer and configure it fi = ImageViewCanvas(self.logger, render='widget') fi.enable_autocuts('on') fi.set_autocut_params('zscale') fi.enable_autozoom('on') fi.set_callback('drag-drop', self.drop_file) fi.set_bg(0.2, 0.2, 0.2) fi.ui_setActive(True) fi.enable_draw(False) self.fitsimage = fi # enable some user interaction bd = fi.get_bindings() bd.enable_all(True) w = fi.get_widget() w.resize(512, 512) # add scrollbar interface around this viewer si = ScrolledView(fi) vbox = QtGui.QVBoxLayout() vbox.setContentsMargins(QtCore.QMargins(2, 2, 2, 2)) vbox.setSpacing(1) vbox.addWidget(si, stretch=1) hbox = QtGui.QHBoxLayout() hbox.setContentsMargins(QtCore.QMargins(4, 2, 4, 2)) wopen = QtGui.QPushButton("Open File") wopen.clicked.connect(self.open_file) wquit = QtGui.QPushButton("Quit") wquit.clicked.connect(self.quit) hbox.addStretch(1) for w in (wopen, wquit): hbox.addWidget(w, stretch=0) hw = QtGui.QWidget() hw.setLayout(hbox) vbox.addWidget(hw, stretch=0) vw = QtGui.QWidget() self.setCentralWidget(vw) vw.setLayout(vbox)
def update_image(self): if (not self.pixmap) or (not self.imgwin): return if isinstance(self.renderer.surface, QPixmap): # optimization when Qt is used as the renderer: # if renderer surface is already an offscreen QPixmap # then we can update the window directly from it #self.pixmap = self.renderer.surface pass else: if isinstance(self.renderer.surface, QImage): # optimization when Qt is used as the renderer: # renderer surface is already a QImage qimage = self.renderer.surface else: # otherwise, get the render surface as an array and # convert to a QImage try: arr = self.renderer.get_surface_as_array(order='BGRA') qimage = self._get_qimage(arr, QImage.Format_RGB32) except Exception as e: self.logger.error("Error from renderer: %s" % (str(e))) return # copy image from renderer to offscreen pixmap painter = QPainter(self.pixmap) #painter.setWorldMatrixEnabled(True) # fill surface with background color size = self.pixmap.size() width, height = size.width(), size.height() # draw image data from buffer to offscreen pixmap painter.drawImage(QtCore.QRect(0, 0, width, height), qimage, QtCore.QRect(0, 0, width, height)) self.logger.debug("updating window from pixmap") if hasattr(self, 'scene'): imgwin_wd, imgwin_ht = self.get_window_size() self.scene.invalidate(0, 0, imgwin_wd, imgwin_ht, QtGui.QGraphicsScene.BackgroundLayer) else: self.imgwin.update()
def draw(self): cpoints = tuple( map(lambda p: self.canvascoords(p[0], p[1]), ((self.x1, self.y1), (self.x2, self.y1), (self.x2, self.y2), (self.x1, self.y2)))) qpoints = list( map(lambda p: QtCore.QPoint(p[0], p[1]), (cpoints + (cpoints[0], )))) qpoly = QPolygon(qpoints) cr = self.setup_cr() cr.drawPolygon(qpoly) if self.editing: self.draw_edit(cr) elif self.showcap: self.draw_caps(cr, self.cap, cpoints) if self.drawdims: fontsize = self.scale_font() cr.setFont(QFont(self.font, pointSize=fontsize)) cx1, cy1 = cpoints[0] cx2, cy2 = cpoints[2] # draw label on X dimension cx = cx1 + (cx2 - cx1) // 2 cy = cy2 + -4 cr.drawText(cx, cy, "%d" % (self.x2 - self.x1)) # draw label on Y dimension cy = cy1 + (cy2 - cy1) // 2 cx = cx2 + 4 cr.drawText(cx, cy, "%d" % (self.y2 - self.y1))
def sort(self, Ncol, order): """Sort table by given column number. """ def sortfn(star): field = self.columns[Ncol][1] return star[field] if QtHelp.have_pyqt4: self.emit(QtCore.SIGNAL("layoutAboutToBeChanged()")) self.starlist = sorted(self.starlist, key=sortfn) if order == QtCore.Qt.DescendingOrder: self.starlist.reverse() if QtHelp.have_pyqt4: self.emit(QtCore.SIGNAL("layoutChanged()"))
def make_button(self, name, wtyp, icon=None, tooltip=None): picon = None if icon: iconfile = os.path.join(self.iconpath, '%s.png' % icon) try: image = QImage(iconfile) pixmap = QPixmap.fromImage(image) picon = QIcon(pixmap) qsize = QtCore.QSize(24, 24) except Exception as e: self.logger.error("Error loading icon '%s': %s" % (iconfile, str(e))) if wtyp == 'button': if picon: w = Widgets.Button() _w = w.get_widget() _w.setIconSize(qsize) _w.setIcon(picon) else: w = Widgets.Button(name) elif wtyp == 'toggle': if picon: w = Widgets.ToggleButton() _w = w.get_widget() _w.setIconSize(qsize) _w.setIcon(picon) else: w = Widgets.ToggleButton() return w
def draw_polygon(self, cpoints): qpoints = list( map(lambda p: QtCore.QPoint(p[0], p[1]), (cpoints + (cpoints[0], )))) qpoly = QPolygon(qpoints) self.cr.drawPolygon(qpoly)
def showxy(self, fitsimage, data_x, data_y): # Cut and show zoom image in zoom window self.zoom_x, self.zoom_y = data_x, data_y image = fitsimage.get_image() if image == None: # No image loaded into this channel return True # If this is a new source, then update our widget with the # attributes of the source if self.fitsimage_focus != fitsimage: self.focus_cb(self.fv, fitsimage) # Cut out and show the zoom detail #self.showzoom(image, data_x, data_y) try: self.zoomtask.stop() except: pass self.zoomtask = QtCore.QTimer() self.zoomtask.setSingleShot(True) self.zoomtask.timeout.connect( lambda: self.showzoom(image, data_x, data_y)) self.zoomtask.start(self.lagtime) return True
def _select_tv(self, star, fromtable=False): self._update_selections() star_idx = self._get_star_path(star) midx = self.table.indexAt(QtCore.QPoint(star_idx, 0)) if not fromtable: self.table.scrollTo(midx)
def __init__(self, logger): super(FitsViewer, self).__init__() self.logger = logger fi = ImageViewZoom(self.logger, render='widget') fi.enable_autocuts('on') fi.set_autocut_params('zscale') fi.enable_autozoom('on') fi.set_callback('drag-drop', self.drop_file) fi.set_bg(0.2, 0.2, 0.2) fi.ui_setActive(True) self.fitsimage = fi bd = fi.get_bindings() bd.enable_pan(True) bd.enable_zoom(True) bd.enable_cuts(True) bd.enable_flip(True) w = fi.get_widget() w.resize(512, 512) vbox = QtGui.QVBoxLayout() vbox.setContentsMargins(QtCore.QMargins(2, 2, 2, 2)) vbox.setSpacing(1) vbox.addWidget(w, stretch=1) hbox = QtGui.QHBoxLayout() hbox.setContentsMargins(QtCore.QMargins(4, 2, 4, 2)) wopen = QtGui.QPushButton("Open File") wopen.clicked.connect(self.open_file) wquit = QtGui.QPushButton("Quit") wquit.clicked.connect(self.quit) hbox.addStretch(1) for w in (wopen, wquit): hbox.addWidget(w, stretch=0) hw = QtGui.QWidget() hw.setLayout(hbox) vbox.addWidget(hw, stretch=0) vw = QtGui.QWidget() self.setCentralWidget(vw) vw.setLayout(vbox)
def browse(self, url): self.logger.debug("Browsing '%s'" % (url)) try: self.browser.load(QtCore.QUrl(url)) self.entry.setText(url) self.browser.show() except Exception as e: self.fv.show_error("Couldn't load web page: %s" % (str(e)))
def __init__(self, logger): super(FitsViewer, self).__init__() self.logger = logger fi = FitsImageZoom(self.logger, render='widget') fi.enable_autocuts('on') fi.enable_zoom('on') fi.enable_cuts(True) fi.enable_flip(True) fi.enable_rotate(True) fi.set_callback('drag-drop', self.drop_file) fi.set_bg(0.2, 0.2, 0.2) fi.ui_setActive(True) self.fitsimage = fi w = fi.get_widget() w.resize(512, 512) vbox = QtGui.QVBoxLayout() vbox.setContentsMargins(QtCore.QMargins(2, 2, 2, 2)) vbox.setSpacing(1) vbox.addWidget(w, stretch=1) hbox = QtGui.QHBoxLayout() hbox.setContentsMargins(QtCore.QMargins(4, 2, 4, 2)) wopen = QtGui.QPushButton("Open File") self.connect(wopen, QtCore.SIGNAL("clicked()"), self.open_file) wquit = QtGui.QPushButton("Quit") self.connect(wquit, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("close()")) hbox.addStretch(1) for w in (wopen, wquit): hbox.addWidget(w, stretch=0) hw = QtGui.QWidget() hw.setLayout(hbox) vbox.addWidget(hw, stretch=0) vw = QtGui.QWidget() self.setCentralWidget(vw) vw.setLayout(vbox)
def position_cursor(self, data_x, data_y): if self.imgwin is None: return win_x, win_y = self.get_canvas_xy(data_x, data_y) w_pt = QtCore.QPoint(win_x, win_y) s_pt = self.imgwin.mapToGlobal(w_pt) # set the cursor position cursor = self.imgwin.cursor() cursor.setPos(s_pt)
def center_cursor(self): if self.imgwin is None: return win_x, win_y = self.get_center() w_pt = QtCore.QPoint(win_x, win_y) s_pt = self.imgwin.mapToGlobal(w_pt) # set the cursor position cursor = self.imgwin.cursor() cursor.setPos(s_pt)
def _render_offscreen(self, drawable, data, dst_x, dst_y, width, height): # NOTE [A] daht, dawd, depth = data.shape self.logger.debug("data shape is %dx%dx%d" % (dawd, daht, depth)) # Get qimage for copying pixel data qimage = self._get_qimage(data) painter = QPainter(drawable) painter.setWorldMatrixEnabled(True) # fill pixmap with background color imgwin_wd, imgwin_ht = self.get_window_size() bgclr = self._get_color(*self.img_bg) painter.fillRect(QtCore.QRect(0, 0, imgwin_wd, imgwin_ht), bgclr) # draw image data from buffer to offscreen pixmap painter.drawImage(QtCore.QRect(dst_x, dst_y, width, height), qimage, QtCore.QRect(0, 0, width, height))
def main(options, args): QtGui.QApplication.setGraphicsSystem('raster') app = QtGui.QApplication(args) app.connect(app, QtCore.SIGNAL('lastWindowClosed()'), app, QtCore.SLOT('quit()')) logger = log.get_logger(name="example2", options=options) w = FitsViewer(logger) w.resize(524, 540) w.show() app.setActiveWindow(w) w.raise_() w.activateWindow() if len(args) > 0: w.load_file(args[0]) app.exec_()
def __init__(self, logger=None, settings=None, render=None): #super(FitsImageQt, self).__init__(logger=logger, settings=settings) FitsImage.FitsImageBase.__init__(self, logger=logger, settings=settings) if render == None: render = 'widget' self.wtype = render if self.wtype == 'widget': self.imgwin = RenderWidget() elif self.wtype == 'scene': self.scene = QtGui.QGraphicsScene() self.imgwin = RenderGraphicsView(self.scene) else: raise FitsImageQtError("Undefined render type: '%s'" % (render)) self.imgwin.fitsimage = self self.pixmap = None self.message = None self.msgtimer = QtCore.QTimer() # QtCore.QObject.connect(self.msgtimer, QtCore.SIGNAL("timeout()"), # self.onscreen_message_off) self.msgtimer.timeout.connect(self.onscreen_message_off) self.msgfont = QtGui.QFont('Sans Serif', pointSize=24) self.set_bg(0.5, 0.5, 0.5, redraw=False) self.set_fg(1.0, 1.0, 1.0, redraw=False) # cursors self.cursor = {} # optimization of redrawing self.defer_redraw = True self.defer_lagtime = 25 self._defer_whence = 0 self._defer_lock = threading.RLock() self._defer_flag = False # self._defer_task = None self._defer_task = QtCore.QTimer() self._defer_task.setSingleShot(True) self._defer_task.timeout.connect(self._redraw) self.t_.setDefaults(show_pan_position=False)
def repaint(self, rect): x1, y1, x2, y2 = rect.getCoords() width = x2 - x1 height = y2 - y1 # redraw the screen from backing pixmap #print "copying pixmap to widget" painter = QtGui.QPainter(self) rect = QtCore.QRect(x1, y1, width, height) painter.drawPixmap(rect, self.pixmap, rect)
def __init__(self, logger, app, kapp, prefs): super(StartMenu, self).__init__() self.logger = logger self.preferences = prefs self.count = 0 self.viewers = {} self.app = app self.kapp = kapp self.app.aboutToQuit.connect(self.quit) vbox = QtGui.QVBoxLayout() vbox.setContentsMargins(QtCore.QMargins(2, 2, 2, 2)) vbox.setSpacing(1) hbox = QtGui.QHBoxLayout() hbox.setContentsMargins(QtCore.QMargins(4, 2, 4, 2)) console = QtGui.QPushButton('Qt Console') if self.kapp.ipkernel is None: console.setEnabled(False) console.clicked.connect(self.kapp.new_qt_console) newfits = QtGui.QPushButton('New Viewer') newfits.clicked.connect(self.new_viewer) wquit = QtGui.QPushButton("Quit") wquit.clicked.connect(self.quit) hbox.addStretch(1) for w in (console, newfits, wquit): hbox.addWidget(w, stretch=0) hw = QtGui.QWidget() hw.setLayout(hbox) vbox.addWidget(hw, stretch=0) vw = QtGui.QWidget() self.setCentralWidget(vw) vw.setLayout(vbox) self.setWindowTitle("Ginga IPython Console") self.showNormal() self.raise_() self.activateWindow()
def make_button(self, name, wtyp, icon=None, tooltip=None): picon = None if icon: iconfile = os.path.join(self.iconpath, '%s.png' % icon) try: image = QtGui.QImage(iconfile) pixmap = QtGui.QPixmap.fromImage(image) picon = QtGui.QIcon(pixmap) qsize = QtCore.QSize(24, 24) except Exception, e: self.logger.error("Error loading icon '%s': %s" % (iconfile, str(e)))
def get_rgb_image_as_buffer(self, output=None, format='png', quality=90): ibuf = output if ibuf is None: ibuf = BytesIO() imgwin_wd, imgwin_ht = self.get_window_size() qpix = self.pixmap.copy(0, 0, imgwin_wd, imgwin_ht) qbuf = QtCore.QBuffer() qbuf.open(QtCore.QIODevice.ReadWrite) qpix.save(qbuf, format=format, quality=quality) ibuf.write(bytes(qbuf.data())) qbuf.close() return ibuf
def redo_delay(self, fitsimage): # Delay regeneration of thumbnail until most changes have propagated try: self.thmbtask.stop() except: pass self.thmbtask = QtCore.QTimer() self.thmbtask.setSingleShot(True) self.thmbtask.timeout.connect(lambda: self.redo_thumbnail(fitsimage)) self.thmbtask.start(self.lagtime) #print "added delay task..." return True