From 4255dd7b62e23da8794074293a89ef597a111c1c Mon Sep 17 00:00:00 2001 From: Linux Date: Sun, 9 Jul 2017 12:48:01 +0300 Subject: [PATCH 1/3] * Change jpegoptim to guetzli * guetzli compresses JPGs MUCH better than jpegoptim, the output quality is near to the original image * guetzli needs a lot of CPU and RAM resources to work, but it is compensated with much better reduce of the size of the image * guetzli's git is here: https://github.com/google/guetzli; it is already in Debian's repos: https://packages.debian.org/search?keywords=guetzli&searchon=names&suite=all§ion=all, it has also already been packaged for ALT Linux and Slackware: https://pkgs.org/download/guetzli * Added Russian translations into the .desktop file --- debian/control | 4 ++-- desktop/trimage.desktop | 4 +++- setup.py | 2 +- src/trimage/trimage.py | 27 ++++++++++++++++++++------- trimage | 0 5 files changed, 26 insertions(+), 11 deletions(-) mode change 100644 => 100755 trimage diff --git a/debian/control b/debian/control index 68bdb14..26fb0f9 100644 --- a/debian/control +++ b/debian/control @@ -9,11 +9,11 @@ Homepage: http://trimage.org Package: trimage Architecture: all -Depends: ${misc:Depends}, ${python:Depends}, python-qt4 (>=4.4), optipng (>=0.6.2.1), advancecomp (>=1.15), jpegoptim (>=1.2.2), pngcrush (>=1.6.7) +Depends: ${misc:Depends}, ${python:Depends}, python-qt4 (>=4.4), optipng (>=0.6.2.1), advancecomp (>=1.15), guetzli, pngcrush (>=1.6.7) XB-Python-Version: ${python:Versions} Description: GUI and command-line interface to optimize image files Trimage is a cross-platform GUI and command-line interface to optimize image - files via optipng, advpng, pngcrush and jpegoptim, depending on the filetype + files via optipng, advpng, pngcrush and guetzli, depending on the filetype (currently, PNG and JPG files are supported). All image files are losslessly compressed on the highest available compression levels. Trimage gives you various input functions to fit your own workflow: A regular file dialog, diff --git a/desktop/trimage.desktop b/desktop/trimage.desktop index 2cf870a..6cd6632 100644 --- a/desktop/trimage.desktop +++ b/desktop/trimage.desktop @@ -1,6 +1,8 @@ [Desktop Entry] Name=Trimage image compressor -Comment=A cross-platform tool for optimizing PNG and JPG files. +Name[ru]=Программа для уменьшения веса картинок Trimage +Comment=A cross-platform tool for optimizing PNG and JPG files +Comment[ru]=Кросс-платформенная утилита для оптимизации файлов PNG и JPG Terminal=false Icon=trimage Type=Application diff --git a/setup.py b/setup.py index bae6f17..08a5db7 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ setup(name = "trimage", ('share/applications', ['desktop/trimage.desktop']), ('share/man/man1', ['doc/trimage.1'])], scripts = ["trimage"], - long_description = """Trimage is a cross-platform GUI and command-line interface to optimize image files via optipng, advpng and jpegoptim, depending on the filetype (currently, PNG and JPG files are supported). It was inspired by imageoptim. All image files are losslessy compressed on the highest available compression levels. Trimage gives you various input functions to fit your own workflow: A regular file dialog, dragging and dropping and various command line options.""", + long_description = """Trimage is a cross-platform GUI and command-line interface to optimize image files via optipng, advpng and guetzli, depending on the filetype (currently, PNG and JPG files are supported). It was inspired by imageoptim. All image files are losslessy compressed on the highest available compression levels. Trimage gives you various input functions to fit your own workflow: A regular file dialog, dragging and dropping and various command line options.""", requires = ["PyQt4 (>=4.4)"], #for py2exe diff --git a/src/trimage/trimage.py b/src/trimage/trimage.py index 84b13a0..e841f04 100644 --- a/src/trimage/trimage.py +++ b/src/trimage/trimage.py @@ -22,7 +22,8 @@ from multiprocessing import cpu_count from ui import Ui_trimage -VERSION = "1.0.5" +# change version to 1.1 after replacing jpegoptim with guetzli +VERSION = "1.1" class StartQT4(QMainWindow): @@ -86,7 +87,7 @@ class StartQT4(QMainWindow): """Set up the command line options.""" parser = OptionParser(version="%prog " + VERSION, description="GUI front-end to compress png and jpg images via " - "optipng, advpng and jpegoptim") + "optipng, advpng and guetzli") parser.set_defaults(verbose=True) parser.add_option("-v", "--verbose", action="store_true", @@ -261,10 +262,12 @@ class StartQT4(QMainWindow): """Check if the required command line apps exist.""" exe = ".exe" if (sys.platform == "win32") else "" status = False - retcode = self.safe_call("jpegoptim" + exe + " --version") - if retcode != 0: - status = True - sys.stderr.write("[error] please install jpegoptim") + + # guetzli does the compression job much better than jpegoptim (and much slower) + #retcode = self.safe_call("jpegoptim" + exe + " --version") + #if retcode != 0: + #status = True + #sys.stderr.write("[error] please install jpegoptim") retcode = self.safe_call("optipng" + exe + " -v") if retcode != 0: @@ -281,6 +284,13 @@ class StartQT4(QMainWindow): status = True sys.stderr.write("[error] please install pngcrush") return status + + # guetzli currently does not have neither --version not --help flags + retcode = self.safe_call("guetzli" + exe) + if retcode != 0: + status = True + sys.stderr.write("[error] please install guetzli") + return status def safe_call(self, command): """ cross-platform command-line check """ @@ -431,7 +441,10 @@ class Image: self.compressing = True exe = ".exe" if (sys.platform == "win32") else "" runString = { - "jpeg": u"jpegoptim" + exe + " -f --strip-all '%(file)s'", + # "jpeg": u"jpegoptim" + exe + " -f --strip-all '%(file)s'", + # I commented out jpegoptim because guetzli compresses MUCH BETTER having a similar output quality + # the default quality level for guetzli, if the parameter '--quality Q' is not passed, it 95. + "jpeg": u"guetzli" + exe + " --quality 95 '%(file)s' '%(file)s.bak' && mv '%(file)s.bak' '%(file)s'", "png": u"optipng" + exe + " -force -o7 '%(file)s'&&advpng" + exe + " -z4 '%(file)s' && pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time '%(file)s' '%(file)s.bak' && mv '%(file)s.bak' '%(file)s'" } # Create a backup file diff --git a/trimage b/trimage old mode 100644 new mode 100755 From cad49c6d719b6855629fba1ad5a6fba0b24c3437 Mon Sep 17 00:00:00 2001 From: Linux Date: Sun, 9 Jul 2017 12:59:48 +0300 Subject: [PATCH 2/3] update README --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index ec43bc4..698ce38 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ A cross-platform tool for optimizing PNG and JPG files. Trimage is a cross-platform GUI and command-line interface to optimize image files via "optipng":http://optipng.sourceforge.net/, "advpng":http://advancemame.sourceforge.net/comp-readme.html and -"jpegoptim":http://www.kokkonen.net/tjko/projects.html, depending on the +"guetzli":https://github.com/google/guetzli, depending on the filetype (currently, PNG and JPG files are supported). It was inspired by "imageoptim":http://imageoptim.pornel.net/. All image files are losslessly compressed on the highest available compression levels. Trimage gives you From ddc6d2da9a7c8d3c14450ac7ebebfd4771a40946 Mon Sep 17 00:00:00 2001 From: Linux Date: Sun, 9 Jul 2017 13:18:00 +0300 Subject: [PATCH 3/3] Update debian spec --- debian/changelog | 7 + debian/control | 5 +- debian/debhelper-build-stamp | 1 + debian/files | 1 + debian/rules | 3 +- debian/trimage.debhelper.log | 20 + debian/trimage.postinst.debhelper | 7 + debian/trimage.prerm.debhelper | 12 + debian/trimage.substvars | 4 + debian/trimage/DEBIAN/control | 17 + debian/trimage/DEBIAN/md5sums | 19 + debian/trimage/DEBIAN/postinst | 9 + debian/trimage/DEBIAN/prerm | 14 + debian/trimage/usr/bin/trimage | 24 + .../dist-packages/trimage-1.0.2.egg-info | 11 + .../trimage/ThreadPool/ThreadPool.py | 280 +++++++++ .../trimage/ThreadPool/__init__.py | 1 + .../dist-packages/trimage/__init__.py | 0 .../trimage/filesize/__init__.py | 2 + .../trimage/filesize/filesize.py | 115 ++++ .../trimage/pixmaps/compressing.gif | Bin 0 -> 1849 bytes .../trimage/pixmaps/list-add.png | Bin 0 -> 676 bytes .../trimage/pixmaps/trimage-icon.png | Bin 0 -> 4542 bytes .../trimage/pixmaps/view-refresh.png | Bin 0 -> 1997 bytes .../dist-packages/trimage/trimage.py | 570 ++++++++++++++++++ .../lib/python2.7/dist-packages/trimage/ui.py | 166 +++++ .../usr/share/applications/trimage.desktop | 12 + debian/trimage/usr/share/doc/trimage/README | 15 + .../usr/share/doc/trimage/changelog.gz | Bin 0 -> 988 bytes .../trimage/usr/share/doc/trimage/copyright | 256 ++++++++ .../icons/hicolor/scalable/apps/trimage.svg | 237 ++++++++ .../trimage/usr/share/man/man1/trimage.1.gz | Bin 0 -> 522 bytes 32 files changed, 1803 insertions(+), 5 deletions(-) create mode 100644 debian/debhelper-build-stamp create mode 100644 debian/files mode change 100644 => 100755 debian/rules create mode 100644 debian/trimage.debhelper.log create mode 100644 debian/trimage.postinst.debhelper create mode 100644 debian/trimage.prerm.debhelper create mode 100644 debian/trimage.substvars create mode 100644 debian/trimage/DEBIAN/control create mode 100644 debian/trimage/DEBIAN/md5sums create mode 100755 debian/trimage/DEBIAN/postinst create mode 100755 debian/trimage/DEBIAN/prerm create mode 100755 debian/trimage/usr/bin/trimage create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage-1.0.2.egg-info create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/ThreadPool/ThreadPool.py create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/ThreadPool/__init__.py create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/__init__.py create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/filesize/__init__.py create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/filesize/filesize.py create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/compressing.gif create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/list-add.png create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/trimage-icon.png create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/view-refresh.png create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/trimage.py create mode 100644 debian/trimage/usr/lib/python2.7/dist-packages/trimage/ui.py create mode 100644 debian/trimage/usr/share/applications/trimage.desktop create mode 100644 debian/trimage/usr/share/doc/trimage/README create mode 100644 debian/trimage/usr/share/doc/trimage/changelog.gz create mode 100644 debian/trimage/usr/share/doc/trimage/copyright create mode 100644 debian/trimage/usr/share/icons/hicolor/scalable/apps/trimage.svg create mode 100644 debian/trimage/usr/share/man/man1/trimage.1.gz diff --git a/debian/changelog b/debian/changelog index 30f9a17..99786ba 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +trimage (1.1) xenial; urgency=medium + + * change jpegoptim to guetzli + * Add Russian translation in trimage.desktop + + -- Mikhail Novosyolov Sun, 09 Jul 2017 13:05:00 +0300 + trimage (1.0.5-0ubuntu1) jaunty; urgency=low * prevent images from becoming larger after recompression diff --git a/debian/control b/debian/control index 26fb0f9..dcfaf55 100644 --- a/debian/control +++ b/debian/control @@ -1,8 +1,8 @@ Source: trimage Section: graphics Priority: optional -Maintainer: Kilian Valkhof -Build-Depends: debhelper (>=7), python-support (>=0.8.7), python +Maintainer: Mikhail Novosyolov +Build-Depends: debhelper (>=7), dh-python, python XS-Python-Version: >=2.6 Standards-Version: 3.9.1 Homepage: http://trimage.org @@ -18,4 +18,3 @@ Description: GUI and command-line interface to optimize image files compressed on the highest available compression levels. Trimage gives you various input functions to fit your own workflow: A regular file dialog, dragging and dropping and various command line options. - diff --git a/debian/debhelper-build-stamp b/debian/debhelper-build-stamp new file mode 100644 index 0000000..ad37ff2 --- /dev/null +++ b/debian/debhelper-build-stamp @@ -0,0 +1 @@ +trimage diff --git a/debian/files b/debian/files new file mode 100644 index 0000000..a246413 --- /dev/null +++ b/debian/files @@ -0,0 +1 @@ +trimage_1.1_all.deb graphics optional diff --git a/debian/rules b/debian/rules old mode 100644 new mode 100755 index 4f2c774..18bcae9 --- a/debian/rules +++ b/debian/rules @@ -1,4 +1,3 @@ #!/usr/bin/make -f %: - dh $@ - + dh $@ --with python2 diff --git a/debian/trimage.debhelper.log b/debian/trimage.debhelper.log new file mode 100644 index 0000000..29f3ba2 --- /dev/null +++ b/debian/trimage.debhelper.log @@ -0,0 +1,20 @@ +dh_update_autotools_config +dh_auto_configure +dh_auto_build +dh_auto_test +dh_prep +dh_auto_install +dh_installdocs +dh_installchangelogs +dh_installman +dh_icons +dh_perl +dh_link +dh_strip_nondeterminism +dh_compress +dh_fixperms +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb diff --git a/debian/trimage.postinst.debhelper b/debian/trimage.postinst.debhelper new file mode 100644 index 0000000..092165e --- /dev/null +++ b/debian/trimage.postinst.debhelper @@ -0,0 +1,7 @@ + +# Automatically added by dh_python2: +if which pycompile >/dev/null 2>&1; then + pycompile -p trimage +fi + +# End automatically added section diff --git a/debian/trimage.prerm.debhelper b/debian/trimage.prerm.debhelper new file mode 100644 index 0000000..e0a5b72 --- /dev/null +++ b/debian/trimage.prerm.debhelper @@ -0,0 +1,12 @@ + +# Automatically added by dh_python2: +if which pyclean >/dev/null 2>&1; then + pyclean -p trimage +else + dpkg -L trimage | grep \.py$ | while read file + do + rm -f "${file}"[co] >/dev/null + done +fi + +# End automatically added section diff --git a/debian/trimage.substvars b/debian/trimage.substvars new file mode 100644 index 0000000..2511b85 --- /dev/null +++ b/debian/trimage.substvars @@ -0,0 +1,4 @@ +python:Versions=2.7 +python:Depends=python:any, python:any (<< 2.8), python:any (>= 2.6~), python:any (>= 2.7.5-5~), python:any (>= 2.7~) +misc:Depends= +misc:Pre-Depends= diff --git a/debian/trimage/DEBIAN/control b/debian/trimage/DEBIAN/control new file mode 100644 index 0000000..75197c2 --- /dev/null +++ b/debian/trimage/DEBIAN/control @@ -0,0 +1,17 @@ +Package: trimage +Version: 1.1 +Architecture: all +Maintainer: Mikhail Novosyolov +Installed-Size: 104 +Depends: python:any (<< 2.8), python:any (>= 2.7.5-5~), python-qt4 (>= 4.4), optipng (>= 0.6.2.1), advancecomp (>= 1.15), guetzli, pngcrush (>= 1.6.7) +Section: graphics +Priority: optional +Homepage: http://trimage.org +Description: GUI and command-line interface to optimize image files + Trimage is a cross-platform GUI and command-line interface to optimize image + files via optipng, advpng, pngcrush and guetzli, depending on the filetype + (currently, PNG and JPG files are supported). All image files are losslessly + compressed on the highest available compression levels. Trimage gives you + various input functions to fit your own workflow: A regular file dialog, + dragging and dropping and various command line options. +Python-Version: 2.7 diff --git a/debian/trimage/DEBIAN/md5sums b/debian/trimage/DEBIAN/md5sums new file mode 100644 index 0000000..34e412b --- /dev/null +++ b/debian/trimage/DEBIAN/md5sums @@ -0,0 +1,19 @@ +9c1f31a6520e133d3e2f0b74b4bc4fd6 usr/bin/trimage +d06474fbf8d34b279b49d8cad59af2d0 usr/lib/python2.7/dist-packages/trimage-1.0.2.egg-info +750f3239a617e569f77881ac0122a2b9 usr/lib/python2.7/dist-packages/trimage/ThreadPool/ThreadPool.py +8111d2e44229ba4ecba01f59329af7c6 usr/lib/python2.7/dist-packages/trimage/ThreadPool/__init__.py +d41d8cd98f00b204e9800998ecf8427e usr/lib/python2.7/dist-packages/trimage/__init__.py +6440f77c90e6d358295cd62d603db1fb usr/lib/python2.7/dist-packages/trimage/filesize/__init__.py +d40a0e5bd2b317aa568e16b95d514df9 usr/lib/python2.7/dist-packages/trimage/filesize/filesize.py +9f2b6e23b29836684c216224628d4394 usr/lib/python2.7/dist-packages/trimage/pixmaps/compressing.gif +42636a9b4adbaee8d612cfd42f09151f usr/lib/python2.7/dist-packages/trimage/pixmaps/list-add.png +0ce6c6d3aa5abefc70f2abe91bfb9c5a usr/lib/python2.7/dist-packages/trimage/pixmaps/trimage-icon.png +aba26621c9399ce15c365e669b2a06dd usr/lib/python2.7/dist-packages/trimage/pixmaps/view-refresh.png +4a4e4f786b30bb755d30b506d0477a1b usr/lib/python2.7/dist-packages/trimage/trimage.py +cde8c6def70c52b2111563211b8fa007 usr/lib/python2.7/dist-packages/trimage/ui.py +e239b7003fa0407cdd6bf28c6d72c2a3 usr/share/applications/trimage.desktop +e1f82ec7e26a52a491ca6a224eff5769 usr/share/doc/trimage/README +3baf9c47a7390888522dd0fee82bf3d5 usr/share/doc/trimage/changelog.gz +ddaf427836d208b1b7115d9e202b65c2 usr/share/doc/trimage/copyright +d866aefacb2190ce623bacf964ec12ee usr/share/icons/hicolor/scalable/apps/trimage.svg +42768f4574b21cdabf82b98c025137fd usr/share/man/man1/trimage.1.gz diff --git a/debian/trimage/DEBIAN/postinst b/debian/trimage/DEBIAN/postinst new file mode 100755 index 0000000..a557ff3 --- /dev/null +++ b/debian/trimage/DEBIAN/postinst @@ -0,0 +1,9 @@ +#!/bin/sh +set -e + +# Automatically added by dh_python2: +if which pycompile >/dev/null 2>&1; then + pycompile -p trimage +fi + +# End automatically added section diff --git a/debian/trimage/DEBIAN/prerm b/debian/trimage/DEBIAN/prerm new file mode 100755 index 0000000..122e042 --- /dev/null +++ b/debian/trimage/DEBIAN/prerm @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +# Automatically added by dh_python2: +if which pyclean >/dev/null 2>&1; then + pyclean -p trimage +else + dpkg -L trimage | grep \.py$ | while read file + do + rm -f "${file}"[co] >/dev/null + done +fi + +# End automatically added section diff --git a/debian/trimage/usr/bin/trimage b/debian/trimage/usr/bin/trimage new file mode 100755 index 0000000..6d44558 --- /dev/null +++ b/debian/trimage/usr/bin/trimage @@ -0,0 +1,24 @@ +#!/usr/bin/python +#coding: utf-8 +# +#Copyright (c) 2010 Kilian Valkhof, Paul Chaplin, Tarnay Kálmán +# +#Permission is hereby granted, free of charge, to any person +#obtaining a copy of this software and associated documentation +#files (the "Software"), to deal in the Software without +#restriction, including without limitation the rights to use, +#copy, modify, merge, publish, distribute, sublicense, and/or sell +#copies of the Software, and to permit persons to whom the +#Software is furnished to do so, subject to the following +#conditions: +# +#The above copyright notice and this permission notice shall be +#included in all copies or substantial portions of the Software. + +import os, sys +import subprocess +import trimage + +if __name__ == "__main__": + path = os.path.join(os.path.dirname(trimage.__file__), "trimage.py") + subprocess.call([sys.executable, path] + sys.argv[1:]) diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage-1.0.2.egg-info b/debian/trimage/usr/lib/python2.7/dist-packages/trimage-1.0.2.egg-info new file mode 100644 index 0000000..671b163 --- /dev/null +++ b/debian/trimage/usr/lib/python2.7/dist-packages/trimage-1.0.2.egg-info @@ -0,0 +1,11 @@ +Metadata-Version: 1.1 +Name: trimage +Version: 1.0.2 +Summary: Trimage image compressor - A cross-platform tool for optimizing PNG and JPG files +Home-page: http://trimage.org +Author: Kilian Valkhof, Paul Chaplin +Author-email: help@trimage.org +License: MIT license +Description: Trimage is a cross-platform GUI and command-line interface to optimize image files via optipng, advpng and guetzli, depending on the filetype (currently, PNG and JPG files are supported). It was inspired by imageoptim. All image files are losslessy compressed on the highest available compression levels. Trimage gives you various input functions to fit your own workflow: A regular file dialog, dragging and dropping and various command line options. +Platform: UNKNOWN +Requires: PyQt4 (>=4.4) diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/ThreadPool/ThreadPool.py b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/ThreadPool/ThreadPool.py new file mode 100644 index 0000000..5c64409 --- /dev/null +++ b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/ThreadPool/ThreadPool.py @@ -0,0 +1,280 @@ +''' +ThreadPool Implementation + +@author: Morten Holdflod Moeller - morten@holdflod.dk +@license: LGPL v3 +''' + +from __future__ import with_statement +from threading import Thread, RLock +from time import sleep +from Queue import Queue, Empty +import logging +import sys + +class NullHandler(logging.Handler): + def emit(self, record): + pass + +h = sys.stderr +logging.getLogger('threadpool').addHandler(h) +logging.getLogger('threadpool.worker').addHandler(h) + + + +class ThreadPoolMixIn: + """Mix-in class to handle each request in a new thread from the ThreadPool.""" + + def __init__(self, threadpool=None): + if (threadpool == None): + threadpool = ThreadPool() + self.__private_threadpool = True + else: + self.__private_threadpool = False + + self.__threadpool = threadpool + + def process_request_thread(self, request, client_address): + """Same as in BaseServer but as a thread. + + In addition, exception handling is done here. + + """ + try: + self.finish_request(request, client_address) + self.close_request(request) + except: + self.handle_error(request, client_address) #IGNORE:W0702 + self.close_request(request) + + def process_request(self, request, client_address): + self.__threadpool.add_job(self.process_request_thread, [request, client_address]) + + def shutdown(self): + if (self.__private_threadpool): self.__threadpool.shutdown() + + +class AddJobException(Exception): + ''' + Exceptoion raised when a Job could not be added + to the queue + ''' + def __init__(self, msg): + Exception.__init__(self, msg) + + +class ThreadPool: + ''' + The class implementing the ThreadPool. + + Instantiate and add jobs using add_job(func, args_list) + ''' + + class Job: #IGNORE:R0903 + ''' + Class encapsulating a job to be handled + by ThreadPool workers + ''' + def __init__(self, function, args, return_callback=None): + self.callable = function + self.arguments = args + self.return_callback = return_callback + + def execute(self): + ''' + Called to execute the function + ''' + try: + return_value = self.callable(*self.arguments) #IGNORE:W0142 + except Exception, excep: #IGNORE:W0703 + logger = logging.getLogger("threadpool.worker") + logger.warning("A job in the ThreadPool raised an exception: " + excep) + #else do nothing cause we don't know what to do... + return + + try: + if (self.return_callback != None): + self.return_callback(return_value) + except Exception, _: #IGNORE:W0703 everything could go wrong... + logger = logging.getLogger('threadpool') + logger.warning('Error while delivering return value to callback function') + + class Worker(Thread): + ''' + A worker thread handling jobs in the thread pool + job queue + ''' + + def __init__(self, pool): + Thread.__init__(self) + + if (not isinstance(pool, ThreadPool)): + raise TypeError("pool is not a ThreadPool instance") + + self.pool = pool + + self.alive = True + self.start() + + def run(self): + ''' + The workers main-loop getting jobs from queue + and executing them + ''' + while self.alive: + #print self.pool.__active_worker_count, self.pool.__worker_count + job = self.pool.get_job() + if (job != None): + self.pool.worker_active() + job.execute() + self.pool.worker_inactive() + else: + self.alive = False + + self.pool.punch_out() + + def __init__(self, max_workers = 5, kill_workers_after = 3): + if (not isinstance(max_workers, int)): + raise TypeError("max_workers is not an int") + if (max_workers < 1): + raise ValueError('max_workers must be >= 1') + + if (not isinstance(kill_workers_after, int)): + raise TypeError("kill_workers_after is not an int") + + self.__max_workers = max_workers + self.__kill_workers_after = kill_workers_after + + # This Queue is assumed Thread Safe + self.__jobs = Queue() + + self.__worker_count_lock = RLock() + self.__worker_count = 0 + self.__active_worker_count = 0 + + self.__shutting_down = False + logger = logging.getLogger('threadpool') + logger.info('started') + + def shutdown(self, wait_for_workers_period = 1, clean_shutdown_reties = 5): + if (not isinstance(clean_shutdown_reties, int)): + raise TypeError("clean_shutdown_reties is not an int") + if (not clean_shutdown_reties >= 0): + raise ValueError('clean_shutdown_reties must be >= 0') + + if (not isinstance(wait_for_workers_period, int)): + raise TypeError("wait_for_workers_period is not an int") + if (not wait_for_workers_period >= 0): + raise ValueError('wait_for_workers_period must be >= 0') + + logger = logging.getLogger("threadpool") + logger.info("shutting down") + + with self.__worker_count_lock: + self.__shutting_down = True + self.__max_workers = 0 + self.__kill_workers_after = 0 + + retries_left = clean_shutdown_reties + while (retries_left > 0): + + with self.__worker_count_lock: + logger.info("waiting for workers to shut down (%i), %i workers left"%(retries_left, self.__worker_count)) + if (self.__worker_count > 0): + retries_left -= 1 + else: + retries_left = 0 + + sleep(wait_for_workers_period) + + + with self.__worker_count_lock: + if (self.__worker_count > 0): + logger.warning("shutdown stopped waiting. Still %i active workers"%self.__worker_count) + clean_shutdown = False + else: + clean_shutdown = True + + logger.info("shutdown complete") + + return clean_shutdown + + def punch_out(self): + ''' + Called by worker to update worker count + when the worker is shutting down + ''' + with self.__worker_count_lock: + self.__worker_count -= 1 + + def __new_worker(self): + ''' + Adding a new worker thread to the thread pool + ''' + with self.__worker_count_lock: + ThreadPool.Worker(self) + self.__worker_count += 1 + + def worker_active(self): + with self.__worker_count_lock: + self.__active_worker_count = self.__active_worker_count + 1 + + def worker_inactive(self): + with self.__worker_count_lock: + self.__active_worker_count = self.__active_worker_count - 1 + + def add_job(self, function, args = None, return_callback=None): + ''' + Put new job into queue + ''' + + if (not callable(function)): + raise TypeError("function is not a callable") + if (not ( args == None or isinstance(args, list))): + raise TypeError("args is not a list") + if (not (return_callback == None or callable(return_callback))): + raise TypeError("return_callback is not a callable") + + if (args == None): + args = [] + + job = ThreadPool.Job(function, args, return_callback) + + with self.__worker_count_lock: + if (self.__shutting_down): + raise AddJobException("ThreadPool is shutting down") + + try: + start_new_worker = False + if (self.__worker_count < self.__max_workers): + if (self.__active_worker_count == self.__worker_count): + start_new_worker = True + + self.__jobs.put(job) + + if (start_new_worker): + self.__new_worker() + + except Exception: + raise AddJobException("Could not add job") + + + def get_job(self): + ''' + Retrieve next job from queue + workers die (and should) when + returning None + ''' + + job = None + try: + if (self.__kill_workers_after < 0): + job = self.__jobs.get(True) + elif (self.__kill_workers_after == 0): + job = self.__jobs.get(False) + else: + job = self.__jobs.get(True, self.__kill_workers_after) + except Empty: + job = None + + return job diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/ThreadPool/__init__.py b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/ThreadPool/__init__.py new file mode 100644 index 0000000..727a8b3 --- /dev/null +++ b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/ThreadPool/__init__.py @@ -0,0 +1 @@ +from ThreadPool import ThreadPool, ThreadPoolMixIn \ No newline at end of file diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/__init__.py b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/filesize/__init__.py b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/filesize/__init__.py new file mode 100644 index 0000000..68d9fc2 --- /dev/null +++ b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/filesize/__init__.py @@ -0,0 +1,2 @@ +from filesize import size +from filesize import traditional, alternative, verbose, iec, si diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/filesize/filesize.py b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/filesize/filesize.py new file mode 100644 index 0000000..db3e1ba --- /dev/null +++ b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/filesize/filesize.py @@ -0,0 +1,115 @@ +''' +hurry.filesize + +@author: Martijn Faassen, Startifact +@license: ZPL 2.1 +''' + +traditional = [ + (1024 ** 5, 'P'), + (1024 ** 4, 'T'), + (1024 ** 3, 'G'), + (1024 ** 2, 'M'), + (1024 ** 1, 'K'), + (1024 ** 0, 'B'), + ] + +alternative = [ + (1024 ** 5, ' PB'), + (1024 ** 4, ' TB'), + (1024 ** 3, ' GB'), + (1024 ** 2, ' MB'), + (1024 ** 1, ' KB'), + (1024 ** 0, (' byte', ' bytes')), + ] + +verbose = [ + (1024 ** 5, (' petabyte', ' petabytes')), + (1024 ** 4, (' terabyte', ' terabytes')), + (1024 ** 3, (' gigabyte', ' gigabytes')), + (1024 ** 2, (' megabyte', ' megabytes')), + (1024 ** 1, (' kilobyte', ' kilobytes')), + (1024 ** 0, (' byte', ' bytes')), + ] + +iec = [ + (1024 ** 5, 'Pi'), + (1024 ** 4, 'Ti'), + (1024 ** 3, 'Gi'), + (1024 ** 2, 'Mi'), + (1024 ** 1, 'Ki'), + (1024 ** 0, ''), + ] + +si = [ + (1000 ** 5, 'P'), + (1000 ** 4, 'T'), + (1000 ** 3, 'G'), + (1000 ** 2, 'M'), + (1000 ** 1, 'K'), + (1000 ** 0, 'B'), + ] + + + +def size(bytes, system=traditional): + """Human-readable file size. + + Using the traditional system, where a factor of 1024 is used:: + + >>> size(10) + '10B' + >>> size(100) + '100B' + >>> size(1000) + '1000B' + >>> size(2000) + '1K' + >>> size(10000) + '9K' + >>> size(20000) + '19K' + >>> size(100000) + '97K' + >>> size(200000) + '195K' + >>> size(1000000) + '976K' + >>> size(2000000) + '1M' + + Using the SI system, with a factor 1000:: + + >>> size(10, system=si) + '10B' + >>> size(100, system=si) + '100B' + >>> size(1000, system=si) + '1K' + >>> size(2000, system=si) + '2K' + >>> size(10000, system=si) + '10K' + >>> size(20000, system=si) + '20K' + >>> size(100000, system=si) + '100K' + >>> size(200000, system=si) + '200K' + >>> size(1000000, system=si) + '1M' + >>> size(2000000, system=si) + '2M' + + """ + for factor, suffix in system: + if bytes >= factor: + break + amount = int(bytes/factor) + if isinstance(suffix, tuple): + singular, multiple = suffix + if amount == 1: + suffix = singular + else: + suffix = multiple + return str(amount) + suffix diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/compressing.gif b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/compressing.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d670db927092272ace564f4c103d5d3460b1e02 GIT binary patch literal 1849 zcmZ?wbhEHb6krfw_`<;O|NnpS_In?{|Cw_9{iFB4!j?a4J@8h%{a*Tpm*&$SZNC2b z@Pn_K6CNzN@KLJcp2vbGrQ2UKkOCC{bNji51UowhxEkphFf%eRFev_$axO|uEJ;mK zD9+}#lXOz1F{9=NCwt&1qCK1PQ|Aym|UDVjyq0R z?IF|o;KZRdLYogJZeU*K(sW4RnS(;yHW9~{5kDpbEOGd_Ln*YmX>*`5=edVYjWO2q z&vG9&TqVRK!J2>G%1A}3jM;&OOQlA~n1!F4i3j6hf0GxMFg4|E0kMVd0AKv>FvMU(iSO_)+fl~!xXQ?%*s{3W$e@(-pC@r z!rc*DYR}rfQbOT=QsitWK!_Ipro#s%0OG3x}%`NB^d-mgWOSMLMg+7Ze5@ z5ou>?U=WeW+Hxr2gM|Pa`)i>?4gwq&Nn##CItp4B9~nsKF5~@>>lQBY?uq4IpMWK< z#@b9=0vb(BPD;FN+-bel9a>J|@%o+hOuP>9DxFPr-bIb(jz!oV0}hv)CaIQvEs7i- zAC*pP3H3{JUkL2icWB<&q01*A)M(Nmz`}ZXWr2VRUr&(s_dU8o?DJo2Em+HOVtK;F z0F7y89L*0G%$52Os{coUlY?7Jhowc6g;_&eKUOKnzg53Y%Q1Um{p2og?l~#?*N{uR`;^jpD)c|Pl^)KL>QGYZp|4+_VBgxA zR;N6vbDG(d$;wzAPzQ3rPMuWCz9uD(=8sZGw7A-=c?yCyt1`80P&Qy&GAm)B!T~Au z!^tx>mWVM=@p5pGk=rkRaI27rl)mA?OlA{-jzbB1!`4c5vM@V6+84&c&s$pCqLj?e z&YI|#sn5e6%g&>z*{jRW!QhjcQ_soHots(9z{1X(n;NZ+)k&2gCwU5_TJ{}M;_&@! zc0}vY3MF&bv(s7{9o#iEeAKQK6lOU@wJz`cxl2%ir{%q>!&(*r*77w`nhF9f1v$(b zT>b5hSJw7%a1?$m)e;tCXAe?KW)t9KPhjWQ)YRZ%XJ#+1kN29u(qR`L!^f`9=bmfM z(W8RhHQ)>lb`6u3PPc-_5v_e1f1FICg$yMaHz_QQ+H~17F+-8fefp}@3W=&sZ@dgT zQumu3IOGsk6S|s}<)g{2Z7#W+T2)o}&dz>aAi=}M8N<%%&cIy3$;n&G;GoS?!@|SE z#LsT4&BbmwS(no_(Ud7i6T4f$A)`6x$%=XEj&r^DNA_A;o zoC2!6nau3W{QO)6(LqWzoJ>7T9DEa%xn?qP@|&?{MwKU*YvGP3uxoU@r)d4$c7&;W zg~5F8#97wYyDw~DjI?M>N-%kuw?vNn&Io-BSnqfQq-6^3dy>fzIEAIZ*)hPOKw7|=jaSu$fj59nfQ3KM#EgfPsf&p> zGdYt%0UQiZs^Cculb2;b?dM@I*_ntG&%> zi_T1`zSdW25;k0|jXhg#OA2Ld%dEW|=r$owqPsh06it8f#ER1jYawj~vAS literal 0 HcmV?d00001 diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/list-add.png b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/list-add.png new file mode 100644 index 0000000000000000000000000000000000000000..bbe0cb78834bec6dd23288d1a975efd767ceb0b9 GIT binary patch literal 676 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4rT@h2A3sW#~2tGn2Vh}LpV4%Za?&Yz`(%h z7~m7)%0L{@&RWI5z+jvPB6Xvt>1HlfaLAG}jgT@9wa8d*p1#y9eW`WUaU%cRa&C=@)D{eHcywS4yX2-f49qVp&uDj8>{zm8eo89Yg^=!D+v+-u% z#+!YcZuM`vHDU9u30rPW1fkoLw%(q+?aq{Kx2JBuGj02w={xRB-*I==uDf$~-<`Aj z{+vB`=j^#RXV3k4d+yEKbAR66d-M0+o4@bg{C)Qq9eA+h(8J}2AFe$5XwC7*YmYzP zeER8@Gtai3eYWG=^PT5k?7r|~-=&uauDm*Q_0{2PuMb~;b@ck{qc`3hyZPq$%{OIj z4^A^MFvyk!`2{mDGBLBTvaxe;a&hzU@bU`?3QEYzDSZF&TqdnVc|99O<%D1@wym>bq{Q9jhKg zgXWTy5{8CM{sXyJ%O~aM+^Bou{bB9lV`5u%T(_N<=6@Yt5x(hZX7;C5a&|u_rF?Yb z{SYxdd-nO?$JYEj!{2>o;|7In>puaS4l_OOvAejibh*lSOp;b`KWDkXSnN!Q%PM{e zgFAa`x)@i!RM6fL>&iRjzG^~I`PswCzx?gav70rvJ{LEeycU$aJYD@<);T3K0RXC! BK9>Lh literal 0 HcmV?d00001 diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/trimage-icon.png b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/trimage-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..984a01eb2fca7f31f10294f2665ef121641fc750 GIT binary patch literal 4542 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 A+W-In literal 0 HcmV?d00001 diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/view-refresh.png b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/pixmaps/view-refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..1861df63d8f4c65a5dbbe2d030c8fa154a3406b7 GIT binary patch literal 1997 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 sys.stderr, u"[error] %s not a supported image file and/or not writeable" % image.fullpath + + """ + UI Functions + """ + + def update_table(self): + """Update the table view with the latest file data.""" + tview = self.ui.processedfiles + # set table model + tmodel = TriTableModel(self, self.imagelist, + ["Filename", "Old Size", "New Size", "Compressed"]) + tview.setModel(tmodel) + + # set minimum size of table + vh = tview.verticalHeader() + vh.setVisible(False) + + # set horizontal header properties + hh = tview.horizontalHeader() + hh.setStretchLastSection(True) + + # set all row heights + nrows = len(self.imagelist) + for row in range(nrows): + tview.setRowHeight(row, 25) + + # set the second column to be longest + tview.setColumnWidth(0, 300) + + # enable recompress button + self.enable_recompress() + + """ + Helper functions + """ + + def enable_recompress(self): + """Enable the recompress button.""" + self.ui.recompress.setEnabled(True) + if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: + self.systemtray.recompress.setEnabled(True) + + def checkapps(self): + """Check if the required command line apps exist.""" + exe = ".exe" if (sys.platform == "win32") else "" + status = False + + # guetzli does the compression job much better than jpegoptim (and much slower) + #retcode = self.safe_call("jpegoptim" + exe + " --version") + #if retcode != 0: + #status = True + #sys.stderr.write("[error] please install jpegoptim") + + retcode = self.safe_call("optipng" + exe + " -v") + if retcode != 0: + status = True + sys.stderr.write("[error] please install optipng") + + retcode = self.safe_call("advpng" + exe + " --version") + if retcode != 0: + status = True + sys.stderr.write("[error] please install advancecomp") + + retcode = self.safe_call("pngcrush" + exe + " -version") + if retcode != 0: + status = True + sys.stderr.write("[error] please install pngcrush") + return status + + # guetzli currently does not have neither --version not --help flags + retcode = self.safe_call("guetzli" + exe) + if retcode != 0: + status = True + sys.stderr.write("[error] please install guetzli") + return status + + def safe_call(self, command): + """ cross-platform command-line check """ + while True: + try: + return call(command, shell=True, stdout=PIPE) + except OSError, e: + if e.errno == errno.EINTR: + continue + else: + raise + + def hide_main_window(self): + if self.isVisible(): + self.hide() + if QSystemTrayIcon.isSystemTrayAvailable(): + self.systemtray.hideMain.setText("&Show window") + else: + self.show() + if QSystemTrayIcon.isSystemTrayAvailable(): + self.systemtray.hideMain.setText("&Hide window") + + def closeEvent(self, event): + self.settings.setValue("geometry", QVariant(self.saveGeometry())) + event.accept() + + +class TriTableModel(QAbstractTableModel): + + def __init__(self, parent, imagelist, header, *args): + """ + @param parent Qt parent object. + @param imagelist A list of tuples. + @param header A list of strings. + """ + QAbstractTableModel.__init__(self, parent, *args) + self.imagelist = imagelist + self.header = header + + def rowCount(self, parent): + """Count the number of rows.""" + return len(self.imagelist) + + def columnCount(self, parent): + """Count the number of columns.""" + return len(self.header) + + def data(self, index, role): + """Fill the table with data.""" + if not index.isValid(): + return QVariant() + elif role == Qt.DisplayRole: + data = self.imagelist[index.row()][index.column()] + return QVariant(data) + elif index.column() == 0 and role == Qt.DecorationRole: + # decorate column 0 with an icon of the image itself + f_icon = self.imagelist[index.row()][4] + return QVariant(f_icon) + else: + return QVariant() + + def headerData(self, col, orientation, role): + """Fill the table headers.""" + if orientation == Qt.Horizontal and (role == Qt.DisplayRole or + role == Qt.DecorationRole): + return QVariant(self.header[col]) + return QVariant() + + +class ImageRow: + + def __init__(self, image, waitingIcon=None): + """ Build the information visible in the table image row. """ + self.image = image + d = { + 'shortname': lambda i: self.statusStr() % i.shortname, + 'oldfilesizestr': lambda i: size(i.oldfilesize, system=alternative) + if i.compressed else "", + 'newfilesizestr': lambda i: size(i.newfilesize, system=alternative) + if i.compressed else "", + 'ratiostr': lambda i: + "%.1f%%" % (100 - (float(i.newfilesize) / i.oldfilesize * 100)) + if i.compressed else "", + 'icon': lambda i: i.icon if i.compressed else waitingIcon, + 'fullpath': lambda i: i.fullpath, #only used by cli + } + names = ['shortname', 'oldfilesizestr', 'newfilesizestr', + 'ratiostr', 'icon'] + for i, n in enumerate(names): + d[i] = d[n] + + self.d = d + + def statusStr(self): + """ Set the status message. """ + if self.image.failed: + return "ERROR: %s" + if self.image.compressing: + message = "Compressing %s..." + return message + if not self.image.compressed and self.image.recompression: + return "Queued for recompression..." + if not self.image.compressed: + return "Queued..." + return "%s" + + def __getitem__(self, key): + return self.d[key](self.image) + + +class Image: + + def __init__(self, fullpath): + """ gather image information. """ + self.valid = False + self.reset() + self.fullpath = fullpath + if path.isfile(self.fullpath) and access(self.fullpath, WRITEABLE): + self.filetype = determinetype(self.fullpath) + if self.filetype in ["jpeg", "png"]: + oldfile = QFileInfo(self.fullpath) + self.shortname = oldfile.fileName() + self.oldfilesize = oldfile.size() + self.icon = QIcon(self.fullpath) + self.valid = True + + #def _determinetype(self): + # """ Determine the filetype of the file using imghdr. """ + # filetype = determinetype(self.fullpath) + # if filetype in ["jpeg", "png"]: + # self.filetype = filetype + # else: + # self.filetype = None + # return self.filetype + + def reset(self): + self.failed = False + self.compressed = False + self.compressing = False + self.recompression = False + + def compress(self): + """ Compress the image and return it to the thread. """ + if not self.valid: + raise "Tried to compress invalid image (unsupported format or not \ + file)" + self.reset() + self.compressing = True + exe = ".exe" if (sys.platform == "win32") else "" + runString = { + # "jpeg": u"jpegoptim" + exe + " -f --strip-all '%(file)s'", + # I commented out jpegoptim because guetzli compresses MUCH BETTER having a similar output quality + # the default quality level for guetzli, if the parameter '--quality Q' is not passed, it 95. + "jpeg": u"guetzli" + exe + " --quality 95 '%(file)s' '%(file)s.bak' && mv '%(file)s.bak' '%(file)s'", + "png": u"optipng" + exe + " -force -o7 '%(file)s'&&advpng" + exe + " -z4 '%(file)s' && pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time '%(file)s' '%(file)s.bak' && mv '%(file)s.bak' '%(file)s'" + } + # Create a backup file + copy(self.fullpath, self.fullpath + '~') + try: + retcode = call(runString[self.filetype] % {"file": self.fullpath}, + shell=True, stdout=PIPE) + except: + retcode = -1 + if retcode == 0: + self.newfilesize = QFile(self.fullpath).size() + self.compressed = True + + # Checks the new file and copy the backup + if self.newfilesize >= self.oldfilesize: + copy(self.fullpath + '~', self.fullpath) + self.newfilesize = self.oldfilesize + + # Removes the backup file + remove(self.fullpath + '~') + else: + self.failed = True + self.compressing = False + self.retcode = retcode + return self + + +class Worker(QThread): + + def __init__(self, parent=None): + QThread.__init__(self, parent) + self.toDisplay = Queue() + self.threadpool = ThreadPool(max_workers=cpu_count()) + + def __del__(self): + self.threadpool.shutdown() + + def compress_file(self, images, showapp, verbose, imagelist): + """Start the worker thread.""" + for image in images: + #FIXME:http://code.google.com/p/pythonthreadpool/issues/detail?id=5 + time.sleep(0.05) + self.threadpool.add_job(image.compress, None, + return_callback=self.toDisplay.put) + self.showapp = showapp + self.verbose = verbose + self.imagelist = imagelist + self.start() + + def run(self): + """Compress the given file, get data from it and call update_table.""" + tp = self.threadpool + while self.showapp or not (tp._ThreadPool__active_worker_count == 0 and + tp._ThreadPool__jobs.empty()): + image = self.toDisplay.get() + + self.emit(SIGNAL("updateUi")) + + if not self.showapp and self.verbose: # we work via the commandline + if image.retcode == 0: + ir = ImageRow(image) + print("File: " + ir['fullpath'] + ", Old Size: " + + ir['oldfilesizestr'] + ", New Size: " + + ir['newfilesizestr'] + ", Ratio: " + ir['ratiostr']) + else: + print >> sys.stderr, u"[error] %s could not be compressed" % image.fullpath + + +class Systray(QWidget): + + def __init__(self, parent): + QWidget.__init__(self) + self.parent = parent + self.createActions() + self.createTrayIcon() + self.trayIcon.show() + + def createActions(self): + self.quitAction = QAction(self.tr("&Quit"), self) + QObject.connect(self.quitAction, SIGNAL("triggered()"), + qApp, SLOT("quit()")) + + self.addFiles = QAction(self.tr("&Add and compress"), self) + icon = QIcon() + icon.addPixmap(QPixmap(self.parent.ui.get_image(("pixmaps/list-add.png"))), + QIcon.Normal, QIcon.Off) + self.addFiles.setIcon(icon) + QObject.connect(self.addFiles, SIGNAL("triggered()"), self.parent.file_dialog) + + self.recompress = QAction(self.tr("&Recompress"), self) + icon2 = QIcon() + icon2.addPixmap(QPixmap(self.parent.ui.get_image(("pixmaps/view-refresh.png"))), + QIcon.Normal, QIcon.Off) + self.recompress.setIcon(icon2) + self.recompress.setDisabled(True) + QObject.connect(self.addFiles, SIGNAL("triggered()"), self.parent.recompress_files) + + self.hideMain = QAction(self.tr("&Hide window"), self) + QObject.connect(self.hideMain, SIGNAL("triggered()"), self.parent.hide_main_window) + + def createTrayIcon(self): + self.trayIconMenu = QMenu(self) + self.trayIconMenu.addAction(self.addFiles) + self.trayIconMenu.addAction(self.recompress) + self.trayIconMenu.addSeparator() + self.trayIconMenu.addAction(self.hideMain) + self.trayIconMenu.addSeparator() + self.trayIconMenu.addAction(self.quitAction) + + if QSystemTrayIcon.isSystemTrayAvailable(): + self.trayIcon = QSystemTrayIcon(self) + self.trayIcon.setContextMenu(self.trayIconMenu) + self.trayIcon.setToolTip("Trimage image compressor") + self.trayIcon.setIcon(QIcon(self.parent.ui.get_image("pixmaps/trimage-icon.png"))) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + myapp = StartQT4() + + if myapp.showapp: + myapp.show() + sys.exit(app.exec_()) diff --git a/debian/trimage/usr/lib/python2.7/dist-packages/trimage/ui.py b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/ui.py new file mode 100644 index 0000000..47937da --- /dev/null +++ b/debian/trimage/usr/lib/python2.7/dist-packages/trimage/ui.py @@ -0,0 +1,166 @@ +from PyQt4.QtCore import * +from PyQt4.QtGui import * +from os import path + +class TrimageTableView(QTableView): + """Init the table drop event.""" + def __init__(self, parent=None): + super(TrimageTableView, self).__init__(parent) + self.setAcceptDrops(True) + + def dragEnterEvent(self, event): + if event.mimeData().hasUrls: + event.accept() + else: + event.ignore() + + def dragMoveEvent(self, event): + event.accept() + + def dropEvent(self, event): + event.accept() + filelist = [] + for url in event.mimeData().urls(): + filelist.append(unicode(url.toLocalFile())) + + self.emit(SIGNAL("fileDropEvent"), (filelist)) + + +class Ui_trimage(object): + def get_image(self, image): + """ Get the correct link to the images used in the UI """ + imagelink = path.join(path.dirname(path.dirname(path.realpath(__file__))), "trimage/" + image) + return imagelink + + def setupUi(self, trimage): + """ Setup the entire UI """ + trimage.setObjectName("trimage") + trimage.resize(600, 170) + + trimageIcon = QIcon(self.get_image("pixmaps/trimage-icon.png")) + trimage.setWindowIcon(trimageIcon) + + self.centralwidget = QWidget(trimage) + self.centralwidget.setObjectName("centralwidget") + + self.gridLayout_2 = QGridLayout(self.centralwidget) + self.gridLayout_2.setMargin(0) + self.gridLayout_2.setSpacing(0) + self.gridLayout_2.setObjectName("gridLayout_2") + + self.widget = QWidget(self.centralwidget) + self.widget.setEnabled(True) + sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth( + self.widget.sizePolicy().hasHeightForWidth()) + self.widget.setSizePolicy(sizePolicy) + self.widget.setObjectName("widget") + + self.verticalLayout = QVBoxLayout(self.widget) + self.verticalLayout.setSpacing(0) + self.verticalLayout.setMargin(0) + self.verticalLayout.setObjectName("verticalLayout") + + self.frame = QFrame(self.widget) + self.frame.setObjectName("frame") + + self.verticalLayout_2 = QVBoxLayout(self.frame) + self.verticalLayout_2.setSpacing(0) + self.verticalLayout_2.setMargin(0) + self.verticalLayout_2.setObjectName("verticalLayout_2") + + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setMargin(10) + self.horizontalLayout.setObjectName("horizontalLayout") + + self.addfiles = QPushButton(self.frame) + font = QFont() + font.setPointSize(9) + self.addfiles.setFont(font) + self.addfiles.setCursor(Qt.PointingHandCursor) + icon = QIcon() + icon.addPixmap(QPixmap(self.get_image("pixmaps/list-add.png")), QIcon.Normal, QIcon.Off) + self.addfiles.setIcon(icon) + self.addfiles.setObjectName("addfiles") + self.addfiles.setAcceptDrops(True) + self.horizontalLayout.addWidget(self.addfiles) + + self.label = QLabel(self.frame) + font = QFont() + font.setPointSize(8) + self.label.setFont(font) + self.label.setFrameShadow(QFrame.Plain) + self.label.setMargin(1) + self.label.setIndent(10) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + + spacerItem = QSpacerItem(498, 20, QSizePolicy.Expanding, + QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.recompress = QPushButton(self.frame) + font = QFont() + font.setPointSize(9) + self.recompress.setFont(font) + self.recompress.setCursor(Qt.PointingHandCursor) + + icon1 = QIcon() + icon1.addPixmap(QPixmap(self.get_image("pixmaps/view-refresh.png")), QIcon.Normal, QIcon.Off) + + self.recompress.setIcon(icon1) + self.recompress.setCheckable(False) + self.recompress.setObjectName("recompress") + self.horizontalLayout.addWidget(self.recompress) + self.verticalLayout_2.addLayout(self.horizontalLayout) + + self.processedfiles = TrimageTableView(self.frame) + self.processedfiles.setEnabled(True) + self.processedfiles.setFrameShape(QFrame.NoFrame) + self.processedfiles.setFrameShadow(QFrame.Plain) + self.processedfiles.setLineWidth(0) + self.processedfiles.setMidLineWidth(0) + self.processedfiles.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + self.processedfiles.setTabKeyNavigation(True) + self.processedfiles.setAlternatingRowColors(True) + self.processedfiles.setTextElideMode(Qt.ElideRight) + self.processedfiles.setShowGrid(True) + self.processedfiles.setGridStyle(Qt.NoPen) + self.processedfiles.setSortingEnabled(False) + self.processedfiles.setObjectName("processedfiles") + self.processedfiles.resizeColumnsToContents() + self.processedfiles.setSelectionMode(QAbstractItemView.NoSelection) + self.verticalLayout_2.addWidget(self.processedfiles) + self.verticalLayout.addWidget(self.frame) + self.gridLayout_2.addWidget(self.widget, 0, 0, 1, 1) + trimage.setCentralWidget(self.centralwidget) + + self.retranslateUi(trimage) + QMetaObject.connectSlotsByName(trimage) + + def retranslateUi(self, trimage): + """ Fill in the texts for all UI elements """ + trimage.setWindowTitle(QApplication.translate("trimage", + "Trimage image compressor", None, QApplication.UnicodeUTF8)) + self.addfiles.setToolTip(QApplication.translate("trimage", + "Add file to the compression list", None, + QApplication.UnicodeUTF8)) + self.addfiles.setText(QApplication.translate("trimage", + "&Add and compress", None, QApplication.UnicodeUTF8)) + self.addfiles.setShortcut(QApplication.translate("trimage", + "Alt+A", None, QApplication.UnicodeUTF8)) + self.label.setText(QApplication.translate("trimage", + "Drag and drop images onto the table", None, + QApplication.UnicodeUTF8)) + self.recompress.setToolTip(QApplication.translate("trimage", + "Recompress all images", None, QApplication.UnicodeUTF8)) + self.recompress.setText(QApplication.translate("trimage", + "&Recompress", None, QApplication.UnicodeUTF8)) + self.recompress.setShortcut(QApplication.translate("trimage", + "Alt+R", None, QApplication.UnicodeUTF8)) + self.processedfiles.setToolTip(QApplication.translate("trimage", + "Drag files in here", None, QApplication.UnicodeUTF8)) + self.processedfiles.setWhatsThis(QApplication.translate("trimage", + "Drag files in here", None, QApplication.UnicodeUTF8)) diff --git a/debian/trimage/usr/share/applications/trimage.desktop b/debian/trimage/usr/share/applications/trimage.desktop new file mode 100644 index 0000000..6cd6632 --- /dev/null +++ b/debian/trimage/usr/share/applications/trimage.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Name=Trimage image compressor +Name[ru]=Программа для уменьшения веса картинок Trimage +Comment=A cross-platform tool for optimizing PNG and JPG files +Comment[ru]=Кросс-платформенная утилита для оптимизации файлов PNG и JPG +Terminal=false +Icon=trimage +Type=Application +Exec=trimage +Categories=Application;Qt;Graphics; +StartupNotify=true + diff --git a/debian/trimage/usr/share/doc/trimage/README b/debian/trimage/usr/share/doc/trimage/README new file mode 100644 index 0000000..698ce38 --- /dev/null +++ b/debian/trimage/usr/share/doc/trimage/README @@ -0,0 +1,15 @@ +Trimage image compressor +A cross-platform tool for optimizing PNG and JPG files. + +Trimage is a cross-platform GUI and command-line interface to optimize image +files via "optipng":http://optipng.sourceforge.net/, +"advpng":http://advancemame.sourceforge.net/comp-readme.html and +"guetzli":https://github.com/google/guetzli, depending on the +filetype (currently, PNG and JPG files are supported). It was inspired by +"imageoptim":http://imageoptim.pornel.net/. All image files are losslessly +compressed on the highest available compression levels. Trimage gives you +various input functions to fit your own workflow: A regular file dialog, +dragging and dropping and various command line options. + +Visit "Trimage.org":http://trimage.org for more information + diff --git a/debian/trimage/usr/share/doc/trimage/changelog.gz b/debian/trimage/usr/share/doc/trimage/changelog.gz new file mode 100644 index 0000000000000000000000000000000000000000..565736f6e5e92155e60a439c277e746615ea4307 GIT binary patch literal 988 zcmb2|=3oE;Cg!)(0`qU12^_!wS@T`)+pyh}<}T^H&U=%M=f$=)2ZVU4moA-rWY(ih z_e<-3y)0K*d*k+{Ly{M^Gq&XfFRA!{|L$MS^Si=z4{a`rvuppJvDGNv`GHujY2D@I zwa)crY#&rZ=58|jc(*~9H}3lb&RY%tnlHZmS6<4ypY{2cO%Ea?)2CcdaXh|1b8=;G z-s8*(&(Ee6tTvx}iLGv_?#_ukxerU{AJ@sve|16Id9B>lIfu71lpoyJ@JOnTi%rb+ zC)cT`t9C?)vety^bU)%b_s7x8aQ_U^MA&iP>cZG*CI)#It2|!InE2SP z*|;d~wph=kmprRJ7Cp7ly6h@<(|=7bclnyV?%ccm^rqEFIcznXA*QAL+xhIO+{Zat z4swen7f$nj+G)CL4|9?89qs6a4r?T)c1sIBzi^E_KO(*NPxJN_Gj`SaGialfYTkoCmz=AwwX@oP?< zcAu*2A9(G>_fFeeYtuIET~V^(^1j6iMTZRps@Hr!l+4^?dHa&6D6jJCZIhEW@-AJz zq~#^Qh5V;223Jlg=ZI!=IWb=k%yQj!G55h0kN=AMPjR=lZt1!E++3}E>z;}!haQP= z`Q-+N+>Y|v;ri;L_pB*vCogE{l5_1}veoE`%Jbl;z1J^!3I^zKGfG^VYuy-8deQe) z;^lKPtkas}&vmEQv*rFN_V9f$f6c#r+({CrmA@uQJk5%s5=%LoCPoR(w<(gG`Pll+=Ff7x z-#*DU_i4wvTTkD%an<>|n=hAs(dlbx?cXwYdeJR?uj&)Q2j$OroCh8 zc2#fjTqMu_GJDFw7boki{w6s!O)bb4*{aha)A9MUM!VeO=EQZ*+?g!zz8`#}AyMcO zw(fNL!Gp$GvA6a2NaV;iYEBU6xSkpleMxY};cbDFw$^On>k7`>Aphsb`pd<3^_uf@ zmgs-p-Mz=JMsJ7uOm|nASLADho3R~t+@Ubg~ps_ z{4w!?e`oEf_kaBf literal 0 HcmV?d00001 diff --git a/debian/trimage/usr/share/doc/trimage/copyright b/debian/trimage/usr/share/doc/trimage/copyright new file mode 100644 index 0000000..2a6f587 --- /dev/null +++ b/debian/trimage/usr/share/doc/trimage/copyright @@ -0,0 +1,256 @@ +This package was debianized by: + + Kilian Valkhof on Tue, 23 Mar 2010 20:18:17 +0100 + +Upstream Author: + + Kilian Valkhof + +Copyright: + + Copyright (C) 2010 Kilian Valkhof, Paul Chaplin + +License: + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + +The Debian packaging is: + + Copyright (C) 2010 Kilian Valkhof, Paul Chaplin + +and is licensed under the MIT license, see above. + +hurry.filesize is: + + Copyright (C) Martijn Faassen, Startifact + +License: + + Zope Public License (ZPL) Version 2.1 + A copyright notice accompanies this license document that identifies the + copyright holders. This license has been certified as open source. It has + also been designated as GPL compatible by the Free Software Foundation (FSF). + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission from + the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of the + copyright holders. Use of them is covered by separate agreement with the + copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of any + change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ThreadPool is: + + Copyright (c) Morten Holdflod Moeller + +License: + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates + the terms and conditions of version 3 of the GNU General Public + License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser + General Public License, and the "GNU GPL" refers to version 3 of the GNU + General Public License. + + "The Library" refers to a covered work governed by this License, + other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided + by the Library, but which is not otherwise based on the Library. + Defining a subclass of a class defined by the Library is deemed a mode + of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an + Application with the Library. The particular version of the Library + with which the Combined Work was made is also called the "Linked + Version". + + The "Minimal Corresponding Source" for a Combined Work means the + Corresponding Source for the Combined Work, excluding any source code + for portions of the Combined Work that, considered in isolation, are + based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the + object code and/or source code for the Application, including any data + and utility programs needed for reproducing the Combined Work from the + Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License + without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a + facility refers to a function or data to be supplied by an Application + that uses the facility (other than as an argument passed when the + facility is invoked), then you may convey a copy of the modified + version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from + a header file that is part of the Library. You may convey such object + code under terms of your choice, provided that, if the incorporated + material is not limited to numerical parameters, data structure + layouts and accessors, or small macros, inline functions and templates + (ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, + taken together, effectively do not restrict modification of the + portions of the Library contained in the Combined Work and reverse + engineering for debugging such modifications, if you also do each of + the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the + Library side by side in a single library together with other library + facilities that are not Applications and are not covered by this + License, and convey such a combined library under terms of your + choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions + of the GNU Lesser General Public License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the + Library as you received it specifies that a certain numbered version + of the GNU Lesser General Public License "or any later version" + applies to it, you have the option of following the terms and + conditions either of that published version or of any later version + published by the Free Software Foundation. If the Library as you + received it does not specify a version number of the GNU Lesser + General Public License, you may choose any version of the GNU Lesser + General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide + whether future versions of the GNU Lesser General Public License shall + apply, that proxy's public statement of acceptance of any version is + permanent authorization for you to choose that version for the + Library. + diff --git a/debian/trimage/usr/share/icons/hicolor/scalable/apps/trimage.svg b/debian/trimage/usr/share/icons/hicolor/scalable/apps/trimage.svg new file mode 100644 index 0000000..bbdf85a --- /dev/null +++ b/debian/trimage/usr/share/icons/hicolor/scalable/apps/trimage.svg @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/debian/trimage/usr/share/man/man1/trimage.1.gz b/debian/trimage/usr/share/man/man1/trimage.1.gz new file mode 100644 index 0000000000000000000000000000000000000000..86e87aef77653b6827fab8cbb585b501db285512 GIT binary patch literal 522 zcmb2|=3oE;Cg#*&@BY~a0{cE|yUh{Oj93_Y)jQgB{ax3)zLzGf4VfzEVemk=ZcT1b zYJKf-KF^LS1B3bdkDrk95If|vYH?aO6ka+sP%OCvvcR zk*Em|r+VqH;+;{;J*6gSmZ&k_RQYhad#S;P-!60XFWpp&%%6PKXvgKC8#;?#q^rJB z4VPlhH{LU~k@@sq;di|X`h5R-`}gMg%FemDFR+L!>L*W5#%{h%MYCL8!_+GN%zC%> z%JDUKdJa6^ahcg(d38Md=5@L`i(a>OuIAnOYx=qUN0bFEm)BOem!8}E_J2=xSZRFR zWjD*ZsMGr&a6MSDOLWgS*7drJuW9bv&HrH2i(vj*t#cRsr0$>Vzr1|;;ROp)@0pd| z5U$!bdzZJd*J-cke~fw;J+)r7`!oOLqfBc3FS*)_cfEYa!}hV@$?Malv5Gp2rTduU hLijD>fABV$D@w1-H~8MK+0OExA+P8O_i1JZ1^`U$_vQcq literal 0 HcmV?d00001