diff options
Diffstat (limited to 'src/toolkit')
| -rw-r--r-- | src/toolkit/__init__.py | 1 | ||||
| -rw-r--r-- | src/toolkit/common.py | 133 | ||||
| -rw-r--r-- | src/toolkit/frame.py | 66 |
3 files changed, 200 insertions, 0 deletions
diff --git a/src/toolkit/__init__.py b/src/toolkit/__init__.py new file mode 100644 index 0000000..3fca275 --- /dev/null +++ b/src/toolkit/__init__.py @@ -0,0 +1 @@ +from toolkit.common import * diff --git a/src/toolkit/common.py b/src/toolkit/common.py new file mode 100644 index 0000000..e3a1649 --- /dev/null +++ b/src/toolkit/common.py @@ -0,0 +1,133 @@ +''' + Common functions +''' +from PyQt5 import QtWidgets +import string +import os +import sys +import subprocess +from collections import OrderedDict + + +def badName(name): + '''Returns whether a name contains non-alphanumeric chars''' + return any([letter in string.punctuation for letter in name]) + + +def alphabetizeDict(dictionary): + '''Alphabetizes a dict into OrderedDict ''' + return OrderedDict(sorted(dictionary.items(), key=lambda t: t[0])) + + +def presetToString(dictionary): + '''Returns string repr of a preset''' + return repr(alphabetizeDict(dictionary)) + + +def presetFromString(string): + '''Turns a string repr of OrderedDict into a regular dict''' + return dict(eval(string)) + + +def appendUppercase(lst): + for form, i in zip(lst, range(len(lst))): + lst.append(form.upper()) + return lst + + +def hideCmdWin(func): + ''' Stops CMD window from appearing on Windows. + Adapted from here: http://code.activestate.com/recipes/409002/ + ''' + def decorator(commandList, **kwargs): + if sys.platform == 'win32': + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + kwargs['startupinfo'] = startupinfo + return func(commandList, **kwargs) + return decorator + + +@hideCmdWin +def checkOutput(commandList, **kwargs): + return subprocess.check_output(commandList, **kwargs) + + +@hideCmdWin +def openPipe(commandList, **kwargs): + return subprocess.Popen(commandList, **kwargs) + + +def disableWhenEncoding(func): + ''' Blocks calls to a function while the video is being exported + in MainWindow. + ''' + def decorator(*args, **kwargs): + if args[0].encoding: + return + else: + return func(*args, **kwargs) + return decorator + + +def pickColor(): + ''' + Use color picker to get color input from the user, + and return this as an RGB string and QPushButton stylesheet. + In a subclass apply stylesheet to any color selection widgets + ''' + dialog = QtWidgets.QColorDialog() + dialog.setOption(QtWidgets.QColorDialog.ShowAlphaChannel, True) + color = dialog.getColor() + if color.isValid(): + RGBstring = '%s,%s,%s' % ( + str(color.red()), str(color.green()), str(color.blue())) + btnStyle = "QPushButton{background-color: %s; outline: none;}" \ + % color.name() + return RGBstring, btnStyle + else: + return None, None + + +def rgbFromString(string): + '''Turns an RGB string like "255, 255, 255" into a tuple''' + try: + tup = tuple([int(i) for i in string.split(',')]) + if len(tup) != 3: + raise ValueError + for i in tup: + if i > 255 or i < 0: + raise ValueError + return tup + except: + return (255, 255, 255) + + +def LoadDefaultSettings(self): + ''' Runs once at each program start-up. Fills in default settings + for any settings not found in settings.ini + ''' + self.resolutions = [ + '1920x1080', + '1280x720', + '854x480' + ] + + default = { + "outputWidth": 1280, + "outputHeight": 720, + "outputFrameRate": 30, + "outputAudioCodec": "AAC", + "outputAudioBitrate": "192", + "outputVideoCodec": "H264", + "outputVideoBitrate": "2500", + "outputVideoFormat": "yuv420p", + "outputPreset": "medium", + "outputFormat": "mp4", + "outputContainer": "MP4", + "projectDir": os.path.join(self.dataDir, 'projects'), + } + + for parm, value in default.items(): + if self.settings.value(parm) is None: + self.settings.setValue(parm, value) diff --git a/src/toolkit/frame.py b/src/toolkit/frame.py new file mode 100644 index 0000000..cddb611 --- /dev/null +++ b/src/toolkit/frame.py @@ -0,0 +1,66 @@ +''' + Common tools for drawing compatible frames in a Component's frameRender() +''' +from PyQt5 import QtGui +from PIL import Image +from PIL.ImageQt import ImageQt +import sys +import os + + +class Frame: + '''Controller class for all frames.''' + + +class FramePainter(QtGui.QPainter): + ''' + A QPainter for a blank frame, which can be converted into a + Pillow image with finalize() + ''' + def __init__(self, width, height): + image = BlankFrame(width, height) + self.image = QtGui.QImage(ImageQt(image)) + super().__init__(self.image) + + def setPen(self, RgbTuple): + super().setPen(PaintColor(*RgbTuple)) + + def finalize(self): + self.end() + imBytes = self.image.bits().asstring(self.image.byteCount()) + + return Image.frombytes( + 'RGBA', (self.image.width(), self.image.height()), imBytes + ) + + +class PaintColor(QtGui.QColor): + '''Reverse the painter colour if the hardware stores RGB values backward''' + def __init__(self, r, g, b, a=255): + if sys.byteorder == 'big': + super().__init__(r, g, b, a) + else: + super().__init__(b, g, r, a) + + +def FloodFrame(width, height, RgbaTuple): + return Image.new("RGBA", (width, height), RgbaTuple) + + +def BlankFrame(width, height): + '''The base frame used by each component to start drawing.''' + return FloodFrame(width, height, (0, 0, 0, 0)) + + +def Checkerboard(width, height): + ''' + A checkerboard to represent transparency to the user. + TODO: Would be cool to generate this image with numpy instead. + ''' + image = FloodFrame(1920, 1080, (0, 0, 0, 0)) + image.paste(Image.open( + os.path.join(Frame.core.wd, "background.png")), + (0, 0) + ) + image = image.resize((width, height)) + return image |
