Issue #427: Hue-saturation dialog: lightness in 'Master'
For whatever reason that made sense at the time, the current
Hue-Saturation code divides the result of Lightness slider
adjustments by 2, which means the user can't ever move the
Lightness slider to produce a solid white or black image, and
requires multiple iterations if the user wants to make the image
very light or very dark.
This patch just removes the division by 2, thus allowing the full
range of Lightness changes without having to use multiple
iterations.
which means that it's now included normally via gimpbase.h
and not any longer via gimpbasetypes.h which we only did out
of lazyness. A *lot* of files in libgimp* and app/ now need to
The latter is broken and doesn't guarantee a decimal point with the
current bug. Also, g_ascii_dtostr() doesn't need the format parameter
and produces nicer output.
- Change the wire protocol's GPProcInstall to transmit the entire
information needed for constructing all GParamSpecs we use, don't
use GimpPDBArgType in GPProcInstall but an enum private to the wire
protocol plus the GParamSpec's GType name. Bump the wire protocol
version.
- Add gimpgpparamspecs.[ch] in both app/plug-in/ and libgimp/ which
take care of converting between GPParamDef and GParamSpec. They
share code as far as possible.
- Change pluginrc writing and parsing to re-use GPParamDef and the
utility functions from gimpgpparamspecs.
- Remove gimp_pdb_compat_param_spec() from app/pdb/gimp-pdb-compat.[ch],
the entire core uses proper GParamSpecs from the wire protocol now,
the whole file will follow down the drain once we use a GValue
representation on the wire too.
- In gimp_plug_in_handle_proc_install(), change the "run-mode"
parameter to a GParamSpecEnum(GIMP_TYPE_RUN_MODE) (if it is not
already an enum). and change all places in app/ to treat it as an
enum value.
- plug-ins: fix cml-explorer to register correctly, a typo in
"run-mode" was never noticed until now.
- Add gimpgpcompat.[ch] in libgimp to deal with all the transforms
between old-style wire communication and using GParamSpec and
GValue, it contains some functions that are subject to change or
even removal in the next steps.
- Change the libgimp GimpProcedure and GimpPlugIn in many ways to be
able to actually install procedures the new way.
- plug-ins: change goat-exercise to completely use the new GimpPlugIn
and GimpProcedure API, look here to see how plug-ins will look in
the future, of course subject to change until this is finished.
- Next: changing GPParam to transmit all information about a GValue.
In gimp:gradient, fix dithering to correspond to how we actually
round float values to 8-bit. In particular, this avoids
introducing noise when a component is fixed at 0 or 1 along a
segment.
Fixes issue #3451 Space invasion/AnyRGB: Luminance blend mode doesn't work
It might be faster to fetch the RGB luminance and do the computation
ourselves than looking up the same fish for each processing request, at
least now we're faster. (commit message and code slightly revised by pippin)
Some blend funcs depend on constants from the specifc color space we are
operating in and needs the space or operation propagated to the worker function
of the operation as discovered in issue #3451.
This commit propagates the operation, leaving the specific blend functions
needing it to call gegl_operation_get_source_space or similar without needing
that overhead for the rest.
Issue #3436 Replace sRGB Y values with Y values from XYZ for the
image's actual RGB space
This patch is for Colors/Desaturate/Desaturate to Luminance or
Luma.
Blacklist the "tools-offset" action in the GUI, and only keep
"filters-offset", to avoid duplication. Update gimp:offset's
description, so that "filters-offset" gets a proper tool-tip.
Add a new gimp:offset operation, which implements equivalent
functionality to gimp_drawable_offset(), in preparation for adding
an interactive offset tool.
To simplify things, add a GIMP_OFFSET_WRAP_AROUND value to the
GimpOffsetType enum, to avoid the need for a separate wrap-around
flag. This makes the gimp-drawable-offset procedure parameters a
little superfluous, but whatever.
In gimp:mask-components, add an "alpha" property, which controls
the masked-in alpha value in case there's no aux buffer. Set it to
0 by default, so that gimp:mask-components behaves normally in the
absence of an aux buffer (as if the aux buffer was empty). Set it
to 1 in the image's visible-mask node, to maintain the current
alpha-component visibility behavior.
This fixes incorrect results when the output bounding box of a
drawable filter is smaller than the drawable, which can lead to a
NULL aux buffer being fed to the filter's gimp:mask-components
node.
In GimpOperationLayerMode and GimpOperationReplace, make sure we
don't return a NULL output buffer, or forward a NULL input buffer,
but rather create an appropriate empty buffer in this case. This
avoids wrong results when the layer-mode op's output is connected
to the aux input of a subsequent op, as a result of the op behaving
differently with a NULL aux buffer (in particular, this can happen
when a drawable filter's output bounding box is smaller than the
drawable.)
Extend last commit to also disregard the composite space when the
layer mode is trivial and only the source region is included in
compositing, since, in this case, the source color is unmodified.
In gimp_layer_mode_get_format(), disregard the requested composite
space when selecting the format, if the input layer mode is alpha-
only, and the requested composite mode is not UNION, since, in this
case, the layer mode doesn't combine the layer/backdrop colors, and
rather only modifies the alpha of one of them. This allows us to
use the preferred format, avoiding gamma conversion.
This particularly improves the performance of the Eraser tool in
perceptual images.
In GimpCurve, replace the use of a fixed-length control-point array
with a dynamically-sized array. Adapt GimpCurve's interface, and
the rest of the code.
In addition to simplifying the code, this fixes a bug where the
curve object could be broken by moving the mouse too fast (yep...),
and allows more accurate point placement, both in the GUI editor,
and through canvas interaction in the Curves tool (see issue #814).
Add a new gimp:fill-source operation, which can act as a source
node for fill operations, instead of a fill buffer. The op takes
a GimpFillOptions object, a drawable, and a pattern offset, and
uses gimp_fill_options_create_buffer() to produce its output.
This allows performing the entire fill operation in chunks as a
graph, instead of allocating a full-size fill buffer, which can
can occupy a lot of space for pattern fills.
Fix gimp:mask-components to use full-oapcity value for the alpha
component when it's masked-in and there's no "aux" input, so that
the image is rendered with full opacity when the alpha channel's
visiblity is toggled off, as per bug #143315.
Replace the use of the deprecated GeglNode::dont-cache property,
and GeglOperationClass::no_cache field, with GeglNode::cache-policy
and GeglOperationClass::cache_policy, respectively.
See commit gegl@7f24430cda0d8c3eff311868823d445edc2a4e12.
Add specialized versions of gimp:mask-components for 8-, 16-, and
32-bpc formats, to improve efficiency, and to preserve the contents
of masked-out components exactly.
Provide public functions for format-selection and processing, which
we'll use in the painting code, instead of reimplementing component
masking.
When the result of compositing has an alpha value of 0, the
corresponding color value is not mathematically defined.
Currently, all out layer modes opt to preserve the destination's
color value in this case. However, REPLACE mode is different
enough to warrant a different behavior:
Unlike the other layer modes, when the compositing opacity
approaches 0 or 1, the output color value approaches the
destination or source color values, respectively, regardless of the
output alpha value. When the opacity doesn't approach 0 or 1, the
output color value generally doesn't approach a limit as the output
alpha value approaches 0, however, when both the destination and
source alpha values are equal, the output color value is always a
simple linear interpolation between the destination and source
color values, according to the opacity. In other words, this means
that it's reasonable to simply use the above linear interpolation
for the output color value, whenever the output alpha value is 0.
Since filters are commonly combined with the input using REPALCE
mode with full opacity, this has the effect that filters may now
modify the color values of fully-transparent pixels. This is
generally desirable, IMO, especially for point filters. Indeed,
painting with REPLACE mode (i.e., with tools that use
gimp_paint_core_replace()) behaved excatly as described above, and
had this property, before we switched gimp_paint_core_replace() to
use the common compositing code; this created a discrepancy between
painting and applying filters, which is now gone.
A side effect of this change is that we can now turn gimp:replace
into a NOP when the opacity is 100% and there's no mask, which
avoids the compositing step when applying filters. We could
previously only apply this optimization to PASS_THROUGH mode, which
is a subclass of REPLACE mode.
Note that the discussion above concerns the UNION composite mode,
which is the only mode we currently use REPLACE in. We modify the
rest of the composite modes to match the new behavior:
CLIP_TO_BACKDROP always preserves the color values of the
destionation, CLIP_TO_LAYER always preserves the color values of
the source, and INTERSECTION always produces fully-zeroed pixels.
In gimp:gradient, when using adaptive supersampling, render the
gradient tile-by-tile, using an iterator, instead of row-by-row.
This significantly improves performance, while also avoiding the
assumption that gimp_adaptive_supersample_area() works row-by-row.
Additionally, when not using supersampling, use a single GRand
instance, since the separation to distinct seed and per-tile
instances, which was a threading optimization (commit
7f39e41254), is no longer needed.
The scratch allocator has been moved to GEGL (commit
gegl@b99032d799dda3436ffa8c1cc28f8b0d34fb965d). Remove gimp-
scratch, and replace all its uses with gegl-scratch.
This commit completely removes the "Edit -> Fade..." feature,
because...
- The main reason is that "fade" requires us to keep two buffers,
instead of one, for each fadeable undo step, doubling (or worse,
since the extra buffer might have higher precision than the
drawable) the space consumed by these steps. This has notable
impact when editing large images. This overhead is incurred even
when not actually using "fade", and since it seems to be very
rarely used, this is too wasteful.
- "Fade" is broken in 2.10: when comitting a filter, we copy the
cached parts of the result into the apply buffer. However, the
result cache sits after the mode node, while the apply buffer
should contain the result of the filter *before* the mode node,
which can lead to wrong results in the general case.
- The same behavior can be trivially achieved "manually", by
duplicating the layer, editing the duplicate, and changing its
opacity/mode.
- If we really want this feature, now that most filters are GEGL
ops, it makes more sense to just add opacity/mode options to the
filter tool, instead of having this be a separate step.
Add a TRIVIAL layer-mode flag, and corresponding
gimp_layer_mode_is_trivial() function, which indicates if the blend
function of a given layer mode is trivial, i.e., either never
modifies the source pixels (for non-subtractive modes), or always
clears the destination pixels (for subtractive modes).
In the Luminance layer-mode, use the scratch allocator for
allocating temporary buffers, instead of using VLAs.
GimpOperationLayerMode already allocates data on the stack,
calculated as not to overflow the stack on any platform, so having
any of its descendants also allocate big buffers on the stack is
risky.
There was a global 3x3 array of babl fishes used for converting between
blending and compositing pixel representations, these were all hard-coded to
operate within the sRGB babl-space family. This commit updates a per-instance
array during operation prepare instead, that comes preconfigured with fishes
derived from the correct space. Since the same operation instance might get
different space input during its life time we store and compare the cached
fishes with the current format (which is unique depending on space).
This should address the problem seen in issue #2592
Use gimp_tile_handler_validate_validate(), added in the commit
before last, in gimp:buffer-source-validate, in order to pre-render
the necessary region of the buffer, instead of performing the
validation implicitly by iterating over the region. This is both
simpler, and, more importantly, allows us to render the entire
region in a single chunk, instead of tile-by-tile, which can be
considerably more efficient, especially with high thread counts.
This essentially extends the dynamic sizing of rendered projection
chunks to layer groups, which are rendered through
gimp:buffer-source-validate, rather than just the main image
projection.
Add a Babl space parameter to gimp_gegl_color_new() and all utility
functions using it. Pass NULL if the GimpRGB actually is sRGB, pass
the image's layer space if the color was already converted using
gimp_pickable_srgb_to_image_color() or similar.
Fixed by implementing Massimo's two findings:
gimp_operation_cage_transform_process(): if aux_buf is NULL, bail out
after initializing out_buf with identity vectors, fixes the crash.
gimp_cage_tool_create_filter(): set the drawable filter's region to
GIMP_FILTER_REGION_DRAWABLE, fixes offset when there is a selection.
All babl formats now have a space equivalent to a color profile,
determining the format's primaries and TRCs. This commit makes GIMP
aware of this.
libgimp:
- enum GimpPrecision: rename GAMMA values to NON_LINEAR and keep GAMMA
as deprecated aliases, add PERCEPTUAL values so we now have LINEAR,
NON_LINEAR and PERCPTUAL for each encoding, matching the babl
encoding variants RGB, R'G'B' and R~G~B~.
- gimp_color_transform_can_gegl_copy() now returns TRUE if both
profiles can return a babl space, increasing the amount of fast babl
color conversions significantly.
- TODO: no solution yet for getting libgimp drawable proxy buffers in
the right format with space.
plug-ins:
- follow the GimpPrecision change.
- TODO: everything else unchanged and partly broken or sub-optimal,
like setting a new image's color profile too late.
app:
- add enum GimpTRCType { LINEAR, NON_LINEAR, PERCEPTUAL } as
replacement for all "linear" booleans.
- change gimp-babl functions to take babl spaces and GimpTRCType
parameters and support all sorts of new perceptual ~ formats.
- a lot of places changed in the early days of goat invasion didn't
take advantage of gimp-babl utility functions and constructed
formats manually. They all needed revisiting and many now use much
simpler code calling gimp-babl API.
- change gimp_babl_format_get_color_profile() to really extract a
newly allocated color profile from the format, and add
gimp_babl_get_builtin_color_profile() which does the same as
gimp_babl_format_get_color_profile() did before. Visited all callers
to decide whether they are looking for the format's actual profile,
or for one of the builtin profiles, simplifying code that only needs
builtin profiles.
- drawables have a new get_space_api(), get_linear() is now get_trc().
- images now have a "layer space" and an API to get it,
gimp_image_get_layer_format() returns formats in that space.
- an image's layer space is created from the image's color profile,
change gimpimage-color-profile to deal with that correctly
- change many babl_format() calls to babl_format_with_space() and take
the space from passed formats or drawables
- add function gimp_layer_fix_format_space() which replaces the
layer's buffer with one that has the image's layer format, but
doesn't change pixel values
- use gimp_layer_fix_format_space() to make sure layers loaded from
XCF and created by plug-ins have the right space when added to the
image, because it's impossible to always assign the right space upon
layer creation
- "assign color profile" and "discard color profile" now require use
of gimp_layer_fix_format_space() too because the profile is now
embedded in all formats via the space. Add
gimp_image_assign_color_profile() which does all that and call it
instead of a simple gimp_image_set_color_profile(), also from the
PDB set-color-profile functions, which are essentially "assign" and
"discard" calls.
- generally, make sure a new image's color profile is set before
adding layers to it, gimp_image_set_color_profile() is more than
before considered know-what-you-are-doing API.
- take special precaution in all places that call
gimp_drawable_convert_type(), we now must pass a new_profile from
all callers that convert layers within the same image (such as
image_convert_type, image_convert_precision), because the layer's
new space can't be determined from the image's layer format during
the call.
- change all "linear" properties to "trc", in all config objects like
for levels and curves, in the histogram, in the widgets. This results
in some GUI that now has three choices instead of two.
TODO: we might want to reduce that back to two later.
- keep "linear" boolean properties around as compat if needed for file
pasring, but always convert the parsed parsed boolean to
GimpTRCType.
- TODO: the image's "enable color management" switch is currently
broken, will fix that in another commit.
Use gimp_input_data_stream_read_line_always(), instead of
g_input_data_stream_read_line(), in a bunch of places that don't
expect EOF. If we don't do that, the code assumes the GError
parameter is set by the function and returns an error indication,
causing the caller to segfault when it tries to access
error->message. Instead, we now process an empty line when EOF is
reached, which is caught by the normal parsing logic.
Additionally:
- Use gimp_ascii_strto[id]() when loading gradients, generated
brushes, and palettes, to improve error checking for invalid
numeric input.
- Improve gradient-segment endpoint consistency check.
- Allow loading palette files with 0 colors. They can be created
during the session, so we might as well successfully load them.
The default stack size for new threads on MacOS is 512 KiB, making
our 512 KiB limit for stack-allocated buffers in
gimp_operation_layer_mode_real_process() too high. Lower it to
256 KiB.
... instead of gegl_buffer_sample()
GEGL commit 26f13cbfe9aaaa8c176162e54fdbb8af6876538e got rid of the
per-buffer cached samplers, making gegl_buffer_sample() much more
expensive, suitable primarily for one-off samples.
Use a sampler object instead.
... which determines if a layer mode's blend function only affects
the alpha, maintaining the backdrop's color. This is currently
true only for ERASE, SPLIT, and ANTI_ERASE modes.
Add gimp_drawable_gradient_adjust_coords(), which adjusts the
gradient segment coords according to the gradient type, so that, in
cases where the gradient span is unrelated to the segment length,
the gradient cache (in GimpOperationGradient) is big enough not to
produce banding. Use the new function in gimp_drawable_gradient()
and in the gradient tool, instead of duplicating the logic.
Move the shapreburst coordinate-adjustment logic to the new
function, and add appropriate logic for conical gradients.
Remove the code that avoids using the gradient cache for conical
gradients from GimpOperationGradient.
Undo the part of commit fa9a4108c3
that moved cache generation from process() to prepare(). prepare()
is called after each property change, in order to calculate the
op's bounding box for invalidation. Since we only need the cache
for actual processing, generating it in process() avoids that
overhead.
Invalidate the gradient cache while setting relevant properties,
and validate it, reconstructing if necessary, during prepare(),
rather than process(), to avoid the need to use a mutex.
Make sure the cache has at least two elements, corresponding to
the initial and final colors of the gradient, since both colors
might be needed, and to avoid division by zero.
Avoid using a cache if its necessary size is too big, or if the
gradient type is conical, since the necessary cache size for
conical gradients is unrelated to the gradient line length.
Improve index rounding during cache lookup.
Lots of indentation fixes.