Some images have Exif.Photo.PixelXDimension and Exif.Photo.PixelYDimension
metadata tags in addition to Exif.Image.ImageWidth and
Exif.Image.ImageHeight (mainly tiff images). So far, we were not updating
these optional tags, meaning they could get out-of-sync with the actual
dimensions when resizing and then exporting the image.
Since these tags are non essential, we will only update them if they are
already present.
Our metadata library exiv2 only registers the most commonly used xmp
namespaces. Other namespaces need to be explicitly registered. We did not
read or try to store these namespaces, which caused a lot of warnings about
"No namespace info available for XMP prefix '...' and then we could not
process that metadata or save/export those tags.
We had to wait for gexiv2 support for registering/reading namespaces, but
that was added in gexiv2 version 0.12.2 (and the "try" version in 0.14.0).
When reading xmp metadata we process all namespaces and add them to our
metadata xml when we haven't seen them before in the same image.
A GHashTable is used to keep track of the prefixes we have seen before.
The new namespace xml tag is skipped in older GIMP versions, but will be
used now to add the namespaces when exporting images with xmp metadata.
We were using fixed size buffer with strcpy/strcat, which gave warnings in
coverity.
Even though in our case there was no chance of buffer overflow, let's
replace this by using g_strconcat, which allocates memory for the
string which we free after use.
Also get rid of a few unneeded memset's for strdata.
Photoshop can save metadata when exporting to tiff or jpeg, including
a thumbnail that we can't update. This can contain sensitive data, so we
should not export it. See issue #8383.
To do this, we add the two Photoshop specific tags that we know of to the
list of tags that should not be exported, so they won't be saved.
In other cases we need to free value, but in this case it was used and
trying to free it caused a GIMP to crash.
Let's duplicate value, so we don't need to special case our g_free.
with many Xmp.photoshop.DocumentAncestors tags
This is similar to #7464, but in this case the XMP metadata was already
included in an XCF image.
We check for the occurrence of Xmp.photoshop.DocumentAncestors and stop
handling values when there are more than a 1000.
It would be easier to just check length for all tags and always
ignore when there are more than a 1000 values.
But in that case we would need to be sure there are no valid reasons for
tags to occur more than a 1000 times. So let's just limit it to this
specific tag.
There are still deprecations going around but for GExiv2 0.14.0 so we
can't change these yet.
Note also that I try a slightly different approach as I don't set a
GError for well-known tags as there is no reason these fail. I only add
a GError when we construct tags or similar calls.
I was waiting for GExiv2 to merge a patch I submitted:
https://gitlab.gnome.org/GNOME/gexiv2/-/merge_requests/20
Then we waited for it to land in a released version then for this
version to be in Debian testing. It's all done now and we bumped the
GExiv2 dependency in the previous commit (which makes it a master-only
fix). So all good.
Some images have huge amounts of XMP tag Xmp.photoshop.DocumentAncestors.
In certain cases more than 100000 values. This is apparently due to a bug
in certain versions of PhotoShop.
This makes deserializing it in the way we currently do too slow, probably
because of continuous reallocations after adding each value. Until we can
change this let's remove everything but the first 1000 values when
serializing. I think it is very unlikely there are any real cases where
more than a 1000 ancestor documents are referenced in an image. Testing
shows that this amount doesn't cause any serious slowdowns.
In cases where the whole EXIF MakerNote is invalid we still load that
MakerNote data and export it too, causing partial invalid EXIF metadata.
We don't need to explicitly save Exif.Photo.MakerNote at all, because
as soon as we try to save a brand specific tag exiv2 will create that
MakerNote tag itself.
So from now we don't save the MakerNote but only the tags that go in it.
In issues like #2159 where exiv2 doesn't parse all tags inside certain
brand specific MakerNotes correctly, we will still export invalid EXIF.
That is an exiv2 issue that we can't do much about unless we remove all
MakerNote metadata including those that we can read, which doesn't seem
like a good idea at all.
On Windows when exporting an image saving the exif and other metadata fails
if the path or filename includes non ASCII characters.
Reason is that gexiv2 changed to using utf-8.
In the past we had to convert the filename to current locale on Windows,
but since it now also expects utf-8 there, just remove the special
handling of filename there.
When saving XMP metadata were using gexiv2_metadata_get_tag_string for all
tags, even those that can have multiple values. This caused those values
to be saved as one value instead of multiple.
To fix this we use gexiv2_metadata_get_tag_multiple, except for XmpText.
Then we add all returned values for that tag separately to our metadata.
On Windows loading metadata from images with non ASCII characters in their
path failed. Part of the fix is in gexiv2 that now converts the path from
utf-8 to utf-16 on Windows.
However we were still sending a localized path to gexiv2 where it was
expecting utf-8. This caused the conversion and thus loading of metadata
to fail. Fix is to remove the special handling for Windows and use the
utf-8 filename.
This is one of the problems mentioned in issue #5863. This commit only fixes
our loading (and saving) of this metadata.
Certain iptc tags like "Keywords" can appear multiple times. We were using
gexiv2_metadata_get_tag_string to get the value but that always returns
the first value so we replaced that by gexiv2_metadata_get_tag_multiple.
`man snprintf` clearly says (in NOTES) that when source and target
overlap, the result in undefined.
g_snprintf() conforms to the same standard hence would not get the
expected result. In my case, the result was just tzstr (e.g. "+01:00").
Partially based on the comments of Massimo Valentini we block all Pentax and PentaxDng
exif Preview tags from being exported. We leave finding a more flexible solution for
problematic tags to a future contributor.
gimp_metadata_add() which is used to set blobs or EXIF, XMP and IPTC
on a GimpMetadata also needs the logic to set "multiple" tags in one
go, or it will lose all but the first one.
We were not taking into account tags that can appear multiple times,
such as "keyword", they are handled by gexiv2 with the
get_tag_multiple() and set_tag_multiple() functions.
gimp_metadata_deserialize_text(): when deserializing our XML format,
check if a tag is already set on the metadata as "multiple" and if yes
retrieve it, append the new value and set it again.
gimp_image_metadata_save_finish(): take care of "multiple" values when
copying tags to new metadata created for saving.
This should preserve all values across an "import, edit, export".
Thing will still break when using the metadata editor, it doesn't
handle multiple values at all, but that code is very hard to
understand.
In gimp_metadata_set_from_{exif,iptc,xmp}(), gracefully reject data
of invalid size, returning an error instead of raising a critical.
In particular, this avoids a CRITICAL when loading an XCF with an
empty exif-ata parasite.
even if we don't have private members (yet). Also make class padding 8
pointers in all headers. This commit moves nothing to private, it just
makes all headers consistent and adjusts .c files accordigly.
Let's make our various usages of this broken function more robust, or at
least return with errors when we can. But this is still seriously
broken. Inside gimp_locale_directory() though, there was nothing I could
do, so I just added a FIXME for at least keeping an eye on it.
... non-latin unicode path.
g_win32_locale_filename_from_utf8() was sometimes returning NULL for
some paths on Windows. Then the call to gexiv2_metadata_open_path() with
a NULL value was crashing plug-ins.
This commit only prevents from crashing by simply failing to load
metadata when this occurs, which means losing metadata support on
Windows depending on filenames. A proper solution will have to be
implemented.
...on macOS (with macports)
Changed gimp_metadata_get_guid() to use a GRand that automatically
seeds itself from /dev/urandom (if available) or the current time.
Don't skip the first 10 bytes. That code was there to skip the magic
"GIMP_XMP_1" of the old "gimp-metadata" parasite. Instead, properly
check for that magic in xcf_load_image() and pass only the actual XMP
to gimp_metadata_set_from_xmp(). Also remove the +10 hack in file-exr.
"exif-data" parasite
To migrate old "exif-data" parasites to GimpMetadata
an exif-only jpeg file is generated in memory, but its
APP1 marker length was 2 bytes short resulting in a
CRITICAL warning:
** (gimp-2.9:9): CRITICAL **: Directory Photo: IFD exceeds data buffer, cannot read next pointer.
Properly terminating the jpeg with an EOI marker also
gets rid of the WARNING:
** (gimp-2.9:9): WARNING **: JPEG format error, rc = 5