/* Copyright 2016 Software Freedom Conservancy Inc. * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. */ class HeifFileFormatProperties : PhotoFileFormatProperties { private static string[] KNOWN_EXTENSIONS = { "heif", "heic" }; private static string[] KNOWN_MIME_TYPES = { "image/heif" }; private static HeifFileFormatProperties instance = null; public static void init() { instance = new HeifFileFormatProperties(); } public static HeifFileFormatProperties get_instance() { return instance; } public override PhotoFileFormat get_file_format() { return PhotoFileFormat.HEIF; } public override PhotoFileFormatFlags get_flags() { return PhotoFileFormatFlags.NONE; } public override string get_user_visible_name() { return _("HEIF"); } public override string get_default_extension() { return KNOWN_EXTENSIONS[0]; } public override string[] get_known_extensions() { return KNOWN_EXTENSIONS; } public override string get_default_mime_type() { return KNOWN_MIME_TYPES[0]; } public override string[] get_mime_types() { return KNOWN_MIME_TYPES; } } public class HeifSniffer : GdkSniffer { private const string[] MAGIC_SEQUENCES = { "heic", "heix", "hevc", "heim", "heis", "hevm", "hevs", "mif1", "msf1"}; public HeifSniffer(File file, PhotoFileSniffer.Options options) { base (file, options); } public override DetectedPhotoInformation? sniff(out bool is_corrupted) throws Error { // Rely on GdkSniffer to detect corruption is_corrupted = false; if (!is_supported_bmff_with_variants(file, MAGIC_SEQUENCES)) return null; DetectedPhotoInformation? detected = base.sniff(out is_corrupted); if (detected == null) return null; if (detected.file_format == PhotoFileFormat.AVIF) detected.file_format = PhotoFileFormat.HEIF; // Heif contains its own rotation information, so we need to ignore the EXIF rotation+ if (detected.metadata != null) { detected.metadata.set_orientation(Orientation.TOP_LEFT); } return (detected.file_format == PhotoFileFormat.HEIF) ? detected : null; } } public class HeifReader : GdkReader { public HeifReader(string filepath) { base (filepath, PhotoFileFormat.HEIF); } public override PhotoMetadata read_metadata() throws Error { PhotoMetadata metadata = new PhotoMetadata(); metadata.read_from_file(get_file()); // Heif contains its own rotation information, so we need to ignore the EXIF rotation metadata.set_orientation(Orientation.TOP_LEFT); return metadata; } } public class HeifMetadataWriter : PhotoFileMetadataWriter { public HeifMetadataWriter(string filepath) { base (filepath, PhotoFileFormat.HEIF); } public override void write_metadata(PhotoMetadata metadata) throws Error { metadata.write_to_file(get_file()); } } public class HeifFileFormatDriver : PhotoFileFormatDriver { private static HeifFileFormatDriver instance = null; public static void init() { instance = new HeifFileFormatDriver(); HeifFileFormatProperties.init(); } public static HeifFileFormatDriver get_instance() { return instance; } public override PhotoFileFormatProperties get_properties() { return HeifFileFormatProperties.get_instance(); } public override PhotoFileReader create_reader(string filepath) { return new HeifReader(filepath); } public override bool can_write_image() { return false; } public override bool can_write_metadata() { return true; } public override PhotoFileWriter? create_writer(string filepath) { return null; } public override PhotoFileMetadataWriter? create_metadata_writer(string filepath) { return new HeifMetadataWriter(filepath); } public override PhotoFileSniffer create_sniffer(File file, PhotoFileSniffer.Options options) { return new HeifSniffer(file, options); } public override PhotoMetadata create_metadata() { return new PhotoMetadata(); } }