Also color labels
Signed-off-by: Vasiliy Doylov <nekocwd@mainlining.org>
This commit is contained in:
parent
a00b668f28
commit
b0d9a44f36
4 changed files with 132 additions and 63 deletions
70
vala-quick-setting/color.vala
Normal file
70
vala-quick-setting/color.vala
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
namespace Color {
|
||||||
|
public Gee.HashMap<Gdk.RGBA?, int> quanitize_pixbuff (Gdk.Pixbuf pixbuf) {
|
||||||
|
var histogram = new Gee.HashMap<Gdk.RGBA?, int>
|
||||||
|
(
|
||||||
|
(a) =>
|
||||||
|
((uint8) a.red * 255 + ((uint8) a.green * 255 << 8) + ((uint8) a.blue * 255 << 16)),
|
||||||
|
(a, b) => (a.red == b.red && a.blue == b.blue && a.green == b.green)
|
||||||
|
);
|
||||||
|
unowned uint8[] pixels = pixbuf.get_pixels ();
|
||||||
|
var width = pixbuf.get_width ();
|
||||||
|
var height = pixbuf.get_height ();
|
||||||
|
var rowstride = pixbuf.get_rowstride ();
|
||||||
|
var n_channels = pixbuf.get_n_channels ();
|
||||||
|
|
||||||
|
for (var y = 0; y < height; y++) {
|
||||||
|
for (var x = 0; x < width; x++) {
|
||||||
|
var offset = y * rowstride + x * n_channels;
|
||||||
|
|
||||||
|
var r = pixels[offset];
|
||||||
|
var g = pixels[offset + 1];
|
||||||
|
var b = pixels[offset + 2];
|
||||||
|
var a = (n_channels == 4) ? pixels[offset + 3] : 255;
|
||||||
|
|
||||||
|
var rgba = Gdk.RGBA () {
|
||||||
|
red = r / 255.0,
|
||||||
|
green = g / 255.0,
|
||||||
|
blue = b / 255.0,
|
||||||
|
alpha = a / 255.0
|
||||||
|
};
|
||||||
|
|
||||||
|
histogram[rgba] = histogram[rgba] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return histogram;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Gdk.RGBA get_most_common_color (ref Gee.HashMap<Gdk.RGBA?, int> histogram) {
|
||||||
|
int max = 0;
|
||||||
|
Gdk.RGBA color = {};
|
||||||
|
foreach (var kv in histogram) {
|
||||||
|
if (kv.value > max) {
|
||||||
|
max = kv.value;
|
||||||
|
color = kv.key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double get_pixel_luminance (Gdk.RGBA pix) {
|
||||||
|
return pix.red * 0.299 + pix.green * 0.587 + pix.blue * 0.114;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Gee.ArrayList<Gdk.RGBA?> sort_colors (Gee.HashMap<Gdk.RGBA?, int> histogram) {
|
||||||
|
var new_keys = new Gee.ArrayList<Gdk.RGBA?> ();
|
||||||
|
var tr = 2;
|
||||||
|
foreach (var key in histogram.keys) {
|
||||||
|
if (key == null)
|
||||||
|
continue;
|
||||||
|
if (histogram[key] < tr)
|
||||||
|
continue;
|
||||||
|
new_keys.add (key);
|
||||||
|
}
|
||||||
|
new_keys.sort ((a, b) => {
|
||||||
|
var a_ = histogram[a];
|
||||||
|
var b_ = histogram[b];
|
||||||
|
return a_ > b_ ? -1 : a_ == b_ ? 0 : 1;
|
||||||
|
});
|
||||||
|
return new_keys;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ vala_quick_setting_resources = gnome.compile_resources(
|
||||||
)
|
)
|
||||||
|
|
||||||
vala_quick_setting_plugin_sources = files(
|
vala_quick_setting_plugin_sources = files(
|
||||||
|
'color.vala',
|
||||||
'extension.vala',
|
'extension.vala',
|
||||||
'player.vala',
|
'player.vala',
|
||||||
'qs.vala',
|
'qs.vala',
|
||||||
|
|
|
@ -41,13 +41,11 @@ public class Extension.Player : Gtk.Box {
|
||||||
return Math.PI / 180.0 * deg;
|
return Math.PI / 180.0 * deg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_colors (Gdk.RGBA[] colors) {
|
void set_colors (Gdk.RGBA start, Gdk.RGBA end, Gdk.RGBA fg) {
|
||||||
var gradient_points = new string[0];
|
var data = ".%s {
|
||||||
for (uint i = 0; i < colors.length; i++) {
|
color: %s;
|
||||||
gradient_points += "%s %d%%".printf (colors[i].to_string (), (int) (100.0 / colors.length * i));
|
background: radial-gradient(circle at left, %s 0%%, %s 100%%);
|
||||||
}
|
}".printf (id, fg.to_string (), start.to_string (), end.to_string ());
|
||||||
var data = ".%s { background: radial-gradient(circle at left, %s); }"
|
|
||||||
.printf (id, string.joinv (",", gradient_points));
|
|
||||||
try {
|
try {
|
||||||
css_provider.load_from_data (data);
|
css_provider.load_from_data (data);
|
||||||
} catch (Error err) {
|
} catch (Error err) {
|
||||||
|
@ -55,64 +53,63 @@ public class Extension.Player : Gtk.Box {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Gee.HashMap<Gdk.RGBA?, int> quanitize_pixbuff (Gdk.Pixbuf pixbuf) {
|
private void generate_style (Gdk.Pixbuf pixbuff) {
|
||||||
var histogram = new Gee.HashMap<Gdk.RGBA?, int>
|
message ("Start");
|
||||||
(
|
var histogram = Color.quanitize_pixbuff (pixbuff);
|
||||||
(a) =>
|
message ("Histogram OK");
|
||||||
((uint8) a.red * 255 + ((uint8) a.green * 255 << 8) + ((uint8) a.blue * 255 << 16)),
|
var colors = Color.sort_colors (histogram);
|
||||||
(a, b) => (a.red == b.red && a.blue == b.blue && a.green == b.green)
|
message ("Sort OK");
|
||||||
);
|
Gdk.RGBA? fg_color = null, bg_start_color = null, bg_end_color = null;
|
||||||
unowned uint8[] pixels = pixbuf.get_pixels ();
|
double fg_lum = 0, bg_start_lum = 0, bg_end_lum = 0;
|
||||||
var width = pixbuf.get_width ();
|
foreach (var color in colors) {
|
||||||
var height = pixbuf.get_height ();
|
if (fg_color != null && bg_start_color != null && bg_end_color != null)
|
||||||
var rowstride = pixbuf.get_rowstride ();
|
break;
|
||||||
var n_channels = pixbuf.get_n_channels ();
|
var lum = Color.get_pixel_luminance (color);
|
||||||
|
if (bg_start_color == null) {
|
||||||
for (var y = 0; y < height; y++) {
|
bg_start_color = color;
|
||||||
for (var x = 0; x < width; x++) {
|
bg_start_lum = lum;
|
||||||
var offset = y * rowstride + x * n_channels;
|
continue;
|
||||||
|
}
|
||||||
var r = pixels[offset];
|
if (Math.fabs (bg_start_lum - lum) > 0.4) {
|
||||||
var g = pixels[offset + 1];
|
if (fg_color != null)
|
||||||
var b = pixels[offset + 2];
|
continue;
|
||||||
var a = (n_channels == 4) ? pixels[offset + 3] : 255;
|
fg_color = color;
|
||||||
|
continue;
|
||||||
var rgba = Gdk.RGBA () {
|
} else if (bg_end_color == null) {
|
||||||
red = r / 255.0,
|
bg_end_color = color;
|
||||||
green = g / 255.0,
|
continue;
|
||||||
blue = b / 255.0,
|
}
|
||||||
alpha = a / 255.0
|
}
|
||||||
|
if (bg_end_color == null) {
|
||||||
|
message ("Failed to chose end background color color. Fallbacking to start color");
|
||||||
|
bg_end_color = bg_start_color;
|
||||||
|
}
|
||||||
|
if (fg_color == null) {
|
||||||
|
message ("Failed to chose forground color. Fallbacking to contrast");
|
||||||
|
if (bg_start_lum > 0.5)
|
||||||
|
fg_color = Gdk.RGBA () {
|
||||||
|
red = 0,
|
||||||
|
green = 0,
|
||||||
|
blue = 0,
|
||||||
|
alpha = 1,
|
||||||
|
};
|
||||||
|
else
|
||||||
|
fg_color = Gdk.RGBA () {
|
||||||
|
red = 1,
|
||||||
|
green = 1,
|
||||||
|
blue = 1,
|
||||||
|
alpha = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
histogram[rgba] += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return histogram;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Gdk.RGBA get_most_common_color (ref Gee.HashMap<Gdk.RGBA?, int> histogram) {
|
Idle.add (() => {
|
||||||
int max = 0;
|
set_colors (bg_start_color, bg_end_color, fg_color);
|
||||||
Gdk.RGBA bebra = {};
|
return false;
|
||||||
foreach (var kv in histogram) {
|
});
|
||||||
if (kv.value > max) {
|
|
||||||
max = kv.value;
|
|
||||||
bebra = kv.key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bebra;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void generate_style (Gdk.Pixbuf pixbuff) {
|
private void run_color_thred (Gdk.Pixbuf pb) {
|
||||||
var histogram = yield quanitize_pixbuff (pixbuff);
|
var thread = new Thread<void> ("Picture", () => generate_style (pb));
|
||||||
|
|
||||||
var bg_colors = new Gdk.RGBA[0];
|
|
||||||
|
|
||||||
for (var i = 0; i < 2; i++) {
|
|
||||||
var c = get_most_common_color (ref histogram);
|
|
||||||
bg_colors += c;
|
|
||||||
histogram[c] = -1;
|
|
||||||
}
|
|
||||||
set_colors (bg_colors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Icon ? process_icon (Icon? icon) {
|
private async Icon ? process_icon (Icon? icon) {
|
||||||
|
@ -136,7 +133,7 @@ public class Extension.Player : Gtk.Box {
|
||||||
// Downscale to 110x110
|
// Downscale to 110x110
|
||||||
pixbuff = pixbuff.scale_simple (110, 110, Gdk.InterpType.BILINEAR);
|
pixbuff = pixbuff.scale_simple (110, 110, Gdk.InterpType.BILINEAR);
|
||||||
// Start background generator
|
// Start background generator
|
||||||
generate_style.begin (pixbuff);
|
run_color_thred (pixbuff);
|
||||||
|
|
||||||
var width = pixbuff.width;
|
var width = pixbuff.width;
|
||||||
var height = pixbuff.height;
|
var height = pixbuff.height;
|
||||||
|
@ -172,7 +169,7 @@ public class Extension.Player : Gtk.Box {
|
||||||
default :
|
default :
|
||||||
foreach (var child2 in ((Gtk.Box) child).get_children ()) {
|
foreach (var child2 in ((Gtk.Box) child).get_children ()) {
|
||||||
switch (child2.get_name ()) {
|
switch (child2.get_name ()) {
|
||||||
case "lbl_artist":
|
case "lbl_artist" :
|
||||||
child2.bind_property ("label", artist, "label");
|
child2.bind_property ("label", artist, "label");
|
||||||
break;
|
break;
|
||||||
case "lbl_title":
|
case "lbl_title":
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
.nekoplayer {
|
.nekoplayer {
|
||||||
/* background: linear-gradient(to bottom, #ff7e5f 0%, #feb47b 100%); */
|
/* background: linear-gradient(to bottom, #ff7e5f 0%, #feb47b 100%); */
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
transition: all 0.1s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nekoplayer-controls button {
|
.nekoplayer-controls button {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue