I will be attaching some examples, but the lowdown is that gradients seem to be blending in sRGB only. This is sad. Reproducible: Always
Created attachment 90948 [details] The kra file for poking at.
Created attachment 90949 [details] png screenshot for easy viewing. Vertical: Gradient 1: 12,13 hdr red over 29.86 blue as a foreground-color-to-transparent. These values are out of range for me, so the blending is extreme, but it's still correct for a linear space. Note the purple. ( :) ) Gradient 2: 12.13 red with 29.86 blue as foreground-to-background-color: These values are still out of range, but instead they have been converted to 1.0 red to 1.0 blue, and are mixed with a non-linear gamma. ( :( ) Gradient 3: Also a foreground-to-background-color gradient with 12.13 red and 16.0 green. Again converted, again wrong mixing. ( :( ) Horizontal: Gradient 1: 1.0 red over 1.0 blue as a foreground-color-to-transparent. The blending is linear and nice ( :) ) Gradient 2: 1.0 white to 0.0 black as a foreground-color-to background-color-gradient. The mixing is non-linear, as evidenced by the middlish color being 0.28 grey. ( :( ) Gradient 3: 1.0 white over 0.0 black as a foreground-color-to-transparent. The blending is linear as evidenced by the middlish colour being 0.55 grey ( :) ) My rendering conversion is set to "Relative Colorimetric" btw, but that should not effect the bad blending of the gradients.
Also, Krita clips gradient-colors at 1.0.
*** Bug 344128 has been marked as a duplicate of this bug. ***
*** Bug 386492 has been marked as a duplicate of this bug. ***
regarding the dithering, there was a brnach that worked on it: https://phabricator.kde.org/source/krita/history/akapustin%252Fdithering2/
*** Bug 402834 has been marked as a duplicate of this bug. ***
In Morevna Project we also had much problems with gradients when used Krita. Example: Gradient from #353e66 to #2d0000 In Krita it gives non-uniform (non-smooth) gradient. In Gimp with the same colors the result is smooth. Does this bug covers described problem?
Created attachment 128472 [details] Gradient generated by Krita (notice non-smooth transition)
Created attachment 128473 [details] Gradient generated by Gimp
Yes, that basically the issue in this feature request.
A possibly relevant merge request was started @ https://invent.kde.org/graphics/krita/-/merge_requests/668
Git commit 4cfda40a29f9ee7548ab5d2f7320f2fca8674f65 by L. E. Segovia. Committed on 10/02/2021 at 18:50. Pushed by lsegovia into branch 'master'. Feature: HDR gradients This commit adds suport in Krita for rendering of HDR, high-bit-depth gradients, and dithering for all output bit depths. Firstly, all gradient operations are now upgraded; this includes color mixing ops (step values, upgraded to 16-bit signed integer), and gradients' default bit depth, which was upgraded to 16-bit integer or the image's bit depth, whichever is higher. Secondly, this commit implements a fully SSE+ vectorizable dithering operator, based on the Pixman low-level graphics library's implementation (MIT-licensed) available at the following commits: https://gitlab.freedesktop.org/pixman/pixman/-/commit/ddcc41b999562efdd9f88daa51ffbf39782748b5 https://gitlab.freedesktop.org/pixman/pixman/-/commit/98b5ec74ca14448349ef6a33a663ad19d446ed6b https://gitlab.freedesktop.org/pixman/pixman/-/commit/cb2ec4268fbde0df3b588ce5cbe2e43e0465452 This version follows closely the original paper of Ulichney's: Robert A. Ulichney. "Void-and-cluster method for dither array generation", Proc. SPIE 1913, Human Vision, Visual Processing, and Digital Display IV, (8 September 1993); doi:10.1117/12.152707 Based on Pixman's work, there are two available options (but three in code, see below): - a no-op downsampler - blue-noise Ulichney's dithering, 64x64, which is the default when enabled - Bayer's ordered dithering, 8x8, which has been left as a backup. The dither operator works by upcasting the pixel to normalized, floating point color space; applying modulated noise with scale 1 / 2^bit_depth, and then downcasting the pixel to the destination depth. For obvious reasons, the first step is skipped if the source is already floating point, and the two latter are no-ops if the destination's floating point. The implementation in this commit is structured in a two-level abstract pattern: - KisDitherOp is the interface that all operators expose to dither a single pixel. They are implemented as instances of KisDitherOpImpl<srcCSTraits, dstCSTraits, DitherType>. - KisDitherOpImpl is the template class that does the hard work described above. Instances of the dither operator are inserted on each colorspace through a templated, inlined factory function, addStandardDitherOps<srcCSTraits>(KoColorSpace *). Given the source bit depth and all known possible destination depths, this template calls another templated function, addDitherOpsByDepth< srcCSTraits, dstCSTraits, DitherType>(KoColorSpace *). Each call to this function creates a KisDitherOpImpl instance corresponding to each triplet of bit depths and dither implementation, and inserts it in the given colorspace. Since this operator needs both source and destination colorspaces' traits, I check at compilation time that all known traits have been considered at op creation. The vectorization properties have been tested with Xcode 11 on macOS, dumping kritalcmsengine.so with objdump, and checking disassembly manually. There are two ways to use this dither operator, once a copy has been obtained: - Use dither(const quint8* src, quint8* dst, int x, int y) to dither a single pixel. - Use dither(const quint8* src, int srcRowStride, quint8* dst, int dstRowStride, int x, int y, int columns, int rows) to dither a whole tile at once. This is the pattern that's used in KisGradientPainter. Additionally to Pixman's implementation, and the optimizations already provided by KoColorSpaceTraits, an optimized version has been made for the case of pass-through dither and no downcasting, where a memcpy call suffices. Finally, this implementation has been made available as a checkbox in: - the Gradient tool - Layer / Layer Styles / Gradient overlay - Fill Layers / Gradient generator Support has also been included for Photoshop's dithered gradients, when importing and exporting PSDs. As with the rest of Krita, they map to blue-noise dithering. Thanks to Wolthera van Hövell, Dmitry Kazakov, and Mathias Wein for their review. CCMAIL: kimageshop@kde.org M +10 -7 libs/global/kis_global.h M +5 -6 libs/image/kis_asl_layer_style_serializer.cpp M +73 -20 libs/image/kis_gradient_painter.cc M +6 -2 libs/image/kis_gradient_painter.h M +3 -1 libs/image/layerstyles/kis_ls_utils.cpp A +203 -0 libs/pigment/KisDitherMaths.h [License: MIT] A +52 -0 libs/pigment/KisDitherOp.h [License: GPL(v2.0+)] A +194 -0 libs/pigment/KisDitherOpImpl.h [License: GPL(v2.0+)] M +40 -3 libs/pigment/KoColorSpace.cpp M +11 -3 libs/pigment/KoColorSpace.h M +2 -2 libs/pigment/KoColorSpaceAbstract.h M +5 -1 libs/pigment/KoColorSpace_p.h M +3 -1 libs/pigment/colorspaces/KoLabColorSpace.cpp M +4 -1 libs/pigment/colorspaces/KoRgbU16ColorSpace.cpp M +3 -2 libs/pigment/colorspaces/KoRgbU8ColorSpace.cpp A +26 -0 libs/pigment/dithering/KisCmykDitherOpFactory.h [License: GPL(v2.0+)] A +26 -0 libs/pigment/dithering/KisGrayDitherOpFactory.h [License: GPL(v2.0+)] A +26 -0 libs/pigment/dithering/KisLabDitherOpFactory.h [License: GPL(v2.0+)] A +27 -0 libs/pigment/dithering/KisRgbDitherOpFactory.h [License: GPL(v2.0+)] A +26 -0 libs/pigment/dithering/KisXyzDitherOpFactory.h [License: GPL(v2.0+)] A +26 -0 libs/pigment/dithering/KisYCbCrDitherOpFactory.h [License: GPL(v2.0+)] M +40 -67 libs/pigment/resources/KoSegmentGradient.cpp M +17 -32 libs/pigment/resources/KoStopGradient.cpp M +11 -0 libs/psd/psd.h M +3 -0 libs/ui/dialogs/kis_dlg_layer_style.cpp M +34 -15 libs/ui/layerstyles/WdgGradientOverlay.ui M +3 -1 plugins/color/lcms2engine/colorspaces/cmyk_f32/CmykF32ColorSpace.cpp M +16 -13 plugins/color/lcms2engine/colorspaces/cmyk_u16/CmykU16ColorSpace.cpp M +1 -3 plugins/color/lcms2engine/colorspaces/cmyk_u16/CmykU16ColorSpace.h M +16 -13 plugins/color/lcms2engine/colorspaces/cmyk_u8/CmykU8ColorSpace.cpp M +1 -3 plugins/color/lcms2engine/colorspaces/cmyk_u8/CmykU8ColorSpace.h M +3 -0 plugins/color/lcms2engine/colorspaces/gray_f16/GrayF16ColorSpace.cpp M +3 -0 plugins/color/lcms2engine/colorspaces/gray_f32/GrayF32ColorSpace.cpp M +9 -6 plugins/color/lcms2engine/colorspaces/gray_u16/GrayU16ColorSpace.cpp M +1 -3 plugins/color/lcms2engine/colorspaces/gray_u16/GrayU16ColorSpace.h M +9 -6 plugins/color/lcms2engine/colorspaces/gray_u8/GrayU8ColorSpace.cpp M +1 -3 plugins/color/lcms2engine/colorspaces/gray_u8/GrayU8ColorSpace.h M +3 -1 plugins/color/lcms2engine/colorspaces/lab_f32/LabF32ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/lab_u16/LabColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/lab_u8/LabU8ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/rgb_f16/RgbF16ColorSpace.cpp M +5 -3 plugins/color/lcms2engine/colorspaces/rgb_f32/RgbF32ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/rgb_u16/RgbU16ColorSpace.cpp M +7 -4 plugins/color/lcms2engine/colorspaces/rgb_u8/RgbU8ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/xyz_f16/XyzF16ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/xyz_f32/XyzF32ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/xyz_u16/XyzU16ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/xyz_u8/XyzU8ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/ycbcr_f32/YCbCrF32ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/ycbcr_u16/YCbCrU16ColorSpace.cpp M +4 -1 plugins/color/lcms2engine/colorspaces/ycbcr_u8/YCbCrU8ColorSpace.cpp M +3 -1 plugins/generators/gradient/KisGradientGenerator.cpp M +4 -0 plugins/generators/gradient/KisGradientGeneratorConfigWidget.cpp M +14 -0 plugins/generators/gradient/KisGradientGeneratorConfigWidget.ui M +12 -1 plugins/generators/gradient/KisGradientGeneratorConfiguration.cpp M +8 -0 plugins/generators/gradient/KisGradientGeneratorConfiguration.h M +17 -2 plugins/tools/basictools/kis_tool_gradient.cc M +4 -0 plugins/tools/basictools/kis_tool_gradient.h https://invent.kde.org/graphics/krita/commit/4cfda40a29f9ee7548ab5d2f7320f2fca8674f65
Git commit 76f54aa2e76684399280f116f5ea9d9e322c749e by L. E. Segovia. Committed on 11/02/2021 at 14:47. Pushed by lsegovia into branch 'master'. Fix same-depth dithering op skipping pixels Related: bug 432758 M +1 -1 libs/pigment/KisDitherOpImpl.h https://invent.kde.org/graphics/krita/commit/76f54aa2e76684399280f116f5ea9d9e322c749e
Git commit a4ac9f32c2531df412daa4bb3775af960644b718 by L. E. Segovia. Committed on 11/02/2021 at 14:47. Pushed by lsegovia into branch 'master'. Fix typo in dither ops for 16-bit integer CMYK Related: bug 432758 M +1 -1 plugins/color/lcms2engine/colorspaces/cmyk_u16/CmykU16ColorSpace.cpp https://invent.kde.org/graphics/krita/commit/a4ac9f32c2531df412daa4bb3775af960644b718
Git commit 688e896fb35107100c66a1069a05be1ee4ddb566 by L. E. Segovia. Committed on 11/02/2021 at 14:47. Pushed by lsegovia into branch 'master'. Subclass the dither operator for CMYK color spaces Floating point CMYK colorspaces have different normalization factors for color and alpha channels. Related: bug 432758 M +222 -4 libs/pigment/dithering/KisCmykDitherOpFactory.h https://invent.kde.org/graphics/krita/commit/688e896fb35107100c66a1069a05be1ee4ddb566