Fix #1053 - Add height and width attributes and MetadataProcess task
Added "height" and "width" attributes to "image" and "fullImage" in the API where possible. The height and width of images wasn't being stored anywhere so I've created a task to add or update the metadata on images and also started adding those to new images when they're submitted in the InitialProcessor.
This commit is contained in:
parent
f2698759cd
commit
4a09d5956a
@ -591,6 +591,22 @@ class MediaEntry(Base, MediaEntryMixin):
|
||||
),
|
||||
}
|
||||
|
||||
# Add image height and width if possible. We didn't use to store this
|
||||
# data and we're not able (and maybe not willing) to re-process all
|
||||
# images so it's possible this might not exist.
|
||||
if self.get_file_metadata("thumb", "height"):
|
||||
height = self.get_file_metadata("thumb", "height")
|
||||
context["image"]["height"] = height
|
||||
if self.get_file_metadata("thumb", "width"):
|
||||
width = self.get_file_metadata("thumb", "width")
|
||||
context["image"]["width"] = width
|
||||
if self.get_file_metadata("original", "height"):
|
||||
height = self.get_file_metadata("original", "height")
|
||||
context["fullImage"]["height"] = height
|
||||
if self.get_file_metadata("original", "height"):
|
||||
width = self.get_file_metadata("original", "width")
|
||||
context["fullImage"]["width"] = width
|
||||
|
||||
return context
|
||||
|
||||
def unserialize(self, data):
|
||||
|
@ -225,19 +225,32 @@ class CommonImageProcessor(MediaProcessor):
|
||||
self.entry, self.process_filename,
|
||||
self.name_builder.fill('{basename}{ext}'))
|
||||
|
||||
def extract_metadata(self):
|
||||
# Is there any GPS data
|
||||
def extract_metadata(self, file):
|
||||
""" Extract all the metadata from the image and store """
|
||||
# Extract GPS data and store in Location
|
||||
gps_data = get_gps_data(self.exif_tags)
|
||||
|
||||
if len(gps_data):
|
||||
Location.create({"position": gps_data}, self.entry)
|
||||
|
||||
# Insert exif data into database
|
||||
exif_all = clean_exif(self.exif_tags)
|
||||
|
||||
if len(exif_all):
|
||||
self.entry.media_data_init(exif_all=exif_all)
|
||||
|
||||
if len(gps_data):
|
||||
Location.create({"position": gps_data}, self.entry)
|
||||
self.entry.media_data_init(**gps_data)
|
||||
# Extract file metadata
|
||||
try:
|
||||
im = Image.open(self.process_filename)
|
||||
except IOError:
|
||||
raise BadMediaFail()
|
||||
|
||||
metadata = {
|
||||
"width": im.size[0],
|
||||
"height": im.size[1],
|
||||
}
|
||||
|
||||
self.entry.set_file_metadata(file, **metadata)
|
||||
|
||||
|
||||
class InitialProcessor(CommonImageProcessor):
|
||||
@ -252,6 +265,9 @@ class InitialProcessor(CommonImageProcessor):
|
||||
"""
|
||||
Determine if this media type is eligible for processing
|
||||
"""
|
||||
if entry is None and state is None:
|
||||
raise ValueError("Must specify either entry or state")
|
||||
|
||||
if not state:
|
||||
state = entry.state
|
||||
return state in (
|
||||
@ -301,7 +317,7 @@ class InitialProcessor(CommonImageProcessor):
|
||||
quality=quality)
|
||||
self.generate_thumb(size=thumb_size, filter=filter, quality=quality)
|
||||
self.copy_original()
|
||||
self.extract_metadata()
|
||||
self.extract_metadata('original')
|
||||
self.delete_queue_file()
|
||||
|
||||
|
||||
@ -318,6 +334,9 @@ class Resizer(CommonImageProcessor):
|
||||
"""
|
||||
Determine if this media type is eligible for processing
|
||||
"""
|
||||
if entry is None and state is None:
|
||||
raise ValueError("Must specify either entry or state")
|
||||
|
||||
if not state:
|
||||
state = entry.state
|
||||
return state in 'processed'
|
||||
@ -366,13 +385,52 @@ class Resizer(CommonImageProcessor):
|
||||
elif file == 'thumb':
|
||||
self.generate_thumb(size=size, filter=filter, quality=quality)
|
||||
|
||||
self.extract_metadata(file)
|
||||
|
||||
class MetadataProcessing(CommonImageProcessor):
|
||||
""" Extraction and storage of media's metadata for processed images """
|
||||
|
||||
name = 'metadatabuilder'
|
||||
description = 'Add or update image metadata'
|
||||
|
||||
@classmethod
|
||||
def media_is_eligible(cls, entry=None, state=None):
|
||||
if entry is None and state is None:
|
||||
raise ValueError("Must specify either entry or state")
|
||||
|
||||
if state is None:
|
||||
state = entry.state
|
||||
|
||||
return state == 'processed'
|
||||
|
||||
@classmethod
|
||||
def generate_parser(cls):
|
||||
parser = argparse.ArgumentParser(
|
||||
description=cls.description,
|
||||
prog=cls.name
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'file',
|
||||
choices=['original', 'medium', 'thumb']
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
@classmethod
|
||||
def args_to_request(cls, args):
|
||||
return request_from_args(args, ['file'])
|
||||
|
||||
def process(self, file):
|
||||
self.common_setup()
|
||||
self.extract_metadata(file)
|
||||
|
||||
class ImageProcessingManager(ProcessingManager):
|
||||
def __init__(self):
|
||||
super(ImageProcessingManager, self).__init__()
|
||||
self.add_processor(InitialProcessor)
|
||||
self.add_processor(Resizer)
|
||||
|
||||
self.add_processor(MetadataProcessing)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
Loading…
x
Reference in New Issue
Block a user