summaryrefslogtreecommitdiff
path: root/src/photos/PhotoFileFormat.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/photos/PhotoFileFormat.vala')
-rw-r--r--src/photos/PhotoFileFormat.vala410
1 files changed, 410 insertions, 0 deletions
diff --git a/src/photos/PhotoFileFormat.vala b/src/photos/PhotoFileFormat.vala
new file mode 100644
index 0000000..2ab2f00
--- /dev/null
+++ b/src/photos/PhotoFileFormat.vala
@@ -0,0 +1,410 @@
+/* Copyright 2010-2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+public errordomain PhotoFormatError {
+ READ_ONLY
+}
+
+//
+// PhotoFileFormat
+//
+
+namespace PhotoFileFormatData {
+ private static PhotoFileFormat[] writeable = null;
+ private static PhotoFileFormat[] image_writeable = null;
+ private static PhotoFileFormat[] metadata_writeable = null;
+
+ private delegate bool ApplicableTest(PhotoFileFormat format);
+
+ private PhotoFileFormat[] find_applicable(ApplicableTest test) {
+ PhotoFileFormat[] applicable = new PhotoFileFormat[0];
+ foreach (PhotoFileFormat format in PhotoFileFormat.get_supported()) {
+ if (test(format))
+ applicable += format;
+ }
+
+ return applicable;
+ }
+
+ public PhotoFileFormat[] get_writeable() {
+ if (writeable == null)
+ writeable = find_applicable((format) => { return format.can_write(); });
+
+ return writeable;
+ }
+
+ public static PhotoFileFormat[] get_image_writeable() {
+ if (image_writeable == null)
+ image_writeable = find_applicable((format) => { return format.can_write_image(); });
+
+ return image_writeable;
+ }
+
+ public static PhotoFileFormat[] get_metadata_writeable() {
+ if (metadata_writeable == null)
+ metadata_writeable = find_applicable((format) => { return format.can_write_metadata(); });
+
+ return metadata_writeable;
+ }
+}
+
+public enum PhotoFileFormat {
+ JFIF,
+ RAW,
+ PNG,
+ TIFF,
+ BMP,
+ UNKNOWN;
+
+ // This is currently listed in the order of detection, that is, the file is examined from
+ // left to right. (See PhotoFileInterrogator.)
+ public static PhotoFileFormat[] get_supported() {
+ return { JFIF, RAW, PNG, TIFF, BMP };
+ }
+
+ public static PhotoFileFormat[] get_writeable() {
+ return PhotoFileFormatData.get_writeable();
+ }
+
+ public static PhotoFileFormat[] get_image_writeable() {
+ return PhotoFileFormatData.get_image_writeable();
+ }
+
+ public static PhotoFileFormat[] get_metadata_writeable() {
+ return PhotoFileFormatData.get_metadata_writeable();
+ }
+
+ public static PhotoFileFormat get_by_basename_extension(string basename) {
+ string name, ext;
+ disassemble_filename(basename, out name, out ext);
+
+ if (is_string_empty(ext))
+ return UNKNOWN;
+
+ foreach (PhotoFileFormat file_format in get_supported()) {
+ if (file_format.get_driver().get_properties().is_recognized_extension(ext))
+ return file_format;
+ }
+
+ return UNKNOWN;
+ }
+
+ public static bool is_file_supported(File file) {
+ return is_basename_supported(file.get_basename());
+ }
+
+ public static bool is_basename_supported(string basename) {
+ string name, ext;
+ disassemble_filename(basename, out name, out ext);
+
+ if (is_string_empty(ext))
+ return false;
+
+ foreach (PhotoFileFormat format in get_supported()) {
+ if (format.get_driver().get_properties().is_recognized_extension(ext))
+ return true;
+ }
+
+ return false;
+ }
+
+ // Guaranteed to be writeable.
+ public static PhotoFileFormat get_system_default_format() {
+ return JFIF;
+ }
+
+ public static PhotoFileFormat get_by_file_extension(File file) {
+ return get_by_basename_extension(file.get_basename());
+ }
+
+ // These values are persisted in the database. DO NOT CHANGE THE INTEGER EQUIVALENTS.
+ public int serialize() {
+ switch (this) {
+ case JFIF:
+ return 0;
+
+ case RAW:
+ return 1;
+
+ case PNG:
+ return 2;
+
+ case TIFF:
+ return 3;
+
+ case BMP:
+ return 4;
+
+ case UNKNOWN:
+ default:
+ return -1;
+ }
+ }
+
+ // These values are persisted in the database. DO NOT CHANGE THE INTEGER EQUIVALENTS.
+ public static PhotoFileFormat unserialize(int value) {
+ switch (value) {
+ case 0:
+ return JFIF;
+
+ case 1:
+ return RAW;
+
+ case 2:
+ return PNG;
+
+ case 3:
+ return TIFF;
+
+ case 4:
+ return BMP;
+
+ default:
+ return UNKNOWN;
+ }
+ }
+
+ public static PhotoFileFormat from_gphoto_type(string type) {
+ switch (type) {
+ case GPhoto.MIME.JPEG:
+ return PhotoFileFormat.JFIF;
+
+ case GPhoto.MIME.RAW:
+ case GPhoto.MIME.CRW:
+ return PhotoFileFormat.RAW;
+
+ case GPhoto.MIME.PNG:
+ return PhotoFileFormat.PNG;
+
+ case GPhoto.MIME.TIFF:
+ return PhotoFileFormat.TIFF;
+
+ case GPhoto.MIME.BMP:
+ return PhotoFileFormat.BMP;
+
+ default:
+ // check file extension against those we support
+ return PhotoFileFormat.UNKNOWN;
+ }
+ }
+
+ // Converts GDK's pixbuf library's name to a PhotoFileFormat
+ public static PhotoFileFormat from_pixbuf_name(string name) {
+ switch (name) {
+ case "jpeg":
+ return PhotoFileFormat.JFIF;
+
+ case "png":
+ return PhotoFileFormat.PNG;
+
+ case "tiff":
+ return PhotoFileFormat.TIFF;
+
+ case "bmp":
+ return PhotoFileFormat.BMP;
+
+ default:
+ return PhotoFileFormat.UNKNOWN;
+ }
+ }
+
+ public void init() {
+ switch (this) {
+ case JFIF:
+ JfifFileFormatDriver.init();
+ break;
+
+ case RAW:
+ RawFileFormatDriver.init();
+ break;
+
+ case PNG:
+ PngFileFormatDriver.init();
+ break;
+
+ case TIFF:
+ Photos.TiffFileFormatDriver.init();
+ break;
+
+ case BMP:
+ Photos.BmpFileFormatDriver.init();
+ break;
+
+ default:
+ error("Unsupported file format %s", this.to_string());
+ }
+ }
+
+ private PhotoFileFormatDriver get_driver() {
+ switch (this) {
+ case JFIF:
+ return JfifFileFormatDriver.get_instance();
+
+ case RAW:
+ return RawFileFormatDriver.get_instance();
+
+ case PNG:
+ return PngFileFormatDriver.get_instance();
+
+ case TIFF:
+ return Photos.TiffFileFormatDriver.get_instance();
+
+ case BMP:
+ return Photos.BmpFileFormatDriver.get_instance();
+
+ default:
+ error("Unsupported file format %s", this.to_string());
+ }
+ }
+
+ public PhotoFileFormatProperties get_properties() {
+ return get_driver().get_properties();
+ }
+
+ // Supplied with a name, returns the name with the file format's default extension.
+ public string get_default_basename(string name) {
+ return "%s.%s".printf(name, get_properties().get_default_extension());
+ }
+
+ public PhotoFileReader create_reader(string filepath) {
+ return get_driver().create_reader(filepath);
+ }
+
+ // This means the image and its metadata are writeable.
+ public bool can_write() {
+ return can_write_image() && can_write_metadata();
+ }
+
+ public bool can_write_image() {
+ return get_driver().can_write_image();
+ }
+
+ public bool can_write_metadata() {
+ return get_driver().can_write_metadata();
+ }
+
+ public PhotoFileWriter create_writer(string filepath) throws PhotoFormatError {
+ PhotoFileWriter writer = get_driver().create_writer(filepath);
+ if (writer == null)
+ throw new PhotoFormatError.READ_ONLY("File format %s is read-only", this.to_string());
+
+ return writer;
+ }
+
+ public PhotoFileMetadataWriter create_metadata_writer(string filepath) throws PhotoFormatError {
+ PhotoFileMetadataWriter writer = get_driver().create_metadata_writer(filepath);
+ if (writer == null)
+ throw new PhotoFormatError.READ_ONLY("File format %s metadata is read-only", this.to_string());
+
+ return writer;
+ }
+
+ public PhotoFileSniffer create_sniffer(File file, PhotoFileSniffer.Options options) {
+ return get_driver().create_sniffer(file, options);
+ }
+
+ public PhotoMetadata create_metadata() {
+ return get_driver().create_metadata();
+ }
+
+ public string get_default_mime_type() {
+ return get_driver().get_properties().get_default_mime_type();
+ }
+
+ public string[] get_mime_types() {
+ return get_driver().get_properties().get_mime_types();
+ }
+
+ public static string[] get_editable_mime_types() {
+ string[] mime_types = {};
+
+ foreach (PhotoFileFormat file_format in PhotoFileFormat.get_supported()) {
+ foreach (string mime_type in file_format.get_mime_types())
+ mime_types += mime_type;
+ }
+
+ return mime_types;
+ }
+}
+
+//
+// PhotoFileFormatDriver
+//
+// Each supported file format is expected to have a PhotoFileFormatDriver that returns all possible
+// resources that are needed to operate on file of its particular type. It's expected that each
+// format subsystem will only create and cache a single instance of this driver, although it's
+// not required.
+//
+// Like the other elements in the PhotoFileFormat family, this class should be thread-safe.
+//
+
+public abstract class PhotoFileFormatDriver {
+ public abstract PhotoFileFormatProperties get_properties();
+
+ public abstract PhotoFileReader create_reader(string filepath);
+
+ public abstract PhotoMetadata create_metadata();
+
+ public abstract bool can_write_image();
+
+ public abstract bool can_write_metadata();
+
+ public abstract PhotoFileWriter? create_writer(string filepath);
+
+ public abstract PhotoFileMetadataWriter? create_metadata_writer(string filepath);
+
+ public abstract PhotoFileSniffer create_sniffer(File file, PhotoFileSniffer.Options options);
+}
+
+//
+// PhotoFileFormatProperties
+//
+// Although each PhotoFileFormatProperties is expected to be largely static and immutable, these
+// classes should be thread-safe.
+//
+
+public enum PhotoFileFormatFlags {
+ NONE = 0x00000000,
+}
+
+public abstract class PhotoFileFormatProperties {
+ public abstract PhotoFileFormat get_file_format();
+
+ public abstract PhotoFileFormatFlags get_flags();
+
+ // Default implementation will search for ext in get_known_extensions(), assuming they are
+ // all stored in lowercase.
+ public virtual bool is_recognized_extension(string ext) {
+ return is_in_ci_array(ext, get_known_extensions());
+ }
+
+ public abstract string get_default_extension();
+
+ public abstract string[] get_known_extensions();
+
+ public abstract string get_default_mime_type();
+
+ public abstract string[] get_mime_types();
+
+ // returns the user-visible name of the file format -- this name is used in user interface
+ // strings whenever the file format needs to named. This name is not the same as the format
+ // enum value converted to a string. The format enum value is meaningful to developers and is
+ // constant across languages (e.g. "JFIF", "TGA") whereas the user-visible name is translatable
+ // and is meaningful to users (e.g. "JPEG", "Truevision TARGA")
+ public abstract string get_user_visible_name();
+
+ // Takes a given file and returns one with the file format's default extension, unless it
+ // already has one of the format's known extensions
+ public File convert_file_extension(File file) {
+ string name, ext;
+ disassemble_filename(file.get_basename(), out name, out ext);
+ if (ext != null && is_recognized_extension(ext))
+ return file;
+
+ return file.get_parent().get_child("%s.%s".printf(name, get_default_extension()));
+ }
+}
+