def draw_selection_rect(self, painter): cr, sr = self.target, self.selection_state.rect painter.setPen(self.SELECT_PEN) painter.setRenderHint(QPainter.Antialiasing, False) if self.selection_state.current_mode == 'selected': # Shade out areas outside the selection rect for r in ( QRectF(cr.topLeft(), QPointF(sr.left(), cr.bottom())), # left QRectF(QPointF(sr.left(), cr.top()), sr.topRight()), # top QRectF(QPointF(sr.right(), cr.top()), cr.bottomRight()), # right QRectF(sr.bottomLeft(), QPointF(sr.right(), cr.bottom())), # bottom ): painter.fillRect(r, self.SHADE_COLOR) dr = self.get_drag_rect() if self.selection_state.in_selection and dr is not None: # Draw the resize rectangle painter.save() painter.setCompositionMode(QPainter.RasterOp_SourceAndNotDestination) painter.setClipRect(sr.adjusted(1, 1, -1, -1)) painter.drawRect(dr) painter.restore() # Draw the selection rectangle painter.setCompositionMode(QPainter.RasterOp_SourceAndNotDestination) painter.drawRect(sr)
def draw_pixmap(self, painter): p = self.current_scaled_pixmap width, height = p.width(), p.height() pwidth, pheight = self.last_canvas_size x = int(abs(pwidth - width)/2.) y = int(abs(pheight - height)/2.) self.target = QRectF(x, y, width, height) painter.drawPixmap(self.target, p, QRectF(p.rect()))
def __call__(self, canvas): if canvas.has_selection and canvas.selection_state.rect is not None: pimg = self.after_image img = self.after_image = QImage(canvas.current_image) rect = QRectF(*get_selection_rect(img, canvas.selection_state.rect, canvas.target)) p = QPainter(img) p.setRenderHint(p.SmoothPixmapTransform, True) p.drawImage(rect, pimg, QRectF(pimg.rect())) p.end() return self.after_image
def _paint_title(self, p: QPainter): p.drawLine(Block.padding, 35 + Block.padding, self.width() - Block.padding, 35 + Block.padding) p.setPen(self._fg_color) f = p.font() f.setPointSize(10) f.setBold(True) p.setFont(f) p.drawText(QRectF(4 + Block.padding, Block.padding + 2, self.width() - 12, 25), str(self.settings["Name"].value())) f.setBold(False) f.setPointSize(8) p.setPen(QColor(self._fg_color.red(), self._fg_color.green(), self._fg_color.blue(), 100)) p.setFont(f) p.drawText(QRectF(4 + Block.padding, 18 + Block.padding, self.width() - 12, 15), str(self.__type_name))
def paint(self, painter, option, index): QStyledItemDelegate.paint(self, painter, option, self.dummy_index) painter.save() painter.setClipRect(QRectF(option.rect)) painter.translate(option.rect.topLeft()) self.to_doc(index, option).drawContents(painter) painter.restore()
def _paint_content(self, p: QPainter): t = self.settings["Value"].type() p.setPen(self._fg_color) f = self.font() f.setPointSize(9) p.setFont(f) p.drawText(QRectF(Block.padding + 5, self.height() / 2 + 10, self.width() - Block.padding * 2 - 10, 30), Qt.AlignCenter, str(t)) f.setPointSize(12) p.setFont(f) s = 'None' if self.settings["Value"].data() is not None: s = str(self.settings["Value"].data()) p.drawText(QRectF(Block.padding + 5, self.height() / 2 - 5, self.width() - Block.padding * 2 - 10, 30), Qt.AlignCenter, s)
def _paint_title(self, p: QPainter): f = p.font() f.setBold(True) f.setPointSize(8) p.setPen(QColor(self._fg_color.red(), self._fg_color.green(), self._fg_color.blue(), 180)) p.setFont(f) title = str(self.name()) + ' : ' + self.type_name() p.drawText(QRectF(6 + Block.padding, 25 + Block.padding, self.width() - 12, 15), title)
def paint(self, painter, option, index): painter.save() painter.setClipRect(QRectF(option.rect)) if hasattr(QStyle, 'CE_ItemViewItem'): QApplication.style().drawControl(QStyle.CE_ItemViewItem, option, painter) elif option.state & QStyle.State_Selected: painter.fillRect(option.rect, option.palette.highlight()) painter.translate(option.rect.topLeft()) self.to_doc(index).drawContents(painter) painter.restore()
def get_drag_rect(self): sr = self.selection_state.rect dc = self.selection_state.drag_corner if None in (sr, dc): return dx, dy = self.dc_size if None in dc: # An edge if dc[0] is None: top = sr.top() if dc[1] == 'top' else sr.bottom() - dy ans = QRectF(sr.left() + dx, top, sr.width() - 2 * dx, dy) else: left = sr.left() if dc[0] == 'left' else sr.right() - dx ans = QRectF(left, sr.top() + dy, dx, sr.height() - 2 * dy) else: # A corner left = sr.left() if dc[0] == 'left' else sr.right() - dx top = sr.top() if dc[1] == 'top' else sr.bottom() - dy ans = QRectF(left, top, dx, dy) return ans
def __init__(self, parent=None): QWidget.__init__(self, parent) self.setMouseTracking(True) self.setFocusPolicy(Qt.ClickFocus) self.selection_state = SelectionState() self.undo_stack = u = QUndoStack() u.setUndoLimit(10) u.canUndoChanged.connect(self.emit_undo_redo_state) u.canRedoChanged.connect(self.emit_undo_redo_state) self.original_image_data = None self.is_valid = False self.original_image_format = None self.current_image = None self.current_scaled_pixmap = None self.last_canvas_size = None self.target = QRectF(0, 0, 0, 0) self.undo_action = a = self.undo_stack.createUndoAction(self, _('Undo') + ' ') a.setIcon(QIcon(I('edit-undo.png'))) self.redo_action = a = self.undo_stack.createRedoAction(self, _('Redo') + ' ') a.setIcon(QIcon(I('edit-redo.png')))
def full(p, xmax, ymax): p.drawRect(0, 0, xmax, ymax) p.drawPolyline(QPoint(0, 0), QPoint(xmax, 0), QPoint(xmax, ymax), QPoint(0, ymax), QPoint(0, 0)) pp = QPainterPath() pp.addRect(0, 0, xmax, ymax) p.drawPath(pp) p.save() for i in xrange(3): col = [0, 0, 0, 200] col[i] = 255 p.setOpacity(0.3) p.fillRect(0, 0, xmax / 10, xmax / 10, QBrush(QColor(*col))) p.setOpacity(1) p.drawRect(0, 0, xmax / 10, xmax / 10) p.translate(xmax / 10, xmax / 10) p.scale(1, 1.5) p.restore() # p.scale(2, 2) # p.rotate(45) p.drawPixmap(0, 0, xmax / 4, xmax / 4, QPixmap(I('library.png'))) p.drawRect(0, 0, xmax / 4, xmax / 4) f = p.font() f.setPointSize(20) # f.setLetterSpacing(f.PercentageSpacing, 200) f.setUnderline(True) # f.setOverline(True) # f.setStrikeOut(True) f.setFamily('Calibri') p.setFont(f) # p.setPen(QColor(0, 0, 255)) # p.scale(2, 2) # p.rotate(45) p.drawText(QPoint(xmax / 3.9, 30), 'Some—text not By’s ū --- Д AV ff ff') b = QBrush(Qt.HorPattern) b.setColor(QColor(Qt.blue)) pix = QPixmap(I('console.png')) w = xmax / 4 p.fillRect(0, ymax / 3, w, w, b) p.fillRect(xmax / 3, ymax / 3, w, w, QBrush(pix)) x, y = 2 * xmax / 3, ymax / 3 p.drawTiledPixmap(QRectF(x, y, w, w), pix, QPointF(10, 10)) x, y = 1, ymax / 1.9 g = QLinearGradient(QPointF(x, y), QPointF(x + w, y + w)) g.setColorAt(0, QColor('#00f')) g.setColorAt(1, QColor('#fff')) p.fillRect(x, y, w, w, QBrush(g))
def setImageCoordinates(self, nx, ny, x0, y0, l0, m0, dl, dm): """Sets up image coordinates. Pixel x0,y0 is centered at location l0,m0 in the plot, pixel size is dl,dm, image size is (nx,ny)""" dprint(2, "image coordinates are", nx, ny, x0, y0, l0, m0, dl, dm) self._nx, self._ny = nx, ny self._l0, self._m0 = l0, m0 self._dl, self._dm = dl, dm self._x0, self._y0 = x0, y0 self._lminmax = (l0 - dl * (x0 + 0.5), l0 + (nx - x0 - 0.5) * dl) if dl < 0: self._lminmax = (self._lminmax[1], self._lminmax[0]) self._mminmax = (m0 - dm * (y0 + 0.5), m0 + (ny - y0 - 0.5) * dm) self._bounding_rect = QRectF(self._lminmax[0], self._mminmax[0], nx * abs(dl), ny * abs(dm)) self._bounding_rect_pix = QRect(0, 0, nx, ny) dprint(2, "image extents are", self._lminmax, self._mminmax)
def mouseMoveEvent(self, ev): changed = False if self.selection_state.in_selection: changed = True self.selection_state.in_selection = False self.selection_state.drag_corner = None pos = ev.pos() cursor = Qt.ArrowCursor try: if not self.target.contains(pos): return if ev.buttons() & Qt.LeftButton: if self.selection_state.last_press_point is not None and self.selection_state.current_mode is not None: if self.selection_state.current_mode == 'select': self.selection_state.rect = QRectF(self.selection_state.last_press_point, pos).normalized() changed = True elif self.selection_state.last_drag_pos is not None: self.selection_state.in_selection = True self.selection_state.drag_corner = self.selection_state.dragging dp = pos - self.selection_state.last_drag_pos self.selection_state.last_drag_pos = pos self.move_selection(dp) cursor = self.get_cursor() changed = True else: if self.selection_state.rect is None or not self.selection_state.rect.contains(pos): return if self.selection_state.current_mode == 'selected': if self.selection_state.rect is not None and self.selection_state.rect.contains(pos): self.selection_state.drag_corner = self.get_drag_corner(pos) self.selection_state.in_selection = True cursor = self.get_cursor() changed = True finally: if changed: self.update() self.setCursor(cursor)
def boundingRect(self): if self.isValid(): return items.PolygonItem.boundingRect(self) return QRectF()
class Canvas(QWidget): BACKGROUND = QColor(60, 60, 60) SHADE_COLOR = QColor(0, 0, 0, 180) SELECT_PEN = QPen(QColor(Qt.white)) selection_state_changed = pyqtSignal(object) undo_redo_state_changed = pyqtSignal(object, object) image_changed = pyqtSignal(object) @property def has_selection(self): return self.selection_state.current_mode == 'selected' @property def is_modified(self): return self.current_image is not self.original_image def __init__(self, parent=None): QWidget.__init__(self, parent) self.setMouseTracking(True) self.setFocusPolicy(Qt.ClickFocus) self.selection_state = SelectionState() self.undo_stack = u = QUndoStack() u.setUndoLimit(10) u.canUndoChanged.connect(self.emit_undo_redo_state) u.canRedoChanged.connect(self.emit_undo_redo_state) self.original_image_data = None self.is_valid = False self.original_image_format = None self.current_image = None self.current_scaled_pixmap = None self.last_canvas_size = None self.target = QRectF(0, 0, 0, 0) self.undo_action = a = self.undo_stack.createUndoAction(self, _('Undo') + ' ') a.setIcon(QIcon(I('edit-undo.png'))) self.redo_action = a = self.undo_stack.createRedoAction(self, _('Redo') + ' ') a.setIcon(QIcon(I('edit-redo.png'))) def load_image(self, data): self.is_valid = False try: fmt = identify_data(data)[-1].encode('ascii') except Exception: fmt = b'' self.original_image_format = fmt.decode('ascii').lower() self.selection_state.reset() self.original_image_data = data self.current_image = i = self.original_image = ( QImage.fromData(data, format=fmt) if fmt else QImage.fromData(data)) self.is_valid = not i.isNull() self.update() self.image_changed.emit(self.current_image) def set_image(self, qimage): self.selection_state.reset() self.current_scaled_pixmap = None self.current_image = qimage self.is_valid = not qimage.isNull() self.update() self.image_changed.emit(self.current_image) def get_image_data(self, quality=90): if not self.is_modified: return self.original_image_data return pixmap_to_data(self.current_image, format=self.original_image_format or 'JPEG', quality=90) def copy(self): if not self.is_valid: return clipboard = QApplication.clipboard() if not self.has_selection or self.selection_state.rect is None: clipboard.setImage(self.current_image) else: trim = Trim(self) clipboard.setImage(trim.after_image) trim.before_image = trim.after_image = None def paste(self): clipboard = QApplication.clipboard() md = clipboard.mimeData() if md.hasImage(): img = QImage(md.imageData()) if not img.isNull(): self.undo_stack.push(Replace(img, _('Paste image'), self)) else: error_dialog(self, _('No image'), _( 'No image available in the clipboard'), show=True) def break_cycles(self): self.undo_stack.clear() self.original_image_data = self.current_image = self.current_scaled_pixmap = None def emit_undo_redo_state(self): self.undo_redo_state_changed.emit(self.undo_action.isEnabled(), self.redo_action.isEnabled()) @imageop def trim_image(self): if self.selection_state.rect is None: error_dialog(self, _('No selection'), _( 'No active selection, first select a region in the image, by dragging with your mouse'), show=True) return False self.undo_stack.push(Trim(self)) return True @imageop def autotrim_image(self): self.undo_stack.push(AutoTrim(self)) return True @imageop def rotate_image(self): self.undo_stack.push(Rotate(self)) return True @imageop def resize_image(self, width, height): self.undo_stack.push(Scale(width, height, self)) return True @imageop def sharpen_image(self, sigma=3.0): self.undo_stack.push(Sharpen(sigma, self)) return True @imageop def blur_image(self, sigma=3.0): self.undo_stack.push(Blur(sigma, self)) return True @imageop def despeckle_image(self): self.undo_stack.push(Despeckle(self)) return True # The selection rectangle {{{ @property def dc_size(self): sr = self.selection_state.rect dx = min(75, sr.width() / 4) dy = min(75, sr.height() / 4) return dx, dy def get_drag_corner(self, pos): dx, dy = self.dc_size sr = self.selection_state.rect x, y = pos.x(), pos.y() hedge = 'left' if x < sr.x() + dx else 'right' if x > sr.right() - dx else None vedge = 'top' if y < sr.y() + dy else 'bottom' if y > sr.bottom() - dy else None return (hedge, vedge) if hedge or vedge else None def get_drag_rect(self): sr = self.selection_state.rect dc = self.selection_state.drag_corner if None in (sr, dc): return dx, dy = self.dc_size if None in dc: # An edge if dc[0] is None: top = sr.top() if dc[1] == 'top' else sr.bottom() - dy ans = QRectF(sr.left() + dx, top, sr.width() - 2 * dx, dy) else: left = sr.left() if dc[0] == 'left' else sr.right() - dx ans = QRectF(left, sr.top() + dy, dx, sr.height() - 2 * dy) else: # A corner left = sr.left() if dc[0] == 'left' else sr.right() - dx top = sr.top() if dc[1] == 'top' else sr.bottom() - dy ans = QRectF(left, top, dx, dy) return ans def get_cursor(self): dc = self.selection_state.drag_corner if dc is None: ans = Qt.OpenHandCursor if self.selection_state.last_drag_pos is None else Qt.ClosedHandCursor elif None in dc: ans = Qt.SizeVerCursor if dc[0] is None else Qt.SizeHorCursor else: ans = Qt.SizeBDiagCursor if dc in {('left', 'bottom'), ('right', 'top')} else Qt.SizeFDiagCursor return ans def move_edge(self, edge, dp): sr = self.selection_state.rect horiz = edge in {'left', 'right'} func = getattr(sr, 'set' + capitalize(edge)) delta = getattr(dp, 'x' if horiz else 'y')() buf = 50 if horiz: minv = self.target.left() if edge == 'left' else sr.left() + buf maxv = sr.right() - buf if edge == 'left' else self.target.right() else: minv = self.target.top() if edge == 'top' else sr.top() + buf maxv = sr.bottom() - buf if edge == 'top' else self.target.bottom() func(max(minv, min(maxv, delta + getattr(sr, edge)()))) def move_selection_rect(self, x, y): sr = self.selection_state.rect half_width = sr.width() / 2.0 half_height = sr.height() / 2.0 c = sr.center() nx = c.x() + x ny = c.y() + y minx = self.target.left() + half_width maxx = self.target.right() - half_width miny, maxy = self.target.top() + half_height, self.target.bottom() - half_height nx = max(minx, min(maxx, nx)) ny = max(miny, min(maxy, ny)) sr.moveCenter(QPointF(nx, ny)) def move_selection(self, dp): dm = self.selection_state.dragging if dm is None: self.move_selection_rect(dp.x(), dp.y()) else: for edge in dm: if edge is not None: self.move_edge(edge, dp) def mousePressEvent(self, ev): if ev.button() == Qt.LeftButton and self.target.contains(ev.pos()): pos = ev.pos() self.selection_state.last_press_point = pos if self.selection_state.current_mode is None: self.selection_state.current_mode = 'select' elif self.selection_state.current_mode == 'selected': if self.selection_state.rect is not None and self.selection_state.rect.contains(pos): self.selection_state.drag_corner = self.selection_state.dragging = self.get_drag_corner(pos) self.selection_state.last_drag_pos = pos self.setCursor(self.get_cursor()) else: self.selection_state.current_mode = 'select' self.selection_state.rect = None self.selection_state_changed.emit(False) def mouseMoveEvent(self, ev): changed = False if self.selection_state.in_selection: changed = True self.selection_state.in_selection = False self.selection_state.drag_corner = None pos = ev.pos() cursor = Qt.ArrowCursor try: if not self.target.contains(pos): return if ev.buttons() & Qt.LeftButton: if self.selection_state.last_press_point is not None and self.selection_state.current_mode is not None: if self.selection_state.current_mode == 'select': self.selection_state.rect = QRectF(self.selection_state.last_press_point, pos).normalized() changed = True elif self.selection_state.last_drag_pos is not None: self.selection_state.in_selection = True self.selection_state.drag_corner = self.selection_state.dragging dp = pos - self.selection_state.last_drag_pos self.selection_state.last_drag_pos = pos self.move_selection(dp) cursor = self.get_cursor() changed = True else: if self.selection_state.rect is None or not self.selection_state.rect.contains(pos): return if self.selection_state.current_mode == 'selected': if self.selection_state.rect is not None and self.selection_state.rect.contains(pos): self.selection_state.drag_corner = self.get_drag_corner(pos) self.selection_state.in_selection = True cursor = self.get_cursor() changed = True finally: if changed: self.update() self.setCursor(cursor) def mouseReleaseEvent(self, ev): if ev.button() == Qt.LeftButton: self.selection_state.dragging = self.selection_state.last_drag_pos = None if self.selection_state.current_mode == 'select': r = self.selection_state.rect if r is None or max(r.width(), r.height()) < 3: self.selection_state.reset() else: self.selection_state.current_mode = 'selected' self.selection_state_changed.emit(self.has_selection) elif self.selection_state.current_mode == 'selected' and self.selection_state.rect is not None and self.selection_state.rect.contains(ev.pos()): self.setCursor(self.get_cursor()) self.update() def keyPressEvent(self, ev): k = ev.key() if k in (Qt.Key_Left, Qt.Key_Right, Qt.Key_Up, Qt.Key_Down) and self.selection_state.rect is not None and self.has_selection: ev.accept() delta = 10 if ev.modifiers() & Qt.ShiftModifier else 1 x = y = 0 if k in (Qt.Key_Left, Qt.Key_Right): x = delta * (-1 if k == Qt.Key_Left else 1) else: y = delta * (-1 if k == Qt.Key_Up else 1) self.move_selection_rect(x, y) self.update() else: return QWidget.keyPressEvent(self, ev) # }}} # Painting {{{ @painter def draw_background(self, painter): painter.fillRect(self.rect(), self.BACKGROUND) @painter def draw_image_error(self, painter): font = painter.font() font.setPointSize(3 * font.pointSize()) font.setBold(True) painter.setFont(font) painter.setPen(QColor(Qt.black)) painter.drawText(self.rect(), Qt.AlignCenter, _('Not a valid image')) def load_pixmap(self): canvas_size = self.rect().width(), self.rect().height() if self.last_canvas_size != canvas_size: if self.last_canvas_size is not None and self.selection_state.rect is not None: self.selection_state.reset() # TODO: Migrate the selection rect self.last_canvas_size = canvas_size self.current_scaled_pixmap = None if self.current_scaled_pixmap is None: pwidth, pheight = self.last_canvas_size i = self.current_image width, height = i.width(), i.height() scaled, width, height = fit_image(width, height, pwidth, pheight) if scaled: i = self.current_image.scaled(width, height, transformMode=Qt.SmoothTransformation) self.current_scaled_pixmap = QPixmap.fromImage(i) @painter def draw_pixmap(self, painter): p = self.current_scaled_pixmap width, height = p.width(), p.height() pwidth, pheight = self.last_canvas_size x = int(abs(pwidth - width)/2.) y = int(abs(pheight - height)/2.) self.target = QRectF(x, y, width, height) painter.drawPixmap(self.target, p, QRectF(p.rect())) @painter def draw_selection_rect(self, painter): cr, sr = self.target, self.selection_state.rect painter.setPen(self.SELECT_PEN) painter.setRenderHint(QPainter.Antialiasing, False) if self.selection_state.current_mode == 'selected': # Shade out areas outside the selection rect for r in ( QRectF(cr.topLeft(), QPointF(sr.left(), cr.bottom())), # left QRectF(QPointF(sr.left(), cr.top()), sr.topRight()), # top QRectF(QPointF(sr.right(), cr.top()), cr.bottomRight()), # right QRectF(sr.bottomLeft(), QPointF(sr.right(), cr.bottom())), # bottom ): painter.fillRect(r, self.SHADE_COLOR) dr = self.get_drag_rect() if self.selection_state.in_selection and dr is not None: # Draw the resize rectangle painter.save() painter.setCompositionMode(QPainter.RasterOp_SourceAndNotDestination) painter.setClipRect(sr.adjusted(1, 1, -1, -1)) painter.drawRect(dr) painter.restore() # Draw the selection rectangle painter.setCompositionMode(QPainter.RasterOp_SourceAndNotDestination) painter.drawRect(sr) def paintEvent(self, event): QWidget.paintEvent(self, event) p = QPainter(self) p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) try: self.draw_background(p) if self.original_image_data is None: return if not self.is_valid: return self.draw_image_error(p) self.load_pixmap() self.draw_pixmap(p) if self.selection_state.rect is not None: self.draw_selection_rect(p) finally: p.end()
def draw(self, painter, xmap, ymap, rect): """Implements QwtPlotItem.draw(), to render the image on the given painter.""" xp1, xp2, xdp, xs1, xs2, xds = xinfo = xmap.p1(), xmap.p2( ), xmap.pDist(), xmap.s1(), xmap.s2(), xmap.sDist() yp1, yp2, ydp, ys1, ys2, yds = yinfo = ymap.p1(), ymap.p2( ), ymap.pDist(), ymap.s1(), ymap.s2(), ymap.sDist() dprint(5, "draw:", rect, xinfo, yinfo) self._current_rect = QRectF(QPointF(xs2, ys1), QSizeF(xds, yds)) self._current_rect_pix = QRect( QPoint(*self.lmToPix(xs1, ys1)), QPoint(*self.lmToPix(xs2, ys2))).intersected( self._bounding_rect_pix) dprint(5, "draw:", self._current_rect_pix) # put together tuple describing current mapping mapping = xinfo, yinfo # if mapping has changed w.r.t. cache (i.e. zoom has changed), discard all cached QImages if mapping != self._cache_mapping: dprint(2, "does not match cached mapping, cache is:", self._cache_mapping) dprint(2, "and we have:", mapping) self.clearDisplayCache() self._cache_mapping = mapping t0 = time.time() # check cached QImage for current image key. qimg = self._cache_qimage.get(self._image_key) if qimg: dprint(5, "QImage found in cache, reusing") # else regenerate image else: # check for cached intensity-mapped data if self._cache_imap is not None: dprint(5, "intensity-mapped data found in cache, reusing") else: if self._cache_interp is not None: dprint(5, "interpolated data found in cache, reusing") else: image = self._image.transpose( ) if self._data_fortran_order else self._image spline_order = 2 xsamp = abs(xmap.sDist() / xmap.pDist()) / abs(self._dl) ysamp = abs(ymap.sDist() / ymap.pDist()) / abs(self._dm) if max(xsamp, ysamp) < .33 or min(xsamp, ysamp) > 2: spline_order = 1 dprint(2, "regenerating drawing cache, sampling factors are", xsamp, ysamp, "spline order is", spline_order) self._cache_imap = None if self._prefilter is None and spline_order > 1: self._prefilter = interpolation.spline_filter( image, order=spline_order) dprint(2, "spline prefiltering took", time.time() - t0, "secs") t0 = time.time() # make arrays of plot coordinates # xp[0],yp[0] corresponds to pixel 0,0, where 0,0 is the upper-left corner of the plot # the maps are in a funny order (w.r.t. meaning of p1/p2/s1/s2), so the indices here are determined empirically # We also adjust by half-pixel, to get the world coordinate of the pixel _center_ xp = xmap.s1() - (xmap.sDist() / xmap.pDist()) * ( 0.5 + numpy.arange(int(xmap.pDist()))) yp = ymap.s2() - (ymap.sDist() / ymap.pDist()) * ( 0.5 + numpy.arange(int(ymap.pDist()))) # now convert plot coordinates into fractional image pixel coordinates xi = self._x0 + (xp - self._l0) / self._dl yi = self._y0 + (yp - self._m0) / self._dm # interpolate image data ### # old code for nearest-neighbour interpolation ### # superceded by interpolation below (we simply round pixel coordinates to go to NN when oversampling) ### xi = xi.round().astype(int) ### oob_x = (xi<0)|(xi>=self._nx) ### xi[oob_x] = 0 ### yi = yi.round().astype(int) ### oob_y = (yi<0)|(yi>=self._ny) ### yi[oob_y] = 0 ### idx = (xi[:,numpy.newaxis]*self._ny + yi[numpy.newaxis,:]).ravel() ### interp_image = self._image.ravel()[idx].reshape((len(xi),len(yi))) ### interp_image[oob_x,:] = 0 ### interp_image[:,oob_y] = 0 ### self._qimage_cache = self.colormap.colorize(interp_image,self._img_range) ### self._qimage_cache_attrs = (rect,xinfo,yinfo) # if either axis is oversampled by a factor of 3 or more, switch to nearest-neighbour interpolation by rounding pixel values if xsamp < .33: xi = xi.round() if ysamp < .33: yi = yi.round() # make [2,nx,ny] array of interpolation coordinates xy = numpy.zeros((2, len(xi), len(yi))) xy[0, :, :] = xi[:, numpy.newaxis] xy[1, :, :] = yi[numpy.newaxis, :] # interpolate. Use NAN for out of range pixels... # for fortran order, tranpose axes for extra speed (flip XY around then) if self._data_fortran_order: xy = xy[-1::-1, ...] if spline_order > 1: interp_image = interpolation.map_coordinates( self._prefilter, xy, order=spline_order, cval=numpy.nan, prefilter=False) else: interp_image = interpolation.map_coordinates( image, xy, order=spline_order, cval=numpy.nan) # ...and put a mask on them (Colormap.colorize() will make these transparent). mask = ~numpy.isfinite(interp_image) self._cache_interp = numpy.ma.masked_array( interp_image, mask) dprint(2, "interpolation took", time.time() - t0, "secs") t0 = time.time() # ok, we have interpolated data in _cache_interp self._cache_imap = self.imap.remap(self._cache_interp) dprint(2, "intensity mapping took", time.time() - t0, "secs") t0 = time.time() # ok, we have intensity-mapped data in _cache_imap qimg = self.colormap.colorize(self._cache_imap) dprint(2, "colorizing took", time.time() - t0, "secs") t0 = time.time() # cache the qimage self._cache_qimage[self._image_key] = qimg.copy() # now draw the image t0 = time.time() painter.drawImage(xp1, yp2, qimg) dprint(2, "drawing took", time.time() - t0, "secs")