Certain cloud providers return a blobname
rather than the actual filename with
g_file_get_uri (). Since our code only checks
the suffix and extension of non-native files,
we received "Unknown File Type" when
trying to load images from those providers.
This patch replaces g_file_get_uri () so that
we get the display-name instead, which
should always have the extension. This
may be changed in the future when we
switch to a FileChooser portal.
This same pattern is also used on the
GimpThumbBox so we see the display-name
rather than the blob name.
Thanks to Khalid Abu Shawarib for the
additional information!
when creating a new image.
We add a new function `gimp_metadata_set_creation_date` to
`libgimpbase/gimpmetadata` to handle setting all relevant
metadata tags.
We add a local function `gimp_image_new_add_creation_metadata` to
add the creation date metadata to relevant functions that create
new images.
We write tags for both the creation date and several modified dates
for IPTC, XMP and Exif metadata. All these use different ways to
express date/time and timezones and I can already see we need to have
another look at other places where we handle modified dates.
This solves the second part of #7287, adding metadata about the
date/time a new image was created.
When starting from an image we created in GIMP, saving/exporting with
metadata and/or thumbnail (thumbnails are part of the exif metadata)
failed, because our metadata was not initialized for newly created
images.
To fix this, create a metadata object in `gimp_create_image`, that way
when creating a new image in the gui, but also when creating an
image programmatically, gets metadata attached at the start.
We need to do that here, because we need to have metadata available
even for images that we import that do not have metadata attached.
A flush happens when closing image displays, and with the idle code, it
means that the actual flush may happen once the image is already freed.
When I was saying that multi-threading is always full of surprises…
The fix is basically to make gimp_projection_flush() thread-safe, so
that it can be called from any thread.
The actual rendering was actually already run in the main thread since
it was in an idle function, but update_region could be touched both from
the main thread and another thread (e.g. the "paint" thread). An
alternative could have been to put some mutex to protect usage, but then
I realized that iter variable was also to be protected, and there was
some code where I am unsure if we had to protect larger parts of code
(in particular with gimp_projection_projectable_bounds_changed() which
was touching update region through gimp_projection_chunk_render_stop()
then directly). The nice headaches of multi-threading!
Moving the whole actual logic of gimp_projection_flush() in the main
thread seems much more robust and maintainable.
Committing every filter one by one had the same drawback as in #12614,
and as destructive effects in general: you have to go back to source
storage precision after every layer. This really shows its limits when
this precision is low (8-bit per component) and/or when the TRC loses
even more data (linear TRC in 8-bit is usually not a good idea) as shown
in the report.
So instead, use the render of the last active filter directly and switch
the drawable's buffer with it.
While it's normal to be limited to the storage precision at drawable
level, we want to have as high precision as possible during processing.
Two pieces of code were problematic in this regard:
1. GimpApplicator had a "gegl:convert-format" node which was converting
back to storage format after every effect. Instead only set this node
after the last effect.
2. "gimp:mask-components" operation was working with the input format.
Let's change this to work with the higher precision when comparing
input and aux format (typically when aux was the output of a previous
filter, now that we didn't convert format back to storage precision,
the aux precision may be bigger).
Resolves#12719 and #12721
In b78f3dad, we assume that a filter is being created for a
single operation. However, certain tools like Bucket Fill might
pass a GEGL Graph node instead. This causes the call to
gegl_node_get_gegl_operation () to return NULL, which then
crashes when we attempt to get the Operation Class.
This path verifies that we have a single operation before
attempting to go further with getting its class.
We always save the filter name in XCFs,
even if the user did not intentionally set
it. This means that "default" names like
Gaussian Blur are not translated when
saved and loaded in XCFs.
This patch adds a new property,
"custom-name", to GimpDrawableFilter.
It is FALSE by default, and only set to
TRUE if the user provides a custom filter
name (currently only possible in the
public filter API). Based off this value,
we either use the saved filter name or
get it from the operation when saving and
loading a filter from the XCF.
What it was doing was casting the input buffer to another TRC, basically
pretending the data was what it was not. In particular, it was casting
linear input buffers to non-linear and all other TRCs to linear.
As was noted in #1958, this was in fact a useful trick, yet it's still a
trick. Basically when it's needed, it's either:
1. because the operation implementation does not work in the technically
correct space. Then the operation code should be fixed;
2. or because several work TRC are valid, then an option should be
proposed by the operation;
3. or for artistic reasons, which people are free to implement as
plug-ins or third-party filters, but it should not be a core GIMP
feature.
Therefore for most cases where it felt needed, the real solution will be
to improve the operations' implementations.
Currently, we do not handle copying multiple channels.
The function call returns NULL but does not set an error
message - this causes a crash when we try to print out
error->message.
This patch changes the g_return_val_if_fail () call to an
IF statement, so that we can initialize the error object
with a message to prevent the crash.
When the user checks "Merge Filters" on interactive filters,
we move the filter to the bottom of the stack so it applies
directly onto the drawable (instead of merging the entire filter
stack).
However, we did not do this reordering for non-interactive filters,
resulting in incorrect output. This patch applies the same logic
so that when you apply a filter like Invert, it affects the drawable
only and does not cause problems for any existing NDE filters.
In particular, we could end up with mask of wrong bytes per pixel, which
was what was happening in the report.
This commit adds a new GimpDrawableFilterMask class because we needed to
implement a specific is_attached() method for effect masks.
Note: the file is added to POTFILES but the only localized string
already existed elsewhere. So this doesn't break string freeze.
1. After discussions on IRC, we agreed that "A new perceptual blending
space was added in GIMP 3.0" was a nicer reason to display for
bumping the XCF version, because instead of focusing on fixes, we
focus on the new feature (a real "perceptual blending space" was
added for modes) and also because naming "perceptual" in some form
seems more helpful for people to figure out what is different.
2. Fixing sensitivity of the non-linear (formerly named perceptual)
actions when the blend or composite spaces are mutable.
In previous versions what has been stored/specified as perceptual blending or
compositing spaces has really been the non-linear variant of the images babl
space.
To maintain loading of old files, the code has been updated to actually mean
non-linear and a new perceptual value has been added to the GimpLayerColorSpace
enum, while preserving all old enum values.
This change bumps XCF file version to 23
It is this way possible to set a drawable as auxiliary input to a filter
in C and GObject-Introspected bindings.
Note that such filters can only be merged, not appended
non-destructively for the time being.
Also adding an example of using it in the C goat exercise, though I
leave it commented out because showing code for direct GEGL usage is
also of interest.
As a side update, I am adding proper support of the NULL or empty string
value for the filter name. In this case, the default human-readable
title of the operation will be used instead.
Similarly to the config arguments, the set functions are not directly
calling core. Instead they are queuing changes until
gimp_drawable_filter_update() is run.
It is now possible to sync the GimpDrawableFilterConfig with core.
Another (simpler on usage) possibility could have been to sync
automatically when a property is updated. But considering that some
filters can be quite slow to render (especially in real-life usage when
working on possibly very big files), and especially that on bindings
with no variable args, scripts will likely have to edit properties one
by one, it could make editing multiple properties very slow. Therefore
the chosen solution is that editing properties stay local on libgimp and
all changed properties are synced with core at once (with a frozen
render until the end for single computation) when calling
gimp_drawable_filter_update().
A few functions were added, but the main one is
gimp_drawable_get_filters() to request the list of filters applied
non-destructively on a drawable. We can't do much with these for the
time being, but this will come.
WIP.
in gimp:offset filter.
Since gimp:offset is now an NDE filter,
always loading the background color from
context causes the color to change each
time the filter is redrawn. This is inconsistent
behavior.
This patch replaces the GimpContext
parameter with GeglColor, and updates
gimp_drawable_offset and related functions
to set the color directly. The libgimp version
loads the background color from context
and passes it on since the API is now
frozen.
Resolves#12478
There was existing code to scale the Lightness value of LAB
colors by 100 to match the 0.0 - 100.0 range used in babl.
However, it was not actually running because the `color_space`
value was not being properly cleaned before the comparison.
For this to work properly, I don't process them line by line, like all
other actions. Instead, I do a post-processing pass where I verify if
both variants were set, and if so, with an acceleration or with an empty
string. Indeed several cases are triggered:
1. We may migrate with 2 custom shortcuts on the same action;
2. we may mix 1 custom shortcut with one of the default shortcuts;
3. we may disable one of the default shortcut but not the other;
4. we may disable both shortcuts.
These were removed in commit 2c4f91f585, though I do wonder if this may
not have been a mistake since edit-paste and edit-paste-in-place are not
exact equivalent. They may still create floating items in some cases.
But that's good enough for now.
This is an improvement over commit ce2a9dc3eb which was only meant to
work for GIMP 3.0. This new code should work for 3.2 and any future
version too. It will try to migrate any configuration folder from GIMP
2.0 to whatever is the current version.
Resolves issue #12252
Unlike the layer and image commands for scale layers,
the Transform Tools use gimp_item_transform () rather than
GimpDrawable's scale/rotate code. Therefore, the filter's crop
was not being refreshed, resulting in the layer being cut off
after the transform.
This patch moves the gimp_drawable_filter_refresh_crop ()
code to gimp_item_transform () so that the new layer size
is taken into account in the filter.
This replaces the GIMP_RGB_LUMINANCE () macro with
babl_process () to retrieve luminance from pixels
in GimpHistogram. This allows us to consider the
color space during the conversion, rather than assuming
sRGB always.
While they work well, the gegl_node_get_bounding_box ()
call causes the entire filter stack to refresh
each time we need to update the filter stack.
This slows down rendering significantly.
For 3.0 RC1, it's better to have good performance
and deal with the less common crop
issue for now. We'll work to find a better
performing solution for 3.0.
There are 2 *_get_list() for buffers and dynamics but since we don't
have clases for these, they still just return a list of names for now.
I opened #12268 for further thinking on these.
Several types functions were using the wording "float" historically to
mean double-precision, e.g. the float array type (which was in fact a
double array). Or the scanner function gimp_scanner_parse_float() was in
fact returning a double value. What if we wanted someday to actually add
float (usually this naming means in C the single-precision IEEE 754
floating point representation) support? How would we name this?
Now technically it's not entirely wrong (a double is still a floating
point). So I've been wondering if that is because maybe we never planned
to have float and double precision may be good enough for all usage in a
plug-in API (which doesn't have to be as generic so the higher precision
is enough)? But how can we be sure? Also we already had some functions
using the wording double (e.g. gimp_procedure_add_double_argument()), so
let's just go the safe route and use the accurate wording.
The additional change in PDB is internal, but there too, I was also
finding very confusing that we were naming double-precision float as
'float' type. So I took the opportunity to update this. It doesn't
change any signature.
In fact the whole commit doesn't change any type or code logic, only
naming, except for one bug fix in the middle which I encountered while
renaming: in gimp_scanner_parse_deprecated_color(), I discovered a
hidden bug in scanning (color-hsv*) values, which was mistakenly using a
double type for an array of float.
So this one is a complicated beast, because inside the flatpak's
sandbox, ~/.var/ will not be the same as on the host (even with home
permission). In particular, we won't be able to find the 2.10 config folder in
there when running GIMP 3.
Yet local ~/.var/app/org.gimp.GIMP/config/ is in fact be mounted to
/var/config/! So inside the sandbox, this is where we must look in to
find a previous 2.10 config folder.
With this change, both flatpak and non-flatpak GIMP should be able to
find a 2.10 config folder both in the host XDG_CONFIG_HOME and inside
~/.var/ by:
* First looking inside XDG_CONFIG_HOME;
* Then looking in ~/.var/app/org.gimp.GIMP/config/ (which in non-flatpak
environment will find a former flatpak config folder);
* Finally looking in /var/config/, but only is /.flatpak-info exists (so
we are in a flatpak, and in there, this is the mapping for the host
~/.var).
This is not tested inside the flatpak sandbox yet.
This was bothering me that we were keeping these macros marked as legacy
in our public headers. Now they aren't so we can delete the whole file
when we'll finally get rid of all usage later, without breaking API.
Resolves#12198.
When dragging a layer to the toolbox to create a new
image, we weren't copying over the filters. This is because
that action still uses gimp_image_new_from_drawable ()
rather than the multi-layer capable gimp_image_new_from_drawables ()
function.
For now, we'll fix the immediate problem by implementing the filter
copy code in this function. Long term, we should port that code to
use gimp_image_new_from_drawables () instead.
...to gimp_drawable_has_visible_filters ().
With NDE filters, it's now possible to have
filters that are not active but still attached
to a layer. This patch renames the API to
prevent confusion as seen in prior
commits.
Similar to afc0a6d1, we need to use gimp_drawable_get_filters () to
get the total number of filters rather than gimp_drawable_has_filters (),
which just returns if any filters in the stack are active/visible.
Because of this, we weren't updating the XCF version to 22 when we
saved a file that had all of its layer effects set to invisible/inactive.
Always update stored colors. When colors are perceptually identical, we
only bypass color rendering code, but not the color value update (even
small value updates need to be echoed across the code, so that what is
shown is always what is set).