Skip to content

Instantly share code, notes, and snippets.

@Zren
Created January 10, 2019 04:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zren/add08f88c31e97130ee01cefb4757675 to your computer and use it in GitHub Desktop.
Save Zren/add08f88c31e97130ee01cefb4757675 to your computer and use it in GitHub Desktop.
A test of automatically generating bg tile colors based on Unity's implementation
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
set(QT_MIN_VERSION "5.4.0")
set(KF5_MIN_VERSION "5.0.0")
find_package(ECM 0.0.11 REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings)
find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Quick Gui)
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Plasma)
set(qml_SRCS
qmldir
)
set(cpp_SRCS
plugin.cpp
iconpalette.cpp
)
add_library(plasma-zrenlib-declarative SHARED ${cpp_SRCS})
target_link_libraries(plasma-zrenlib-declarative
Qt5::Gui
Qt5::Quick
KF5::Plasma
)
set(PRIVATE_QML_INSTALL_DIR ${QML_INSTALL_DIR}/com/github/zren/zrenlib)
install(TARGETS plasma-zrenlib-declarative DESTINATION ${PRIVATE_QML_INSTALL_DIR})
install(FILES ${qml_SRCS} DESTINATION ${PRIVATE_QML_INSTALL_DIR})
import QtQuick 2.0
import QtQuick.Layouts 1.0
import QtQuick.Window 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import com.github.zren.zrenlib 1.0 as ZrenLib
Window {
id: window
width: 640
height: 480
visible: true
ZrenLib.IconPalette {
id: iconPalette
}
Rectangle {
anchors.fill: parent
color: "#000"
}
Flow {
anchors.fill: parent
Repeater {
model: [
'plasma',
'firefox',
'system-file-manager',
'manjaro',
'blender',
'steam',
'chromium',
'hexchat',
'gimp',
'libreoffice-startcenter',
'libreoffice-base',
'libreoffice-calc',
'libreoffice-draw',
'libreoffice-impress',
'libreoffice-math',
'libreoffice-writer',
'ark',
'systemsettings',
'mpv',
'utilities-terminal',
'sublime-text',
'okular',
]
Item {
id: iconTestItem
property string iconName: modelData
property int margin: 2 * units.devicePixelRatio
property int padding: units.largeSpacing
property int iconSize: units.iconSizes.large
implicitWidth: margin + padding + iconSize + padding + margin
implicitHeight: margin + padding + iconSize + padding + margin
Rectangle {
id: bgRect
anchors.fill: parent
anchors.margins: iconTestItem.margin
color: "#000"
PlasmaCore.IconItem {
id: iconItem
anchors.fill: parent
anchors.margins: iconTestItem.padding
source: iconTestItem.iconName
}
Text {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: iconTestItem.margin
text: iconTestItem.iconName
font.pointSize: -1
font.pixelSize: 12 * units.devicePixelRatio
color: "#eee"
font.weight: Font.Bold
style: Text.Outline
styleColor: Qt.rgba(0, 0, 0, 0.6)
wrapMode: Text.Wrap
}
}
function main() {
if (!iconItem.valid) {
return
}
var grabbed = iconItem.grabToImage(function(result){
console.log('result.url', result.url)
console.log('result.image', result.image)
var c = iconPalette.getColor(result.image)
console.log('result.color', c)
bgRect.color = c
}, Qt.size(iconItem.width, iconItem.height))
console.log('size', Qt.size(iconItem.width, iconItem.height))
console.log('grabbed', grabbed)
}
Connections {
target: window
onReady: iconTestItem.main()
}
}
} // Repeater
} // GridLayout
signal ready()
// Component.onCompleted: main()
Timer {
running: true
interval: 1000
onTriggered: ready()
}
}
#include "iconpalette.h"
#include <QColor>
#include <QImage>
IconPalette::IconPalette(QObject *parent) : QObject(parent) {
}
IconPalette::~IconPalette() {
}
// https://bazaar.launchpad.net/~unity-team/unity/trunk/view/head:/launcher/LauncherIcon.cpp#L279
QColor IconPalette::getColor(const QImage image) const {
qDebug() << "IconPalette::getColor";
// return QColor(0, 0, 0);
// return image->pixelColor(0, 0);
int width = image.width();
int height = image.height();
qDebug() << "\twidth" << width;
qDebug() << "\theight" << height;
long int rtotal = 0, gtotal = 0, btotal = 0;
float total = 0.0f;
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
QColor c = image.pixelColor(i, j);
float saturation = qMax(c.redF(), qMax(c.greenF(), c.blueF())) - qMin(c.redF(), qMin(c.greenF(), c.blueF()));
float relevance = 0.1f + 0.9f * c.alphaF() * saturation;
rtotal += c.red() * relevance;
gtotal += c.green() * relevance;
btotal += c.blue() * relevance;
total += relevance * 255;
}
}
qDebug() << "\trtotal" << rtotal;
qDebug() << "\tgtotal" << gtotal;
qDebug() << "\tbtotal" << btotal;
qDebug() << "\ttotal" << total;
int r = rtotal/total * 255;
int g = gtotal/total * 255;
int b = btotal/total * 255;
qDebug() << "\tr" << r;
qDebug() << "\tg" << g;
qDebug() << "\tb" << b;
QColor rgb = QColor(r, g, b);
QColor hsv = rgb.toHsv();
float s = hsv.saturationF();
if (s > 0.15f) {
s = 0.65f;
}
qDebug() << "\thue" << hsv.hsvHueF();
qDebug() << "\tsaturation" << s;
qDebug() << "\tvalue" << 0.90f;
hsv.setHsvF(hsv.hsvHueF(), s, 0.90f);
return hsv;
}
#ifndef ICONPALETTE_H
#define ICONPALETTE_H
#include <QObject>
#include <QDebug>
#include <QColor>
#include <QImage>
class IconPalette : public QObject {
Q_OBJECT
public:
explicit IconPalette(QObject *parent = 0);
~IconPalette();
Q_INVOKABLE QColor getColor(const QImage image) const;
};
#endif
#include "plugin.h"
#include "iconpalette.h"
#include <QtQml>
void Plugin::registerTypes(const char* uri) {
qmlRegisterType<IconPalette>(uri, 1, 0, "IconPalette");
}
#ifndef PLUGIN_H
#define PLUGIN_H
#include <QtQml/QQmlExtensionPlugin>
class Plugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
public:
virtual void registerTypes(const char * uri);
};
#endif // PLUGIN_H
module com.github.zren.zrenlib
plugin plasma-zrenlib-declarative
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment