Esempio n. 1
0
    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self,
                                         logger=logger,
                                         rgbmap=rgbmap,
                                         settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        self.qimg_fmt = QImage.Format_RGB32
        # find out optimum format for backing store
        #self.qimg_fmt = QPixmap(1, 1).toImage().format()
        # Qt needs this to be in BGR(A)
        self.rgb_order = 'BGRA'

        # default renderer is Qt one
        self.renderer = CanvasRenderer(self, surface_type='qpixmap')

        self.msgtimer = Timer()
        self.msgtimer.add_callback('expired',
                                   lambda timer: self.onscreen_message_off())

        # For optomized redrawing
        self._defer_task = Timer()
        self._defer_task.add_callback('expired',
                                      lambda timer: self.delayed_redraw())
Esempio n. 2
0
    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self,
                                         logger=logger,
                                         rgbmap=rgbmap,
                                         settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        # Qt expects 32bit BGRA data for color images
        self._rgb_order = 'BGRA'

        self.renderer = CanvasRenderer(self)

        self.msgtimer = Timer(0.0, lambda timer: self.onscreen_message_off())

        # cursors
        self.cursor = {}

        # For optomized redrawing
        self._defer_task = Timer(0.0, lambda timer: self.delayed_redraw())
Esempio n. 3
0
    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self, logger=logger,
                                         rgbmap=rgbmap, settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        # Qt expects 32bit BGRA data for color images
        self._rgb_order = 'BGRA'

        self.renderer = CanvasRenderer(self)

        self.msgtimer = Timer(0.0, lambda timer: self.onscreen_message_off())

        # For optomized redrawing
        self._defer_task = Timer(0.0, lambda timer: self.delayed_redraw())
Esempio n. 4
0
    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self,
                                         logger=logger,
                                         rgbmap=rgbmap,
                                         settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        # NOTE: we could use the following, but it is only for Qt5.x
        # Asking for image in BGRA puts numpy array in ARGB format
        self.rgb_order = 'BGRA'
        self.qimg_fmt = QImage.Format_ARGB32

        self.renderer = CanvasRenderer(self)

        self.msgtimer = Timer()
        self.msgtimer.add_callback('expired',
                                   lambda timer: self.onscreen_message_off())

        # For optomized redrawing
        self._defer_task = Timer()
        self._defer_task.add_callback('expired',
                                      lambda timer: self.delayed_redraw())
Esempio n. 5
0
    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self, logger=logger,
                                         rgbmap=rgbmap, settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        self.qimg_fmt = QImage.Format_RGB32
        # find out optimum format for backing store
        #self.qimg_fmt = QPixmap(1, 1).toImage().format()
        # Qt needs this to be in BGR(A)
        self.rgb_order = 'BGRA'

        # default renderer is Qt one
        self.renderer = CanvasRenderer(self, surface_type='qpixmap')

        self.msgtimer = Timer()
        self.msgtimer.add_callback('expired',
                                   lambda timer: self.onscreen_message_off())

        # For optomized redrawing
        self._defer_task = Timer()
        self._defer_task.add_callback('expired',
                                      lambda timer: self.delayed_redraw())
Esempio n. 6
0
class ImageViewQt(ImageView.ImageViewBase):
    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self,
                                         logger=logger,
                                         rgbmap=rgbmap,
                                         settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        # Qt expects 32bit BGRA data for color images
        self._rgb_order = 'BGRA'

        self.renderer = CanvasRenderer(self)

        self.msgtimer = Timer(0.0, lambda timer: self.onscreen_message_off())

        # cursors
        self.cursor = {}

        # For optomized redrawing
        self._defer_task = Timer(0.0, lambda timer: self.delayed_redraw())

    def get_widget(self):
        return self.imgwin

    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 render_image(self, rgbobj, dst_x, dst_y):
        """Render the image represented by (rgbobj) at dst_x, dst_y
        in the pixel space.
        """
        self.logger.debug("redraw pixmap=%s" % (self.pixmap))
        if self.pixmap is None:
            return
        self.logger.debug("drawing to pixmap")

        # Prepare array for rendering
        arr = rgbobj.get_array(self._rgb_order)
        (height, width) = arr.shape[:2]

        return self._render_offscreen(self.pixmap, arr, dst_x, dst_y, width,
                                      height)

    def configure_window(self, width, height):
        self.logger.debug("window size reconfigured to %dx%d" %
                          (width, height))
        if hasattr(self, 'scene'):
            self.scene.setSceneRect(0, 0, width, height)
        # If we need to build a new pixmap do it here.  We allocate one
        # twice as big as necessary to prevent having to reinstantiate it
        # all the time.  On Qt this causes unpleasant flashing in the display.
        if (self.pixmap is None) or (self.pixmap.width() < width) or \
           (self.pixmap.height() < height):
            pixmap = QPixmap(width * 2, height * 2)
            #pixmap.fill(QColor("black"))
            self.pixmap = pixmap
            self.imgwin.set_pixmap(pixmap)

        self.configure(width, height)

    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 get_rgb_image_as_bytes(self, format='png', quality=90):
        ibuf = self.get_rgb_image_as_buffer(format=format, quality=quality)
        return bytes(ibuf.getvalue())

    def get_rgb_image_as_widget(self, output=None, format='png', quality=90):
        imgwin_wd, imgwin_ht = self.get_window_size()
        qpix = self.pixmap.copy(0, 0, imgwin_wd, imgwin_ht)
        return qpix.toImage()

    def save_rgb_image_as_file(self, filepath, format='png', quality=90):
        qimg = self.get_rgb_image_as_widget()
        res = qimg.save(filepath, format=format, quality=quality)

    def get_image_as_widget(self):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        arr = self.getwin_array(order=self._rgb_order)
        image = self._get_qimage(arr)
        return image

    def save_image_as_file(self, filepath, format='png', quality=90):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        qimg = self.get_image_as_widget()
        res = qimg.save(filepath, format=format, quality=quality)

    def reschedule_redraw(self, time_sec):
        self._defer_task.cancel()
        self._defer_task.start(time_sec)

    def update_image(self):
        if (not self.pixmap) or (not self.imgwin):
            return

        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()
            #self.imgwin.show()

    def set_cursor(self, cursor):
        if self.imgwin is not None:
            self.imgwin.setCursor(cursor)

    def define_cursor(self, ctype, cursor):
        self.cursor[ctype] = cursor

    def get_cursor(self, ctype):
        return self.cursor[ctype]

    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 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 get_rgb_order(self):
        return self._rgb_order

    def switch_cursor(self, ctype):
        self.set_cursor(self.cursor[ctype])

    def _get_qimage(self, bgra):
        h, w, channels = bgra.shape

        fmt = QImage.Format_ARGB32
        result = QImage(bgra.data, w, h, fmt)
        # Need to hang on to a reference to the array
        result.ndarray = bgra
        return result

    def _get_color(self, r, g, b):
        n = 255.0
        clr = QColor(int(r * n), int(g * n), int(b * n))
        return clr

    def onscreen_message(self, text, delay=None, redraw=True):
        self.msgtimer.cancel()
        self.set_onscreen_message(text, redraw=redraw)
        if delay is not None:
            self.msgtimer.start(delay)

    def onscreen_message_off(self):
        return self.onscreen_message(None)
Esempio n. 7
0
class ImageViewQt(ImageView.ImageViewBase):

    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self, logger=logger,
                                         rgbmap=rgbmap, settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        # Qt expects 32bit BGRA data for color images
        self._rgb_order = 'BGRA'

        self.renderer = CanvasRenderer(self)

        self.msgtimer = Timer(0.0, lambda timer: self.onscreen_message_off())

        # For optomized redrawing
        self._defer_task = Timer(0.0, lambda timer: self.delayed_redraw())

    def get_widget(self):
        return self.imgwin

    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 render_image(self, rgbobj, dst_x, dst_y):
        """Render the image represented by (rgbobj) at dst_x, dst_y
        in the pixel space.
        """
        self.logger.debug("redraw pixmap=%s" % (self.pixmap))
        if self.pixmap is None:
            return
        self.logger.debug("drawing to pixmap")

        # Prepare array for rendering
        arr = rgbobj.get_array(self._rgb_order)
        (height, width) = arr.shape[:2]

        return self._render_offscreen(self.pixmap, arr, dst_x, dst_y,
                                      width, height)

    def configure_window(self, width, height):
        self.logger.debug("window size reconfigured to %dx%d" % (
            width, height))
        if hasattr(self, 'scene'):
            # By default, a QGraphicsView comes with a 1-pixel margin
            # You will get scrollbars unless you account for this
            # See http://stackoverflow.com/questions/3513788/qt-qgraphicsview-without-scrollbar
            width, height = width - 2, height - 2
            self.scene.setSceneRect(1, 1, width-2, height-2)
        # If we need to build a new pixmap do it here.  We allocate one
        # twice as big as necessary to prevent having to reinstantiate it
        # all the time.  On Qt this causes unpleasant flashing in the display.
        if (self.pixmap is None) or (self.pixmap.width() < width) or \
           (self.pixmap.height() < height):
            pixmap = QPixmap(width*2, height*2)
            #pixmap.fill(QColor("black"))
            self.pixmap = pixmap
            self.imgwin.set_pixmap(pixmap)

        self.configure(width, height)

    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 get_rgb_image_as_widget(self, output=None, format='png',
                                quality=90):
        imgwin_wd, imgwin_ht = self.get_window_size()
        qpix = self.pixmap.copy(0, 0,
                                imgwin_wd, imgwin_ht)
        return qpix.toImage()

    def save_rgb_image_as_file(self, filepath, format='png', quality=90):
        qimg = self.get_rgb_image_as_widget()
        res = qimg.save(filepath, format=format, quality=quality)

    def get_plain_image_as_widget(self):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        arr = self.getwin_array(order=self._rgb_order)
        image = self._get_qimage(arr)
        return image

    def save_plain_image_as_file(self, filepath, format='png', quality=90):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        qimg = self.get_plain_image_as_widget()
        res = qimg.save(filepath, format=format, quality=quality)

    def reschedule_redraw(self, time_sec):
        self._defer_task.cancel()
        self._defer_task.start(time_sec)

    def update_image(self):
        if (not self.pixmap) or (not self.imgwin):
            return

        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()
            #self.imgwin.show()

    def set_cursor(self, cursor):
        if self.imgwin is not None:
            self.imgwin.setCursor(cursor)

    def make_cursor(self, iconpath, x, y):
        image = QImage()
        image.load(iconpath)
        pm = QPixmap(image)
        return QCursor(pm, x, y)

    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 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 get_rgb_order(self):
        return self._rgb_order

    def _get_qimage(self, bgra):
        h, w, channels = bgra.shape

        fmt = QImage.Format_ARGB32
        result = QImage(bgra.data, w, h, fmt)
        # Need to hang on to a reference to the array
        result.ndarray = bgra
        return result

    def _get_color(self, r, g, b):
        n = 255.0
        clr = QColor(int(r*n), int(g*n), int(b*n))
        return clr

    def onscreen_message(self, text, delay=None, redraw=True):
        self.msgtimer.cancel()
        self.set_onscreen_message(text, redraw=redraw)
        if delay is not None:
            self.msgtimer.start(delay)
Esempio n. 8
0
 def make_timer(self):
     return Timer()
Esempio n. 9
0
class ImageViewQt(ImageView.ImageViewBase):
    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self,
                                         logger=logger,
                                         rgbmap=rgbmap,
                                         settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        self.qimg_fmt = QImage.Format_RGB32
        # find out optimum format for backing store
        #self.qimg_fmt = QPixmap(1, 1).toImage().format()
        # Qt needs this to be in BGR(A)
        self.rgb_order = 'BGRA'

        # default renderer is Qt one
        self.renderer = CanvasRenderer(self, surface_type='qpixmap')

        self.msgtimer = Timer()
        self.msgtimer.add_callback('expired',
                                   lambda timer: self.onscreen_message_off())

        # For optomized redrawing
        self._defer_task = Timer()
        self._defer_task.add_callback('expired',
                                      lambda timer: self.delayed_redraw())

    def get_widget(self):
        return self.imgwin

    def configure_window(self, width, height):
        self.logger.debug("window size reconfigured to %dx%d" %
                          (width, height))

        if hasattr(self, 'scene'):
            # By default, a QGraphicsView comes with a 1-pixel margin
            # You will get scrollbars unless you account for this
            # See http://stackoverflow.com/questions/3513788/qt-qgraphicsview-without-scrollbar
            width, height = width - 2, height - 2
            self.scene.setSceneRect(1, 1, width - 2, height - 2)

        # tell renderer about our new size
        self.renderer.resize((width, height))

        if isinstance(self.renderer.surface, QPixmap):
            # optimization when Qt is used as the renderer:
            # renderer surface is already a QPixmap
            self.pixmap = self.renderer.surface
            self.imgwin.set_pixmap(self.pixmap)

        else:
            # If we need to build a new pixmap do it here.  We allocate one
            # twice as big as necessary to prevent having to reinstantiate it
            # all the time.  On Qt this causes unpleasant flashing in the display.
            if ((self.pixmap is None) or (self.pixmap.width() < width)
                    or (self.pixmap.height() < height)):
                pixmap = QPixmap(width * 2, height * 2)
                self.pixmap = pixmap
                self.imgwin.set_pixmap(pixmap)

        self.configure(width, height)

    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 get_rgb_image_as_widget(self):
        imgwin_wd, imgwin_ht = self.get_window_size()
        qpix = self.pixmap.copy(0, 0, imgwin_wd, imgwin_ht)
        return qpix.toImage()

    def save_rgb_image_as_file(self, filepath, format='png', quality=90):
        qimg = self.get_rgb_image_as_widget()
        qimg.save(filepath, format=format, quality=quality)

    def get_plain_image_as_widget(self):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        arr = self.getwin_array(order=self.rgb_order)
        image = self._get_qimage(arr, self.qimg_fmt)
        return image

    def save_plain_image_as_file(self, filepath, format='png', quality=90):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        qimg = self.get_plain_image_as_widget()
        qimg.save(filepath, format=format, quality=quality)

    def reschedule_redraw(self, time_sec):
        self._defer_task.stop()
        self._defer_task.start(time_sec)

    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 _get_qimage(self, rgb_data, format):
        rgb_data = np.ascontiguousarray(rgb_data)
        ht, wd, channels = rgb_data.shape

        result = QImage(rgb_data.data, wd, ht, format)
        # Need to hang on to a reference to the array
        result.ndarray = rgb_data
        return result

    def set_cursor(self, cursor):
        if self.imgwin is not None:
            self.imgwin.setCursor(cursor)

    def make_cursor(self, iconpath, x, y):
        image = QImage()
        image.load(iconpath)
        pm = QPixmap(image)
        return QCursor(pm, x, y)

    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 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 make_timer(self):
        return Timer()

    def onscreen_message(self, text, delay=None, redraw=True):
        self.msgtimer.stop()
        self.set_onscreen_message(text, redraw=redraw)
        if delay is not None:
            self.msgtimer.start(delay)

    def take_focus(self):
        self.imgwin.setFocus()
Esempio n. 10
0
class ImageViewQt(ImageView.ImageViewBase):
    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self,
                                         logger=logger,
                                         rgbmap=rgbmap,
                                         settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        # NOTE: we could use the following, but it is only for Qt5.x
        # Asking for image in BGRA puts numpy array in ARGB format
        self.rgb_order = 'BGRA'
        self.qimg_fmt = QImage.Format_ARGB32

        self.renderer = CanvasRenderer(self)

        self.msgtimer = Timer()
        self.msgtimer.add_callback('expired',
                                   lambda timer: self.onscreen_message_off())

        # For optomized redrawing
        self._defer_task = Timer()
        self._defer_task.add_callback('expired',
                                      lambda timer: self.delayed_redraw())

    def get_widget(self):
        return self.imgwin

    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 render_image(self, rgbobj, dst_x, dst_y):
        """Render the image represented by (rgbobj) at dst_x, dst_y
        in the pixel space.
        """
        self.logger.debug("redraw pixmap=%s" % (self.pixmap))
        if self.pixmap is None:
            return
        self.logger.debug("drawing to pixmap")

        # Prepare array for rendering
        arr = rgbobj.get_array(self.rgb_order)
        (height, width) = arr.shape[:2]

        return self._render_offscreen(self.pixmap, arr, dst_x, dst_y, width,
                                      height)

    def configure_window(self, width, height):
        self.logger.debug("window size reconfigured to %dx%d" %
                          (width, height))
        if hasattr(self, 'scene'):
            # By default, a QGraphicsView comes with a 1-pixel margin
            # You will get scrollbars unless you account for this
            # See http://stackoverflow.com/questions/3513788/qt-qgraphicsview-without-scrollbar
            width, height = width - 2, height - 2
            self.scene.setSceneRect(1, 1, width - 2, height - 2)
        # If we need to build a new pixmap do it here.  We allocate one
        # twice as big as necessary to prevent having to reinstantiate it
        # all the time.  On Qt this causes unpleasant flashing in the display.
        if ((self.pixmap is None) or (self.pixmap.width() < width)
                or (self.pixmap.height() < height)):
            pixmap = QPixmap(width * 2, height * 2)
            #pixmap.fill(QColor("black"))
            self.pixmap = pixmap
            self.imgwin.set_pixmap(pixmap)

        self.configure(width, height)

    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 get_rgb_image_as_widget(self):
        imgwin_wd, imgwin_ht = self.get_window_size()
        qpix = self.pixmap.copy(0, 0, imgwin_wd, imgwin_ht)
        return qpix.toImage()

    def save_rgb_image_as_file(self, filepath, format='png', quality=90):
        qimg = self.get_rgb_image_as_widget()
        qimg.save(filepath, format=format, quality=quality)

    def get_plain_image_as_widget(self):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        arr = self.getwin_array(order=self.rgb_order)
        image = self._get_qimage(arr)
        return image

    def save_plain_image_as_file(self, filepath, format='png', quality=90):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        qimg = self.get_plain_image_as_widget()
        qimg.save(filepath, format=format, quality=quality)

    def reschedule_redraw(self, time_sec):
        self._defer_task.stop()
        self._defer_task.start(time_sec)

    def update_image(self):
        if (not self.pixmap) or (not self.imgwin):
            return

        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 set_cursor(self, cursor):
        if self.imgwin is not None:
            self.imgwin.setCursor(cursor)

    def make_cursor(self, iconpath, x, y):
        image = QImage()
        image.load(iconpath)
        pm = QPixmap(image)
        return QCursor(pm, x, y)

    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 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 make_timer(self):
        return Timer()

    def _get_qimage(self, rgb_data):
        ht, wd, channels = rgb_data.shape

        result = QImage(rgb_data.data, wd, ht, self.qimg_fmt)
        # Need to hang on to a reference to the array
        result.ndarray = rgb_data
        return result

    def _get_color(self, r, g, b):
        n = 255.0
        clr = QColor(int(r * n), int(g * n), int(b * n))
        return clr

    def onscreen_message(self, text, delay=None, redraw=True):
        self.msgtimer.stop()
        self.set_onscreen_message(text, redraw=redraw)
        if delay is not None:
            self.msgtimer.start(delay)

    def take_focus(self):
        self.imgwin.setFocus()
Esempio n. 11
0
class ImageViewQt(ImageView.ImageViewBase):

    def __init__(self, logger=None, rgbmap=None, settings=None, render=None):
        ImageView.ImageViewBase.__init__(self, logger=logger,
                                         rgbmap=rgbmap, settings=settings)

        if render is 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 ImageViewQtError("Undefined render type: '%s'" % (render))
        self.imgwin.viewer = self
        self.pixmap = None
        self.qimg_fmt = QImage.Format_RGB32
        # find out optimum format for backing store
        #self.qimg_fmt = QPixmap(1, 1).toImage().format()
        # Qt needs this to be in BGR(A)
        self.rgb_order = 'BGRA'

        # default renderer is Qt one
        self.renderer = CanvasRenderer(self, surface_type='qpixmap')

        self.msgtimer = Timer()
        self.msgtimer.add_callback('expired',
                                   lambda timer: self.onscreen_message_off())

        # For optomized redrawing
        self._defer_task = Timer()
        self._defer_task.add_callback('expired',
                                      lambda timer: self.delayed_redraw())

    def get_widget(self):
        return self.imgwin

    def configure_window(self, width, height):
        self.logger.debug("window size reconfigured to %dx%d" % (
            width, height))

        if hasattr(self, 'scene'):
            # By default, a QGraphicsView comes with a 1-pixel margin
            # You will get scrollbars unless you account for this
            # See http://stackoverflow.com/questions/3513788/qt-qgraphicsview-without-scrollbar
            width, height = width - 2, height - 2
            self.scene.setSceneRect(1, 1, width - 2, height - 2)

        # tell renderer about our new size
        self.renderer.resize((width, height))

        if isinstance(self.renderer.surface, QPixmap):
            # optimization when Qt is used as the renderer:
            # renderer surface is already a QPixmap
            self.pixmap = self.renderer.surface
            self.imgwin.set_pixmap(self.pixmap)

        else:
            # If we need to build a new pixmap do it here.  We allocate one
            # twice as big as necessary to prevent having to reinstantiate it
            # all the time.  On Qt this causes unpleasant flashing in the display.
            if ((self.pixmap is None) or (self.pixmap.width() < width) or
                    (self.pixmap.height() < height)):
                pixmap = QPixmap(width * 2, height * 2)
                self.pixmap = pixmap
                self.imgwin.set_pixmap(pixmap)

        self.configure(width, height)

    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 get_rgb_image_as_widget(self):
        imgwin_wd, imgwin_ht = self.get_window_size()
        qpix = self.pixmap.copy(0, 0, imgwin_wd, imgwin_ht)
        return qpix.toImage()

    def save_rgb_image_as_file(self, filepath, format='png', quality=90):
        qimg = self.get_rgb_image_as_widget()
        qimg.save(filepath, format=format, quality=quality)

    def get_plain_image_as_widget(self):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        arr = self.getwin_array(order=self.rgb_order)
        image = self._get_qimage(arr, self.qimg_fmt)
        return image

    def save_plain_image_as_file(self, filepath, format='png', quality=90):
        """Used for generating thumbnails.  Does not include overlaid
        graphics.
        """
        qimg = self.get_plain_image_as_widget()
        qimg.save(filepath, format=format, quality=quality)

    def reschedule_redraw(self, time_sec):
        self._defer_task.stop()
        self._defer_task.start(time_sec)

    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 _get_qimage(self, rgb_data, format):
        rgb_data = np.ascontiguousarray(rgb_data)
        ht, wd, channels = rgb_data.shape

        result = QImage(rgb_data.data, wd, ht, format)
        # Need to hang on to a reference to the array
        result.ndarray = rgb_data
        return result

    def set_cursor(self, cursor):
        if self.imgwin is not None:
            self.imgwin.setCursor(cursor)

    def make_cursor(self, iconpath, x, y):
        image = QImage()
        image.load(iconpath)
        pm = QPixmap(image)
        return QCursor(pm, x, y)

    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 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 make_timer(self):
        return Timer()

    def onscreen_message(self, text, delay=None, redraw=True):
        self.msgtimer.stop()
        self.set_onscreen_message(text, redraw=redraw)
        if delay is not None:
            self.msgtimer.start(delay)

    def take_focus(self):
        self.imgwin.setFocus()