From ffbf9c8b438ef8d203da54807b6ff5db3cc4d334 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Odin=20H=C3=B8rthe=20Omdal?= Date: Mon, 12 May 2014 23:41:03 +0200 Subject: [PATCH] Implement Raw Image media type plugin --- docs/source/siteadmin/media-types.rst | 28 ++++++- mediagoblin/media_types/image/__init__.py | 2 - mediagoblin/media_types/raw_image/__init__.py | 37 +++++++++ mediagoblin/media_types/raw_image/models.py | 21 +++++ .../media_types/raw_image/processing.py | 82 +++++++++++++++++++ 5 files changed, 165 insertions(+), 5 deletions(-) create mode 100644 mediagoblin/media_types/raw_image/__init__.py create mode 100644 mediagoblin/media_types/raw_image/models.py create mode 100644 mediagoblin/media_types/raw_image/processing.py diff --git a/docs/source/siteadmin/media-types.rst b/docs/source/siteadmin/media-types.rst index 3e8a94e9..44ad02bb 100644 --- a/docs/source/siteadmin/media-types.rst +++ b/docs/source/siteadmin/media-types.rst @@ -1,6 +1,6 @@ .. MediaGoblin Documentation - Written in 2011, 2012 by MediaGoblin contributors + Written in 2011, 2012, 2014 by MediaGoblin contributors To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to @@ -18,8 +18,8 @@ Media Types ==================== In the future, there will be all sorts of media types you can enable, -but in the meanwhile there are five additional media types: video, audio, -ascii art, STL/3d models, PDF and Document. +but in the meanwhile there are six additional media types: video, audio, +raw image, ascii art, STL/3d models, PDF and Document. First, you should probably read ":doc:`configuration`" to make sure you know how to modify the mediagoblin config file. @@ -149,6 +149,28 @@ Run You should now be able to upload and listen to audio files! +Raw image +========= + +To enable raw image you need to install pyexiv2. On Debianoid systems + +.. code-block:: bash + + sudo apt-get install python-pyexiv2 + +Add ``[[mediagoblin.media_types.raw_image]]`` under the ``[plugins]`` +section in your ``mediagoblin_local.ini`` and restart MediaGoblin. + +Run + +.. code-block:: bash + + ./bin/gmg dbupdate + +Now you should be able to submit raw images, and mediagoblin should +extract the JPEG preview from them. + + Ascii art ========= diff --git a/mediagoblin/media_types/image/__init__.py b/mediagoblin/media_types/image/__init__.py index f5b49f01..06e0f08f 100644 --- a/mediagoblin/media_types/image/__init__.py +++ b/mediagoblin/media_types/image/__init__.py @@ -27,8 +27,6 @@ _log = logging.getLogger(__name__) ACCEPTED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "tiff"] MEDIA_TYPE = 'mediagoblin.media_types.image' -def setup_plugin(): - config = pluginapi.get_config(MEDIA_TYPE) class ImageMediaManager(MediaManagerBase): human_readable = "Image" diff --git a/mediagoblin/media_types/raw_image/__init__.py b/mediagoblin/media_types/raw_image/__init__.py new file mode 100644 index 00000000..046a9b2a --- /dev/null +++ b/mediagoblin/media_types/raw_image/__init__.py @@ -0,0 +1,37 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2014 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from mediagoblin.media_types.image import ImageMediaManager +from mediagoblin.media_types.raw_image.processing import ( + ACCEPTED_EXTENSIONS, MEDIA_TYPE, + RawImageProcessingManager, sniff_handler) + + +class RawImageMediaManager(ImageMediaManager): + human_readable = "Raw image" + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, RawImageMediaManager + + +hooks = { + 'get_media_type_and_manager': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + ('media_manager', MEDIA_TYPE): lambda: RawImageMediaManager, + ('reprocess_manager', MEDIA_TYPE): lambda: RawImageProcessingManager, +} diff --git a/mediagoblin/media_types/raw_image/models.py b/mediagoblin/media_types/raw_image/models.py new file mode 100644 index 00000000..d3d68b93 --- /dev/null +++ b/mediagoblin/media_types/raw_image/models.py @@ -0,0 +1,21 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2014 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from mediagoblin.media_types.image.models import ( + BACKREF_NAME, DATA_MODEL) + + +MODELS = None diff --git a/mediagoblin/media_types/raw_image/processing.py b/mediagoblin/media_types/raw_image/processing.py new file mode 100644 index 00000000..83b01559 --- /dev/null +++ b/mediagoblin/media_types/raw_image/processing.py @@ -0,0 +1,82 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2014 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import os +import logging + +# This needs to handle the case where it's missing +import pyexiv2 + +from mediagoblin.media_types.image.processing import ( + InitialProcessor, Resizer) +from mediagoblin.processing import ( + FilenameBuilder, ProcessingManager) + + +_log = logging.getLogger(__name__) + +MEDIA_TYPE = 'mediagoblin.media_types.raw_image' +ACCEPTED_EXTENSIONS = ['nef',] + + +# The entire function have to be copied + +def sniff_handler(media_file, filename): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) + name, ext = os.path.splitext(filename) + clean_ext = ext[1:].lower() # Strip the . from ext and make lowercase + + if clean_ext in ACCEPTED_EXTENSIONS: + _log.info('Found file extension in supported filetypes') + return MEDIA_TYPE + else: + _log.debug('Media present, extension not found in {0}'.format( + ACCEPTED_EXTENSIONS)) + + return None + + +class InitialRawProcessor(InitialProcessor): + def common_setup(self): + """ + Pull out a full-size JPEG-preview + """ + super(self.__class__, self).common_setup() + + self._original_raw = self.process_filename + + # Read EXIF data + md = pyexiv2.ImageMetadata(self._original_raw) + md.read() + self.process_filename = os.path.join(self.conversions_subdir, + self.entry.queued_media_file[-1]) + + # Extract the biggest preview and write it as our working image + md.previews[-1].write_to_file( + self.process_filename.encode('utf-8')) + self.process_filename += ".jpg" + _log.debug('Wrote new file from {0} to preview (jpg) {1}'.format( + self._original_raw, self.process_filename)) + + # Override the namebuilder with our new jpg-based name + self.name_builder = FilenameBuilder(self.process_filename) + + +class RawImageProcessingManager(ProcessingManager): + def __init__(self): + super(self.__class__, self).__init__() + self.add_processor(InitialRawProcessor) + self.add_processor(Resizer) -- 2.25.1