Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion src/effects/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { PixelizeEffect } from './pixelize.js';
import { DerivativeEffect } from './derivative.js';
import { RgbToHslEffect } from './rgb_to_hsl.js';
import { HslToRgbEffect } from './hsl_to_rgb.js';
import { LuminosityEffect } from './luminosity.js';

// We do in this way because I've not found another way to store our preferences in a dictionnary
// while calling `gettext` on it while in preferences. Not so pretty, but works.
Expand All @@ -33,6 +34,7 @@ export function get_effects_groups(_ = _ => "") {
"derivative",
"noise",
"color",
"luminosity",
"rgb_to_hsl",
"hsl_to_rgb"
]
Expand Down Expand Up @@ -167,11 +169,71 @@ export function get_supported_effects(_ = () => "") {
color: {
name: _("Color"),
description: _("The color to blend in. The blending amount is controled by the opacity of the color."),
type: "rgba"
type: "rgba",
use_alpha: true,
}
}
},

luminosity: {
class: LuminosityEffect,
name: _("Luminosity"),
description: _("An effect that affects the luminosity of the image."),
is_advanced: false,
editable_params: {
brightness_shift: {
name: _("Shift brightness"),
description: _("The brightness to add of remove to the image."),
type: "float",
min: -1.,
max: 1.,
increment: 0.01,
big_increment: 0.1,
digits: 2
},
brightness_multiplicator: {
name: _("Multiply brightness"),
description: _("The brightness multiplicator of the image, so that 0 means no brightness and 2 means infinite brightness."),
type: "float",
min: 0.,
max: 2.,
increment: 0.01,
big_increment: 0.1,
digits: 2
},
contrast: {
name: _("Contrast"),
description: _("The contrast of the image in regard to the center of the contrast."),
type: "float",
min: 0.,
max: 2.,
increment: 0.01,
big_increment: 0.1,
digits: 2
},
contrast_center: {
name: _("Contrast center"),
description: _("The center of the contrast to use."),
type: "float",
min: 0.,
max: 1.,
increment: 0.01,
big_increment: 0.1,
digits: 2
},
saturation_multiplicator: {
name: _("Saturation"),
description: _("The saturation of the image, so that 0 means no saturation and 2 means infinite saturation."),
type: "float",
min: 0.,
max: 2.,
increment: 0.01,
big_increment: 0.1,
digits: 2
},
}
},

pixelize: {
class: PixelizeEffect,
name: _("Pixelize"),
Expand Down
33 changes: 33 additions & 0 deletions src/effects/luminosity.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
uniform sampler2D tex;
uniform float brightness_shift;
uniform float brightness_multiplicator;
uniform float contrast;
uniform float contrast_center;
uniform float saturation_multiplicator;

vec3 hsl_to_rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

vec3 rgb_to_hsl(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

void main() {
vec4 c = texture2D(tex, cogl_tex_coord_in[0].st);

vec3 pix_hsl = rgb_to_hsl(c.xyz) / c.a;
pix_hsl.z = clamp(pix_hsl.z * brightness_multiplicator, 0., 1.);
pix_hsl.z = clamp((pix_hsl.z - contrast_center) * contrast + contrast_center + brightness_shift, 0., 1.);
pix_hsl.y = clamp(pix_hsl.y * saturation_multiplicator, 0., 1.);

cogl_color_out = vec4(hsl_to_rgb(pix_hsl) * c.a, c.a);
}
141 changes: 141 additions & 0 deletions src/effects/luminosity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import GObject from 'gi://GObject';

import * as utils from '../conveniences/utils.js';
const Shell = await utils.import_in_shell_only('gi://Shell');
const Clutter = await utils.import_in_shell_only('gi://Clutter');

const SHADER_FILENAME = 'luminosity.glsl';
const DEFAULT_PARAMS = {
brightness_shift: 0., brightness_multiplicator: 1., contrast: 1., contrast_center: 0.5, saturation_multiplicator: 1.
};


export const LuminosityEffect = utils.IS_IN_PREFERENCES ?
{ default_params: DEFAULT_PARAMS } :
new GObject.registerClass({
GTypeName: "LuminosityEffect",
Properties: {
'brightness_shift': GObject.ParamSpec.double(
`brightness_shift`,
`Brightness shift`,
`Brightness shift value in shader`,
GObject.ParamFlags.READWRITE,
-1.0, 1.0,
0.0,
),
'brightness_multiplicator': GObject.ParamSpec.double(
`brightness_multiplicator`,
`Brightness multiplicator`,
`Brightness multiplicator value in shader`,
GObject.ParamFlags.READWRITE,
0.0, 2.0,
1.0,
),
'contrast': GObject.ParamSpec.double(
`contrast`,
`Contrast`,
`Contrast value in shader`,
GObject.ParamFlags.READWRITE,
0.0, 2.0,
1.0,
),
'contrast_center': GObject.ParamSpec.double(
`contrast_center`,
`Contrast center`,
`Contrast center value in shader`,
GObject.ParamFlags.READWRITE,
0.0, 1.0,
0.5,
),
'saturation_multiplicator': GObject.ParamSpec.double(
`saturation_multiplicator`,
`Saturation multiplicator`,
`Saturation multiplicator value in shader`,
GObject.ParamFlags.READWRITE,
0.0, 2.0,
1.0,
),
}
}, class LuminosityEffect extends Clutter.ShaderEffect {
constructor(params) {
super(params);

utils.setup_params(this, params);

// set shader source
this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
if (this._source)
this.set_shader_source(this._source);
}

static get default_params() {
return DEFAULT_PARAMS;
}

get brightness_shift() {
return this._brightness;
}

set brightness_shift(value) {
if (this._brightness_shift !== value) {
this._brightness_shift = value;

this.set_uniform_value('brightness_shift', parseFloat(this._brightness_shift - 1e-6));
}
}


get brightness_multiplicator() {
return this._brightness_multiplicator;
}

set brightness_multiplicator(value) {
if (this._brightness_multiplicator !== value) {
this._brightness_multiplicator = value;

let brightness_mul = 600.;
if (value < 1.995)
brightness_mul = 3. * (1. / (1. - (value / 2.) ** 2) - 1.);
this.set_uniform_value('brightness_multiplicator', parseFloat(brightness_mul - 1e-6));
}
}

get contrast() {
return this._contrast;
}

set contrast(value) {
if (this._contrast !== value) {
this._contrast = value;

this.set_uniform_value('contrast', parseFloat(this._contrast - 1e-6));
}
}

get contrast_center() {
return this._contrast_center;
}

set contrast_center(value) {
if (this._contrast_center !== value) {
this._contrast_center = value;

this.set_uniform_value('contrast_center', parseFloat(this._contrast_center - 1e-6));
}
}

get saturation_multiplicator() {
return this._saturation_multiplicator;
}

set saturation_multiplicator(value) {
if (this._saturation_multiplicator !== value) {
this._saturation_multiplicator = value;

let saturation_mul = 600.;
if (value < 1.995)
saturation_mul = 3. * (1. / (1. - (value / 2.) ** 2) - 1.);
this.set_uniform_value('saturation_multiplicator', parseFloat(saturation_mul - 1e-6));
}
}
});
12 changes: 9 additions & 3 deletions src/preferences/pipelines_management/effect_row.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,18 +154,24 @@ export const EffectRow = GObject.registerClass({
width_request: 75,
height_request: 45,
show_editor: true,
use_alpha: true
use_alpha: param.use_alpha
});
row.add_suffix(color_button);
// set original color
let c = color_button.get_rgba().copy();
[c.red, c.green, c.blue, c.alpha] = this.get_effect_param(param_key);
if (param.use_alpha)
[c.red, c.green, c.blue, c.alpha] = this.get_effect_param(param_key);
else
[c.red, c.green, c.blue] = this.get_effect_param(param_key);
color_button.set_rgba(c);
// update on on 'color-set'
color_button.connect(
'color-set', () => {
let c = color_button.get_rgba();
this.set_effect_param(param_key, [c.red, c.green, c.blue, c.alpha]);
if (param.use_alpha)
this.set_effect_param(param_key, [c.red, c.green, c.blue, c.alpha]);
else
this.set_effect_param(param_key, [c.red, c.green, c.blue]);
}
);
break;
Expand Down