def process_image(incontext, root, destination, dirname, basename, category, title_from_filename=True): source_path = os.path.join(root, dirname, basename) metadata = metadata_for_media_file(root, os.path.join(dirname, basename), title_from_filename=title_from_filename) name, _ = os.path.splitext(basename) name = name.lower() destination_path = os.path.join(destination, dirname, name) utils.makedirs(destination_path) transform_files = [] transform_metadata = collections.defaultdict(list) transforms = evaluate_tests( incontext.configuration.media["profiles"]["default"], { "basename": os.path.basename(source_path), "metadata": metadata }) for transform in transforms: transform_extension = extension_for_format(source_path, transform.format) transform_destination = os.path.join( destination_path, transform.basename) + transform_extension result = transform.perform(source=source_path, destination=transform_destination) if not isinstance(result, TransformResult): raise AssertionError("Invalid result type.") transform_files.extend(result.files) transform_documents = [] for document in result.documents: document["filename"] = os.path.join(name, document["filename"]) document["url"] = os.path.join("/", dirname, name) + document["url"] transform_documents.append(document) for set in transform.sets: transform_metadata[set].extend(transform_documents) metadata["category"] = category metadata["template"] = "photo.html" # TODO: Pass this in as a default. metadata["path"] = converters.ensure_leading_slash( os.path.join(dirname, basename)) for key, value in transform_metadata.items(): metadata[key] = value if len(value) > 1 else value[ 0] # Single arrays should be direct values. if metadata["scale"] is None: # Ensure images have a scale. metadata["scale"] = 1 metadata_document = store.Document(metadata['url'], metadata, os.path.getmtime(source_path)) incontext.environment["DOCUMENT_STORE"].add(metadata_document) return {'files': transform_files, 'urls': [metadata['url']]}
def inner(path): root, dirname, basename = utils.tripple(from_directory, path) destination = os.path.join(to_directory, dirname, basename) utils.makedirs(os.path.join(to_directory, dirname)) data = gallery.metadata_for_media_file( root, os.path.join(dirname, basename), title_from_filename=title_from_filename) data["category"] = category data[ "template"] = "photo.html" # TODO: Change this to be part of the configuration. name, _ = os.path.splitext(basename) mp4_name = "%s.mp4" % name mp4_path = os.path.join(to_directory, dirname, mp4_name) if not os.path.exists(mp4_path): subprocess.check_call([ "ffmpeg", "-y", "-i", path, "-vcodec", "h264", "-acodec", "aac", "-strict", "-2", "-vf", "scale=1080:trunc(ow/a/2)*2", "-loglevel", LOG_LEVEL_PANIC, mp4_path ]) thumbnail_name = "%s-thumbnail.jpg" % name thumbnail_path = os.path.join(to_directory, dirname, thumbnail_name) if not os.path.exists(thumbnail_path): subprocess.check_call([ "ffmpeg", "-y", "-i", path, "-ss", "00:00:1.000", "-vframes", "1", "-loglevel", LOG_LEVEL_PANIC, thumbnail_path ]) size = gallery.get_size(thumbnail_path, 1) data["thumbnail"] = utils.merge_dictionaries( { 'filename': thumbnail_name, 'url': os.path.join("/", dirname, thumbnail_name) }, size) data["video"] = utils.merge_dictionaries( { 'filename': mp4_name, 'url': os.path.join("/", dirname, mp4_name) }, size) data["path"] = converters.ensure_leading_slash(path) document = store.Document(data["url"], data, os.path.getmtime(path)) incontext.environment["DOCUMENT_STORE"].add(document) return {'files': [mp4_path, thumbnail_path], 'urls': [document.url]}
def frontmatter_document(root, path, default_category='general'): """ Parse the contents of a frontmatter document as a DocumentStore Document. @param root: Root of the site. @type root: str @param path: Document path, relative to the root of the site. @type path: str @return: Document representing the contents of the frontmatter document. @rtype: store.Document """ data = {} data = merge_dictionaries(data, read_frontmatter(os.path.join(root, path))) data = merge_dictionaries(data, {key: value for key, value in parse_path(path).items() if ((key != "title" or "title" not in data) and (key != "date" or "date" not in data))}) data["path"] = ensure_leading_slash(path) if "category" not in data: data["category"] = default_category return store.Document(data['url'], data, os.path.getmtime(os.path.join(root, path)))
def process_image(incontext, root, destination, dirname, basename, category, title_from_filename=True): source_path = os.path.join(root, dirname, basename) identifier = generate_identifier(basename) destination_dir = os.path.join(destination, dirname) destination_path = os.path.join(destination_dir, basename) markdown_path = os.path.join(destination_dir, "%s.markdown" % identifier) name, ext = os.path.splitext(basename) utils.makedirs(destination_dir) metadata = load_metadata(markdown_path) DEFAULT_PROFILES = { "image": { "width": 1600, "scale": 1 }, "thumbnail": { "height": 240, "scale": 2 }, } EQUIRECTANGULAR_PROFILES = { "image": { "width": 10000, "scale": 1 }, "thumbnail": { "height": 240, "scale": 2 }, } # Use the common path parsing from converters to ensure we pick up information like the title, etc. metadata = converters.parse_path(os.path.join(dirname, basename), title_from_filename=title_from_filename) # Read data from the EXIF and add it to the metadata exif_data = exif(source_path) # Select title with priority: Title, ObjectName if "ObjectName" in exif_data: metadata["title"] = exif_data["ObjectName"] if "Title" in exif_data: metadata["title"] = exif_data["Title"] metadata["content"] = first_value_or_none( exif_data, ["ImageDescription", "Description", "ArtworkContentDescription"]) if "DateTimeOriginal" in exif_data: metadata["date"] = exif_data["DateTimeOriginal"] if "ProjectionType" in exif_data: metadata["projection"] = exif_data["ProjectionType"] logging.debug(f"projection = {metadata['projection']}") # Read the location from the exif. if "GPSLatitude" in exif_data and "GPSLongitude" in exif_data: metadata["location"] = { "latitude": exif_data["GPSLatitude"], "longitude": exif_data["GPSLongitude"] } # Determine which profiles to use; we use a different profile for equirectangular projections. # TODO: In an ideal world we would allow all of this special case behaviour to be configured in site.yaml # so there are no custom modifications required to the script. profiles = DEFAULT_PROFILES if "projection" in metadata and metadata["projection"] == "equirectangular": profiles = EQUIRECTANGULAR_PROFILES # Generate the various different image sizes. # TODO: Consider making this common code for all images. for profile_name, profile_details in profiles.items(): filename = "%s-%s%s" % (identifier, profile_name.replace("_", "-"), ext) if profile_name == "image": filename = "%s%s" % (identifier, ext) scale = 1 if "scale" in profile_details: scale = profile_details["scale"] width = None if "width" in profile_details: width = profile_details["width"] height = None if "height" in profile_details: height = profile_details["height"] source_scale = metadata["scale"] if metadata["scale"] is not None else 1 # TODO: Rename generate_thumbnail. metadata[profile_name] = generate_thumbnail(source_path, destination, dirname, filename, (width, height), source_scale, scale) # Configure the page details. metadata["category"] = category metadata["template"] = "photo.html" # TODO: Pass this in as a default. metadata["path"] = converters.ensure_leading_slash( os.path.join(dirname, basename)) metadata_document = store.Document(metadata['url'], metadata, os.path.getmtime(source_path)) incontext.environment["DOCUMENT_STORE"].add(metadata_document) files = [markdown_path] + [ os.path.join(destination, dirname, metadata[f]["filename"]) for f in profiles.keys() ] files = [ os.path.join(destination, dirname, metadata[f]["filename"]) for f in profiles.keys() ] return {'files': files, 'urls': [metadata['url']]}