various bugfixes, blankFrame method for components

don't crash from broken project files or nonexistent videopaths, and shareable common paths in core.py
This commit is contained in:
tassaron 2017-06-15 22:15:03 -04:00
parent 8603fa12e3
commit c05efc73ee
11 changed files with 105 additions and 55 deletions

View File

@ -1,4 +1,5 @@
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from PIL import Image
class Component(QtCore.QObject): class Component(QtCore.QObject):
@ -45,6 +46,9 @@ class Component(QtCore.QObject):
for var, value in kwargs.items(): for var, value in kwargs.items():
exec('self.%s = value' % var) exec('self.%s = value' % var)
def blankFrame(self, width, height):
return Image.new("RGBA", (width, height), (0, 0, 0, 0))
def pickColor(self): def pickColor(self):
dialog = QtGui.QColorDialog() dialog = QtGui.QColorDialog()
dialog.setOption(QtGui.QColorDialog.ShowAlphaChannel, True) dialog.setOption(QtGui.QColorDialog.ShowAlphaChannel, True)

View File

@ -71,7 +71,7 @@ class Component(__base__.Component):
def drawFrame(self, width, height): def drawFrame(self, width, height):
r, g, b = self.color1 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): def loadPreset(self, pr, presetName=None):
super().loadPreset(pr, presetName) super().loadPreset(pr, presetName)

View File

@ -38,6 +38,7 @@ class Component(__base__.Component):
super().update() super().update()
def previewRender(self, previewWorker): def previewRender(self, previewWorker):
self.imageFormats = previewWorker.core.imageFormats
width = int(previewWorker.core.settings.value('outputWidth')) width = int(previewWorker.core.settings.value('outputWidth'))
height = int(previewWorker.core.settings.value('outputHeight')) height = int(previewWorker.core.settings.value('outputHeight'))
return self.drawFrame(width, height) return self.drawFrame(width, height)
@ -52,7 +53,7 @@ class Component(__base__.Component):
return self.drawFrame(width, height) return self.drawFrame(width, height)
def drawFrame(self, 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): if self.imagePath and os.path.exists(self.imagePath):
image = Image.open(self.imagePath) image = Image.open(self.imagePath)
if self.stretched and image.size != (width, height): if self.stretched and image.size != (width, height):
@ -85,7 +86,8 @@ class Component(__base__.Component):
def pickImage(self): def pickImage(self):
imgDir = self.settings.value("backgroundDir", os.path.expanduser("~")) imgDir = self.settings.value("backgroundDir", os.path.expanduser("~"))
filename = QtGui.QFileDialog.getOpenFileName( 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: if filename:
self.settings.setValue("backgroundDir", os.path.dirname(filename)) self.settings.setValue("backgroundDir", os.path.dirname(filename))
self.page.lineEdit_image.setText(filename) self.page.lineEdit_image.setText(filename)

View File

@ -230,7 +230,7 @@
<number>10</number> <number>10</number>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>200</number> <number>400</number>
</property> </property>
<property name="value"> <property name="value">
<number>100</number> <number>100</number>

View File

@ -145,7 +145,7 @@ class Component(__base__.Component):
bF = width / 64 bF = width / 64
bH = bF / 2 bH = bF / 2
bQ = bF / 4 bQ = bF / 4
imTop = Image.new("RGBA", (width, height), (0, 0, 0, 0)) imTop = self.blankFrame(width, height)
draw = ImageDraw.Draw(imTop) draw = ImageDraw.Draw(imTop)
r, g, b = color r, g, b = color
color2 = (r, g, b, 125) color2 = (r, g, b, 125)
@ -163,7 +163,7 @@ class Component(__base__.Component):
imBottom = imTop.transpose(Image.FLIP_TOP_BOTTOM) 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: if layout == 0:
y = 0 - int(height/100*43) y = 0 - int(height/100*43)

View File

@ -126,7 +126,7 @@ class Component(__base__.Component):
def addText(self, width, height): def addText(self, width, height):
x, y = self.getXY() x, y = self.getXY()
im = Image.new("RGBA", (width, height), (0, 0, 0, 0)) im = self.blankFrame(width, height)
image = ImageQt(im) image = ImageQt(im)
painter = QPainter(image) painter = QPainter(image)

View File

@ -128,12 +128,13 @@ class Component(__base__.Component):
super().update() super().update()
def previewRender(self, previewWorker): def previewRender(self, previewWorker):
self.videoFormats = previewWorker.core.videoFormats
width = int(previewWorker.core.settings.value('outputWidth')) width = int(previewWorker.core.settings.value('outputWidth'))
height = int(previewWorker.core.settings.value('outputHeight')) height = int(previewWorker.core.settings.value('outputHeight'))
self.updateChunksize(width, height) self.updateChunksize(width, height)
frame = self.getPreviewFrame(width, height) frame = self.getPreviewFrame(width, height)
if not frame: if not frame:
return Image.new("RGBA", (width, height), (0, 0, 0, 0)) return self.blankFrame(width, height)
else: else:
return frame return frame
@ -141,6 +142,7 @@ class Component(__base__.Component):
super().preFrameRender(**kwargs) super().preFrameRender(**kwargs)
width = int(self.worker.core.settings.value('outputWidth')) width = int(self.worker.core.settings.value('outputWidth'))
height = int(self.worker.core.settings.value('outputHeight')) height = int(self.worker.core.settings.value('outputHeight'))
self.blankFrame_ = self.blankFrame(width, height)
self.updateChunksize(width, height) self.updateChunksize(width, height)
self.video = Video( self.video = Video(
ffmpeg=self.parent.core.FFMPEG_BIN, videoPath=self.videoPath, ffmpeg=self.parent.core.FFMPEG_BIN, videoPath=self.videoPath,
@ -148,10 +150,13 @@ class Component(__base__.Component):
frameRate=int(self.settings.value("outputFrameRate")), frameRate=int(self.settings.value("outputFrameRate")),
parent=self.parent, loopVideo=self.loopVideo, parent=self.parent, loopVideo=self.loopVideo,
component=self, scale=self.scale component=self, scale=self.scale
) ) if os.path.exists(self.videoPath) else None
def frameRender(self, moduleNo, arrayNo, frameNo): 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): def loadPreset(self, pr, presetName=None):
super().loadPreset(pr, presetName) super().loadPreset(pr, presetName)
@ -177,7 +182,7 @@ class Component(__base__.Component):
imgDir = self.settings.value("backgroundDir", os.path.expanduser("~")) imgDir = self.settings.value("backgroundDir", os.path.expanduser("~"))
filename = QtGui.QFileDialog.getOpenFileName( filename = QtGui.QFileDialog.getOpenFileName(
self.page, "Choose Video", self.page, "Choose Video",
imgDir, "Video Files (*.mp4 *.mov)" imgDir, "Video Files (%s)" % " ".join(self.videoFormats)
) )
if filename: if filename:
self.settings.setValue("backgroundDir", os.path.dirname(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): def finalizeFrame(self, imageData, width, height):
if self.distort: if self.distort:
image = Image.frombytes( try:
'RGBA', image = Image.frombytes(
(width, height), 'RGBA',
imageData) (width, height),
imageData)
except ValueError:
print('#### ignored invalid data caused by distortion ####')
image = self.blankFrame(width, height)
else: else:
image = Image.frombytes( image = Image.frombytes(
'RGBA', 'RGBA',
@ -240,7 +249,7 @@ def finalizeFrame(self, imageData, width, height):
if self.scale != 100 \ if self.scale != 100 \
or self.xPosition != 0 or self.yPosition != 0: 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)) frame.paste(image, box=(self.xPosition, self.yPosition))
else: else:
frame = image frame = image

View File

@ -234,7 +234,7 @@
<number>10</number> <number>10</number>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>200</number> <number>400</number>
</property> </property>
<property name="value"> <property name="value">
<number>100</number> <number>100</number>

102
core.py
View File

@ -24,6 +24,32 @@ class Core():
self.presetDir = os.path.join(self.dataDir, 'presets') self.presetDir = os.path.join(self.dataDir, 'presets')
self.wd = os.path.dirname(os.path.realpath(__file__)) self.wd = os.path.dirname(os.path.realpath(__file__))
self.loadEncoderOptions() 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.findComponents()
self.selectedComponents = [] self.selectedComponents = []
@ -116,44 +142,48 @@ class Core():
which implements an insertComponent method''' which implements an insertComponent method'''
errcode, data = self.parseAvFile(filepath) errcode, data = self.parseAvFile(filepath)
if errcode == 0: if errcode == 0:
for i, tup in enumerate(data['Components']): try:
name, vers, preset = tup for i, tup in enumerate(data['Components']):
clearThis = False name, vers, preset = tup
clearThis = False
# add loaded named presets to savedPresets dict # 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:
if 'preset' in preset and preset['preset'] != None: if 'preset' in preset and preset['preset'] != None:
self.selectedComponents[-1].loadPreset( nam = preset['preset']
preset filepath2 = os.path.join(
) self.presetDir, name, str(vers), nam)
else: origSaveValueStore = self.getPreset(filepath2)
self.selectedComponents[-1].loadPreset( if origSaveValueStore:
preset, self.savedPresets[nam] = dict(origSaveValueStore)
preset['preset'] else:
) # saved preset was renamed or deleted
except KeyError as e: clearThis = True
print('%s missing value %s' %
(self.selectedComponents[-1], e))
if clearThis: # insert component into the loader
self.clearPreset(-1, 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 typ, value, _ = data
if typ.__name__ == KeyError: if typ.__name__ == KeyError:
# probably just an old version, still loadable # probably just an old version, still loadable
@ -398,3 +428,9 @@ class Core():
def presetFromString(string): def presetFromString(string):
'''Turns a string repr of OrderedDict into a regular dict''' '''Turns a string repr of OrderedDict into a regular dict'''
return dict(eval(string)) return dict(eval(string))
@staticmethod
def appendUppercase(lst):
for form, i in zip(lst, range(len(lst))):
lst.append(form.upper())
return lst

View File

@ -310,7 +310,7 @@ class MainWindow(QtCore.QObject):
fileName = QtGui.QFileDialog.getOpenFileName( fileName = QtGui.QFileDialog.getOpenFileName(
self.window, "Open Music File", self.window, "Open Music File",
inputDir, "Music Files (*.mp3 *.wav *.ogg *.fla *.aac)") inputDir, "Music Files (%s)" % " ".join(self.core.audioFormats))
if not fileName == "": if not fileName == "":
self.settings.setValue("inputDir", os.path.dirname(fileName)) self.settings.setValue("inputDir", os.path.dirname(fileName))
@ -322,7 +322,7 @@ class MainWindow(QtCore.QObject):
fileName = QtGui.QFileDialog.getSaveFileName( fileName = QtGui.QFileDialog.getSaveFileName(
self.window, "Set Output Video File", self.window, "Set Output Video File",
outputDir, outputDir,
"Video Files (*.mp4 *.mov *.mkv *.avi *.webm *.flv);; All Files (*)") "Video Files (%s);; All Files (*)" % " ".join(self.core.videoFormats))
if not fileName == "": if not fileName == "":
self.settings.setValue("outputDir", os.path.dirname(fileName)) self.settings.setValue("outputDir", os.path.dirname(fileName))

View File

@ -1,11 +1,9 @@
from PyQt4 import QtCore, QtGui, uic from PyQt4 import QtCore, QtGui, uic
from PyQt4.QtCore import pyqtSignal, pyqtSlot from PyQt4.QtCore import pyqtSignal, pyqtSlot
from PIL import Image, ImageDraw, ImageFont from PIL import Image
from PIL.ImageQt import ImageQt from PIL.ImageQt import ImageQt
import core import core
import time
from queue import Queue, Empty from queue import Queue, Empty
import numpy
import os import os
from copy import copy from copy import copy
@ -18,6 +16,7 @@ class Worker(QtCore.QObject):
QtCore.QObject.__init__(self) QtCore.QObject.__init__(self)
parent.newTask.connect(self.createPreviewImage) parent.newTask.connect(self.createPreviewImage)
parent.processTask.connect(self.process) parent.processTask.connect(self.process)
self.parent = parent
self.core = core.Core() self.core = core.Core()
self.queue = queue self.queue = queue
self.core.settings = parent.settings self.core.settings = parent.settings