gimp_display_shell_render() writes to a GeglBuffer backed by allocated memory
(shell->profile_data). Unfortunately while converting prevision in
gimp_image_convert_precision(), we change the "precision" property (hence the
source format) first, hence end up trying to write data in a too small buffer.
This crash was hard to find as it was not showing up on my machine (though it
did produce rendering artifacts!), unless I built both GIMP and babl with
`b_sanitize=address`.
Note that an alternate fix was to make sure that the profile_data buffer is big
enough (by calling gimp_display_shell_profile_update() before rendering), but
anyway the image is in an inconsistent state while conversion is in progress:
whereas the `src_format` is the new one, the `src_profile` is still the old one
(and cannot be changed before we finish converting).
Moreover the render happen regularly on progress signals, once after each
converted drawable. So each of these rendering step happens in an inconsistent
state, with the wrong profile set, some of the drawables converted and others
not yet.
We could still render properly if each drawable's buffer used space-aware format
(thus allowing different drawables to use different profiles/spaces), but it
feels over-engineering the problem. It might be much better to ignore rendering
steps while converting the image precision. Moreover it would obviously make a
faster conversion.
See discussions in #9136 for this crash, which didn't have dedicated report
AFAIK.
A bug in babl would run the color conversion twice when the input and output
buffer is the same and a LUT is available for the color transform. This is a
workaround in GIMP code (especially because we still don't require the latest
babl version), though a real bug fix will soon happen too in babl itself as
well.
gimp_channel_is_empty returns FALSE if channel is NULL. This causes
gimp_layer_invalidate_boundary to crash if the mask channel is NULL.
With a NULL channel gimp_channel_is_empty should return TRUE, just like
the similar gimp_image_is_empty does, because returning FALSE here
suggests we have a non empty channel.
(cherry picked from commit 22af0bcfe6)
With large image sizes a 32-bit int is not enough for the intermediate
computations, which byte per pixel, width and height are.
So, just like the function below it does: gimp_gegl_pyramid_get_memsize,
we will cast these to gint64.
Thanks to Massimo Valentini for finding the cause.
(cherry picked from commit ba841a98da)
Fix as suggested by Massimo with formatting adjustments by me.
The use of gulong and glong is not cross platform safe: on Windows it is
32-bit and on most other platforms 64-bit.
Let's use guint64 and gint64 instead.
(cherry picked from commit d2c5591088)
As noted in issue #6032 the error message when trying to open a pattern
file with dimension larger than supported could be a little clearer.
We do this by adding the maximum allowed dimensions to the error message.
(cherry picked from commit 317b5d9cff)
For GIMP patterns we have maximum allowed dimensions which we check when
loading a pattern. However, we did not check this when saving a pattern.
See issue #6032.
This commit adds a check when saving a pattern and adds a descriptive
error to make clear why saving fails.
(cherry picked from commit f130fe1917)
g_alloca() is unadvised. Even though it might be more efficient in some
specific cases, it is pretty subject to stack overflow when a lot of
memory is requested.
Let's allocate dynamic memory instead. To avoid doing it too much, let's
just reuse the same pointer especially since region of interest will
usually be the same size when iterating a buffer, except for border
ones (which would usually be smaller, so we can use the same allocated
buffer again). I still make size checks, just in case.
(cherry picked from commit f2fb98cb69)
Removing useless condition, add a g_return_if_fail() assertion for the
only (impossible unless bug) case which we don't expect. Also set
default mindist to G_MAXLONG instead of a magic number (which was ok now
but might become a problem if some day colormap allowed more than 16-bit
per channel colors).
Finally break when we reach a distance of 0 since we won't get lower
anyway, so better stop early.
Thanks to Rafał Mikrut and Øyvind Kolås for code commenting.
(cherry picked from commit d6dac25579)
We cannot just compare the drawable format with the model-type specs of
the color model. We need to include the space now.
In my case, some random screenshot converted to gray then indexed would
assert because the format is "Y' u8-space-gray-sRGB" (or for layers with
alpha: "Y'A u8-space-gray-sRGB"), hence indexed conversion failed and
ended up dark.
(cherry picked from commit c0e605ef96)
This commit also makes snap to grid and snap to vectors work off-canvas.
Since we now have off-canvas viewing, it just makes sense that snapping
would work there too.
Note that I disable snap to grid when "Show All" is OFF. I am actually
unsure this is right (as "Show All" is a view action, and we usually
don't change behavior based on view actions; for instance snap to guides
are not disabled if guides are hidden). Yet I noticed we do this in
various other features when off-canvas. We kind of use this view flag as
a switch for features working off-canvas (for instance, color picking
works off-canvas only when "Show All" is ON). So let's keep the same
logics for now at least.
Snap to guide or snap to vectors will always work though, because guides
and vectors are always visible off-canvas (even when "Show All" is OFF).
They always have been (visible, not snappable off-canvas; now they are
both).
(cherry picked from commit 82438728fb)
… DBus calls.
In particular, Aryeom would start GIMP and directly double click some
image to be loaded in GIMP in the very short while when splash is
visible. Previous code would wait for the `restored` flag to be TRUE.
This was nearly it as we can actually start loading images as soon as
the 'restore' signal has passed. Yet the flag is set in the main
handler, but we actually also need the <Image> UI manager to exist,
which is created in gui_restore_after_callback() (so also a 'restore'
handler, yet after the main signal handler, i.e. after `restored` is set
to TRUE). Without this, gui_display_create() would fail with a CRITICAL,
hence file_open_with_proc_and_display() as well.
I could have tried to set the `restored` flag later, maybe with some
clever signal handling trick (and handle both the GUI and non-GUI cases,
i.e. I cannot set the flag inside gui_restore_after_callback() as it
would break the non-GUI cases). Instead I go for a simpler logics with a
new `initialized` flag which is only meant to be set once, once
everything has been loaded, i.e. once you can consider GIMP to be fully
running hence ready to process any common runtime command.
(cherry picked from commit a86ed68870)
Basically if you enabled OpenCL or any of the experimental tools, it
will show the Playground in Preferences. Otherwise, say you enabled some
experimental feature months ago (e.g. with the CLI option) and you now
experience crashes or whatnot. And you forgot how to change it, and only
remembered that there was something in Preferences. It would make you
crazy to not find the tab again to disable the option.
This is even more important as OpenCL is moving from a normal option to
a playground option. So you might not even have ever seen the Playground
tab in Preferences and would not know how to disable OpenCL after you
enabled it originally in "System Resources" tab.
So now Playground is visible with any of these 3 conditions:
* If you use an unstable version.
* If you run GIMP with --show-playground option.
* If you previously enabled one of the playground options.
(cherry picked from commit d3ef6cfb18)
Fix horizontal downscaling of brush mipmap levels with odd width.
We'd previously fail to skip the last pixel of each input row,
which isn't included in the output when the width is odd, causing
subsequent output rows to be shifted to the right.
(cherry picked from commit c4a201eaf4)
In GimpDrawableFilter and GimpFilterTool, use an absolute offset
for the split-preview guide position, instead of storing it as a
fraction of the drawable's width/height. The latter could
introduce rounding error, which would result in wrong coordinates
when converted back to an absolute offset.
(cherry picked from commit 214936e8c6)
Mostly I am adding a counter to the insignifiant zone fill, to be double
sure we are not going to fill huge areas (this should not happen already
anyway) and also it is no use to sample the line art buffer in such
case.
(cherry picked from commit 248477a125)
In GimpImageProxy, implement GimpColorManaged by forwarding the
functions to the underlying GimpImage, and forwarding the signals
in the other direction. This fixes color-managed view in the
Navigation dockable.
(cherry picked from commit 258c8454d5)
When converting an image to indexed mode, zero-out transparent
pixels instead of leaving junk in their indices, which might well
be out of range of the palette.
(cherry picked from commit 09870d4b15)
Wherever we store arbitrary-format colors in an opaque buffer, use
double for the buffer, instead of char, so that it has a strict-
enough alignment to handle all our used pixel formats.
(cherry picked from commit a90f59d961)
There is no non-hackish way of fixing this without adding a new
"use-opacity-paint-mode" property to GimpToolPreset and a new toggle
in GimpToolPresetEditor. Restoring opacity and paint mode can now be
controlled explicitly, and defaults to TRUE.
(cherry picked from commit 97b714d428)
By only doing the snapping to white/black for whitest/blackest palette
entries when the original RGB data contained these colors we permit
choosing near white/black colors in the cases where this might be
a desirable result as the whitest/blackest colors.
(cherry picked from commit d4387987b5)
The median-cut algorithm to derive a suitable palette for the image
computes each index to be used as the average of colors in a 3d box
in a color space, making the result value drift away from the extremes.
This makes it nigh impossible to achieve pure white or black, even
when the original image contained these colors, like in scans of
printed documents and technical drawings.
We counteract the drift by snapping the whitest color to white and the
blackest color to black if the resulting colors of median-cut are
already sufficiently close to white or black.
(cherry picked from commit 9bb3ff42d7)
In gimp_curve_config_copy(), make sure to copy the curve type
*before* the points, so that, when changing the type from FREE to
SMOOTH, we don't overwrite the copied points with interpolated
samples.
(cherry picked from commit 56693a8393)
Add a new gimp_drawable_apply_operation_with_config() function,
which takes an operation node together with a config object, and
applies the operation using the config options, including both the
operation-specific options, and the common GimpOperationSettings
options.
Use the function in gimp_gegl_procedure_execute(), so that
reapplying a filter takes the common operation settings used
originally into account.
... which determines if a node's operation-class has a specific
key, and can be used instead of gimp_gegl_node_get_key() when only
existence is important, to avoid compiler warnings.
Update the rest of the code to use the new function.
Cropping tools will no longer discard layer data that falls out of the
crop region if the layer's pixels are locked
(cherry picked from commit 9a9e2e9a19)
In gimp_symmetry_{mirror,mandala}_update_strokes(), adjust the
symmetry origin according to the drawable offset, so that it
remains fixed relative to the image regardless of the drawable
position.
(cherry picked from commit 6ed9b2bb7a)
In gimp_image_duplicate(), explicitly mark the new image as dirty,
so that its dirty time is set. This avoids showing a NULL message
in place of the dirty time when closing the image.
(cherry picked from commit 83f935873a)
In gimp_drawable_get_sub_preview_async(), when the drawable buffer
has a validate handler (i.e., when it's a group layer), use a chunk
iterator to validate the buffer in chunks, where each chunk is
validated in a separate invocation of the async function. This
prevents validation from blocking the main thread for too long when
the buffer is not already fully validated.
(cherry picked from commit 64bf77aed8)
In gimp_drawable_get_sub_preview_async(), when the drawable buffer
has a validate handler (i.e., when the drawable is a group layer),
validate the requested area before calling gegl_buffer_get(), so
that the buffer is validated in a single step, instead of tile-by-
tile.
(cherry picked from commit 919ddce773)