1/*****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Add-On Graphical Effects module.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38*****************************************************************************/
39
40import QtQuick 2.12
41import QtGraphicalEffects.private 1.12
42
43/*!
44    \qmltype LevelAdjust
45    \inqmlmodule QtGraphicalEffects
46    \since QtGraphicalEffects 1.0
47    \inherits QtQuick2::Item
48    \ingroup qtgraphicaleffects-color
49    \brief Adjusts color levels in the RGBA color space.
50
51    This effect adjusts the source item colors separately for each color
52    channel. Source item contrast can be adjusted and color balance altered.
53
54    \table
55    \header
56        \li Source
57        \li Effect applied
58    \row
59        \li \image Original_butterfly.png
60        \li \image LevelAdjust_butterfly.png
61    \endtable
62
63    \note This effect is available when running with OpenGL.
64
65    \section1 Example
66
67    The following example shows how to apply the effect.
68    \snippet LevelAdjust-example.qml example
69
70*/
71Item {
72    id: rootItem
73
74    /*!
75        This property defines the source item that provides the source pixels
76        for the effect.
77
78        \note It is not supported to let the effect include itself, for
79        instance by setting source to the effect's parent.
80    */
81    property variant source
82
83    /*!
84        This property defines the change factor for how the value of each pixel
85        color channel is altered according to the equation:
86
87        \code
88        result.rgb = pow(original.rgb, 1.0 / gamma.rgb);
89        \endcode
90
91        Setting the gamma values under QtVector3d(1.0, 1.0, 1.0) makes the image
92        darker, the values above QtVector3d(1.0, 1.0, 1.0) lighten it.
93
94        The value ranges from QtVector3d(0.0, 0.0, 0.0) (darkest) to inf
95        (lightest). By default, the property is set to \c QtVector3d(1.0, 1.0,
96        1.0) (no change).
97
98        \table
99        \header
100        \li Output examples with different gamma values
101        \li
102        \li
103        \row
104            \li \image LevelAdjust_gamma1.png
105            \li \image LevelAdjust_gamma2.png
106            \li \image LevelAdjust_gamma3.png
107        \row
108            \li \b { gamma: Qt.vector3d(1.0, 1.0, 1.0) }
109            \li \b { gamma: Qt.vector3d(1.0, 0.4, 2.0) }
110            \li \b { gamma: Qt.vector3d(1.0, 0.1, 4.0) }
111        \row
112            \li \l minimumInput: #000000
113            \li \l minimumInput: #000000
114            \li \l minimumInput: #000000
115        \row
116            \li \l maximumInput: #ffffff
117            \li \l maximumInput: #ffffff
118            \li \l maximumInput: #ffffff
119        \row
120            \li \l minimumOutput: #000000
121            \li \l minimumOutput: #000000
122            \li \l minimumOutput: #000000
123        \row
124            \li \l maximumOutput: #ffffff
125            \li \l maximumOutput: #ffffff
126            \li \l maximumOutput: #ffffff
127        \endtable
128
129        \table
130        \header
131            \li Pixel color channel luminance curves of the above images.
132            \li
133            \li
134        \row
135            \li \image LevelAdjust_default_curve.png
136            \li \image LevelAdjust_gamma2_curve.png
137            \li \image LevelAdjust_gamma3_curve.png
138        \row
139            \li X-axis: pixel original luminance
140            \li
141            \li
142        \row
143            \li Y-axis: color channel luminance with effect applied
144            \li
145            \li
146        \endtable
147    */
148    property variant gamma: Qt.vector3d(1.0, 1.0, 1.0)
149
150    /*!
151        This property defines the minimum input level for each color channel. It
152        sets the black-point, all pixels having lower value than this property
153        are rendered as black (per color channel). Increasing the value darkens
154        the dark areas.
155
156        The value ranges from "#00000000" to "#ffffffff". By default, the
157        property is set to \c "#00000000" (no change).
158
159        \table
160        \header
161        \li Output examples with different minimumInput values
162        \li
163        \li
164        \row
165            \li \image LevelAdjust_minimumInput1.png
166            \li \image LevelAdjust_minimumInput2.png
167            \li \image LevelAdjust_minimumInput3.png
168        \row
169            \li \b { minimumInput: #00000000 }
170            \li \b { minimumInput: #00000040 }
171            \li \b { minimumInput: #00000070 }
172        \row
173            \li \l maximumInput: #ffffff
174            \li \l maximumInput: #ffffff
175            \li \l maximumInput: #ffffff
176        \row
177            \li \l minimumOutput: #000000
178            \li \l minimumOutput: #000000
179            \li \l minimumOutput: #000000
180        \row
181            \li \l maximumOutput: #ffffff
182            \li \l maximumOutput: #ffffff
183            \li \l maximumOutput: #ffffff
184        \row
185            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
186            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
187            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
188        \endtable
189
190        \table
191        \header
192            \li Pixel color channel luminance curves of the above images.
193            \li
194            \li
195        \row
196            \li \image LevelAdjust_default_curve.png
197            \li \image LevelAdjust_minimumInput2_curve.png
198            \li \image LevelAdjust_minimumInput3_curve.png
199        \row
200            \li X-axis: pixel original luminance
201            \li
202            \li
203        \row
204            \li Y-axis: color channel luminance with effect applied
205            \li
206            \li
207        \endtable
208
209    */
210    property color minimumInput: Qt.rgba(0.0, 0.0, 0.0, 0.0)
211
212    /*!
213        This property defines the maximum input level for each color channel.
214        It sets the white-point, all pixels having higher value than this
215        property are rendered as white (per color channel).
216        Decreasing the value lightens the light areas.
217
218        The value ranges from "#ffffffff" to "#00000000". By default, the
219        property is set to \c "#ffffffff" (no change).
220
221        \table
222        \header
223        \li Output examples with different maximumInput values
224        \li
225        \li
226        \row
227            \li \image LevelAdjust_maximumInput1.png
228            \li \image LevelAdjust_maximumInput2.png
229            \li \image LevelAdjust_maximumInput3.png
230        \row
231            \li \b { maximumInput: #FFFFFFFF }
232            \li \b { maximumInput: #FFFFFF80 }
233            \li \b { maximumInput: #FFFFFF30 }
234        \row
235            \li \l minimumInput: #000000
236            \li \l minimumInput: #000000
237            \li \l minimumInput: #000000
238        \row
239            \li \l minimumOutput: #000000
240            \li \l minimumOutput: #000000
241            \li \l minimumOutput: #000000
242        \row
243            \li \l maximumOutput: #ffffff
244            \li \l maximumOutput: #ffffff
245            \li \l maximumOutput: #ffffff
246        \row
247            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
248            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
249            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
250        \endtable
251
252        \table
253        \header
254            \li Pixel color channel luminance curves of the above images.
255            \li
256            \li
257        \row
258            \li \image LevelAdjust_default_curve.png
259            \li \image LevelAdjust_maximumInput2_curve.png
260            \li \image LevelAdjust_maximumInput3_curve.png
261        \row
262            \li X-axis: pixel original luminance
263            \li
264            \li
265        \row
266            \li Y-axis: color channel luminance with effect applied
267            \li
268            \li
269        \endtable
270
271    */
272    property color maximumInput: Qt.rgba(1.0, 1.0, 1.0, 1.0)
273
274    /*!
275        This property defines the minimum output level for each color channel.
276        Increasing the value lightens the dark areas, reducing the contrast.
277
278        The value ranges from "#00000000" to "#ffffffff". By default, the
279        property is set to \c "#00000000" (no change).
280
281        \table
282        \header
283        \li Output examples with different minimumOutput values
284        \li
285        \li
286        \row
287            \li \image LevelAdjust_minimumOutput1.png
288            \li \image LevelAdjust_minimumOutput2.png
289            \li \image LevelAdjust_minimumOutput3.png
290        \row
291            \li \b { minimumOutput: #00000000 }
292            \li \b { minimumOutput: #00000070 }
293            \li \b { minimumOutput: #000000A0 }
294        \row
295            \li \l minimumInput: #000000
296            \li \l minimumInput: #000000
297            \li \l minimumInput: #000000
298        \row
299            \li \l maximumInput: #ffffff
300            \li \l maximumInput: #ffffff
301            \li \l maximumInput: #ffffff
302        \row
303            \li \l maximumOutput: #ffffff
304            \li \l maximumOutput: #ffffff
305            \li \l maximumOutput: #ffffff
306        \row
307            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
308            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
309            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
310        \endtable
311
312        \table
313        \header
314            \li Pixel color channel luminance curves of the above images.
315            \li
316            \li
317        \row
318            \li \image LevelAdjust_default_curve.png
319            \li \image LevelAdjust_minimumOutput2_curve.png
320            \li \image LevelAdjust_minimumOutput3_curve.png
321        \row
322            \li X-axis: pixel original luminance
323            \li
324            \li
325        \row
326            \li Y-axis: color channel luminance with effect applied
327            \li
328            \li
329        \endtable
330
331    */
332    property color minimumOutput: Qt.rgba(0.0, 0.0, 0.0, 0.0)
333
334    /*!
335        This property defines the maximum output level for each color channel.
336        Decreasing the value darkens the light areas, reducing the contrast.
337
338        The value ranges from "#ffffffff" to "#00000000". By default, the
339        property is set to \c "#ffffffff" (no change).
340
341        \table
342        \header
343        \li Output examples with different maximumOutput values
344        \li
345        \li
346        \row
347            \li \image LevelAdjust_maximumOutput1.png
348            \li \image LevelAdjust_maximumOutput2.png
349            \li \image LevelAdjust_maximumOutput3.png
350        \row
351            \li \b { maximumOutput: #FFFFFFFF }
352            \li \b { maximumOutput: #FFFFFF80 }
353            \li \b { maximumOutput: #FFFFFF30 }
354        \row
355            \li \l minimumInput: #000000
356            \li \l minimumInput: #000000
357            \li \l minimumInput: #000000
358        \row
359            \li \l maximumInput: #ffffff
360            \li \l maximumInput: #ffffff
361            \li \l maximumInput: #ffffff
362        \row
363            \li \l minimumOutput: #000000
364            \li \l minimumOutput: #000000
365            \li \l minimumOutput: #000000
366        \row
367            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
368            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
369            \li \l gamma: Qt.vector3d(1.0, 1.0, 1.0)
370        \endtable
371
372        \table
373        \header
374            \li Pixel color channel luminance curves of the above images.
375            \li
376            \li
377        \row
378            \li \image LevelAdjust_default_curve.png
379            \li \image LevelAdjust_maximumOutput2_curve.png
380            \li \image LevelAdjust_maximumOutput3_curve.png
381        \row
382            \li X-axis: pixel original luminance
383            \li
384            \li
385        \row
386            \li Y-axis: color channel luminance with effect applied
387            \li
388            \li
389        \endtable
390    */
391    property color maximumOutput: Qt.rgba(1.0, 1.0, 1.0, 1.0)
392
393    /*!
394        This property allows the effect output pixels to be cached in order to
395        improve the rendering performance.
396
397        Every time the source or effect properties are changed, the pixels in
398        the cache must be updated. Memory consumption is increased, because an
399        extra buffer of memory is required for storing the effect output.
400
401        It is recommended to disable the cache when the source or the effect
402        properties are animated.
403
404        By default, the property is set to \c false.
405    */
406    property bool cached: false
407
408    SourceProxy {
409        id: sourceProxy
410        input: rootItem.source
411        interpolation: input && input.smooth ? SourceProxy.LinearInterpolation : SourceProxy.NearestInterpolation
412    }
413
414    ShaderEffectSource {
415        id: cacheItem
416        anchors.fill: parent
417        visible: rootItem.cached
418        smooth: true
419        sourceItem: shaderItem
420        live: true
421        hideSource: visible
422    }
423
424    ShaderEffect {
425        id: shaderItem
426        property variant source: sourceProxy.output
427        property variant minimumInputRGB: Qt.vector3d(rootItem.minimumInput.r, rootItem.minimumInput.g, rootItem.minimumInput.b)
428        property variant maximumInputRGB: Qt.vector3d(rootItem.maximumInput.r, rootItem.maximumInput.g, rootItem.maximumInput.b)
429        property real minimumInputAlpha: rootItem.minimumInput.a
430        property real maximumInputAlpha: rootItem.maximumInput.a
431        property variant minimumOutputRGB: Qt.vector3d(rootItem.minimumOutput.r, rootItem.minimumOutput.g, rootItem.minimumOutput.b)
432        property variant maximumOutputRGB: Qt.vector3d(rootItem.maximumOutput.r, rootItem.maximumOutput.g, rootItem.maximumOutput.b)
433        property real minimumOutputAlpha: rootItem.minimumOutput.a
434        property real maximumOutputAlpha: rootItem.maximumOutput.a
435        property variant gamma: Qt.vector3d(1.0 / Math.max(rootItem.gamma.x, 0.0001), 1.0 / Math.max(rootItem.gamma.y, 0.0001), 1.0 / Math.max(rootItem.gamma.z, 0.0001))
436        anchors.fill: parent
437
438        fragmentShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/leveladjust.frag"
439    }
440}
441