1 //
2 // ImageConverterManager.cs
3 //
4 // Author:
5 //       Jonathan Pobst <monkey@jpobst.com>
6 //
7 // Copyright (c) 2010 Jonathan Pobst
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26 
27 using System;
28 using System.Collections.Generic;
29 using System.Linq;
30 using Gdk;
31 using System.IO;
32 
33 namespace Pinta.Core
34 {
35 	public class ImageConverterManager
36 	{
37 		private List<FormatDescriptor> formats;
38 
ImageConverterManager()39 		public ImageConverterManager ()
40 		{
41 			formats = new List<FormatDescriptor> ();
42 
43 			// Create all the formats supported by Gdk
44 			foreach (var format in Pixbuf.Formats) {
45 				string formatName = format.Name.ToLowerInvariant ();
46 				string formatNameUpperCase = formatName.ToUpperInvariant ();
47 				string[] extensions;
48 
49 				switch (formatName) {
50 					case "jpeg":
51 						extensions = new string[] { "jpg", "jpeg", "JPG", "JPEG" };
52 						break;
53 					case "tiff":
54 						extensions = new string[] { "tif", "tiff", "TIF", "TIFF" };
55 						break;
56 					default:
57 						extensions = new string[] { formatName, formatNameUpperCase };
58 						break;
59 				}
60 
61 				GdkPixbufFormat importer = new GdkPixbufFormat (format.Name.ToLowerInvariant ());
62 				IImageExporter exporter;
63 
64 				if (formatName == "jpeg")
65 					exporter = importer = new JpegFormat ();
66 				else if (formatName == "tga")
67 					exporter = new TgaExporter ();
68 				else if (format.IsWritable)
69 					exporter = importer;
70 				else
71 					exporter = null;
72 
73 				RegisterFormat (new FormatDescriptor (formatNameUpperCase, extensions, importer, exporter));
74 			}
75 
76 			// Create all the formats we have our own importers/exporters for
77 			OraFormat oraHandler = new OraFormat ();
78 			RegisterFormat (new FormatDescriptor ("OpenRaster", new string[] { "ora", "ORA" }, oraHandler, oraHandler));
79 		}
80 
81 		public IEnumerable<FormatDescriptor> Formats { get { return formats; } }
82 
83 		/// <summary>
84 		/// Registers a new file format.
85 		/// </summary>
RegisterFormat(FormatDescriptor fd)86 		public void RegisterFormat (FormatDescriptor fd)
87 		{
88 			formats.Add (fd);
89 		}
90 
91 		/// <summary>
92 		/// Unregisters the file format for the given extension.
93 		/// </summary>
UnregisterFormatByExtension(string extension)94 		public void UnregisterFormatByExtension (string extension)
95 		{
96 			extension = NormalizeExtension (extension);
97 
98 			formats.RemoveAll (f => f.Extensions.Contains (extension));
99 		}
100 
101 		/// <summary>
102 		/// Returns the default format that should be used when saving a file.
103 		/// This is normally the last format that was chosen by the user.
104 		/// </summary>
GetDefaultSaveFormat()105 		public FormatDescriptor GetDefaultSaveFormat ()
106 		{
107 			string extension = PintaCore.Settings.GetSetting<string> ("default-image-type", "jpeg");
108 
109 			var fd = GetFormatByExtension (extension);
110 
111 			// We found the last one we used
112 			if (fd != null)
113 				return fd;
114 
115 			// Return any format we have
116 			foreach (var f in Formats)
117 				if (!f.IsReadOnly ())
118 					return f;
119 
120 			// We don't have any formats
121 			throw new InvalidOperationException ("There are no image formats supported.");
122 		}
123 
124 		/// <summary>
125 		/// Finds the correct exporter to use for opening the given file, or null
126 		/// if no exporter exists for the file.
127 		/// </summary>
GetExporterByFile(string file)128 		public IImageExporter GetExporterByFile (string file)
129 		{
130 			string extension = Path.GetExtension (file);
131 			return GetExporterByExtension (extension);
132 		}
133 
134 		/// <summary>
135 		/// Finds the file format for the given file name, or null
136 		/// if no file format exists for that file.
137 		/// </summary>
GetFormatByFile(string file)138 		public FormatDescriptor GetFormatByFile (string file)
139 		{
140 			string extension = Path.GetExtension (file);
141 
142 			extension = NormalizeExtension (extension);
143 
144 			return Formats.Where (p => p.Extensions.Contains (extension)).FirstOrDefault ();
145 		}
146 
147 		/// <summary>
148 		/// Finds the correct importer to use for opening the given file, or null
149 		/// if no importer exists for the file.
150 		/// </summary>
GetImporterByFile(string file)151 		public IImageImporter GetImporterByFile (string file)
152 		{
153 			string extension = Path.GetExtension (file);
154 
155 			if (extension == null) {
156 				return null;
157 			} else {
158 				return GetImporterByExtension (extension);
159 			}
160 		}
161 
162 		/// <summary>
163 		/// Sets the default format used when saving files to the given extension.
164 		/// </summary>
SetDefaultFormat(string extension)165 		public void SetDefaultFormat (string extension)
166 		{
167 			extension = NormalizeExtension (extension);
168 
169 			PintaCore.Settings.PutSetting ("default-image-type", extension);
170 			PintaCore.Settings.SaveSettings ();
171 		}
172 
173 		/// <summary>
174 		/// Finds the correct exporter to use for the given file extension, or null
175 		/// if no exporter exists for that extension.
176 		/// </summary>
GetExporterByExtension(string extension)177 		private IImageExporter GetExporterByExtension (string extension)
178 		{
179 			FormatDescriptor format = GetFormatByExtension (extension);
180 
181 			if (format == null)
182 				return null;
183 
184 			return format.Exporter;
185 		}
186 
187 		/// <summary>
188 		/// Finds the correct importer to use for the given file extension, or null
189 		/// if no importer exists for that extension.
190 		/// </summary>
GetImporterByExtension(string extension)191 		private IImageImporter GetImporterByExtension (string extension)
192 		{
193 			FormatDescriptor format = GetFormatByExtension (extension);
194 
195 			if (format == null)
196 				return null;
197 
198 			return format.Importer;
199 		}
200 
201 		/// <summary>
202 		/// Finds the file format for the given file extension, or null
203 		/// if no file format exists for that extension.
204 		/// </summary>
GetFormatByExtension(string extension)205 		private FormatDescriptor GetFormatByExtension (string extension)
206 		{
207 			extension = NormalizeExtension (extension);
208 
209 			return Formats.Where (p => p.Extensions.Contains (extension)).FirstOrDefault ();
210 		}
211 
212 		/// <summary>
213 		/// Normalizes the extension.
214 		/// </summary>
NormalizeExtension(string extension)215 		private static string NormalizeExtension (string extension)
216 		{
217 			return extension.ToLowerInvariant ().TrimStart ('.').Trim ();
218 		}
219 	}
220 }
221