Gilles has uploaded a new change for review. https://gerrit.wikimedia.org/r/253666
Change subject: Initial commit ...................................................................... Initial commit This thumbor optimizer provides the ability to filter exif fields, only to leave the ones defined in the thumbor config. It also provides the ability to swap an ICC profile for another (which we'll use to swap sRGB for TinyRGB). It relies on exiftool. Bug: T111722 Bug: T118480 Change-Id: Icd25678ea1e294b4f7ed9e519b6508832f5b3fd0 --- A LICENSE A requirements.txt A setup.py A tox.ini A wikimedia_thumbor_exif_optimizer/__init__.py 5 files changed, 153 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/thumbor/exif-optimizer refs/changes/66/253666/1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..133846d --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Gilles Dubuc, Wikimedia Foundation + +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. + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ef29d7d --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +thumbor diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..adfac16 --- /dev/null +++ b/setup.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +from setuptools import setup, find_packages + + +setup( + name='wikimedia_thumbor_exif_optimizer', + version='0.1.1', + url='https://github.com/wikimedia/thumbor-exif-optimizer', + license='MIT', + author='Gilles Dubuc, Wikimedia Foundation', + description='Thumbor optimizer processing EXIF', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + platforms='any', + install_requires=[ + 'thumbor', + ], + extras_require={ + 'tests': [ + 'pyvows', + 'coverage', + ], + }, + classifiers=[ + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..9e359d2 --- /dev/null +++ b/tox.ini @@ -0,0 +1,12 @@ +[tox] +minversion = 1.6 +skipsdist = True +envlist = flake8 + +[testenv] +setenv = VIRTUAL_ENV={envdir} +deps = -r{toxinidir}/requirements.txt + +[testenv:flake8] +commands = flake8 {posargs} +deps = flake8 diff --git a/wikimedia_thumbor_exif_optimizer/__init__.py b/wikimedia_thumbor_exif_optimizer/__init__.py new file mode 100644 index 0000000..46a5725 --- /dev/null +++ b/wikimedia_thumbor_exif_optimizer/__init__.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# thumbor imaging service +# https://github.com/thumbor/thumbor/wiki + +# Licensed under the MIT license: +# http://www.opensource.org/licenses/mit-license +# Copyright (c) 2011 globo.com [email protected] +# Copyright (c) 2015 Wikimedia Foundation + +# EXIF optimizer, aims to reduce thumbnail weight as much as possible +# while retaining some critical metadata + +import os +import subprocess + +from thumbor.optimizers import BaseOptimizer +from thumbor.utils import logger + + +class Optimizer(BaseOptimizer): + def __init__(self, context): + super(Optimizer, self).__init__(context) + + self.runnable = True + self.exiftool_path = self.context.config.EXIFTOOL_PATH + self.exif_fields_to_keep = self.context.config.EXIF_FIELDS_TO_KEEP + self.tinyrgb_path = self.context.config.EXIF_TINYRGB_PATH + self.tinyrgb_icc_replace = self.context.config.EXIF_TINYRGB_ICC_REPLACE + + if not (os.path.isfile(self.exiftool_path) + and os.access(self.exiftool_path, os.X_OK)): + logger.error( + "ERROR exiftool path '{0}' is not accessible" + .format(self.exiftool_path) + ) + self.runnable = False + + if not (os.path.isfile(self.tinyrgb_path) + and os.access(self.tinyrgb_path, os.R_OK)): + logger.error( + "ERROR tinyrgb path '{0}' is not accessible" + .format(self.tinyrgb_path) + ) + self.tinyrgb_path = False + + def should_run(self, image_extension, buffer): + good_extension = 'jpg' in image_extension or 'jpeg' in image_extension + return good_extension and self.runnable + + def optimize(self, buffer, input_file, output_file): + exif_fields = ' -' + ' -'.join(self.exif_fields_to_keep) + + # TinyRGB is a lightweight sRGB swap-in replacement created by Facebook + # If the image is sRGB, swap the existing heavy profile for TinyRGB + # Only works if icc_profile is configured to be preserved in + # EXIF_FIELDS_TO_KEEP + if (self.tinyrgb_path): + command = '%s -DeviceModelDesc -S -T %s' % ( + self.exiftool_path, + input_file, + ) + + logger.debug("[EXIFTOOL] running: " + command) + output = subprocess.check_output(command, shell=True) + + if (output.rstrip().lower() == self.tinyrgb_icc_replace.lower()): + new_icc = '"-icc_profile<=%s"' % ( + self.tinyrgb_path + ) + exif_fields = exif_fields.replace('-icc_profile', new_icc) + + # Strip all EXIF fields except the ones we want to + # explicitely copy over + command = '%s %s -all= -tagsFromFile @ %s -m -o - > %s ' % ( + self.exiftool_path, + input_file, + exif_fields, + output_file, + ) + with open(os.devnull) as null: + logger.debug("[EXIFTOOL] running: " + command) + subprocess.call(command, shell=True, stdin=null) -- To view, visit https://gerrit.wikimedia.org/r/253666 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Icd25678ea1e294b4f7ed9e519b6508832f5b3fd0 Gerrit-PatchSet: 1 Gerrit-Project: thumbor/exif-optimizer Gerrit-Branch: master Gerrit-Owner: Gilles <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
