1 /* This file is part of GEGL
2  *
3  * GEGL is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 3 of the License, or (at your option) any later version.
7  *
8  * GEGL is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
15  *
16  * Copyright 2020 Brian Stafford
17  */
18 
19 #ifndef __GEGL_METADATA_H__
20 #define __GEGL_METADATA_H__
21 
22 #include <glib-object.h>
23 
24 G_BEGIN_DECLS
25 
26 /**
27  * SECTION:gegl-metadata
28  * @title: GeglMetadata
29  * @short_description: A metadata interface for use with file modules.
30  * @see_also: #GeglMetadataStore #GeglMetadataHash
31  *
32  * Objects which need to store or retrieve image metadata when saving and
33  * loading image files should implement GeglMetadata. The object should be cast
34  * with GEGL_METADATA() and passed to the file load or save module via the
35  * `metadata` property. Image file modules should not implement the metadata
36  * property if either the module or file format does not support metadata.
37  *
38  * Gegl understands (but is not limited to) the following well-known metadata
39  * variables:
40  *
41  * - artist: Name of image creator.
42  * - comment: Miscellaneous comment; conversion from GIF comment.
43  * - copyright: Copyright notice.
44  * - description: Description of image (possibly long).
45  * - disclaimer: Legal disclaimer.
46  * - software: Software used to create the image.
47  * - source: Device used to create the image.
48  * - timestamp: Time of original image creation.
49  * - title: Short (one line) title or caption for image.
50  * - warning: Warning of nature of content.
51  *
52  * The Gegl Metadata subsystem can be used in one of three ways described
53  * below in order of increasing complexity:
54  *
55  * 1. Recommended: Create a #GeglMetadataHash and pass it to a file loader
56  *    or saver via its `metadata` property. #GeglMetadataHash is a subclass of
57  *    #GeglMetadataStore which saves metadata in a hash table but which adds no
58  *    new properties or methods.  Image file metadata to be retrieved or saved
59  *    is accessed via #GeglMetadataStore properties or methods. Metadata values
60  *    not directly supported by Gegl may be declared using a #GParamSpec.
61  * 2. Subclass #GeglMetadataStore. This may be useful if an application stores
62  *    metadata in internal structures which may be accessed via the subclass.
63  *    The subclass is used identically to #GeglMetadataHash.
64  *    #GeglMetadataStore aims to be sufficiently flexible to cover the majority
65  *    of application requirements.
66  * 3. Implement the #GeglMetadata interface. This option should only be used if
67  *    #GeglMetadataStore cannot adequately satisfy application requirements.
68  *    Particular attention should be paid to semantics of the interface methods
69  *    as the file modules interact directly with these.
70  *
71  * For more complex requirements than provided by the metadata subsystem it is
72  * probably better to use a library such as `exiv2` or similar.
73  */
74 
75 /**
76  * GeglResolutionUnit:
77  * @GEGL_RESOLUTION_UNIT_NONE: Unknown or resolution not applicable.
78  * @GEGL_RESOLUTION_UNIT_DPI: Dots or pixels per inch.
79  * @GEGL_RESOLUTION_UNIT_DPM: Dots or pixels per metre.
80  *
81  * An enumerated type specifying resolution (density) units.  If resolution
82  * units are unknown, X and Y resolution specify the pixel aspect ratio.
83  */
84 typedef enum
85   {
86     GEGL_RESOLUTION_UNIT_NONE,
87     GEGL_RESOLUTION_UNIT_DPI,
88     GEGL_RESOLUTION_UNIT_DPM
89   }
90 GeglResolutionUnit;
91 
92 /**
93  * GeglMapFlags:
94  * @GEGL_MAP_EXCLUDE_UNMAPPED: Prevent further mapping from being registered.
95  *
96  * Flags controlling the mapping strategy.
97  */
98 typedef enum _GeglMapFlags
99   {
100     GEGL_MAP_EXCLUDE_UNMAPPED = 1
101   }
102 GeglMapFlags;
103 
104 
105 #define GEGL_TYPE_METADATA          (gegl_metadata_get_type ())
106 G_DECLARE_INTERFACE (GeglMetadata, gegl_metadata, GEGL, METADATA, GObject)
107 
108 /**
109  * GeglMetadataMap:
110  * @local_name: Name of metadata variable used in the file module.
111  * @name: Standard metadata variable name used by Gegl.
112  * @transform: Optional #GValue transform function.
113  *
114  * Struct to describe how a metadata variable is mapped from the name used by
115  * the image file module to the name used by Gegl.  An optional transform
116  * function may be specified, e.g. to transform from a #GDatetime to a string.
117  */
118 typedef struct _GeglMetadataMap {
119   const gchar *local_name;
120   const gchar *name;
121   GValueTransform transform;
122 } GeglMetadataMap;
123 
124 /**
125  * GeglMetadataIter:
126  *
127  * An opaque type representing a metadata iterator.
128  */
129 typedef struct {
130   /*< private >*/
131   guint       stamp;
132   gpointer    user_data;
133   gpointer    user_data2;
134   gpointer    user_data3;
135 } GeglMetadataIter;
136 
137 /**
138  * GeglMetadataInterface:
139  * @register_map: See gegl_metadata_register_map().  If called with a NULL map,
140  * the registration is deleted.
141  * @set_resolution: See gegl_metadata_set_resolution().
142  * @get_resolution: See gegl_metadata_get_resolution().
143  * @iter_lookup: See gegl_metadata_iter_lookup().
144  * @iter_init: See gegl_metadata_iter_init().
145  * @iter_next: See gegl_metadata_iter_next().
146  * @iter_set_value: See gegl_metadata_iter_set_value().
147  * @iter_get_value: See gegl_metadata_iter_get_value().
148  *
149  * The #GeglMetadata interface structure.
150  */
151 struct _GeglMetadataInterface
152 {
153   /*< private >*/
154   GTypeInterface base_iface;
155 
156   void        (*register_map)         (GeglMetadata *metadata,
157                                        const gchar *file_module,
158                                        guint flags,
159                                        const GeglMetadataMap *map,
160                                        gsize n_map);
161 
162   /*< public >*/
163   gboolean    (*set_resolution)       (GeglMetadata *metadata,
164                                        GeglResolutionUnit unit,
165                                        gfloat x, gfloat y);
166   gboolean    (*get_resolution)       (GeglMetadata *metadata,
167                                        GeglResolutionUnit *unit,
168                                        gfloat *x, gfloat *y);
169 
170   gboolean    (*iter_lookup)          (GeglMetadata *metadata,
171                                        GeglMetadataIter *iter,
172                                        const gchar *key);
173   void        (*iter_init)            (GeglMetadata *metadata,
174                                        GeglMetadataIter *iter);
175   const gchar *(*iter_next)           (GeglMetadata *metadata,
176                                        GeglMetadataIter *iter);
177   gboolean    (*iter_set_value)       (GeglMetadata *metadata,
178                                        GeglMetadataIter *iter,
179                                        const GValue *value);
180   gboolean    (*iter_get_value)       (GeglMetadata *metadata,
181                                        GeglMetadataIter *iter,
182                                        GValue *value);
183 };
184 
185 /**
186  * gegl_metadata_register_map:
187  * @metadata:   The #GeglMetadata interface
188  * @file_module: String identifying the file module, e.g, `"gegl:png-save"`
189  * @flags:      Flags specifying capabilities of underlying file format
190  * @map: (array length=n_map): Array of mappings from file module metadata
191  *              names to Gegl well-known names.
192  * @n_map:      Number of entries in @map
193  *
194  * Set the name of the file module and pass an array of mappings from
195  * file-format specific metadata names to those used by Gegl. A GValue
196  * transformation function may be supplied, e.g. to parse or format timestamps.
197  */
198 void            gegl_metadata_register_map      (GeglMetadata *metadata,
199                                                  const gchar *file_module,
200                                                  guint flags,
201                                                  const GeglMetadataMap *map,
202                                                  gsize n_map);
203 
204 /**
205  * gegl_metadata_unregister_map:
206  * @metadata:   The #GeglMetadata interface
207  *
208  * Unregister the file module mappings and any further mappings added or
209  * modified by the application.  This should be called after the file module
210  * completes operations.
211  */
212 void            gegl_metadata_unregister_map    (GeglMetadata *metadata);
213 
214 /**
215  * gegl_metadata_set_resolution:
216  * @metadata:   The #GeglMetadata interface
217  * @unit:       Specify #GeglResolutionUnit
218  * @x:          X resolution
219  * @y:          Y resolution
220  *
221  * Set resolution retrieved from image file's metadata.  Intended for use by
222  * the image file reader.  If resolution is not supported by the application or
223  * if the operation fails %FALSE is returned and the values are ignored.
224  *
225  * Returns:     %TRUE if successful.
226  */
227 gboolean        gegl_metadata_set_resolution    (GeglMetadata *metadata,
228                                                  GeglResolutionUnit unit,
229                                                  gfloat x, gfloat y);
230 
231 /**
232  * gegl_metadata_get_resolution:
233  * @metadata:   The #GeglMetadata interface
234  * @unit:       #GeglResolutionUnit return location
235  * @x:          X resolution return location
236  * @y:          Y resolution return location
237  *
238  * Retrieve resolution from the application image metadata.  Intended for use
239  * by the image file writer.  If resolution is not supported by the application
240  * or if the operation fails %FALSE is returned and the resolution values are
241  * not updated.
242  *
243  * Returns:     %TRUE if successful.
244  */
245 gboolean        gegl_metadata_get_resolution    (GeglMetadata *metadata,
246                                                  GeglResolutionUnit *unit,
247                                                  gfloat *x, gfloat *y);
248 
249 /**
250  * gegl_metadata_iter_lookup:
251  * @metadata:   The #GeglMetadata interface
252  * @iter:       #GeglMetadataIter to be initialised
253  * @key:        Name of the value look up
254  *
255  * Look up the specified key and initialise an iterator to reference the
256  * associated metadata. The iterator is used in conjunction with
257  * gegl_metadata_set_value() and gegl_metadata_get_value(). Note that this
258  * iterator is not valid for gegl_metadata_iter_next().
259  *
260  * Returns:     %TRUE if key is found.
261  */
262 gboolean        gegl_metadata_iter_lookup       (GeglMetadata *metadata,
263                                                  GeglMetadataIter *iter,
264                                                  const gchar *key);
265 
266 /**
267  * gegl_metadata_iter_init:
268  * @metadata:   The #GeglMetadata interface
269  * @iter:       #GeglMetadataIter to be initialised
270  *
271  * Initialise an iterator to find all supported metadata keys.
272  */
273 void            gegl_metadata_iter_init         (GeglMetadata *metadata,
274                                                  GeglMetadataIter *iter);
275 
276 /**
277  * gegl_metadata_iter_next:
278  * @metadata:   The #GeglMetadata interface
279  * @iter:       #GeglMetadataIter to be updated
280  *
281  * Move the iterator to the next metadata item
282  *
283  * Returns:     key name if found, else %NULL
284  */
285 const gchar    *gegl_metadata_iter_next         (GeglMetadata *metadata,
286                                                  GeglMetadataIter *iter);
287 
288 /**
289  * gegl_metadata_iter_set_value:
290  * @metadata:   The #GeglMetadata interface
291  * @iter:       #GeglMetadataIter referencing the value to set
292  * @value:      Value to set in the interface
293  *
294  * Set application data retrieved from image file's metadata.  Intended for use
295  * by the image file reader.  If the operation fails it returns %FALSE and
296  * @value is ignored.
297  *
298  * Returns:     %TRUE if successful.
299  */
300 gboolean        gegl_metadata_iter_set_value    (GeglMetadata *metadata,
301                                                  GeglMetadataIter *iter,
302                                                  const GValue *value);
303 
304 /**
305  * gegl_metadata_iter_get_value:
306  * @metadata:   The #GeglMetadata interface
307  * @iter:       #GeglMetadataIter referencing the value to get
308  * @value:      Value to set in the interface
309  *
310  * Retrieve image file metadata from the application.  Intended for use by the
311  * image file writer. If the operation fails it returns %FALSE and @value is
312  * not updated.
313  *
314  * Returns:     %TRUE if successful.
315  */
316 gboolean        gegl_metadata_iter_get_value    (GeglMetadata *metadata,
317                                                  GeglMetadataIter *iter,
318                                                  GValue *value);
319 
320 G_END_DECLS
321 
322 #endif
323