def draw_anagram(anagram):
  
  BOX_LEFT      = 4
  BOX_TOP       = 22
  BOX_X_OFFSET  = 31
  BOX_Y_OFFSET  = 61
  
  TEXT_X_OFFSET = 13
  TEXT_Y_OFFSET = 9
  TEXT_CLT      = 8
  FONT          = CLT[TEXT_CLT]['font']
  
  MAX_LETTERS   = 15
  
  BOX = QImage(os.path.join(ANAGRAM_DIR, "box.png"))
  QUESTION = QImage(os.path.join(ANAGRAM_DIR, "question.png"))
  out = QImage(os.path.join(ANAGRAM_DIR, "bg.png"))
  
  text = anagram.solution.translated
  
  if len(text) == 0:
    return out
  
  if not out.format() is QImage.Format_ARGB32_Premultiplied:
    out = out.convertToFormat(QImage.Format_ARGB32_Premultiplied)
  
  painter = QPainter(out)
  painter.setRenderHint(QPainter.Antialiasing, True)
  
  # Put them in a list so it's easier to loop.
  visible = [range(1, len(text) + 1), anagram.easy, anagram.normal, anagram.hard]
  
  x = BOX_LEFT
  y = BOX_TOP
  
  for row in range(len(visible)):
    
    if not visible[row] == None:
      for i, char in enumerate(text):
      
        if (i + 1) in visible[row]:
          
          painter.drawImage(QRect(x, y, BOX.width(), BOX.height()), BOX, BOX.rect())
          
          # Get info on our current letter.
          letter, (xshift, yshift, final_w, final_h) = get_letter(TEXT_CLT, char)
          painter.drawImage(QRect(x + TEXT_X_OFFSET + xshift, y + TEXT_Y_OFFSET + yshift, final_w, final_h), letter, letter.rect())
        
        else:
          painter.drawImage(QRect(x, y, QUESTION.width(), QUESTION.height()), QUESTION, QUESTION.rect())
        
        x += BOX_X_OFFSET
      
    x = BOX_LEFT
    y += BOX_Y_OFFSET
  
  painter.end()
  
  return out
def draw_anagram(anagram):
  
  BOX_LEFT      = 4
  BOX_TOP       = 22
  BOX_X_OFFSET  = 31
  BOX_Y_OFFSET  = 61
  
  TEXT_X_OFFSET = 13
  TEXT_Y_OFFSET = 9
  TEXT_CLT      = 8
  FONT          = CLT_STYLES[TEXT_CLT].font
  
  MAX_LETTERS   = 15
  
  BOX = QImage(os.path.join(ANAGRAM_DIR, "box.png"))
  QUESTION = QImage(os.path.join(ANAGRAM_DIR, "question.png"))
  out = QImage(os.path.join(ANAGRAM_DIR, "bg.png"))
  
  text = anagram.solution[common.editor_config.lang_trans]
  
  if len(text) == 0:
    return out
  
  if not out.format() is QImage.Format_ARGB32_Premultiplied:
    out = out.convertToFormat(QImage.Format_ARGB32_Premultiplied)
  
  painter = QPainter(out)
  painter.setRenderHint(QPainter.Antialiasing, True)
  
  # Put them in a list so it's easier to loop.
  visible = [range(1, len(text) + 1), anagram.easy, anagram.normal, anagram.hard]
  
  x = BOX_LEFT
  y = BOX_TOP
  
  for row in range(len(visible)):
    
    if not visible[row] == None:
      for i, char in enumerate(text):
      
        if (i + 1) in visible[row]:
          
          painter.drawImage(QRect(x, y, BOX.width(), BOX.height()), BOX, BOX.rect())
          
          # Get info on our current letter.
          letter, (xshift, yshift, final_w, final_h) = get_letter(TEXT_CLT, char)
          painter.drawImage(QRect(x + TEXT_X_OFFSET + xshift, y + TEXT_Y_OFFSET + yshift, final_w, final_h), letter, letter.rect())
        
        else:
          painter.drawImage(QRect(x, y, QUESTION.width(), QUESTION.height()), QUESTION, QUESTION.rect())
        
        x += BOX_X_OFFSET
      
    x = BOX_LEFT
    y += BOX_Y_OFFSET
  
  painter.end()
  
  return out
示例#3
0
文件: opengl.py 项目: markusd/rocket
 def loadFromFile(cls, path, internalFormat=GL_RGBA):
     image = QImage(path)
     image = QGLWidget.convertToGLFormat(image)
     dataFormat = { QImage.Format_ARGB32: GL_RGBA }.get(image.format(), None)
     dataType = GL_UNSIGNED_BYTE
     data = [0] * image.numBytes()
     bits = image.constBits()
     bits.setsize(image.numBytes())
     for i in range(image.numBytes()):
         data[i] = bits[i][0]
     return Texture2D(image.width(), image.height(), internalFormat, dataFormat, dataType, data)
def get_trial(scene_info, show_bg = True, show_sprite = True, show_box = True):
  
  case_num = scene_info.chapter
  sprite_id = scene_info.sprite
  
  if case_num > 6 or case_num <= 0:
    case_num = 1
  
  out = None
  
  if show_bg:
    if scene_info.movie >= 0:
      out = get_movie(scene_info.movie)
    elif scene_info.flash >= 0:
      out = get_flash(scene_info.flash)
    elif scene_info.bgd >= 0:
      out = get_bgd(scene_info.bgd)
    else:
      # out = QImage(os.path.join(BG_DIR, "bg_%03d.png" % (199 + case_num)))
      out = get_bg(199 + case_num)
  else:
    out = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
    out.fill(QColor(0, 0, 0, 0).rgba())
  
  if not out.format() is QImage.Format_ARGB32_Premultiplied:
    out = out.convertToFormat(QImage.Format_ARGB32_Premultiplied)
  
  painter = QPainter(out)
  painter.setRenderHint(QPainter.Antialiasing, True)
  
  if show_sprite:
    sprite_id.sprite_type = SPRITE_TYPE.stand
    
    sprite = get_sprite(sprite_id)
    if sprite:
      painter.drawImage(out.rect(), sprite, sprite.rect())
  
  if not scene_info.img_filter == IMG_FILTERS.unfiltered:
    painter.end()
    out = filter_image(out, scene_info.img_filter)
    painter = QPainter(out)
    painter.setRenderHint(QPainter.Antialiasing, True)
  
  if show_box:
  
    box = get_box(scene_info)
    painter.drawImage(out.rect(), box, box.rect())
  
  return out
def get_trial(scene_info, show_bg=True, show_sprite=True, show_box=True):

    case_num = scene_info.chapter
    sprite_id = scene_info.sprite

    if case_num > 6 or case_num <= 0:
        case_num = 1

    out = None

    if show_bg:
        if scene_info.movie >= 0:
            out = get_movie(scene_info.movie)
        elif scene_info.flash >= 0:
            out = get_flash(scene_info.flash)
        elif scene_info.bgd >= 0:
            out = get_bgd(scene_info.bgd)
        else:
            # out = QImage(os.path.join(BG_DIR, "bg_%03d.png" % (199 + case_num)))
            out = get_bg(199 + case_num)
    else:
        out = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
        out.fill(QColor(0, 0, 0, 0).rgba())

    if not out.format() is QImage.Format_ARGB32_Premultiplied:
        out = out.convertToFormat(QImage.Format_ARGB32_Premultiplied)

    painter = QPainter(out)
    painter.setRenderHint(QPainter.Antialiasing, True)

    if show_sprite:
        sprite_id.sprite_type = SPRITE_TYPE.stand

        sprite = get_sprite(sprite_id)
        if sprite:
            painter.drawImage(out.rect(), sprite, sprite.rect())

    if not scene_info.img_filter == IMG_FILTERS.unfiltered:
        painter.end()
        out = filter_image(out, scene_info.img_filter)
        painter = QPainter(out)
        painter.setRenderHint(QPainter.Antialiasing, True)

    if show_box:

        box = get_box(scene_info)
        painter.drawImage(out.rect(), box, box.rect())

    return out
示例#6
0
    def loadFromFile( self, fileName ):
        " Loads a pixmap from a file "
        image = QImage( fileName )
        if image.isNull():
            raise Exception( "Unsupported pixmap format (" + fileName + ")" )

        self.pixmapLabel.setPixmap( QPixmap.fromImage( image ) )
        self.pixmapLabel.adjustSize()

        self.fileSize = os.path.getsize( fileName )
        if self.fileSize < 1024:
            fileSizeString = str( self.fileSize ) + "bytes"
        else:
            kiloBytes = self.fileSize / 1024
            if (self.fileSize % 1024) >= 512:
                kiloBytes += 1
            fileSizeString = str( kiloBytes ) + "kb"
        self.info = str( image.width() ) + "px/" + \
                    str( image.height() ) + "px/" + fileSizeString
        try:
            self.formatInfo = self.formatStrings[ image.format() ]
        except:
            self.formatInfo = "Unknown"
        return
示例#7
0
	def createQImage(self):
		with open('img1', 'rb') as f:
			content = f.read()
		self._image = QImage()
		print self._image.loadFromData(content)
		print QImage.format(self._image)
示例#8
0
文件: pqPngs.py 项目: jlg234bob/PPQT
class pngDisplay(QWidget):
    def __init__(self, parent=None):
        super(pngDisplay, self).__init__(parent)
        #self.profiler = cProfile.Profile()
        # create the label that displays the image - cribbing from the Image
        # Viewer example in the Qt docs.
        self.imLabel = QLabel()
        self.imLabel.setBackgroundRole(QPalette.Base)
        self.imLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.imLabel.setScaledContents(True)
        # Create a gray field to use when no png is available
        self.defaultPM = QPixmap(700,900)
        self.defaultPM.fill(QColor("gray"))
        # Create a scroll area within which to display our imLabel, this
        # enables the creation of horizontal and vertical scroll bars, when
        # the imLabel exceeds the size of the scroll area.
        self.scarea = QScrollArea()
        # The following two lines make sure that page up/dn gets through
        # the scrollarea widget and up to us.
        self.setFocusPolicy(Qt.ClickFocus)
        self.scarea.setFocusProxy(self)
        self.scarea.setBackgroundRole(QPalette.Dark)
        #self.scarea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        #self.scarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scarea.setWidget(self.imLabel)
        # create the text label that will have the page number in it
        self.txLabel = QLabel(u"No image")
        self.txLabel.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
        self.txLabel.setFrameStyle(QFrame.Sunken | QFrame.StyledPanel)
        # Create a spinbox to set the zoom from 15 to 200 with a label:
        # (originally a slider, hence the name)
        self.minZoom = 0.15
        self.maxZoom = 2.00
        self.zlider = QSpinBox()
        self.zlider.setRange(int(100*self.minZoom),int(100*self.maxZoom))
        # connect the value change signal to a slot to handle it
        self.connect(self.zlider, SIGNAL("valueChanged(int)"), self.newZoomFactor)
        # create the to-width and to-height zoom buttons
        zoomWidthButton = QPushButton(u'to Width')
        self.connect(zoomWidthButton, SIGNAL("clicked()"), self.zoomToWidth)
        zoomHeightButton = QPushButton(u'to Height')
        self.connect(zoomHeightButton, SIGNAL("clicked()"), self.zoomToHeight)
        # Make an hbox to contain the spinbox and two pushbuttons, with
        # stretch on left and right to center the group.
        zlabel = QLabel(
            u'&Zoom ' + str(self.zlider.minimum())
            + '-' + str(self.zlider.maximum()) + '%')
        zlabel.setBuddy(self.zlider)
        zhbox = QHBoxLayout()
        zhbox.addStretch(1)
        zhbox.addWidget(zlabel,0,Qt.AlignLeft)
        zhbox.addWidget(self.zlider,0)
        zhbox.addStretch(1)
        zhbox.addWidget(zoomWidthButton)
        zhbox.addWidget(zoomHeightButton)
        zhbox.addStretch(1)
        # With all the pieces in hand, create our layout basically a
        # vertical stack: scroll area, label, slider box.
        vbox = QVBoxLayout()
        # the image gets a high stretch and default alignment, the text
        # label hugs the bottom and doesn't stretch at all.
        vbox.addWidget(self.txLabel,0,Qt.AlignBottom)
        vbox.addWidget(self.scarea,10)
        vbox.addLayout(zhbox,0)
        self.setLayout(vbox)
        # Initialize assuming no book is open.
        self.ready = False # nothing to display
        # Recover the last-set zoom factor from the settings object, default 1.0
        qv = IMC.settings.value("pngs/zoomFactor",QVariant(1.0))
        self.zoomFactor = qv.toFloat()[0]
        # The following causes entry into newZoomFactor, below, which tests
        # self.ready, hence the latter has to be assigned-to first.
        self.zlider.setValue(int(self.zoomFactor*100))
        self.clear()

    # local subroutine to initialize our contents for an empty edit.
    # called from _init_ and from newPosition when we discover the file
    # has been cleared on us. Don't reset the zoomFactor, leave it as
    # the user last set it.
    def clear(self):
        # Clear the page name, used by pqNotes
        IMC.currentImageNumber = None # will be name of last png file e.g. "002"
        # Clear the page filename, used in our caption label
        self.lastPage = QString() # last file name e.g. "002.png"
        # Clear the path to the pngs folder, used to fetch image files
        self.pngPath = QString()
        # Clear the index of the last-shown page in the page table
        # -1 means no page is being displayed.
        self.lastIndex = -1
        # Clear the index of the next page to display, normally same as last
        self.nextIndex = -1
        # Set not-ready to indicate no pngs directory available.
        self.ready = False
        # Clear out & release storage of our QImage and QPixmaps
        self.pixmap = QPixmap() # null pixmap
        self.image = QImage()
        self.noImage() # show gray image

    # Display a blank gray frame and "No Image" below.
    # Called from clear() above and from showPage when no valid image.
    def noImage(self) :
        self.imLabel.setPixmap(self.defaultPM)
        self.txLabel.setText(u"No image")
        self.lastIndex = -1 # didn't see a prior page
        self.nextIndex = -1

    # This slot gets the main window's signal shuttingDown.
    # We save our current zoom factor into IMC.settings.
    def shuttingDown(self):
        IMC.settings.setValue("pngs/zoomFactor",QVariant(self.zoomFactor))

    # This slot gets pqMain's signal docHasChanged(QString), telling
    # us that a different document has been loaded. This could be for
    # a successful File>Open, or a failed File>Open or File>New.
    # The bookPath is a null QString for File>New, or the full bookPath.
    # If the latter, we convert that into the path to the pngs folder,
    # and see if bookPath/pngs is a directory. If so, we set self.ready
    # to true, indicating it is worthwhile to try opening image files.
    # At this point the gray image is displayed and previously would remain displayed
    # until the user moved the cursor in some way, generating cursorPositionChanged.
    # That's a minor annoyance, to avoid it we will fake that signal now.
    def newFile(self, bookPath):
        if not bookPath.isNull(): # this was successful File>Open
            finf = QFileInfo(bookPath)
            self.pngPath = finf.absolutePath().append(u"/pngs/")
            finf = QFileInfo(self.pngPath)
            if finf.exists() and finf.isDir(): # looking good
                self.ready = True
                self.newPosition()
            else:
                # We could inform the user we couldn't find a pngs folder,
                # but you know -- the user is probably already aware of that.
                self.clear() # just put up the gray default image
        else: # It was a File>New
            self.clear()

    # This function is the slot that is connected to the editor's
    # cursorPositionChanged signal. Its input is cursor position and
    # the page table. Its output is to set self.nextIndex to the
    # desired next image table row, and to call showPage.
    def newPosition(self):
        if self.ready :
            # We have a book and some pngs. Find the position of the higher end
            # of the current selection.
            pos = IMC.editWidget.textCursor().selectionEnd()
            # Get the page table index that matches this position, or -1
            # if that is above the first psep, or there is no page data
            self.nextIndex = IMC.pageTable.getIndex(pos)
        else :# No file loaded or no pngs folder found.
            self.nextIndex = -1
        if self.nextIndex != self.lastIndex :
            self.showPage()

    # Display the page indexed by self.nextIndex. This is called when the cursor
    # moves to a new page (newPosition, above), or when the PageUp/Dn keys are used,
    # (keyPressEvent, below) or when the zoom factor changes in any of several ways.
    def showPage(self):
        # If self.lastIndex is different from self.nextIndex, the page has
        # changed, and we need to load a new image.
        if self.lastIndex != self.nextIndex :
            self.lastIndex = self.nextIndex # don't come here again until it changes.
            if self.lastIndex > -1 :
                # Form the image filename as a Qstring, e.g. "025" and save that for
                # use by pqNotes:
                IMC.currentImageNumber = IMC.pageTable.getScan(self.lastIndex)
                # dbg = unicode(IMC.currentImageNumber)
                # Form the complete filename by appending ".png" and save as
                # self.lastPage for use in forming our caption label.
                self.lastPage = QString(IMC.currentImageNumber).append(QString(u".png"))
                # dbg = unicode(self.lastPage)
                # Form the full path to the image. Try to load it as a QImage.
                pngName = QString(self.pngPath).append(self.lastPage)
                self.image = QImage(pngName,'PNG')
                # dbg = unicode(self.image)
                # dbg = self.image.isNull()
                # If that successfully loaded an image, make sure it is one byte/pixel.
                if not self.image.isNull() \
                   and self.image.format() != QImage.Format_Indexed8 :
                    # It might be Format_Mono (1 bit/pixel) or even Format_RGB32.
                    self.image = self.image.convertToFormat(QImage.Format_Indexed8,Qt.ColorOnly)
                # Convert the image to a pixmap. If it's null, so is the pixmap.
                self.pixmap = QPixmap.fromImage(self.image,Qt.ColorOnly)
            else :
                IMC.currentImageNumber = QString(u"n.a.")
                self.lastPage = QString()
                self.image = QImage()
                self.pixmap = QPixmap()
        if not self.pixmap.isNull():
            # We successfully found and loaded an image and converted it to pixmap.
            # Load it in our label for display, set the zoom factor, and the caption.
            # We do this every time through (even if lastIndex equalled nextIndex)
            # because the zoomfactor might have changed.
            self.imLabel.setPixmap(self.pixmap)
            self.imLabel.resize( self.zoomFactor * self.pixmap.size() )
            folio = IMC.pageTable.getDisplay(self.lastIndex)
            self.txLabel.setText(u"image {0} (folio {1})".format(self.lastPage,folio))
        else: # no file was loaded. It's ok if pages are missing
            self.noImage() # display the gray image.

    # Catch the signal from the Zoom spinbox with a new value.
    # Store the new value as a float, and if we have a page, repaint it.
    def newZoomFactor(self,new_value):
        self.zoomFactor = new_value / 100
        if self.ready :
            self.showPage()

    # Catch the click on zoom-to-width and zoom-to height. The job is basically
    # the same for both. 1: Using the QImage that should be in self.image,
    # scan the pixels to find the width (height) of the nonwhite area.
    # 2. Get the ratio of that to our image label's viewport width (height).
    # 4. Set that ratio as the zoom factor and redraw the image. And finally
    # 5. Set the scroll position(s) of our scroll area to left-justify the text.
    #
    # We get access to the pixels using QImage:bits() which gives us a PyQt4
    # "voidptr" that we can index to get byte values.
    #
    def zoomToWidth(self):
        if (not self.ready) or (self.image.isNull()) :
            return # nothing to do here
        #self.profiler.enable() #dbg
        # Query the Color look-up table and build a list of the Green values
        # corresponding to each possible pixel value. Probably there are just
        # two colors so colortab is [0,255] but there could be more, depending
        # on how the PNG was defined, 16 or 32 or even 255 grayscale.
        colortab = [ int((self.image.color(c) >> 4) & 255)
                     for c in range(self.image.colorCount()) ]
        ncols = self.image.width() # number of logical pixels across
        stride = (ncols + 3) & (-4) # number of bytes per scanline
        nrows = self.image.height() # number of pixels high
        vptr = self.image.bits() # uchar * bunch-o-pixel-bytes
        vptr.setsize(stride * nrows) # make the pointer indexable

        # Scan in from left and right to find the outermost dark spots.
        # Looking for single pixels yeilds too many false positives, so we
        # look for three adjacent pixels that sum to less than 32.
        # Most pages start with many lines of white pixels so in hopes of
        # establishing the outer edge early, we start at the middle, go to
        # the end, then do the top half.
        left_side = int(ncols/2) # leftmost dark spot seen so far
        # scan from the middle down
        for r in xrange(int(nrows/2)*stride, (nrows-1)*stride, stride) :
            pa, pb = 255, 255 # virtual white outside border
            for c in xrange(left_side):
                pc = colortab[ ord(vptr[c + r]) ]
                if (pa + pb + pc) < 32 : # black or dark gray pair
                    left_side = c # new, further-left, left margin
                    break # no need to look further on this line
                pa = pb
                pb = pc
        # scan from the top to the middle, hopefully left_side is small now
        for r in xrange(0, int(nrows/2)*stride, stride) :
            pa, pb = 255, 255 # virtual white outside border
            for c in xrange(left_side):
                pc = colortab[ ord(vptr[c + r]) ]
                if (pa + pb + pc) < 32 : # black or dark gray pair
                    left_side = c # new, further-left, left margin
                    break # no need to look further on this line
                pa = pb
                pb = pc
        # Now do the same for the right margin.
        right_side = int(ncols/2) # rightmost dark spot seen so far
        for r in xrange(int(nrows/2)*stride, (nrows-1)*stride, stride) :
            pa, pb = 255, 255 # virtual white outside border
            for c in xrange(ncols-1,right_side,-1) :
                pc = colortab[ ord(vptr[c + r]) ]
                if (pa + pb + pc) < 32 : # black or dark gray pair
                    right_side = c # new, further-right, right margin
                    break
                pa = pb
                pb = pc
        for r in xrange(0, int(nrows/2)*stride, stride)  :
            pa, pb = 255, 255 # virtual white outside border
            for c in xrange(ncols-1,right_side,-1) :
                pc = colortab[ ord(vptr[c + r]) ]
                if (pa + pb + pc) < 32 : # black or dark gray pair
                    right_side = c # new, further-right, right margin
                    break
                pa = pb
                pb = pc
        # The area with color runs from left_side to right_side. How does
        # that compare to the size of our viewport? Scale to that and redraw.
        #print('ls {0} rs {1} vp {2}'.format(left_side,right_side,self.scarea.viewport().width()))
        text_size = right_side - left_side + 2
        port_width = self.scarea.viewport().width()
        self.zoomFactor = max( self.minZoom, min( self.maxZoom, port_width / text_size ) )
        # the next line signals newZoomFactor, which calls showPage.
        self.zlider.setValue(int(100*self.zoomFactor))
        # Set the scrollbar to show the page from its left margin.
        self.scarea.horizontalScrollBar().setValue(int( left_side * self.zoomFactor) )
        #self.profiler.disable() #dbg
        #pstats.Stats(self.profiler).print_stats() # dbg


    def zoomToHeight(self):
        if (not self.ready) or (self.image.isNull()) :
            return # nothing to do here
        # Query the Color look-up table and build a list of the Green values
        # corresponding to each possible pixel value. Probably there are just
        # two colors so colortab is [0,255] but there could be more, depending
        # on how the PNG was defined, 16 or 32 or even 255 grayscale.
        colortab = [ int((self.image.color(c) >> 4) & 255)
                     for c in range(self.image.colorCount()) ]
        ncols = self.image.width() # number of logical pixels across
        stride = (ncols + 3) & (-4) # number of bytes per scanline
        nrows = self.image.height() # number of pixels high
        vptr = self.image.bits() # uchar * bunch-o-pixel-bytes
        vptr.setsize(stride * nrows) # make the pointer indexable
        # Scan in from top and bottom to find the outermost rows with
        # significant pixels.
        top_side = -1 # The uppermost row with a significant spot of black
        offset = 0 # vptr index to the first/next pixel row
        for r in range(nrows) :
            pa, pb = 255, 255 # virtual white outside border
            for c in range(ncols) :
                pc = colortab[ ord(vptr[offset + c]) ]
                if (pa + pb + pc) < 32 : # black or dark gray triplet
                    top_side = r # that's the row,
                    break # ..so stop scanning
                pa, pb = pb, pc
            if top_side >= 0 : # we hit
                break # ..so don't scan down any further
            offset += stride # continue to next row
        # top_side indexes the first row with a significant blot
        if top_side == -1 : # never found one: an all-white page. bug out.
            return
        bottom_side = nrows # The lowest row with a significant blot
        offset = stride * nrows # vptr index to last/next row of pixels
        for r in range(nrows,top_side,-1) :
            offset -= stride
            pa, pb = 255, 255 # virtual white outside border
            for c in range(ncols) :
                pc = colortab[ ord(vptr[offset + c]) ]
                if (pa + pb + pc) < 32 : # black or dark gray triplet
                    bottom_side = r
                    break
                pa, pb = pb, pc
            if bottom_side < nrows : # we hit
                break
        # bottom_side is the lowest row with significant pixels. It must be
        # < nrows, there is at least one row (top_side) with a dot in it.
        # However if the page is mostly white, don't zoom to that extent.
        if bottom_side < (top_side+100) :
            return # seems to be a mostly-white page, give up
        # The text area runs from scanline top_side to bottom_side.
        text_height = bottom_side - top_side + 1
        port_height = self.scarea.viewport().height()
        self.zoomFactor = max( self.minZoom, min( self.maxZoom, port_height / text_height ) )
        self.zlider.setValue(int(100*self.zoomFactor)) # signals newZoomFactor->showPage
        # Set the scrollbar to show the page from its top margin.
        self.scarea.verticalScrollBar().setValue(int( top_side * self.zoomFactor) )

    # Re-implement the parent's keyPressEvent in order to provide zoom:
    # ctrl-plus increases the image size by 1.25
    # ctrl-minus decreases the image size by 0.8
    # Also trap pageup/dn and use to walk through images.
    # At this point we do not reposition the editor to match the page viewed.
    # we page up/dn but as soon as focus returns to the editor and the cursor
    # moves, this display will snap back to the edited page. As a user that
    # seems best, come over to Pngs and page ahead to see what's coming, then
    # back to the editor to read or type.
    def keyPressEvent(self, event):
        # assume we will not handle this key and clear its accepted flag
        event.ignore()
        # If we are initialized and have displayed some page, look at the key
        if self.ready:
            kkey = int( int(event.modifiers()) & IMC.keypadDeModifier) | int(event.key())
            if kkey in IMC.zoomKeys :
                # ctl/cmd + or -, do the zoom
                event.accept()
                fac = (0.8) if (kkey == IMC.ctl_minus) else (1.25)
                fac *= self.zoomFactor # target zoom factor
                if (fac >= self.minZoom) and (fac <= self.maxZoom): # keep in bounds
                    self.zoomFactor = fac
                    self.zlider.setValue(int(100*fac))
                    self.showPage()
            elif (event.key() == Qt.Key_PageUp) or (event.key() == Qt.Key_PageDown) :
                event.accept() # real pgUp or pgDn, we do it
                fac = 1 if (event.key() == Qt.Key_PageDown) else -1
                fac += self.lastIndex
                if (fac >= 0) and (fac < IMC.pageTable.size()) :
                    # not off either end of the book, so,
                    self.nextIndex = fac
                    self.showPage()
        if not event.isAccepted() : # we don't do those, pass them on
            super(pngDisplay, self).keyPressEvent(event)
def get_box(scene_info):
  
  mode       = scene_info.mode
  box_color  = scene_info.box_color
  box_type   = scene_info.box_type
  speaking   = scene_info.speaking
  speaker_id = scene_info.speaker
  headshot   = scene_info.headshot
  chapter    = scene_info.chapter
  
  if box_color != common.BOX_COLORS.yellow and box_color != common.BOX_COLORS.green and box_color != common.BOX_COLORS.blue:
    box_color = common.BOX_COLORS.yellow
  
  out = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
  out.fill(QColor(0, 0, 0, 0).rgba())
  
  painter = QPainter(out)
  painter.setRenderHint(QPainter.Antialiasing, True)
  
  # Some commonality between the boxes.
  box     = QImage()
  button  = QImage()
  
  nametag_x     = 0
  nametag_y     = 0
  nametag_color = QColor(255, 255, 255, 255)
  nametag_vert  = False
  
  if box_type == common.BOX_TYPES.flat:
    box    = QImage(os.path.join(TEXTBOX_DIR, "box_gray.png"))
    button = QImage(os.path.join(TEXTBOX_DIR, "button_%s.png" % box_color))
    
    nametag_x     = 10
    nametag_y     = 176
    nametag_color = QColor(255, 255, 255, 255)
    nametag_vert  = False
  
  elif box_type == common.BOX_TYPES.novel:
    box = QImage(os.path.join(TEXTBOX_DIR, "box_novel.png"))
  
  elif box_type == common.BOX_TYPES.normal:
    
    if mode == common.SCENE_MODES.normal:
      
      box    = QImage(os.path.join(TEXTBOX_DIR, "box.png"))
      button = QImage(os.path.join(TEXTBOX_DIR, "button_%s.png" % box_color))
      
      nametag_x     = 0
      nametag_y     = 220
      nametag_color = QColor(50, 50, 50, 255)
      nametag_vert  = True
  
      if not box.format() is QImage.Format_ARGB32_Premultiplied:
        box = box.convertToFormat(QImage.Format_ARGB32_Premultiplied)
      
      box_painter = QPainter(box)
      box_painter.setRenderHint(QPainter.Antialiasing, True)
      
      if speaker_id == 0: # Main character gets a special text box.
        namebox = QImage(os.path.join(TEXTBOX_DIR, "name_%s_mc.png" % box_color))
      else:
        namebox = QImage(os.path.join(TEXTBOX_DIR, "name_%s.png" % box_color))
        
      box_painter.drawImage(box.rect(), namebox, namebox.rect())
      
      box_painter.end()
    
    elif mode == common.SCENE_MODES.trial:
      
      box_base = QImage(os.path.join(TRIAL_DIR, "trial_box.png"))
      banner   = QImage(os.path.join(TRIAL_DIR, "trial_banner.png"))
      
      if speaker_id == 0: # Main character gets a special text box.
        namebox = QImage(os.path.join(TRIAL_DIR, "trial_name_mc.png"))
      else:
        namebox = QImage(os.path.join(TRIAL_DIR, "trial_name.png"))
      
      if not headshot == None:
        case_num = QImage(os.path.join(TRIAL_DIR, "case_%02d.png" % chapter))
        headshot = QImage(os.path.join(TRIAL_DIR, "headshot", "%02d.png" % headshot))
        underlay = QImage(os.path.join(TRIAL_DIR, "trial_headshot.png"))
      else:
        case_num = QImage()
        underlay = QImage()
        headshot = QImage()
      
      button = QImage(os.path.join(TRIAL_DIR, "button.png"))
      nametag_x     = 12
      nametag_y     = 168
      nametag_color = QColor(255, 255, 255, 255)
      nametag_vert  = False
      
      box = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
      box.fill(QColor(0, 0, 0, 0).rgba())
      
      box_painter = QPainter(box)
      box_painter.setRenderHint(QPainter.Antialiasing, True)
      
      box_painter.drawImage(box.rect(), banner,   banner.rect())
      box_painter.drawImage(box.rect(), namebox,  namebox.rect())
      box_painter.drawImage(box.rect(), box_base, box_base.rect())
      box_painter.drawImage(box.rect(), underlay, underlay.rect())
      box_painter.drawImage(box.rect(), headshot, headshot.rect())
      box_painter.drawImage(box.rect(), case_num, case_num.rect())
      
      box_painter.end()
    
    else:
      box = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
      box.fill(QColor(0, 0, 0, 0).rgba())
  
  painter.drawImage(out.rect(), box,     box.rect())
  painter.drawImage(out.rect(), button,  button.rect())
  
  if not speaker_id == None:
    nametag = get_nametag(speaker_id, nametag_x, nametag_y, nametag_color, nametag_vert)
    painter.drawImage(out.rect(), nametag, nametag.rect())
  
  painter.end()
  
  return out
def draw_scene(scene_info, text = None):
  bg = None
  max_length = 0
  kill_blanks = False
  
  if scene_info.mode in [common.SCENE_MODES.normal, common.SCENE_MODES.normal_flat]:
    bg = get_normal(scene_info)
    
    if scene_info.box_type == common.BOX_TYPES.flat:
      scene_info.mode = common.SCENE_MODES.normal_flat
    else:
      scene_info.mode = common.SCENE_MODES.normal
    
  elif scene_info.mode == common.SCENE_MODES.trial:
    bg = get_trial(scene_info)
  
  elif scene_info.mode == common.SCENE_MODES.novel:
    scene_info.box_type = common.BOX_TYPES.novel
    bg = get_normal(scene_info)
  
  elif scene_info.mode == common.SCENE_MODES.rules:
    bg = QImage(os.path.join(MENU_DIR, "rules.png"))
  
  elif scene_info.mode == common.SCENE_MODES.ammo:
    bg = QImage(os.path.join(MENU_DIR, "ammo-desc.png"))
    overlay = get_ammo(scene_info.file_id, 254, 117)
  
    if not bg.format() is QImage.Format_ARGB32_Premultiplied:
      bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)
    
    painter = QPainter(bg)
    painter.setCompositionMode(QPainter.CompositionMode_DestinationOver)
    painter.drawImage(bg.rect(), overlay, overlay.rect())
    painter.end()
    
    name = get_ammo_name(scene_info.file_id)
    if name:
      bg = print_text(bg, name, common.SCENE_MODES.ammoname, TEXT_FORMATS[common.SCENE_MODES.ammoname], False)
  
  elif scene_info.mode == common.SCENE_MODES.ammoname:
    bg = QImage(os.path.join(MENU_DIR, "ammo-list.png"))
    overlay = get_ammo(scene_info.file_id, 254, 61)
  
    if not bg.format() is QImage.Format_ARGB32_Premultiplied:
      bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)
    
    painter = QPainter(bg)
    painter.setCompositionMode(QPainter.CompositionMode_DestinationOver)
    painter.drawImage(bg.rect(), overlay, overlay.rect())
    painter.end()
  
  elif scene_info.mode == common.SCENE_MODES.present:
    bg = QImage(os.path.join(MENU_DIR, "present-desc.png"))
    overlay = get_present(scene_info.file_id, 248, 96)
  
    if not bg.format() is QImage.Format_ARGB32_Premultiplied:
      bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), overlay, overlay.rect())
    painter.end()
    
    name = get_present_name(scene_info.file_id)
    if name:
      bg = print_text(bg, name, common.SCENE_MODES.presentname, TEXT_FORMATS[common.SCENE_MODES.presentname], False)
  
  elif scene_info.mode == common.SCENE_MODES.presentname:
    bg = QImage(os.path.join(MENU_DIR, "present-list.png"))
    overlay = get_present(scene_info.file_id, 248, 46)
  
    if not bg.format() is QImage.Format_ARGB32_Premultiplied:
      bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), overlay, overlay.rect())
    painter.end()
  
  elif scene_info.mode == common.SCENE_MODES.menu:
    bg = QImage(os.path.join(MENU_DIR, "menu.png"))
  
  elif scene_info.mode == common.SCENE_MODES.report or scene_info.mode == common.SCENE_MODES.report2:
    bg = QImage(os.path.join(MENU_DIR, "report.png"))
  
  elif scene_info.mode == common.SCENE_MODES.skill or scene_info.mode == common.SCENE_MODES.skill2:
    bg = QImage(os.path.join(MENU_DIR, "skills.png"))
  
  elif scene_info.mode == common.SCENE_MODES.map:
    bg = QImage(os.path.join(MENU_DIR, "map.png"))
  
  elif scene_info.mode == common.SCENE_MODES.music:
    bg = QImage(os.path.join(MENU_DIR, "soundtest.png"))
  
  elif scene_info.mode in [common.SCENE_MODES.eventname, common.SCENE_MODES.moviename, common.SCENE_MODES.artworkname]:
    bg = QImage(os.path.join(MENU_DIR, "gallery.png"))
    
    if scene_info.mode == common.SCENE_MODES.eventname:
      overlay = get_event_icon(scene_info.file_id)
    elif scene_info.mode == common.SCENE_MODES.moviename:
      overlay = get_movie_icon(scene_info.file_id)
    elif scene_info.mode == common.SCENE_MODES.artworkname:
      overlay = get_artwork_icon(scene_info.file_id)
  
    if not bg.format() is QImage.Format_ARGB32_Premultiplied:
      bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), overlay, overlay.rect())
    painter.end()
  
  elif scene_info.mode == common.SCENE_MODES.theatre:
    bg = get_normal(scene_info)
  
  elif scene_info.mode == common.SCENE_MODES.debate or scene_info.mode == common.SCENE_MODES.hanron:
    bg = get_trial(scene_info, show_box = False)
    
  else:
    bg = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
    bg.fill(QColor(0, 0, 0, 255).rgba())
  
  if not bg.format() is QImage.Format_ARGB32_Premultiplied:
    bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)
  
  if scene_info.cutin != -1:
    cutin = get_cutin(scene_info.cutin)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), cutin, cutin.rect())
    painter.end()
  
  if scene_info.ammo != -1:
    ammo = get_ammo_ingame(scene_info.ammo)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), ammo, ammo.rect())
    painter.end()
  
  if scene_info.present != -1:
    present = get_present_ingame(scene_info.present)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), present, present.rect())
    painter.end()
  
  if scene_info.special == common.SCENE_SPECIAL.option:
    overlay = QImage(os.path.join(TEXTBOX_DIR, "option_bar.png"))
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), overlay, overlay.rect())
    painter.end()
    
    if not text == None and not text == "":
      bg = print_text(bg, text, common.SCENE_SPECIAL.option, TEXT_FORMATS[common.SCENE_SPECIAL.option], False)
      
  if not text == None and not text == "":
    bg = print_text(bg, text, scene_info.mode, TEXT_FORMATS[scene_info.mode])
  
  return bg
def get_box(scene_info):

    mode = scene_info.mode
    box_color = scene_info.box_color
    box_type = scene_info.box_type
    speaking = scene_info.speaking
    speaker_id = scene_info.speaker
    headshot = scene_info.headshot
    chapter = scene_info.chapter

    if box_color != common.BOX_COLORS.yellow and box_color != common.BOX_COLORS.green and box_color != common.BOX_COLORS.blue:
        box_color = common.BOX_COLORS.yellow

    out = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
    out.fill(QColor(0, 0, 0, 0).rgba())

    painter = QPainter(out)
    painter.setRenderHint(QPainter.Antialiasing, True)

    # Some commonality between the boxes.
    box = QImage()
    button = QImage()

    nametag_x = 0
    nametag_y = 0
    nametag_color = QColor(255, 255, 255, 255)
    nametag_vert = False

    if box_type == common.BOX_TYPES.flat:
        box = QImage(os.path.join(TEXTBOX_DIR, "box_gray.png"))
        button = QImage(os.path.join(TEXTBOX_DIR, "button_%s.png" % box_color))

        nametag_x = 10
        nametag_y = 176
        nametag_color = QColor(255, 255, 255, 255)
        nametag_vert = False

    elif box_type == common.BOX_TYPES.novel:
        box = QImage(os.path.join(TEXTBOX_DIR, "box_novel.png"))

    elif box_type == common.BOX_TYPES.normal:

        if mode == common.SCENE_MODES.normal:

            box = QImage(os.path.join(TEXTBOX_DIR, "box.png"))
            button = QImage(
                os.path.join(TEXTBOX_DIR, "button_%s.png" % box_color))

            nametag_x = 0
            nametag_y = 220
            nametag_color = QColor(50, 50, 50, 255)
            nametag_vert = True

            if not box.format() is QImage.Format_ARGB32_Premultiplied:
                box = box.convertToFormat(QImage.Format_ARGB32_Premultiplied)

            box_painter = QPainter(box)
            box_painter.setRenderHint(QPainter.Antialiasing, True)

            if speaker_id == 0:  # Main character gets a special text box.
                namebox = QImage(
                    os.path.join(TEXTBOX_DIR, "name_%s_mc.png" % box_color))
            else:
                namebox = QImage(
                    os.path.join(TEXTBOX_DIR, "name_%s.png" % box_color))

            box_painter.drawImage(box.rect(), namebox, namebox.rect())

            box_painter.end()

        elif mode == common.SCENE_MODES.trial:

            box_base = QImage(os.path.join(TRIAL_DIR, "trial_box.png"))
            banner = QImage(os.path.join(TRIAL_DIR, "trial_banner.png"))

            if speaker_id == 0:  # Main character gets a special text box.
                namebox = QImage(os.path.join(TRIAL_DIR, "trial_name_mc.png"))
            else:
                namebox = QImage(os.path.join(TRIAL_DIR, "trial_name.png"))

            if not headshot == None:
                case_num = QImage(
                    os.path.join(TRIAL_DIR, "case_%02d.png" % chapter))
                headshot = QImage(
                    os.path.join(TRIAL_DIR, "headshot", "%02d.png" % headshot))
                underlay = QImage(os.path.join(TRIAL_DIR,
                                               "trial_headshot.png"))
            else:
                case_num = QImage()
                underlay = QImage()
                headshot = QImage()

            button = QImage(os.path.join(TRIAL_DIR, "button.png"))
            nametag_x = 12
            nametag_y = 168
            nametag_color = QColor(255, 255, 255, 255)
            nametag_vert = False

            box = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
            box.fill(QColor(0, 0, 0, 0).rgba())

            box_painter = QPainter(box)
            box_painter.setRenderHint(QPainter.Antialiasing, True)

            box_painter.drawImage(box.rect(), banner, banner.rect())
            box_painter.drawImage(box.rect(), namebox, namebox.rect())
            box_painter.drawImage(box.rect(), box_base, box_base.rect())
            box_painter.drawImage(box.rect(), underlay, underlay.rect())
            box_painter.drawImage(box.rect(), headshot, headshot.rect())
            box_painter.drawImage(box.rect(), case_num, case_num.rect())

            box_painter.end()

        else:
            box = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
            box.fill(QColor(0, 0, 0, 0).rgba())

    painter.drawImage(out.rect(), box, box.rect())
    painter.drawImage(out.rect(), button, button.rect())

    if not speaker_id == None:
        nametag = get_nametag(speaker_id, nametag_x, nametag_y, nametag_color,
                              nametag_vert)
        painter.drawImage(out.rect(), nametag, nametag.rect())

    painter.end()

    return out
def draw_scene(scene_info, text=None):
    bg = None
    max_length = 0
    kill_blanks = False

    if scene_info.mode in [
            common.SCENE_MODES.normal, common.SCENE_MODES.normal_flat
    ]:
        bg = get_normal(scene_info)

        if scene_info.box_type == common.BOX_TYPES.flat:
            scene_info.mode = common.SCENE_MODES.normal_flat
        else:
            scene_info.mode = common.SCENE_MODES.normal

    elif scene_info.mode == common.SCENE_MODES.trial:
        bg = get_trial(scene_info)

    elif scene_info.mode == common.SCENE_MODES.novel:
        scene_info.box_type = common.BOX_TYPES.novel
        bg = get_normal(scene_info)

    elif scene_info.mode == common.SCENE_MODES.rules:
        bg = QImage(os.path.join(MENU_DIR, "rules.png"))

    elif scene_info.mode == common.SCENE_MODES.ammo:
        bg = QImage(os.path.join(MENU_DIR, "ammo-desc.png"))
        overlay = get_ammo(scene_info.file_id, 254, 117)

        if not bg.format() is QImage.Format_ARGB32_Premultiplied:
            bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)

        painter = QPainter(bg)
        painter.setCompositionMode(QPainter.CompositionMode_DestinationOver)
        painter.drawImage(bg.rect(), overlay, overlay.rect())
        painter.end()

        name = get_ammo_name(scene_info.file_id)
        if name:
            bg = print_text(bg, name, common.SCENE_MODES.ammoname,
                            TEXT_FORMATS[common.SCENE_MODES.ammoname], False)

    elif scene_info.mode == common.SCENE_MODES.ammoname:
        bg = QImage(os.path.join(MENU_DIR, "ammo-list.png"))
        overlay = get_ammo(scene_info.file_id, 254, 61)

        if not bg.format() is QImage.Format_ARGB32_Premultiplied:
            bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)

        painter = QPainter(bg)
        painter.setCompositionMode(QPainter.CompositionMode_DestinationOver)
        painter.drawImage(bg.rect(), overlay, overlay.rect())
        painter.end()

    elif scene_info.mode == common.SCENE_MODES.present:
        bg = QImage(os.path.join(MENU_DIR, "present-desc.png"))
        overlay = get_present(scene_info.file_id, 248, 96)

        if not bg.format() is QImage.Format_ARGB32_Premultiplied:
            bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)

        painter = QPainter(bg)
        painter.drawImage(bg.rect(), overlay, overlay.rect())
        painter.end()

        name = get_present_name(scene_info.file_id)
        if name:
            bg = print_text(bg, name, common.SCENE_MODES.presentname,
                            TEXT_FORMATS[common.SCENE_MODES.presentname],
                            False)

    elif scene_info.mode == common.SCENE_MODES.presentname:
        bg = QImage(os.path.join(MENU_DIR, "present-list.png"))
        overlay = get_present(scene_info.file_id, 248, 46)

        if not bg.format() is QImage.Format_ARGB32_Premultiplied:
            bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)

        painter = QPainter(bg)
        painter.drawImage(bg.rect(), overlay, overlay.rect())
        painter.end()

    elif scene_info.mode == common.SCENE_MODES.menu:
        bg = QImage(os.path.join(MENU_DIR, "menu.png"))

    elif scene_info.mode == common.SCENE_MODES.report or scene_info.mode == common.SCENE_MODES.report2:
        bg = QImage(os.path.join(MENU_DIR, "report.png"))

    elif scene_info.mode == common.SCENE_MODES.skill or scene_info.mode == common.SCENE_MODES.skill2:
        bg = QImage(os.path.join(MENU_DIR, "skills.png"))

    elif scene_info.mode == common.SCENE_MODES.map:
        bg = QImage(os.path.join(MENU_DIR, "map.png"))

    elif scene_info.mode == common.SCENE_MODES.music:
        bg = QImage(os.path.join(MENU_DIR, "soundtest.png"))

    elif scene_info.mode in [
            common.SCENE_MODES.eventname, common.SCENE_MODES.moviename,
            common.SCENE_MODES.artworkname
    ]:
        bg = QImage(os.path.join(MENU_DIR, "gallery.png"))

        if scene_info.mode == common.SCENE_MODES.eventname:
            overlay = get_event_icon(scene_info.file_id)
        elif scene_info.mode == common.SCENE_MODES.moviename:
            overlay = get_movie_icon(scene_info.file_id)
        elif scene_info.mode == common.SCENE_MODES.artworkname:
            overlay = get_artwork_icon(scene_info.file_id)

        if not bg.format() is QImage.Format_ARGB32_Premultiplied:
            bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)

        painter = QPainter(bg)
        painter.drawImage(bg.rect(), overlay, overlay.rect())
        painter.end()

    elif scene_info.mode == common.SCENE_MODES.theatre:
        bg = get_normal(scene_info)

    elif scene_info.mode == common.SCENE_MODES.debate or scene_info.mode == common.SCENE_MODES.hanron:
        bg = get_trial(scene_info, show_box=False)

    else:
        bg = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
        bg.fill(QColor(0, 0, 0, 255).rgba())

    if not bg.format() is QImage.Format_ARGB32_Premultiplied:
        bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)

    if scene_info.cutin != -1:
        cutin = get_cutin(scene_info.cutin)

        painter = QPainter(bg)
        painter.drawImage(bg.rect(), cutin, cutin.rect())
        painter.end()

    if scene_info.ammo != -1:
        ammo = get_ammo_ingame(scene_info.ammo)

        painter = QPainter(bg)
        painter.drawImage(bg.rect(), ammo, ammo.rect())
        painter.end()

    if scene_info.present != -1:
        present = get_present_ingame(scene_info.present)

        painter = QPainter(bg)
        painter.drawImage(bg.rect(), present, present.rect())
        painter.end()

    if scene_info.special == common.SCENE_SPECIAL.option:
        overlay = QImage(os.path.join(TEXTBOX_DIR, "option_bar.png"))
        painter = QPainter(bg)
        painter.drawImage(bg.rect(), overlay, overlay.rect())
        painter.end()

        if not text == None and not text == "":
            bg = print_text(bg, text, common.SCENE_SPECIAL.option,
                            TEXT_FORMATS[common.SCENE_SPECIAL.option], False)

    if not text == None and not text == "":
        bg = print_text(bg, text, scene_info.mode,
                        TEXT_FORMATS[scene_info.mode])

    return bg
def get_box(scene_info):
  
  mode       = scene_info.mode
  box_color  = scene_info.box_color
  box_type   = scene_info.box_type
  speaking   = scene_info.speaking
  speaker_id = scene_info.speaker
  headshot   = scene_info.headshot
  chapter    = scene_info.chapter
  
  if box_color != common.BOX_COLORS.orange and box_color != common.BOX_COLORS.green and box_color != common.BOX_COLORS.blue:
    box_color = common.BOX_COLORS.orange
  
  if not speaker_id in common.CHAR_IDS:
    speaker_id = None
  
  out = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
  out.fill(QColor(0, 0, 0, 0).rgba())
  
  painter = QPainter(out)
  painter.setRenderHint(QPainter.Antialiasing, True)
  
  # Some commonality between the boxes.
  box     = QImage()
  button  = QImage()
  
  if not speaker_id == None:
    nametag = QImage(os.path.join(NAMETAG_DIR, "%02d" % speaker_id))
  else:
    nametag = QImage()
  
  nametag_offset = ()
  
  if box_type == common.BOX_TYPES.flat:
    box    = QImage(os.path.join(TEXTBOX_DIR, "box_gray.png"))
    button = QImage(os.path.join(TEXTBOX_DIR, "button_gray.png"))
    nametag_color = QColor(255, 255, 255, 255)
    nametag_offset = (9, 187)
  
  elif box_type == common.BOX_TYPES.normal:
    
    if mode == common.SCENE_MODES.normal:
      
      box    = QImage(os.path.join(TEXTBOX_DIR, "box.png"))
      button = QImage(os.path.join(TEXTBOX_DIR, "button_%s.png" % box_color))
      nametag_color = QColor(60, 60, 60, 255)
      nametag_offset = (10, 180)
  
      if not box.format() is QImage.Format_ARGB32_Premultiplied:
        box = box.convertToFormat(QImage.Format_ARGB32_Premultiplied)
      
      box_painter = QPainter(box)
      box_painter.setRenderHint(QPainter.Antialiasing, True)
      
      if speaking and not speaker_id == None:
        label_file = os.path.join(TEXTBOX_DIR, "speaking_label.png")
        speaking_file = os.path.join(TEXTBOX_DIR, "speaking_%s.png" % box_color)
        
        label = QImage(label_file)
        speaking_img = QImage(speaking_file)
        
        box_painter.drawImage(box.rect(), speaking_img, speaking_img.rect())
        box_painter.drawImage(box.rect(), label, label.rect())
      
      if speaker_id == 0: # Naegi gets a special text box.
        namebox = QImage(os.path.join(TEXTBOX_DIR, "name_naegi_%s.png" % box_color))
      elif not speaker_id == None:
        namebox = QImage(os.path.join(TEXTBOX_DIR, "name_%s.png" % box_color))
      else:
        namebox = QImage()
        
      box_painter.drawImage(box.rect(), namebox, namebox.rect())
      
      box_painter.end()
    
    elif mode == common.SCENE_MODES.trial:
      
      if not headshot == None:
        box_base = QImage(os.path.join(TRIAL_DIR, "trial_speaking.png"))
        case_num = QImage(os.path.join(TRIAL_DIR, "case", "case%1d.png" % chapter))
        underlay = QImage(os.path.join(TRIAL_DIR, "pink.png"))
      else:
        box_base = QImage(os.path.join(TRIAL_DIR, "trial_narration.png"))
        case_num = QImage()
        underlay = QImage()
      
      if not headshot == None:
        headshot = QImage(os.path.join(TRIAL_DIR, "headshot", "%02d.png" % headshot))
      else:
        headshot = QImage()
      
      button = QImage(os.path.join(TRIAL_DIR, "button.png"))
      nametag_color = QColor(0, 0, 0, 255)
      nametag_offset = (20, 183)
      
      box = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
      box.fill(QColor(0, 0, 0, 0).rgba())
      
      box_painter = QPainter(box)
      box_painter.setRenderHint(QPainter.Antialiasing, True)
      
      box_painter.drawImage(box.rect(), underlay, underlay.rect())
      box_painter.drawImage(box.rect(), headshot, headshot.rect())
      box_painter.drawImage(box.rect(), box_base, box_base.rect())
      box_painter.drawImage(box.rect(), case_num, case_num.rect())
      
      box_painter.end()
    
    else:
      box = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
      box.fill(QColor(0, 0, 0, 0).rgba())
  
  painter.drawImage(out.rect(), box,     box.rect())
  painter.drawImage(out.rect(), button,  button.rect())
  
  if not speaker_id == None:
    nametag = replace_all_colors(nametag, nametag_color)
    painter.drawImage(QRect(nametag_offset[0], nametag_offset[1], nametag.width(), nametag.height()), nametag, nametag.rect())
  
  painter.end()
  
  return out
def draw_scene(scene_info, text = None):
  bg = None
  max_length = 0
  kill_blanks = False
  
  if scene_info.mode == common.SCENE_MODES.normal:
    bg = get_normal(scene_info)
    
  elif scene_info.mode == common.SCENE_MODES.trial:
    bg = get_trial(scene_info)
  
  elif scene_info.mode == common.SCENE_MODES.rules:
    bg = QImage(os.path.join(MENU_DIR, "rules.png"))
  
  elif scene_info.mode in [common.SCENE_MODES.ammo, common.SCENE_MODES.ammoname, common.SCENE_MODES.present, common.SCENE_MODES.presentname]:
    bg = QImage(os.path.join(MENU_DIR, "ammo.png"))
    
    if scene_info.mode in [common.SCENE_MODES.ammo, common.SCENE_MODES.ammoname]:
      overlay = get_ammo_menu(scene_info.file_id)
    else:
      overlay = get_present_icon(scene_info.file_id)
  
    if not bg.format() is QImage.Format_ARGB32_Premultiplied:
      bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), overlay, overlay.rect())
    painter.end()
  
  elif scene_info.mode == common.SCENE_MODES.menu:
    bg = QImage(os.path.join(MENU_DIR, "menu.png"))
  
  elif scene_info.mode == common.SCENE_MODES.report or scene_info.mode == common.SCENE_MODES.report2:
    bg = QImage(os.path.join(MENU_DIR, "report.png"))
  
  elif scene_info.mode == common.SCENE_MODES.skill or scene_info.mode == common.SCENE_MODES.skill2:
    bg = QImage(os.path.join(MENU_DIR, "skills.png"))
  
  elif scene_info.mode == common.SCENE_MODES.map:
    bg = QImage(os.path.join(MENU_DIR, "map.png"))
  
  elif scene_info.mode == common.SCENE_MODES.music:
    bg = QImage(os.path.join(MENU_DIR, "soundtest.png"))
  
  elif scene_info.mode == common.SCENE_MODES.eventname or scene_info.mode == common.SCENE_MODES.moviename:
    bg = QImage(os.path.join(MENU_DIR, "gallery.png"))
    
    if scene_info.mode == common.SCENE_MODES.eventname:
      overlay = get_event_icon(scene_info.file_id)
    else:
      overlay = get_movie_icon(scene_info.file_id)
  
    if not bg.format() is QImage.Format_ARGB32_Premultiplied:
      bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), overlay, overlay.rect())
    painter.end()
  
  elif scene_info.mode == common.SCENE_MODES.theatre:
    bg = get_normal(scene_info)
  
  elif scene_info.mode == common.SCENE_MODES.debate:
    bg = get_trial(scene_info, show_box = False)
    
  else:
    bg = QImage(IMG_W, IMG_H, QImage.Format_ARGB32_Premultiplied)
    bg.fill(QColor(0, 0, 0, 255).rgba())
  
  if not bg.format() is QImage.Format_ARGB32_Premultiplied:
    bg = bg.convertToFormat(QImage.Format_ARGB32_Premultiplied)
  
  if scene_info.cutin != -1:
    cutin = get_cutin(scene_info.cutin)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), cutin, cutin.rect())
    painter.end()
  
  if scene_info.ammo != -1:
    ammo = get_ammo_ingame(scene_info.ammo)
    
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), ammo, ammo.rect())
    painter.end()
  
  if scene_info.special == common.SCENE_SPECIAL.option:
    overlay = QImage(os.path.join(TEXTBOX_DIR, "option_bar.png"))
    painter = QPainter(bg)
    painter.drawImage(bg.rect(), overlay, overlay.rect())
    painter.end()
    
    if not text == None and not text == "":
      bg = print_text(bg, text, common.SCENE_SPECIAL.option, False)
      
  if not text == None and not text == "":
    bg = print_text(bg, text, scene_info.mode)
  
  return bg