Beispiel #1
0
    def view(self, item, zoom=0, rotation=0):
        """
        view an image
        """
        logger.log( 9, 'view(item, zoom=%s, rotation=%s)', zoom, rotation)

        if self.blend:
            self.blend.stop()
            self.blend.remove()
            self.blend = None
            
        if zoom:
            self.event_context    = 'image_zoom'
        else:
            self.event_context    = 'image'

        filename = item.filename

        self.fileitem = item
        self.parent   = item.menuw

        if not self.free_cache in item.menuw.show_callbacks:
            item.menuw.show_callbacks.append(self.free_cache)

        self.filename = filename
        self.rotation = rotation

        if filename and len(filename) > 0:
            image = self.osd.loadbitmap(filename, cache=self.bitmapcache)
        else:
            # Using Container-Image
            image, w, h = item.loadimage()

        if not self.__added_app:
            rc.add_app(self)
            self.__added_app = True

        if not image:
            self.osd.clearscreen(color=self.osd.COL_BLACK)
            self.osd.drawstringframed(_('Can\'t Open Image\n"%s"') % Unicode(filename),
                config.OSD_OVERSCAN_LEFT + 20, config.OSD_OVERSCAN_TOP + 20,
                self.osd.width - (config.OSD_OVERSCAN_LEFT+config.OSD_OVERSCAN_RIGHT) - 40,
                self.osd.height - (config.OSD_OVERSCAN_TOP+config.OSD_OVERSCAN_BOTTOM) - 40,
                self.osd.getfont(config.OSD_DEFAULT_FONTNAME, config.OSD_DEFAULT_FONTSIZE),
                fgcolor=self.osd.COL_ORANGE, align_h='center', align_v='center', mode='soft')
            self.osd.update()
            return

        width, height = image.get_size()

        # Bounding box default values
        bbx = bby = bbw = bbh = 0

        if zoom:
            # Translate the 9-element grid to bounding boxes
            if config.IMAGEVIEWER_REVERSED_IMAGES:
                if self.rotation == 90:
                    bb = { 1:(2,2), 2:(2,1), 3:(2,0),
                           4:(1,2), 5:(1,1), 6:(1,0),
                           7:(0,2), 8:(0,1), 9:(0,0) }
                elif self.rotation == 180:
                    bb = { 1:(2,0), 2:(1,0), 3:(0,0),
                           4:(2,1), 5:(1,1), 6:(0,1),
                           7:(2,2), 8:(1,2), 9:(0,2) }
                elif self.rotation == 270:
                    bb = { 1:(0,0), 2:(0,1), 3:(0,2),
                           4:(1,0), 5:(1,1), 6:(1,2),
                           7:(2,0), 8:(2,1), 9:(2,2) }
                else:
                    bb = { 1:(0,2), 2:(1,2), 3:(2,2),
                           4:(0,1), 5:(1,1), 6:(2,1),
                           7:(0,0), 8:(1,0), 9:(2,0) }
            else:
                if self.rotation == 90:
                    bb = { 1:(2,0), 2:(2,1), 3:(2,2),
                           4:(1,0), 5:(1,1), 6:(1,2),
                           7:(0,0), 8:(0,1), 9:(0,2) }
                elif self.rotation == 180:
                    bb = { 1:(2,2), 2:(1,2), 3:(0,2),
                           4:(2,1), 5:(1,1), 6:(0,1),
                           7:(2,0), 8:(1,0), 9:(0,0) }
                elif self.rotation == 270:
                    bb = { 1:(0,2), 2:(0,1), 3:(0,0),
                           4:(1,2), 5:(1,1), 6:(1,0),
                           7:(2,2), 8:(2,1), 9:(2,0) }
                else:
                    bb = { 1:(0,0), 2:(1,0), 3:(2,0),
                           4:(0,1), 5:(1,1), 6:(2,1),
                           7:(0,2), 8:(1,2), 9:(2,2) }

            if isinstance(zoom, int):
                h, v = bb[zoom]
            else:
                h, v = bb[zoom[0]]

            # Bounding box center
            bbcx = ([1, 3, 5][h]) * width / 6
            bbcy = ([1, 3, 5][v]) * height / 6

            if self.rotation % 180:
                # different calculations because image width is screen height
                scale_x = float(self.osd_width) / (height / 3)
                scale_y = float(self.osd_height) / (width / 3)
                scale = min(scale_x, scale_y)

                # read comment for the bbw and bbh calculations below
                bbw = min(max((width / 3) * scale, self.osd_height), width) / scale
                bbh = min(max((height / 3) * scale, self.osd_width), height) / scale

            else:
                scale_x = float(self.osd_width) / (width / 3)
                scale_y = float(self.osd_height) / (height / 3)
                scale = min(scale_x, scale_y)

                # the bb width is the width / 3 * scale, to avoid black bars left
                # and right exapand it to the osd_width but not if this is more than the
                # image width (same for height)
                bbw = min(max((width / 3) * scale, self.osd_width), width) / scale
                bbh = min(max((height / 3) * scale, self.osd_height), height) / scale

            # calculate the beginning of the bounding box
            bbx = max(0, bbcx - bbw/2)
            bby = max(0, bbcy - bbh/2)

            if bbx + bbw > width:  bbx = width - bbw
            if bby + bbh > height: bby = height - bbh

            if self.rotation % 180:
                new_h, new_w = bbw * scale, bbh * scale
            else:
                new_w, new_h = bbw * scale, bbh * scale

        else:
            if self.rotation % 180:
                height, width = width, height

            # scale_x = scale_y = 1.0
            # if width > osd_width: scale_x = float(osd_width) / width
            # if height > osd_height: scale_y = float(osd_height) / height
            scale_x = float(self.osd_width) / width
            scale_y = float(self.osd_height) / height

            scale = min(scale_x, scale_y)

            new_w, new_h = int(scale*width), int(scale*height)


        # Now we have all necessary information about zoom yes/no and
        # the kind of rotation

        x = (self.osd_width - new_w) / 2
        y = (self.osd_height - new_h) / 2

        last_item,last_image = self.last_image


        if not isinstance(zoom, int):
            # change zoom based on rotation
            if self.rotation == 90:
                zoom = zoom[0], -zoom[2], zoom[1]
            if self.rotation == 180:
                zoom = zoom[0], -zoom[1], -zoom[2]
            if self.rotation == 270:
                zoom = zoom[0], zoom[2], -zoom[1]

            # don't move outside the image
            if bbx + zoom[1] < 0:
                zoom = zoom[0], -bbx, zoom[2]
            if bbx + zoom[1] > width - bbw:
                zoom = zoom[0], width - (bbw + bbx), zoom[2]
            if bby + zoom[2] < 0:
                zoom = zoom[0], zoom[1], -bby
            if bby + zoom[2] > height - bbh:
                zoom = zoom[0], zoom[1], height - (bbh + bby)

            # change bbx
            bbx += zoom[1]
            bby += zoom[2]

        # save zoom, but revert the rotation mix up
        if not isinstance(zoom, int) and self.rotation:
            if self.rotation == 90:
                zoom = zoom[0], zoom[2], -zoom[1]
            if self.rotation == 180:
                zoom = zoom[0], -zoom[1], -zoom[2]
            if self.rotation == 270:
                zoom = zoom[0], -zoom[2], zoom[1]
        self.zoom = zoom

        self.last_image  = (item, (image, x, y, scale, bbx, bby, bbw, bbh, self.rotation))

        if (last_image and last_item != item and config.IMAGEVIEWER_BLEND_MODE != None):
            screen = self.osd.screen.convert()
            screen.fill((0,0,0,0))
            screen.blit(self.osd.zoomsurface(image, scale, bbx, bby, bbw, bbh,
                                        rotation=self.rotation).convert(), (x, y))
            # update the OSD
            self.drawosd(layer=screen)

            self.blend = Transition(self.osd.screen, screen, config.IMAGEVIEWER_BLEND_MODE)
            self.blend.start()
            self.blend.inprogress.connect(self.__blend_done, item)

        else:
            self.osd.clearscreen(color=self.osd.COL_BLACK)
            self.osd.drawsurface(image, x, y, scale, bbx, bby, bbw, bbh, rotation=self.rotation)

            # update the OSD
            self.drawosd()
            self.__drawn(item)
Beispiel #2
0
class ImageViewer(GUIObject):

    def __init__(self):
        logger.log( 9, 'ImageViewer.__init__()')
        GUIObject.__init__(self)
        self.osd_mode = 0    # Draw file info on the image
        self.zoom = 0   # Image zoom
        self.zoom_btns = { str(IMAGE_NO_ZOOM):0, str(IMAGE_ZOOM_GRID1):1,
                           str(IMAGE_ZOOM_GRID2):2, str(IMAGE_ZOOM_GRID3):3,
                           str(IMAGE_ZOOM_GRID4):4, str(IMAGE_ZOOM_GRID5):5,
                           str(IMAGE_ZOOM_GRID6):6, str(IMAGE_ZOOM_GRID7):7,
                           str(IMAGE_ZOOM_GRID8):8, str(IMAGE_ZOOM_GRID9):9 }

        self.slideshow   = config.IMAGEVIEWER_AUTOPLAY
        self.duration    = config.IMAGEVIEWER_DURATION
        self.event_context = 'image'
        self.last_image  = (None, None)
        self.render      = render.get_singleton()
        self.osd         = osd.get_singleton()
        self.osd_height  = self.osd.height
        self.osd_width   = self.osd.width * float(config.OSD_PIXEL_ASPECT)

        self.timer = None
        self.blend = None
        self.__added_app = False
        self.free_cache()


    def free_cache(self):
        """
        free the current cache to save memory
        """
        logger.log( 9, 'free_cache()')
        self.bitmapcache = util.objectcache.ObjectCache(3, desc='viewer')
        if self.parent and self.free_cache in self.parent.show_callbacks:
            self.parent.show_callbacks.remove(self.free_cache)


    def view(self, item, zoom=0, rotation=0):
        """
        view an image
        """
        logger.log( 9, 'view(item, zoom=%s, rotation=%s)', zoom, rotation)

        if self.blend:
            self.blend.stop()
            self.blend.remove()
            self.blend = None
            
        if zoom:
            self.event_context    = 'image_zoom'
        else:
            self.event_context    = 'image'

        filename = item.filename

        self.fileitem = item
        self.parent   = item.menuw

        if not self.free_cache in item.menuw.show_callbacks:
            item.menuw.show_callbacks.append(self.free_cache)

        self.filename = filename
        self.rotation = rotation

        if filename and len(filename) > 0:
            image = self.osd.loadbitmap(filename, cache=self.bitmapcache)
        else:
            # Using Container-Image
            image, w, h = item.loadimage()

        if not self.__added_app:
            rc.add_app(self)
            self.__added_app = True

        if not image:
            self.osd.clearscreen(color=self.osd.COL_BLACK)
            self.osd.drawstringframed(_('Can\'t Open Image\n"%s"') % Unicode(filename),
                config.OSD_OVERSCAN_LEFT + 20, config.OSD_OVERSCAN_TOP + 20,
                self.osd.width - (config.OSD_OVERSCAN_LEFT+config.OSD_OVERSCAN_RIGHT) - 40,
                self.osd.height - (config.OSD_OVERSCAN_TOP+config.OSD_OVERSCAN_BOTTOM) - 40,
                self.osd.getfont(config.OSD_DEFAULT_FONTNAME, config.OSD_DEFAULT_FONTSIZE),
                fgcolor=self.osd.COL_ORANGE, align_h='center', align_v='center', mode='soft')
            self.osd.update()
            return

        width, height = image.get_size()

        # Bounding box default values
        bbx = bby = bbw = bbh = 0

        if zoom:
            # Translate the 9-element grid to bounding boxes
            if config.IMAGEVIEWER_REVERSED_IMAGES:
                if self.rotation == 90:
                    bb = { 1:(2,2), 2:(2,1), 3:(2,0),
                           4:(1,2), 5:(1,1), 6:(1,0),
                           7:(0,2), 8:(0,1), 9:(0,0) }
                elif self.rotation == 180:
                    bb = { 1:(2,0), 2:(1,0), 3:(0,0),
                           4:(2,1), 5:(1,1), 6:(0,1),
                           7:(2,2), 8:(1,2), 9:(0,2) }
                elif self.rotation == 270:
                    bb = { 1:(0,0), 2:(0,1), 3:(0,2),
                           4:(1,0), 5:(1,1), 6:(1,2),
                           7:(2,0), 8:(2,1), 9:(2,2) }
                else:
                    bb = { 1:(0,2), 2:(1,2), 3:(2,2),
                           4:(0,1), 5:(1,1), 6:(2,1),
                           7:(0,0), 8:(1,0), 9:(2,0) }
            else:
                if self.rotation == 90:
                    bb = { 1:(2,0), 2:(2,1), 3:(2,2),
                           4:(1,0), 5:(1,1), 6:(1,2),
                           7:(0,0), 8:(0,1), 9:(0,2) }
                elif self.rotation == 180:
                    bb = { 1:(2,2), 2:(1,2), 3:(0,2),
                           4:(2,1), 5:(1,1), 6:(0,1),
                           7:(2,0), 8:(1,0), 9:(0,0) }
                elif self.rotation == 270:
                    bb = { 1:(0,2), 2:(0,1), 3:(0,0),
                           4:(1,2), 5:(1,1), 6:(1,0),
                           7:(2,2), 8:(2,1), 9:(2,0) }
                else:
                    bb = { 1:(0,0), 2:(1,0), 3:(2,0),
                           4:(0,1), 5:(1,1), 6:(2,1),
                           7:(0,2), 8:(1,2), 9:(2,2) }

            if isinstance(zoom, int):
                h, v = bb[zoom]
            else:
                h, v = bb[zoom[0]]

            # Bounding box center
            bbcx = ([1, 3, 5][h]) * width / 6
            bbcy = ([1, 3, 5][v]) * height / 6

            if self.rotation % 180:
                # different calculations because image width is screen height
                scale_x = float(self.osd_width) / (height / 3)
                scale_y = float(self.osd_height) / (width / 3)
                scale = min(scale_x, scale_y)

                # read comment for the bbw and bbh calculations below
                bbw = min(max((width / 3) * scale, self.osd_height), width) / scale
                bbh = min(max((height / 3) * scale, self.osd_width), height) / scale

            else:
                scale_x = float(self.osd_width) / (width / 3)
                scale_y = float(self.osd_height) / (height / 3)
                scale = min(scale_x, scale_y)

                # the bb width is the width / 3 * scale, to avoid black bars left
                # and right exapand it to the osd_width but not if this is more than the
                # image width (same for height)
                bbw = min(max((width / 3) * scale, self.osd_width), width) / scale
                bbh = min(max((height / 3) * scale, self.osd_height), height) / scale

            # calculate the beginning of the bounding box
            bbx = max(0, bbcx - bbw/2)
            bby = max(0, bbcy - bbh/2)

            if bbx + bbw > width:  bbx = width - bbw
            if bby + bbh > height: bby = height - bbh

            if self.rotation % 180:
                new_h, new_w = bbw * scale, bbh * scale
            else:
                new_w, new_h = bbw * scale, bbh * scale

        else:
            if self.rotation % 180:
                height, width = width, height

            # scale_x = scale_y = 1.0
            # if width > osd_width: scale_x = float(osd_width) / width
            # if height > osd_height: scale_y = float(osd_height) / height
            scale_x = float(self.osd_width) / width
            scale_y = float(self.osd_height) / height

            scale = min(scale_x, scale_y)

            new_w, new_h = int(scale*width), int(scale*height)


        # Now we have all necessary information about zoom yes/no and
        # the kind of rotation

        x = (self.osd_width - new_w) / 2
        y = (self.osd_height - new_h) / 2

        last_item,last_image = self.last_image


        if not isinstance(zoom, int):
            # change zoom based on rotation
            if self.rotation == 90:
                zoom = zoom[0], -zoom[2], zoom[1]
            if self.rotation == 180:
                zoom = zoom[0], -zoom[1], -zoom[2]
            if self.rotation == 270:
                zoom = zoom[0], zoom[2], -zoom[1]

            # don't move outside the image
            if bbx + zoom[1] < 0:
                zoom = zoom[0], -bbx, zoom[2]
            if bbx + zoom[1] > width - bbw:
                zoom = zoom[0], width - (bbw + bbx), zoom[2]
            if bby + zoom[2] < 0:
                zoom = zoom[0], zoom[1], -bby
            if bby + zoom[2] > height - bbh:
                zoom = zoom[0], zoom[1], height - (bbh + bby)

            # change bbx
            bbx += zoom[1]
            bby += zoom[2]

        # save zoom, but revert the rotation mix up
        if not isinstance(zoom, int) and self.rotation:
            if self.rotation == 90:
                zoom = zoom[0], zoom[2], -zoom[1]
            if self.rotation == 180:
                zoom = zoom[0], -zoom[1], -zoom[2]
            if self.rotation == 270:
                zoom = zoom[0], -zoom[2], zoom[1]
        self.zoom = zoom

        self.last_image  = (item, (image, x, y, scale, bbx, bby, bbw, bbh, self.rotation))

        if (last_image and last_item != item and config.IMAGEVIEWER_BLEND_MODE != None):
            screen = self.osd.screen.convert()
            screen.fill((0,0,0,0))
            screen.blit(self.osd.zoomsurface(image, scale, bbx, bby, bbw, bbh,
                                        rotation=self.rotation).convert(), (x, y))
            # update the OSD
            self.drawosd(layer=screen)

            self.blend = Transition(self.osd.screen, screen, config.IMAGEVIEWER_BLEND_MODE)
            self.blend.start()
            self.blend.inprogress.connect(self.__blend_done, item)

        else:
            self.osd.clearscreen(color=self.osd.COL_BLACK)
            self.osd.drawsurface(image, x, y, scale, bbx, bby, bbw, bbh, rotation=self.rotation)

            # update the OSD
            self.drawosd()
            self.__drawn(item)

    def __drawn(self, item):

        if plugin.getbyname('osd'):
            plugin.getbyname('osd').draw(('osd', None), self.osd)

        # draw
        self.osd.update()

        # start timer
        if self.duration and self.slideshow and not self.timer:
            self.timer = kaa.OneShotTimer(self.signalhandler)
            self.timer.start(self.duration)


        # stop slideshow at the end if configured
        try:
            index = item.parent.play_items.index(item)+1
            length = len(item.parent.play_items)
            if index == length:
                self.slideshow = config.IMAGEVIEWER_AUTOPLAY

            # send information event to LCD2
            rc.post_event(Event('IMAGE_VIEW_INFO', arg=(index, length, item.name)))
        except Exception, why:
            logger.warning('Invalid parent item: %s', why)

        # XXX Hack to move the selected item to the current showing image
        # XXX TODO: find a way to add it to directory.py or playlist.py
        if item.parent and hasattr(item.parent, 'menu') and item.parent.menu and \
               item in item.parent.menu.choices:
            item.parent.menu.selected = item
            item.menuw.force_page_rebuild = True

        return None
Beispiel #3
0
    def view(self, item, zoom=0, rotation=0):
        #print 'view(self, item, zoom=%s, rotation=%s)' % (zoom, rotation)
        if zoom:
            self.app_mode = 'image_zoom'
        else:
            self.app_mode = 'image'

        filename = item.filename

        self.fileitem = item
        self.parent = item.menuw

        if not self.free_cache in item.menuw.show_callbacks:
            item.menuw.show_callbacks.append(self.free_cache)

        self.filename = filename
        self.rotation = rotation

        if filename and len(filename) > 0:
            image = self.osd.loadbitmap(filename, cache=self.bitmapcache)
        else:
            # Using Container-Image
            image = item.loadimage()

        rc.app(self)

        if not image:
            self.osd.clearscreen(color=self.osd.COL_BLACK)
            self.osd.drawstringframed(
                _('Can\'t Open Image\n\'%s\'') % Unicode(filename),
                config.OSD_OVERSCAN_X + 20,
                config.OSD_OVERSCAN_Y + 20,
                self.osd.width - 2 * config.OSD_OVERSCAN_X - 40,
                self.osd.height - 2 * config.OSD_OVERSCAN_Y - 40,
                self.osd.getfont(config.OSD_DEFAULT_FONTNAME,
                                 config.OSD_DEFAULT_FONTSIZE),
                fgcolor=self.osd.COL_ORANGE,
                align_h='center',
                align_v='center',
                mode='soft')
            self.osd.update()
            return

        width, height = image.get_size()

        # Bounding box default values
        bbx = bby = bbw = bbh = 0

        if zoom:
            # Translate the 9-element grid to bounding boxes
            if self.rotation == 90:
                bb = {
                    1: (2, 0),
                    2: (2, 1),
                    3: (2, 2),
                    4: (1, 0),
                    5: (1, 1),
                    6: (1, 2),
                    7: (0, 0),
                    8: (0, 1),
                    9: (0, 2)
                }
            elif self.rotation == 180:
                bb = {
                    1: (2, 2),
                    2: (1, 2),
                    3: (0, 2),
                    4: (2, 1),
                    5: (1, 1),
                    6: (0, 1),
                    7: (2, 0),
                    8: (1, 0),
                    9: (0, 0)
                }
            elif self.rotation == 270:
                bb = {
                    1: (0, 2),
                    2: (0, 1),
                    3: (0, 0),
                    4: (1, 2),
                    5: (1, 1),
                    6: (1, 0),
                    7: (2, 2),
                    8: (2, 1),
                    9: (2, 0)
                }
            else:
                bb = {
                    1: (0, 0),
                    2: (1, 0),
                    3: (2, 0),
                    4: (0, 1),
                    5: (1, 1),
                    6: (2, 1),
                    7: (0, 2),
                    8: (1, 2),
                    9: (2, 2)
                }

            if isinstance(zoom, int):
                h, v = bb[zoom]
            else:
                h, v = bb[zoom[0]]

            # Bounding box center
            bbcx = ([1, 3, 5][h]) * width / 6
            bbcy = ([1, 3, 5][v]) * height / 6

            if self.rotation % 180:
                # different calculations because image width is screen height
                scale_x = float(self.osd.width) / (height / 3)
                scale_y = float(self.osd.height) / (width / 3)
                scale = min(scale_x, scale_y)

                # read comment for the bbw and bbh calculations below
                bbw = min(max(
                    (width / 3) * scale, self.osd.height), width) / scale
                bbh = min(max(
                    (height / 3) * scale, self.osd.width), height) / scale

            else:
                scale_x = float(self.osd.width) / (width / 3)
                scale_y = float(self.osd.height) / (height / 3)
                scale = min(scale_x, scale_y)

                # the bb width is the width / 3 * scale, to avoid black bars left
                # and right exapand it to the osd.width but not if this is more than the
                # image width (same for height)
                bbw = min(max(
                    (width / 3) * scale, self.osd.width), width) / scale
                bbh = min(max(
                    (height / 3) * scale, self.osd.height), height) / scale

            # calculate the beginning of the bounding box
            bbx = max(0, bbcx - bbw / 2)
            bby = max(0, bbcy - bbh / 2)

            if bbx + bbw > width: bbx = width - bbw
            if bby + bbh > height: bby = height - bbh

            if self.rotation % 180:
                new_h, new_w = bbw * scale, bbh * scale
            else:
                new_w, new_h = bbw * scale, bbh * scale

        else:
            if self.rotation % 180:
                height, width = width, height

            # scale_x = scale_y = 1.0
            # if width > osd.width: scale_x = float(osd.width) / width
            # if height > osd.height: scale_y = float(osd.height) / height
            scale_x = float(self.osd.width) / width
            scale_y = float(self.osd.height) / height

            scale = min(scale_x, scale_y)

            new_w, new_h = int(scale * width), int(scale * height)

        # Now we have all necessary informations about zoom yes/no and
        # the kind of rotation

        x = (self.osd.width - new_w) / 2
        y = (self.osd.height - new_h) / 2

        last_image = self.last_image[1]

        if not isinstance(zoom, int):
            # change zoom based on rotation
            if self.rotation == 90:
                zoom = zoom[0], -zoom[2], zoom[1]
            if self.rotation == 180:
                zoom = zoom[0], -zoom[1], -zoom[2]
            if self.rotation == 270:
                zoom = zoom[0], zoom[2], -zoom[1]

            # don't move outside the image
            if bbx + zoom[1] < 0:
                zoom = zoom[0], -bbx, zoom[2]
            if bbx + zoom[1] > width - bbw:
                zoom = zoom[0], width - (bbw + bbx), zoom[2]
            if bby + zoom[2] < 0:
                zoom = zoom[0], zoom[1], -bby
            if bby + zoom[2] > height - bbh:
                zoom = zoom[0], zoom[1], height - (bbh + bby)

            # change bbx
            bbx += zoom[1]
            bby += zoom[2]

        if (last_image and self.last_image[0] != item
                and config.IMAGEVIEWER_BLEND_MODE != None):
            screen = self.osd.screen.convert()
            screen.fill((0, 0, 0, 0))
            screen.blit(
                self.osd.zoomsurface(image,
                                     scale,
                                     bbx,
                                     bby,
                                     bbw,
                                     bbh,
                                     rotation=self.rotation).convert(), (x, y))
            # update the OSD
            self.drawosd(layer=screen)

            blend = Transition(self.osd.screen, screen,
                               config.IMAGEVIEWER_BLEND_MODE)
            blend.start()
            while not blend.finished:
                rc.poll()
            blend.remove()

        else:
            self.osd.clearscreen(color=self.osd.COL_BLACK)
            self.osd.drawsurface(image,
                                 x,
                                 y,
                                 scale,
                                 bbx,
                                 bby,
                                 bbw,
                                 bbh,
                                 rotation=self.rotation)

            # update the OSD
            self.drawosd()

        if plugin.getbyname('osd'):
            plugin.getbyname('osd').draw(('osd', None), self.osd)

        # draw
        self.osd.update()

        # start timer
        if self.fileitem.duration and self.slideshow and not self.signal_registered:
            rc.register(self.signalhandler, False,
                        self.fileitem.duration * 100)
            self.signal_registered = True

        self.last_image = (item, (image, x, y, scale, bbx, bby, bbw, bbh,
                                  self.rotation))

        # XXX Hack to move the selected item to the current showing image
        # XXX TODO: find a way to add it to directory.py or playlist.py
        if item.parent and hasattr(item.parent, 'menu') and item.parent.menu and \
               item in item.parent.menu.choices:
            item.parent.menu.selected = item
            item.menuw.force_page_rebuild = True

        # save zoom, but revert the rotation mix up
        if not isinstance(zoom, int) and self.rotation:
            if self.rotation == 90:
                zoom = zoom[0], zoom[2], -zoom[1]
            if self.rotation == 180:
                zoom = zoom[0], -zoom[1], -zoom[2]
            if self.rotation == 270:
                zoom = zoom[0], -zoom[2], zoom[1]
        self.zoom = zoom
        return None