예제 #1
0
class QVideoPreview(QWidget):
    frameChanged = pyqtSignal(int, QTime)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.imageView = QImageView(self)
        self.frameSelection = QFrameSelect(self)
        self.frameSelection.frameSelectionChanged.connect(self.updateImage)
        layout = QVBoxLayout()
        self.setLayout(layout)
        layout.addWidget(self.imageView)
        layout.addWidget(self.frameSelection)

    def setSource(self, source):
        self._source = source
        self.frameSelection.setPtsTimeArray(source.pts_time)
        self.setFrameIndex(0)
        s, ms = divmod(int(1000 * source.pts_time[0]), 1000)
        m, s = divmod(s, 60)
        h, m = divmod(m, 60)
        self.updateImage(0, QTime(h, m, s, ms))

    def setFrameIndex(self, value):
        self.frameSelection.slider.setValue(value)

    def updateImage(self, n, t):
        try:
            frame = next(self._source.iterFrames(n, whence="framenumber"))

        except Exception:
            return

        self.imageView.setFrame(frame.to_image().convert("RGBA").toqpixmap())
        self.frameChanged.emit(n, t)
예제 #2
0
    def _createControls(self):
        self.setWindowTitle("Configure Crop")

        layout = QVBoxLayout(self)
        self.setLayout(layout)

        self.sourceWidget = QWidget(self)
        self.sourceSelection = self.createSourceControl(self.sourceWidget)
        self.sourceSelection.currentDataChanged.connect(self.setFilterSource)

        srclayout = QHBoxLayout()
        srclayout.addWidget(QLabel("Source: ", self.sourceWidget))
        srclayout.addWidget(self.sourceSelection)

        self.sourceWidget.setLayout(srclayout)
        layout.addWidget(self.sourceWidget)

        self.cropWidget = QCrop(self)
        self.cropWidget.cropRight.valueChanged.connect(self.setCropRight)
        self.cropWidget.cropLeft.valueChanged.connect(self.setCropLeft)
        self.cropWidget.cropTop.valueChanged.connect(self.setCropTop)
        self.cropWidget.cropBottom.valueChanged.connect(self.setCropBottom)

        self.slider = QFrameSelect(self)
        self.slider.frameSelectionChanged.connect(self.loadFrame)

        layout.addWidget(self.cropWidget)
        layout.addWidget(self.slider)

        self._prepareDlgButtons()
예제 #3
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.imageView = QImageView(self)
     self.frameSelection = QFrameSelect(self)
     self.frameSelection.frameSelectionChanged.connect(self.updateImage)
     layout = QVBoxLayout()
     self.setLayout(layout)
     layout.addWidget(self.imageView)
     layout.addWidget(self.frameSelection)
예제 #4
0
    def _createControls(self):
        self.setWindowTitle("Configure Crossfade")

        layout = QVBoxLayout(self)
        self.setLayout(layout)

        self.sourceWidget = QWidget(self)

        self.source1Selection = self.createSourceControl(self.sourceWidget)
        self.source1Selection.setSelectFunc(self.isValidSource1)
        self.source1Selection.currentDataChanged.connect(self.setFilterSource1)
        self.source1Fade = QCheckBox("Fade Out", self)
        self.source1Fade.stateChanged.connect(self.setSource1Fade)

        self.source2Selection = self.createSourceControl(self.sourceWidget)
        self.source2Selection.setSelectFunc(self.isValidSource2)
        self.source2Selection.currentDataChanged.connect(self.setFilterSource2)
        self.source2Fade = QCheckBox("Fade In", self)
        self.source2Fade.stateChanged.connect(self.setSource2Fade)

        srclayout = QVBoxLayout()
        src1layout = QHBoxLayout()
        src2layout = QHBoxLayout()
        srclayout.addLayout(src1layout)
        srclayout.addLayout(src2layout)

        src1layout.addWidget(QLabel("Source 1: ", self.sourceWidget))
        src1layout.addWidget(self.source1Selection)
        src1layout.addWidget(self.source1Fade)

        src2layout.addWidget(QLabel("Source 2: ", self.sourceWidget))
        src2layout.addWidget(self.source2Selection)
        src2layout.addWidget(self.source2Fade)

        self.sourceWidget.setLayout(srclayout)
        layout.addWidget(self.sourceWidget)

        self.imageView = QImageView(self)
        self.frameSelect = QFrameSelect(self)
        self.frameSelect.frameSelectionChanged.connect(
            self.handleFrameSelectionChange)
        layout.addWidget(self.imageView)
        layout.addWidget(self.frameSelect)

        self._prepareDlgButtons()
예제 #5
0
    def _createControls(self):
        self.setWindowTitle("Configure Hue/Saturation/Luminosity")

        layout = QVBoxLayout(self)
        self.setLayout(layout)

        self.sourceWidget = QWidget(self)
        self.sourceSelection = self.createSourceControl(self.sourceWidget)
        self.sourceSelection.currentDataChanged.connect(self.setFilterSource)

        srclayout = QHBoxLayout()
        srclayout.addWidget(QLabel("Source: ", self.sourceWidget))
        srclayout.addWidget(self.sourceSelection)

        self.sourceWidget.setLayout(srclayout)
        layout.addWidget(self.sourceWidget)

        self.imageView = QImageView(self)
        layout.addWidget(self.imageView)

        self.slider = QFrameSelect(self)
        self.slider.frameSelectionChanged.connect(self.loadFrame)
        layout.addWidget(self.slider)

        hueLabel = QLabel("Hue adjustment:", self)
        self.hueSpinBox = QSpinBox(self)
        self.hueSpinBox.setMinimum(-179)
        self.hueSpinBox.setMaximum(180)
        self.hueSpinBox.valueChanged.connect(
            self._handleHueSpinBoxValueChanged)

        satLabel = QLabel("Saturation factor:", self)
        self.satSpinBox = QDoubleSpinBox(self)
        self.satSpinBox.setDecimals(2)
        self.satSpinBox.setSingleStep(0.1)
        self.satSpinBox.setMinimum(0)
        self.satSpinBox.setMaximum(10)
        self.satSpinBox.valueChanged.connect(
            self._handleSatSpinBoxValueChanged)

        lumLabel = QLabel("Luminosity factor:", self)
        self.lumSpinBox = QDoubleSpinBox(self)
        self.lumSpinBox.setDecimals(2)
        self.lumSpinBox.setMinimum(0)
        self.lumSpinBox.setMaximum(10)
        self.lumSpinBox.valueChanged.connect(
            self._handleLumSpinBoxValueChanged)

        hlayout = QHBoxLayout()

        hlayout.addStretch()
        hlayout.addWidget(hueLabel)
        hlayout.addWidget(self.hueSpinBox)

        hlayout.addStretch()
        hlayout.addWidget(satLabel)
        hlayout.addWidget(self.satSpinBox)

        hlayout.addStretch()
        hlayout.addWidget(lumLabel)
        hlayout.addWidget(self.lumSpinBox)

        hlayout.addStretch()

        layout.addLayout(hlayout)

        self._prepareDlgButtons()
예제 #6
0
class QHSLAdjDlg(QFilterConfig):
    allowedtypes = ("video",)

    def _createControls(self):
        self.setWindowTitle("Configure Hue/Saturation/Luminosity")

        layout = QVBoxLayout(self)
        self.setLayout(layout)

        self.sourceWidget = QWidget(self)
        self.sourceSelection = self.createSourceControl(self.sourceWidget)
        self.sourceSelection.currentDataChanged.connect(self.setFilterSource)

        srclayout = QHBoxLayout()
        srclayout.addWidget(QLabel("Source: ", self.sourceWidget))
        srclayout.addWidget(self.sourceSelection)

        self.sourceWidget.setLayout(srclayout)
        layout.addWidget(self.sourceWidget)

        self.imageView = QImageView(self)
        layout.addWidget(self.imageView)

        self.slider = QFrameSelect(self)
        self.slider.frameSelectionChanged.connect(self.loadFrame)
        layout.addWidget(self.slider)

        hueLabel = QLabel("Hue adjustment:", self)
        self.hueSpinBox = QSpinBox(self)
        self.hueSpinBox.setMinimum(-179)
        self.hueSpinBox.setMaximum(180)
        self.hueSpinBox.valueChanged.connect(
            self._handleHueSpinBoxValueChanged)

        satLabel = QLabel("Saturation factor:", self)
        self.satSpinBox = QDoubleSpinBox(self)
        self.satSpinBox.setDecimals(2)
        self.satSpinBox.setSingleStep(0.1)
        self.satSpinBox.setMinimum(0)
        self.satSpinBox.setMaximum(10)
        self.satSpinBox.valueChanged.connect(
            self._handleSatSpinBoxValueChanged)

        lumLabel = QLabel("Luminosity factor:", self)
        self.lumSpinBox = QDoubleSpinBox(self)
        self.lumSpinBox.setDecimals(2)
        self.lumSpinBox.setMinimum(0)
        self.lumSpinBox.setMaximum(10)
        self.lumSpinBox.valueChanged.connect(
            self._handleLumSpinBoxValueChanged)

        hlayout = QHBoxLayout()

        hlayout.addStretch()
        hlayout.addWidget(hueLabel)
        hlayout.addWidget(self.hueSpinBox)

        hlayout.addStretch()
        hlayout.addWidget(satLabel)
        hlayout.addWidget(self.satSpinBox)

        hlayout.addStretch()
        hlayout.addWidget(lumLabel)
        hlayout.addWidget(self.lumSpinBox)

        hlayout.addStretch()

        layout.addLayout(hlayout)

        self._prepareDlgButtons()

    def createNewFilterInstance(self):
        return HSLAdjust()

    def _resetControls(self):
        self.hueSpinBox.blockSignals(True)
        self.hueSpinBox.setValue(self.filtercopy.dh)
        self.hueSpinBox.blockSignals(False)

        self.satSpinBox.blockSignals(True)
        self.satSpinBox.setValue(self.filtercopy.sfactor)
        self.satSpinBox.blockSignals(False)

        self.lumSpinBox.blockSignals(True)
        self.lumSpinBox.setValue(self.filtercopy.lgamma)
        self.lumSpinBox.blockSignals(False)

        if self.filtercopy.prev is not None:
            self.slider.setPtsTimeArray(self.filtercopy.prev.pts_time)
            self.loadFrame(self.slider.slider.value(), QTime())

    def _handleHueSpinBoxValueChanged(self, value):
        self.filtercopy.dh = value
        self.isModified()
        self.loadFrame(self.slider.slider.value(), None)

    def _handleSatSpinBoxValueChanged(self, value):
        self.filtercopy.sfactor = value
        self.isModified()
        self.loadFrame(self.slider.slider.value(), None)

    def _handleLumSpinBoxValueChanged(self, value):
        self.filtercopy.sfactor = value
        self.isModified()
        self.loadFrame(self.slider.slider.value(), None)

    @pyqtSlot(int, QTime)
    def loadFrame(self, n, t):
        if self.filtercopy.prev is not None:
            frame = next(self.filtercopy.iterFrames(n, whence="framenumber"))
            im = frame.to_image()
            pixmap = im.convert("RGBA").toqpixmap()
            self.imageView.setFrame(pixmap)

    def _prevChanged(self, source):
        self.slider.setPtsTimeArray(source.pts_time)
        self.loadFrame(self.slider.slider.value(),
                       self.slider.currentTime.time())
예제 #7
0
class QCrossFade(QFilterConfig):
    allowedtypes = ("video", "audio")

    def _createControls(self):
        self.setWindowTitle("Configure Crossfade")

        layout = QVBoxLayout(self)
        self.setLayout(layout)

        self.sourceWidget = QWidget(self)

        self.source1Selection = self.createSourceControl(self.sourceWidget)
        self.source1Selection.setSelectFunc(self.isValidSource1)
        self.source1Selection.currentDataChanged.connect(self.setFilterSource1)
        self.source1Fade = QCheckBox("Fade Out", self)
        self.source1Fade.stateChanged.connect(self.setSource1Fade)

        self.source2Selection = self.createSourceControl(self.sourceWidget)
        self.source2Selection.setSelectFunc(self.isValidSource2)
        self.source2Selection.currentDataChanged.connect(self.setFilterSource2)
        self.source2Fade = QCheckBox("Fade In", self)
        self.source2Fade.stateChanged.connect(self.setSource2Fade)

        srclayout = QVBoxLayout()
        src1layout = QHBoxLayout()
        src2layout = QHBoxLayout()
        srclayout.addLayout(src1layout)
        srclayout.addLayout(src2layout)

        src1layout.addWidget(QLabel("Source 1: ", self.sourceWidget))
        src1layout.addWidget(self.source1Selection)
        src1layout.addWidget(self.source1Fade)

        src2layout.addWidget(QLabel("Source 2: ", self.sourceWidget))
        src2layout.addWidget(self.source2Selection)
        src2layout.addWidget(self.source2Fade)

        self.sourceWidget.setLayout(srclayout)
        layout.addWidget(self.sourceWidget)

        self.imageView = QImageView(self)
        self.frameSelect = QFrameSelect(self)
        self.frameSelect.frameSelectionChanged.connect(
            self.handleFrameSelectionChange)
        layout.addWidget(self.imageView)
        layout.addWidget(self.frameSelect)

        self._prepareDlgButtons()

    def _resetSourceModels(self):
        self._resetSourceModel(self.source1Selection)
        self._resetSourceModel(self.source2Selection)

    @pyqtSlot(int, QTime)
    def handleFrameSelectionChange(self, n, t):
        self.setFrame(n)

    def setSource1Fade(self, value):
        if value:
            self.filtercopy.flags &= ~1

        else:
            self.filtercopy.flags |= 1

        if (self.filtercopy.prev is not None
                and self.filtercopy.prev.type == "video"):
            self.setFrame(self.frameSelect.slider.value())

        self.isModified()

    def setSource2Fade(self, value):
        if value:
            self.filtercopy.flags &= ~2

        else:
            self.filtercopy.flags |= 2

        if (self.filtercopy.prev is not None
                and self.filtercopy.prev.type == "video"):
            self.setFrame(self.frameSelect.slider.value())

        self.isModified()

    def setFrame(self, n):
        try:
            frame = next(self.filtercopy.iterFrames(n, whence="framenumber"))

        except StopIteration:
            self.imageView.setFrame(
                QPixmap(self.filtercopy.width, self.filtercopy.height))
            return

        im = frame.to_image()
        pixmap = im.convert("RGBA").toqpixmap()
        self.imageView.setFrame(pixmap)

    def createNewFilterInstance(self):
        return CrossFade()

    def _resetSourceControls(self):
        self._showSourceControls(self.inputFiles or self.availableFilters)
        self._setSourceSelection(self.source1Selection,
                                 self.filtercopy.source1)
        self._setSourceSelection(self.source2Selection,
                                 self.filtercopy.source2)

    def _resetControls(self):
        if self.filtercopy is not None:
            self.source1Fade.blockSignals(True)
            self.source1Fade.setCheckState(0 if (
                1 & self.filtercopy.flags) else 2)
            self.source1Fade.blockSignals(False)

            self.source2Fade.blockSignals(True)
            self.source2Fade.setCheckState(0 if (
                2 & self.filtercopy.flags) else 2)
            self.source2Fade.blockSignals(False)

            self.frameSelect.setVisible(self.filtercopy.type == "video")
            self.imageView.setVisible(self.filtercopy.type == "video")

            if self.filtercopy.type == "video":
                self.frameSelect.setPtsTimeArray(self.filtercopy.pts_time)
                self.setFrame(0)

            self.setEnabled(True)

        else:
            self.source1Fade.blockSignals(True)
            self.source1Fade.setCheckState(2)
            self.source1Fade.blockSignals(False)

            self.source2Fade.blockSignals(True)
            self.source2Fade.setCheckState(2)
            self.source2Fade.blockSignals(False)

            self.frameSelect.setVisible(False)
            self.imageView.setVisible(False)
            self.setEnabled(False)

    def setFilterSource1(self, source):
        self.imageView.setVisible(source is not None
                                  and source.type == "video")
        self.filtercopy.source1 = source
        self.isModified()

        if (source is not None and self.filtercopy.source2 is not None
                and source.type == "video"):
            self.frameSelect.setPtsTimeArray(source.pts_time)
            self.setFrame(self.frameSelect.slider.value())

    def setFilterSource2(self, source):
        self.imageView.setVisible(source is not None
                                  and source.type == "video")
        self.filtercopy.source2 = source
        self.isModified()

        if (source is not None and self.filtercopy.source1 is not None
                and source.type == "video"):
            self.frameSelect.setPtsTimeArray(source.pts_time)
            self.setFrame(self.frameSelect.slider.value())

    def isValidSource1(self, other):
        if other is self.filter:
            return False

        if (isinstance(other, BaseFilter)
                and self.filter in other.dependencies):
            return False

        if self.filtercopy.source2 is None:
            return other.type in ("video", "audio")

        if other.type is None:
            return True

        elif self.filtercopy.source2.type == "video":
            return (self.filtercopy.source2.framecount == other.framecount
                    and self.filtercopy.source2.width == other.width
                    and self.filtercopy.source2.height == other.height
                    and (abs(self.filtercopy.source2.pts_time - other.pts_time)
                         < 0.008).all())

        elif self.filtercopy.source2.type == "audio":
            return (self.filtercopy.source2.channels == other.channels
                    and abs(self.filtercopy.source2.duration - other.duration)
                    < 0.00001)

    def isValidSource2(self, other):
        if other is self.filter:
            return False

        if isinstance(other, BaseFilter) and self.filter in other.dependencies:
            return False

        if other.type is None:
            return True

        if self.filtercopy.source1 is None:
            return other.type in ("video", "audio")

        elif self.filtercopy.source1.type == "video":
            return (self.filtercopy.source1.framecount == other.framecount
                    and self.filtercopy.source1.width == other.width
                    and self.filtercopy.source1.height == other.height
                    and (abs(self.filtercopy.source1.pts_time - other.pts_time)
                         < 0.008).all())

        elif self.filtercopy.source1.type == "audio":
            return (self.filtercopy.source1.channels == other.channels
                    and abs(self.filtercopy.source1.duration - other.duration)
                    < 0.00001)
예제 #8
0
class CropDlg(QFilterConfig):
    allowedtypes = ("video",)

    def _createControls(self):
        self.setWindowTitle("Configure Crop")

        layout = QVBoxLayout(self)
        self.setLayout(layout)

        self.sourceWidget = QWidget(self)
        self.sourceSelection = self.createSourceControl(self.sourceWidget)
        self.sourceSelection.currentDataChanged.connect(self.setFilterSource)

        srclayout = QHBoxLayout()
        srclayout.addWidget(QLabel("Source: ", self.sourceWidget))
        srclayout.addWidget(self.sourceSelection)

        self.sourceWidget.setLayout(srclayout)
        layout.addWidget(self.sourceWidget)

        self.cropWidget = QCrop(self)
        self.cropWidget.cropRight.valueChanged.connect(self.setCropRight)
        self.cropWidget.cropLeft.valueChanged.connect(self.setCropLeft)
        self.cropWidget.cropTop.valueChanged.connect(self.setCropTop)
        self.cropWidget.cropBottom.valueChanged.connect(self.setCropBottom)

        self.slider = QFrameSelect(self)
        self.slider.frameSelectionChanged.connect(self.loadFrame)

        layout.addWidget(self.cropWidget)
        layout.addWidget(self.slider)

        self._prepareDlgButtons()

    @pyqtSlot(int, QTime)
    def loadFrame(self, n, t):
        if self.filtercopy.prev is not None:
            frame = next(
                self.filtercopy.prev.iterFrames(n, whence="framenumber"))

            im = frame.to_image()
            pixmap = im.convert("RGBA").toqpixmap()
            self.cropWidget.setFrame(pixmap)
            self.cropWidget.resize(pixmap.size())

    def createNewFilterInstance(self):
        return Crop()

    def _prevChanged(self, source):
        self._resetControlMaximums()
        self.slider.setPtsTimeArray(source.pts_time)
        self.loadFrame(self.slider.slider.value(),
                       self.slider.currentTime.time())

    def _resetControlMaximums(self):
        if self.filtercopy.prev is not None:
            self.cropWidget.cropTop.setMaximum(
                self.filtercopy.prev.height - self.filtercopy.cropbottom - 2)
            self.cropWidget.cropBottom.setMaximum(
                self.filtercopy.prev.height - self.filtercopy.croptop - 2)
            self.cropWidget.cropRight.setMaximum(
                self.filtercopy.prev.width - self.filtercopy.cropleft - 2)
            self.cropWidget.cropLeft.setMaximum(
                self.filtercopy.prev.width - self.filtercopy.cropright - 2)

    def _resetControls(self):
        self.cropWidget.cropTop.blockSignals(True)
        self.cropWidget.cropTop.setValue(self.filtercopy.croptop)
        self.cropWidget.cropTop.blockSignals(False)

        self.cropWidget.cropBottom.blockSignals(True)
        self.cropWidget.cropBottom.setValue(self.filtercopy.cropbottom)
        self.cropWidget.cropBottom.blockSignals(False)

        self.cropWidget.cropLeft.blockSignals(True)
        self.cropWidget.cropLeft.setValue(self.filtercopy.cropleft)
        self.cropWidget.cropLeft.blockSignals(False)

        self.cropWidget.cropRight.blockSignals(True)
        self.cropWidget.cropRight.setValue(self.filtercopy.cropright)
        self.cropWidget.cropRight.blockSignals(False)

        if self.filtercopy.prev is not None:
            self.cropWidget.setFrameWidth(self.filtercopy.prev.width)
            self.cropWidget.setFrameHeight(self.filtercopy.prev.height)
            self.slider.setPtsTimeArray(self.filtercopy.prev.pts_time)
            self.loadFrame(self.slider.slider.value(), QTime())

        else:
            self.cropWidget.setFrameWidth(1920)
            self.cropWidget.setFrameHeight(1080)
            self.slider.setPtsTimeArray(None)

    @pyqtSlot(int)
    def setCropTop(self, croptop):
        self.filtercopy.croptop = croptop
        self.isModified()

    @pyqtSlot(int)
    def setCropBottom(self, cropbottom):
        self.filtercopy.cropbottom = cropbottom
        self.isModified()

    @pyqtSlot(int)
    def setCropLeft(self, cropleft):
        self.filtercopy.cropleft = cropleft
        self.isModified()

    @pyqtSlot(int)
    def setCropRight(self, cropright):
        self.filtercopy.cropright = cropright
        self.isModified()