Esempio n. 1
0
def getDngProfileDict(filename):
    """
    Read profile related tags from a dng or dcp file.
    Return a dictionary of (str) decoded {tagname : tagvalue} pairs.
    @param filename:
    @type filename: str
    @return: dictionary
    @rtype: dict
    """
    with exiftool.ExifTool() as e:
        profileDict = e.readBinaryDataAsDict(filename,
                                             taglist=['LinearizationTable',
                                                      'ProfileLookTableData',
                                                      'ProfileLookTableDims',
                                                      'ProfileLookTableEncoding',
                                                      'ProfileToneCurve',
                                                      'CalibrationIlluminant1',
                                                      'CalibrationIlluminant2',
                                                      'ColorMatrix1',
                                                      'ColorMatrix2',
                                                      'CameraCalibration1',
                                                      'CameraCalibration2',
                                                      'ForwardMatrix1',
                                                      'ForwardMatrix2',
                                                      'AnalogBalance'
                                                      ])
    return profileDict
Esempio n. 2
0
 def setRating(self, action):
     # rating : the tag is written into the .mie file; the file is
     # created if needed.
     listWdg = self.listWdg
     sel = listWdg.selectedItems()
     if action.text() in ['0', '1', '2', '3', '4', '5']:
         with exiftool.ExifTool() as e:
             value = int(action.text())
             for item in sel:
                 filename = item.data(Qt.UserRole)[0]
                 e.writeXMPTag(filename, 'XMP:rating', value)
                 item.setText(basename(filename) + '\n' + ''.join(['*'] * value))
Esempio n. 3
0
 def contextMenuHandler(action):
     global isSuspended
     if action.text() == 'Pause':
         isSuspended = True
         # quit full screen mode
         newWin.showMaximized()
     elif action.text() == 'Full Screen':
         if action.isChecked():
             newWin.showFullScreen()
         else:
             newWin.showMaximized()
     elif action.text() == 'Resume':
         newWin.close()
         isSuspended = False
         playDiaporama(diaporamaGenerator, parent=window)
     # rating : the tag is written into the .mie file; the file is
     # created if needed.
     elif action.text() in ['0', '1', '2', '3', '4', '5']:
         with exiftool.ExifTool() as e:
             e.writeXMPTag(name, 'XMP:rating', int(action.text()))
Esempio n. 4
0
def playDiaporama(diaporamaGenerator, parent=None):
    """
    Open a new window and play a slide show.
    @param diaporamaGenerator: generator for file names
    @type  diaporamaGenerator: iterator object
    @param parent:
    @type parent:
    """
    global isSuspended
    isSuspended = False

    # init diaporama window
    newWin = QMainWindow(parent)
    newWin.setAttribute(Qt.WA_DeleteOnClose)
    newWin.setContextMenuPolicy(Qt.CustomContextMenu)
    newWin.setWindowTitle(parent.tr('Slide show'))
    label = imageLabel(mainForm=parent)
    label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
    label.img = None
    newWin.setCentralWidget(label)
    newWin.showFullScreen()
    # Pause key shortcut
    actionEsc = QAction('Pause', None)
    actionEsc.setShortcut(QKeySequence(Qt.Key_Escape))
    newWin.addAction(actionEsc)

    # context menu event handler
    def contextMenuHandler(action):
        global isSuspended
        if action.text() == 'Pause':
            isSuspended = True
            # quit full screen mode
            newWin.showMaximized()
        elif action.text() == 'Full Screen':
            if action.isChecked():
                newWin.showFullScreen()
            else:
                newWin.showMaximized()
        elif action.text() == 'Resume':
            newWin.close()
            isSuspended = False
            playDiaporama(diaporamaGenerator, parent=window)
        # rating : the tag is written into the .mie file; the file is
        # created if needed.
        elif action.text() in ['0', '1', '2', '3', '4', '5']:
            with exiftool.ExifTool() as e:
                e.writeXMPTag(name, 'XMP:rating', int(action.text()))

    # connect shortkey action
    actionEsc.triggered.connect(
        lambda checked=False, name=actionEsc: contextMenuHandler(
            name))  # named arg checked is sent

    # context menu
    def contextMenu(position):
        menu = QMenu()
        actionEsc.setEnabled(not isSuspended)
        action2 = QAction('Full Screen', None)
        action2.setCheckable(True)
        action2.setChecked(newWin.windowState() & Qt.WindowFullScreen)
        action3 = QAction('Resume', None)
        action3.setEnabled(isSuspended)
        for action in [actionEsc, action2, action3]:
            menu.addAction(action)
            action.triggered.connect(
                lambda checked=False, name=action: contextMenuHandler(
                    name))  # named arg checked is sent
        subMenuRating = menu.addMenu('Rating')
        for i in range(6):
            action = QAction(str(i), None)
            subMenuRating.addAction(action)
            action.triggered.connect(
                lambda checked=False, name=action: contextMenuHandler(
                    name))  # named arg checked is sent
        menu.exec_(position)

    # connect contextMenuRequested
    newWin.customContextMenuRequested.connect(contextMenu)
    newWin.setToolTip("Esc to exit full screen mode")
    newWin.setWhatsThis(""" <b>Slide Show</b><br>
        The slide show cycles through the starting directory and its subfolders to display images.
        Photos rated 0 or 1 star are not shown (by default, all photos are rated 5 stars).<br>
        Hit the Esc key to <b>exit full screen mode and pause.</b><br> Use the Context Menu for <b>rating and resuming.</b>
        The rating is saved in the .mie sidecar and the image file is not modified.
        """)  # end of setWhatsThis
    # play diaporama
    window.modeDiaporama = True
    while True:
        if isSuspended:
            newWin.setWindowTitle(newWin.windowTitle() + ' Paused')
            break
        try:
            if not newWin.isVisible():
                break
            name = next(diaporamaGenerator)
            # search rating in metadata
            rating = 5  # default
            with exiftool.ExifTool() as e:
                try:
                    rt = e.readXMPTag(
                        name,
                        'XMP:rating')  # raise ValueError if sidecar not found
                    r = search("\d", rt)
                    if r is not None:
                        rating = int(r.group(0))
                except ValueError:
                    rating = 5
            # don't display image with low rating
            if rating < 2:
                app.processEvents()
            imImg = imImage.loadImageFromFile(name,
                                              createsidecar=False,
                                              cmsConfigure=True,
                                              window=window)
            # zoom might be modified by the mouse wheel : remember
            if label.img is not None:
                imImg.Zoom_coeff = label.img.Zoom_coeff
            coeff = imImg.resize_coeff(label)
            imImg.yOffset -= (imImg.height() * coeff - label.height()) / 2.0
            imImg.xOffset -= (imImg.width() * coeff - label.width()) / 2.0
            app.processEvents()
            if isSuspended:
                newWin.setWindowTitle(newWin.windowTitle() + ' Paused')
                break
            newWin.setWindowTitle(
                parent.tr('Slide show') + ' ' + name + ' ' +
                ' '.join(['*'] * imImg.meta.rating))
            gc.collect()
            label.img = imImg
            label.repaint()
            app.processEvents()
            gc.collect()
            sleep(2)
            app.processEvents()
        except StopIteration:
            newWin.close()
            window.diaporamaGenerator = None
            break
        except ValueError:
            continue
        except RuntimeError:
            window.diaporamaGenerator = None
            break
        except:
            window.diaporamaGenerator = None
            window.modeDiaporama = False
            raise
        app.processEvents()
    window.modeDiaporama = False
Esempio n. 5
0
 def run(self):
     # next() raises a StopIteration exception when the generator ends.
     # If this exception is unhandled by run(), it causes thread termination.
     # If wdg internal C++ object was destroyed by main thread (form closing)
     # a RuntimeError exception is raised and causes thread termination too.
     # Thus, no further synchronization is needed.
     from bLUeTop import exiftool
     with exiftool.ExifTool() as e:
         while True:
             try:
                 filename = next(self.fileListGen)
                 # get orientation
                 try:
                     # read metadata from sidecar (.mie) if it exists, otherwise from image file.
                     profile, metadata = e.get_metadata(
                         filename,
                         tags=("colorspace", "profileDescription",
                               "orientation", "model", "rating",
                               "FileCreateDate"),
                         createsidecar=False)
                 except ValueError:
                     metadata = {}
                 # get image info
                 tmp = [
                     value for key, value in metadata.items()
                     if 'orientation' in key.lower()
                 ]
                 orientation = tmp[
                     0] if tmp else 1  # metadata.get("EXIF:Orientation", 1)
                 # EXIF:DateTimeOriginal seems to be missing in many files
                 tmp = [
                     value for key, value in metadata.items()
                     if 'date' in key.lower()
                 ]
                 date = tmp[
                     0] if tmp else ''  # metadata.get("EXIF:ModifyDate", '')
                 tmp = [
                     value for key, value in metadata.items()
                     if 'rating' in key.lower()
                 ]
                 rating = tmp[
                     0] if tmp else 0  # metadata.get("XMP:Rating", 5)
                 rating = ''.join(['*'] * int(rating))
                 transformation = exiftool.decodeExifOrientation(
                     orientation)
                 # get thumbnail
                 img = e.get_thumbNail(filename, thumbname='thumbnailimage')
                 # no thumbnail found : try preview
                 if img.isNull():
                     img = e.get_thumbNail(
                         filename, thumbname='PreviewImage'
                     )  # the order is important : for jpeg PreviewImage is full sized !
                 # all failed : open image
                 if img.isNull():
                     img = QImage(filename)
                 # remove possible black borders, except for .NEF
                 if filename[-3:] not in ['nef', 'NEF']:
                     bBorder = 7
                     img = img.copy(
                         QRect(0, bBorder, img.width(),
                               img.height() - 2 * bBorder))
                 pxm = QPixmap.fromImage(img)
                 if not transformation.isIdentity():
                     pxm = pxm.transformed(transformation)
                 # set item caption and tooltip
                 item = QListWidgetItem(
                     QIcon(pxm), basename(filename))  # + '\n' + rating)
                 item.setToolTip(
                     basename(filename) + ' ' + date + ' ' + rating)
                 # set item mimeData to get filename=item.data(Qt.UserRole)[0] transformation=item.data(Qt.UserRole)[1]
                 item.setData(Qt.UserRole, (filename, transformation))
                 self.wdg.addItem(item)
             # for clean exiting we catch all exceptions and force break
             except OSError:
                 continue
             except:
                 break