diff --git a/components/__base__.py b/components/__base__.py index bc6644b..88f22d4 100644 --- a/components/__base__.py +++ b/components/__base__.py @@ -1,4 +1,5 @@ from PyQt4 import QtGui, QtCore +from PIL import Image class Component(QtCore.QObject): @@ -45,6 +46,9 @@ class Component(QtCore.QObject): for var, value in kwargs.items(): exec('self.%s = value' % var) + def blankFrame(self, width, height): + return Image.new("RGBA", (width, height), (0, 0, 0, 0)) + def pickColor(self): dialog = QtGui.QColorDialog() dialog.setOption(QtGui.QColorDialog.ShowAlphaChannel, True) diff --git a/components/color.py b/components/color.py index 5912bfa..36f3906 100644 --- a/components/color.py +++ b/components/color.py @@ -71,7 +71,7 @@ class Component(__base__.Component): def drawFrame(self, width, height): r, g, b = self.color1 - return Image.new("RGBA", (width, height), (r, g, b, 255)) + return self.blankFrame(width, height) def loadPreset(self, pr, presetName=None): super().loadPreset(pr, presetName) diff --git a/components/image.py b/components/image.py index a2f0521..b6aa29b 100644 --- a/components/image.py +++ b/components/image.py @@ -38,6 +38,7 @@ class Component(__base__.Component): super().update() def previewRender(self, previewWorker): + self.imageFormats = previewWorker.core.imageFormats width = int(previewWorker.core.settings.value('outputWidth')) height = int(previewWorker.core.settings.value('outputHeight')) return self.drawFrame(width, height) @@ -52,7 +53,7 @@ class Component(__base__.Component): return self.drawFrame(width, height) def drawFrame(self, width, height): - frame = Image.new("RGBA", (width, height), (0, 0, 0, 0)) + frame = self.blankFrame(width, height) if self.imagePath and os.path.exists(self.imagePath): image = Image.open(self.imagePath) if self.stretched and image.size != (width, height): @@ -85,7 +86,8 @@ class Component(__base__.Component): def pickImage(self): imgDir = self.settings.value("backgroundDir", os.path.expanduser("~")) filename = QtGui.QFileDialog.getOpenFileName( - self.page, "Choose Image", imgDir, "Image Files (*.jpg *.png)") + self.page, "Choose Image", imgDir, + "Image Files (%s)" % " ".join(self.imageFormats)) if filename: self.settings.setValue("backgroundDir", os.path.dirname(filename)) self.page.lineEdit_image.setText(filename) diff --git a/components/image.ui b/components/image.ui index 685e997..6df03a5 100644 --- a/components/image.ui +++ b/components/image.ui @@ -230,7 +230,7 @@ 10 - 200 + 400 100 diff --git a/components/original.py b/components/original.py index 9df2815..5e2f9d4 100644 --- a/components/original.py +++ b/components/original.py @@ -145,7 +145,7 @@ class Component(__base__.Component): bF = width / 64 bH = bF / 2 bQ = bF / 4 - imTop = Image.new("RGBA", (width, height), (0, 0, 0, 0)) + imTop = self.blankFrame(width, height) draw = ImageDraw.Draw(imTop) r, g, b = color color2 = (r, g, b, 125) @@ -163,7 +163,7 @@ class Component(__base__.Component): imBottom = imTop.transpose(Image.FLIP_TOP_BOTTOM) - im = Image.new("RGBA", (width, height), (0, 0, 0, 0)) + im = self.blankFrame(width, height) if layout == 0: y = 0 - int(height/100*43) diff --git a/components/text.py b/components/text.py index 165a093..f8ef7b3 100644 --- a/components/text.py +++ b/components/text.py @@ -126,7 +126,7 @@ class Component(__base__.Component): def addText(self, width, height): x, y = self.getXY() - im = Image.new("RGBA", (width, height), (0, 0, 0, 0)) + im = self.blankFrame(width, height) image = ImageQt(im) painter = QPainter(image) diff --git a/components/video.py b/components/video.py index 5f55211..3d43a18 100644 --- a/components/video.py +++ b/components/video.py @@ -128,12 +128,13 @@ class Component(__base__.Component): super().update() def previewRender(self, previewWorker): + self.videoFormats = previewWorker.core.videoFormats width = int(previewWorker.core.settings.value('outputWidth')) height = int(previewWorker.core.settings.value('outputHeight')) self.updateChunksize(width, height) frame = self.getPreviewFrame(width, height) if not frame: - return Image.new("RGBA", (width, height), (0, 0, 0, 0)) + return self.blankFrame(width, height) else: return frame @@ -141,6 +142,7 @@ class Component(__base__.Component): super().preFrameRender(**kwargs) width = int(self.worker.core.settings.value('outputWidth')) height = int(self.worker.core.settings.value('outputHeight')) + self.blankFrame_ = self.blankFrame(width, height) self.updateChunksize(width, height) self.video = Video( ffmpeg=self.parent.core.FFMPEG_BIN, videoPath=self.videoPath, @@ -148,10 +150,13 @@ class Component(__base__.Component): frameRate=int(self.settings.value("outputFrameRate")), parent=self.parent, loopVideo=self.loopVideo, component=self, scale=self.scale - ) + ) if os.path.exists(self.videoPath) else None def frameRender(self, moduleNo, arrayNo, frameNo): - return self.video.frame(frameNo) + if self.video: + return self.video.frame(frameNo) + else: + return self.blankFrame_ def loadPreset(self, pr, presetName=None): super().loadPreset(pr, presetName) @@ -177,7 +182,7 @@ class Component(__base__.Component): imgDir = self.settings.value("backgroundDir", os.path.expanduser("~")) filename = QtGui.QFileDialog.getOpenFileName( self.page, "Choose Video", - imgDir, "Video Files (*.mp4 *.mov)" + imgDir, "Video Files (%s)" % " ".join(self.videoFormats) ) if filename: self.settings.setValue("backgroundDir", os.path.dirname(filename)) @@ -228,10 +233,14 @@ def scale(scale, width, height, returntype=None): def finalizeFrame(self, imageData, width, height): if self.distort: - image = Image.frombytes( - 'RGBA', - (width, height), - imageData) + try: + image = Image.frombytes( + 'RGBA', + (width, height), + imageData) + except ValueError: + print('#### ignored invalid data caused by distortion ####') + image = self.blankFrame(width, height) else: image = Image.frombytes( 'RGBA', @@ -240,7 +249,7 @@ def finalizeFrame(self, imageData, width, height): if self.scale != 100 \ or self.xPosition != 0 or self.yPosition != 0: - frame = Image.new("RGBA", (width, height), (0, 0, 0, 0)) + frame = self.blankFrame(width, height) frame.paste(image, box=(self.xPosition, self.yPosition)) else: frame = image diff --git a/components/video.ui b/components/video.ui index fa088fa..f05e8a5 100644 --- a/components/video.ui +++ b/components/video.ui @@ -234,7 +234,7 @@ 10 - 200 + 400 100 diff --git a/core.py b/core.py index 8eb7d16..3fca7bf 100644 --- a/core.py +++ b/core.py @@ -24,6 +24,32 @@ class Core(): self.presetDir = os.path.join(self.dataDir, 'presets') self.wd = os.path.dirname(os.path.realpath(__file__)) self.loadEncoderOptions() + self.videoFormats = Core.appendUppercase([ + '*.mp4', + '*.mov', + '*.mkv', + '*.avi', + '*.webm', + '*.flv', + ]) + self.audioFormats = Core.appendUppercase([ + '*.mp3', + '*.wav', + '*.ogg', + '*.fla', + '*.aac', + ]) + self.imageFormats = Core.appendUppercase([ + '*.png', + '*.jpg', + '*.tif', + '*.tiff', + '*.gif', + '*.bmp', + '*.ico', + '*.xbm', + '*.xpm', + ]) self.findComponents() self.selectedComponents = [] @@ -116,44 +142,48 @@ class Core(): which implements an insertComponent method''' errcode, data = self.parseAvFile(filepath) if errcode == 0: - for i, tup in enumerate(data['Components']): - name, vers, preset = tup - clearThis = False + try: + for i, tup in enumerate(data['Components']): + name, vers, preset = tup + clearThis = False - # add loaded named presets to savedPresets dict - if 'preset' in preset and preset['preset'] != None: - nam = preset['preset'] - filepath2 = os.path.join( - self.presetDir, name, str(vers), nam) - origSaveValueStore = self.getPreset(filepath2) - if origSaveValueStore: - self.savedPresets[nam] = dict(origSaveValueStore) - else: - # saved preset was renamed or deleted - clearThis = True - - # insert component into the loader - loader.insertComponent( - self.moduleIndexFor(name), -1) - try: + # add loaded named presets to savedPresets dict if 'preset' in preset and preset['preset'] != None: - self.selectedComponents[-1].loadPreset( - preset - ) - else: - self.selectedComponents[-1].loadPreset( - preset, - preset['preset'] - ) - except KeyError as e: - print('%s missing value %s' % - (self.selectedComponents[-1], e)) + nam = preset['preset'] + filepath2 = os.path.join( + self.presetDir, name, str(vers), nam) + origSaveValueStore = self.getPreset(filepath2) + if origSaveValueStore: + self.savedPresets[nam] = dict(origSaveValueStore) + else: + # saved preset was renamed or deleted + clearThis = True - if clearThis: - self.clearPreset(-1, loader) + # insert component into the loader + loader.insertComponent( + self.moduleIndexFor(name), -1) + try: + if 'preset' in preset and preset['preset'] != None: + self.selectedComponents[-1].loadPreset( + preset + ) + else: + self.selectedComponents[-1].loadPreset( + preset, + preset['preset'] + ) + except KeyError as e: + print('%s missing value %s' % + (self.selectedComponents[-1], e)) + + if clearThis: + self.clearPreset(-1, loader) + except: + errcode = 1 + data = sys.exc_info() - elif errcode == 1: + if errcode == 1: typ, value, _ = data if typ.__name__ == KeyError: # probably just an old version, still loadable @@ -398,3 +428,9 @@ class Core(): def presetFromString(string): '''Turns a string repr of OrderedDict into a regular dict''' return dict(eval(string)) + + @staticmethod + def appendUppercase(lst): + for form, i in zip(lst, range(len(lst))): + lst.append(form.upper()) + return lst diff --git a/mainwindow.py b/mainwindow.py index ad1df10..f1959cb 100644 --- a/mainwindow.py +++ b/mainwindow.py @@ -310,7 +310,7 @@ class MainWindow(QtCore.QObject): fileName = QtGui.QFileDialog.getOpenFileName( self.window, "Open Music File", - inputDir, "Music Files (*.mp3 *.wav *.ogg *.fla *.aac)") + inputDir, "Music Files (%s)" % " ".join(self.core.audioFormats)) if not fileName == "": self.settings.setValue("inputDir", os.path.dirname(fileName)) @@ -322,7 +322,7 @@ class MainWindow(QtCore.QObject): fileName = QtGui.QFileDialog.getSaveFileName( self.window, "Set Output Video File", outputDir, - "Video Files (*.mp4 *.mov *.mkv *.avi *.webm *.flv);; All Files (*)") + "Video Files (%s);; All Files (*)" % " ".join(self.core.videoFormats)) if not fileName == "": self.settings.setValue("outputDir", os.path.dirname(fileName)) diff --git a/preview_thread.py b/preview_thread.py index d54dba5..e3e8279 100644 --- a/preview_thread.py +++ b/preview_thread.py @@ -1,11 +1,9 @@ from PyQt4 import QtCore, QtGui, uic from PyQt4.QtCore import pyqtSignal, pyqtSlot -from PIL import Image, ImageDraw, ImageFont +from PIL import Image from PIL.ImageQt import ImageQt import core -import time from queue import Queue, Empty -import numpy import os from copy import copy @@ -18,6 +16,7 @@ class Worker(QtCore.QObject): QtCore.QObject.__init__(self) parent.newTask.connect(self.createPreviewImage) parent.processTask.connect(self.process) + self.parent = parent self.core = core.Core() self.queue = queue self.core.settings = parent.settings