diff --git a/libs/libkis/ManagedColor.cpp b/libs/libkis/ManagedColor.cpp index ae4de80657..fb3b7abac1 100644 --- a/libs/libkis/ManagedColor.cpp +++ b/libs/libkis/ManagedColor.cpp @@ -1,164 +1,176 @@ /* * Copyright (C) 2017 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "ManagedColor.h" #include #include #include #include +#include #include #include #include #include #include struct ManagedColor::Private { KoColor color; }; ManagedColor::ManagedColor(QObject *parent) : QObject(parent) , d(new Private()) { // Default black rgb color } ManagedColor::ManagedColor(const QString &colorModel, const QString &colorDepth, const QString &colorProfile, QObject *parent) : QObject(parent) , d(new Private()) { const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(colorModel, colorDepth, colorProfile); if (colorSpace) { d->color = KoColor(colorSpace); } } ManagedColor::ManagedColor(KoColor color, QObject *parent) : QObject(parent) , d(new Private()) { d->color = color; } ManagedColor::~ManagedColor() { } bool ManagedColor::operator==(const ManagedColor &other) const { return d->color == other.d->color; } QColor ManagedColor::colorForCanvas(Canvas *canvas) const { QColor c = QColor(0,0,0); if (canvas && canvas->displayColorConverter() && canvas->displayColorConverter()->displayRendererInterface()) { KoColorDisplayRendererInterface *converter = canvas->displayColorConverter()->displayRendererInterface(); if (converter) { c = converter->toQColor(d->color); } else { c = KoDumbColorDisplayRenderer::instance()->toQColor(d->color); } } else { c = KoDumbColorDisplayRenderer::instance()->toQColor(d->color); } return c; } QString ManagedColor::colorDepth() const { return d->color.colorSpace()->colorDepthId().id(); } QString ManagedColor::colorModel() const { return d->color.colorSpace()->colorModelId().id(); } QString ManagedColor::colorProfile() const { return d->color.colorSpace()->profile()->name(); } bool ManagedColor::setColorProfile(const QString &colorProfile) { const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(colorProfile); if (!profile) return false; d->color.setProfile(profile); return true; } bool ManagedColor::setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile) { const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(colorModel, colorDepth, colorProfile); if (!colorSpace) return false; d->color.convertTo(colorSpace); return true; } QVector ManagedColor::components() const { QVector values(d->color.colorSpace()->channelCount()); d->color.colorSpace()->normalisedChannelsValue(d->color.data(), values); return values; } +QVector ManagedColor::componentsOrdered() const +{ + QVector valuesUnsorted = components(); + QVector values(d->color.colorSpace()->channelCount()); + for (int i=0; icolor.colorSpace()->channels()); + values[location] = valuesUnsorted[i]; + } + return values; +} + void ManagedColor::setComponents(const QVector &values) { d->color.colorSpace()->fromNormalisedChannelsValue(d->color.data(), values); } QString ManagedColor::toXML() const { QDomDocument doc; QDomElement root = doc.createElement("Color"); root.setAttribute("bitdepth", colorDepth()); doc.appendChild(root); d->color.toXML(doc, root); return doc.toString(); } void ManagedColor::fromXML(const QString &xml) { QDomDocument doc; doc.setContent(xml); QDomElement e = doc.documentElement(); QDomElement c = e.firstChildElement("Color"); KoColor kc; if (!c.isNull()) { QString colorDepthId = c.attribute("bitdepth", Integer8BitsColorDepthID.id()); d->color = KoColor::fromXML(c, colorDepthId); } } QString ManagedColor::toQString() { return KoColor::toQString(d->color); } KoColor ManagedColor::color() const { return d->color; } diff --git a/libs/libkis/ManagedColor.h b/libs/libkis/ManagedColor.h index cd56ed85f6..52e8c1d830 100644 --- a/libs/libkis/ManagedColor.h +++ b/libs/libkis/ManagedColor.h @@ -1,203 +1,209 @@ /* * Copyright (C) 2017 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef MANAGEDCOLOR_H #define MANAGEDCOLOR_H #include #include #include #include "kritalibkis_export.h" #include "libkis.h" class KoColor; /** * @brief The ManagedColor class is a class to handle colors that are color managed. * A managed color is a color of which we know the model(RGB, LAB, CMYK, etc), the bitdepth and * the specific properties of its colorspace, such as the whitepoint, chromacities, trc, etc, as represented * by the color profile. * * Krita has two color management systems. LCMS and OCIO. * LCMS is the one handling the ICC profile stuff, and the major one handling that ManagedColor deals with. * OCIO support is only in the display of the colors. ManagedColor has some support for it in colorForCanvas() * * All colors in Krita are color managed. QColors are understood as RGB-type colors in the sRGB space. * * We recommend you make a color like this: * * @code * colorYellow = ManagedColor("RGBA", "U8", "") * QVector yellowComponents = colorYellow.components() * yellowComponents[0] = 1.0 * yellowComponents[1] = 1.0 * yellowComponents[2] = 0 * yellowComponents[3] = 1.0 * * colorYellow.setComponents(yellowComponents) * QColor yellow = colorYellow.colorForCanvas(canvas) * @endcode */ class KRITALIBKIS_EXPORT ManagedColor : public QObject { Q_OBJECT public: /** * @brief ManagedColor * Create a ManagedColor that is black and transparent. */ explicit ManagedColor(QObject *parent = 0); /** * @brief ManagedColor create a managed color with the given color space properties. * @see setColorModel() for more details. */ ManagedColor(const QString &colorModel, const QString &colorDepth, const QString &colorProfile, QObject *parent = 0); ManagedColor(KoColor color, QObject *parent = 0); ~ManagedColor() override; bool operator==(const ManagedColor &other) const; /** * @brief colorForCanvas * @param canvas the canvas whose color management you'd like to use. In Krita, different views have * seperate canvasses, and these can have different OCIO configurations active. * @return the QColor as it would be displaying on the canvas. This result can be used to draw widgets with * the correct configuration applied. */ QColor colorForCanvas(Canvas *canvas) const; /** * colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @return the color depth. */ QString colorDepth() const; /** * @brief colorModel retrieve the current color model of this document: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @return the internal color model string. */ QString colorModel() const; /** * @return the name of the current color profile */ QString colorProfile() const; /** * @brief setColorProfile set the color profile of the image to the given profile. The profile has to * be registered with krita and be compatible with the current color model and depth; the image data * is not converted. * @param colorProfile * @return false if the colorProfile name does not correspond to to a registered profile or if assigning * the profile failed. */ bool setColorProfile(const QString &colorProfile); /** * @brief setColorSpace convert the nodes and the image to the given colorspace. The conversion is * done with Perceptual as intent, High Quality and No LCMS Optimizations as flags and no blackpoint * compensation. * * @param colorModel A string describing the color model of the image: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @param colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @param colorProfile a valid color profile for this color model and color depth combination. * @return false the combination of these arguments does not correspond to a colorspace. */ bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile); /** * @brief components * @return a QVector containing the channel/components of this color normalized. This includes the alphachannel. */ QVector components() const; + /** + * @brief componentsOrdered() + * @return same as Components, except the values are ordered to the display. + */ + QVector componentsOrdered() const; + /** * @brief setComponents * Set the channel/components with normalized values. For integer colorspace, this obviously means the limit * is between 0.0-1.0, but for floating point colorspaces, 2.4 or 103.5 are still meaningful (if bright) values. * @param values the QVector containing the new channel/component values. These should be normalized. */ void setComponents(const QVector &values); /** * Serialize this color following Create's swatch color specification available * at http://create.freedesktop.org/wiki/index.php/Swatches_-_colour_file_format */ QString toXML() const; /** * Unserialize a color following Create's swatch color specification available * at http://create.freedesktop.org/wiki/index.php/Swatches_-_colour_file_format * * @param XXX * * @return the unserialized color, or an empty color object if the function failed * to unserialize the color */ void fromXML(const QString &xml); /** * @brief toQString create a user-visible string of the channel names and the channel values * @param color the color to create the string from * @return a string that can be used to display the values of this color to the user. */ QString toQString(); private: friend class View; KoColor color() const; struct Private; const QScopedPointer d; }; #endif // MANAGEDCOLOR_H diff --git a/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_exporter_gimppalette.py b/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_exporter_gimppalette.py new file mode 100644 index 0000000000..f63e7e12ad --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_exporter_gimppalette.py @@ -0,0 +1,48 @@ +''' +A script that converts the palette named "Default" to a Gimp palette. +This ideally needs some gui and the like to select the palette to export.. +By Wolthera. +''' + + +# Importing the relevant dependancies: +import sys +from PyQt5.QtGui import * +from PyQt5.QtWidgets import * +import math +from krita import * + +allPalettes = Application.resources("palette") +paletteName = "Default" +self.currentPalette = Palette(allPalettes["paletteName"]) +# open the appropriate file... +gplFile = open(paletteName+".gpl", "w") +gplFile.write("GIMP Palette\n") +gplFile.write("Name: "+paletteName+"\n") +gplFile.write("Columns: "+str(self.currentPalette.columnCount())+"\n") +gplFile.write("#"+self.currentPalette.comment()+"\n") +colorCount = self.currentPalette.colorsCountGroup("") + +for i in range(colorCount): + entry = self.currentPalette.colorSetEntryFromGroup(i, "") + color = self.currentPalette.colorForEntry(entry) + #convert to sRGB + color.setColorSpace("RGBA", "U8", "sRGB built-in") + + red = max(min(int(color.componentsOrdered()[0]*255), 255), 0) + green = max(min(int(color.componentsOrdered()[1]*255), 255), 0) + blue = max(min(int(color.componentsOrdered()[2]*255), 255), 0) + gplFile.write(str(red)+" "+str(green)+" "+str(blue)+" "+entry.id+"-"+entry.name+"\n") + groupNames = self.currentPalette.groupNames() + for groupName in groupNames: + colorCount = self.currentPalette.colorsCountGroup(groupName) + for i in range(colorCount): + entry = self.currentPalette.colorSetEntryFromGroup(i, groupName) + color = self.currentPalette.colorForEntry(entry) + #convert to sRGB + color.setColorSpace("RGBA", "U8", "sRGB built-in") + red = max(min(int(color.componentsOrdered()[0]*255), 255), 0) + green = max(min(int(color.componentsOrdered()[1]*255), 255), 0) + blue = max(min(int(color.componentsOrdered()[2]*255), 255), 0) + gplFile.write(str(red)+" "+str(green)+" "+str(blue)+" "+entry.id+"-"+entry.name+"\n") +gplFile.close() diff --git a/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_exporter_inkscapeSVG.py b/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_exporter_inkscapeSVG.py new file mode 100644 index 0000000000..8d07f74c97 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_exporter_inkscapeSVG.py @@ -0,0 +1,124 @@ +''' +A script that converts the palette named "Default" to a SVG so that Inkscape may use the colors +This ideally needs some gui and the like to select the palette to export.. also, the icc-color stuff doesn't work right +ecause we'd need the ability to get the url of the colorprofile somehow, and then we can make @colorprofile things in the definitions. +By Wolthera. +''' + + +# Importing the relevant dependancies: +import sys +from PyQt5.QtGui import * +from PyQt5.QtXml import * +from PyQt5.QtWidgets import * +import math +from krita import * + +allPalettes = Application.resources("palette") +paletteName = "Default" +self.currentPalette = Palette(allPalettes[paletteName]) +# open the appropriate file... +svgFile = open(paletteName+".svg", "w") +svgDoc = QDomDocument() +svgBaseElement = svgDoc.createElement("svg") +svgBaseElement.setAttribute("xmlns:osb", "http://www.openswatchbook.org/uri/2009/osb") +svgBaseElement.setAttribute("xmlns:svg", "http://www.w3.org/2000/svg") +svgDefs = svgDoc.createElement("defs") +svgSwatches = svgDoc.createElement("g") +svgSwatches.setAttribute("id", "Swatches") +Row = 0 +Column = 0 + +colorCount = self.currentPalette.colorsCountGroup("") + +for i in range(colorCount): + entry = self.currentPalette.colorSetEntryFromGroup(i, "") + color = self.currentPalette.colorForEntry(entry) + + iccColor = "icc-color("+color.colorProfile() + for c in range(len(color.componentsOrdered())-1): + iccColor = iccColor+","+str(color.componentsOrdered()[c]) + iccColor = iccColor+")" + #convert to sRGB + color.setColorSpace("RGBA", "U8", "sRGB built-in") + red = max(min(int(color.componentsOrdered()[0]*255), 255), 0) + green = max(min(int(color.componentsOrdered()[1]*255), 255), 0) + blue = max(min(int(color.componentsOrdered()[2]*255), 255), 0) + hexcode = "#"+str(format(red, '02x'))+str(format(green, '02x'))+str(format(blue, '02x')) + swatchName = str(i)+"-"+entry.name + swatchName = swatchName.replace(" ", "-") + swatchMain = svgDoc.createElement("linearGradient") + swatchMain.setAttribute("osb:paint", "solid") + swatchMain.setAttribute("id", swatchName) + swatchSub = svgDoc.createElement("stop") + swatchSub.setAttribute("style", "stop-color: "+hexcode+" "+iccColor+";stop-opacity:1;") + swatchMain.appendChild(swatchSub) + svgDefs.appendChild(swatchMain) + svgSingleSwatch = svgDoc.createElement("rect") + svgSingleSwatch.setAttribute("x", str(int(Column*20))) + svgSingleSwatch.setAttribute("y", str(int(Row*20))) + svgSingleSwatch.setAttribute("width", str(int(20))) + svgSingleSwatch.setAttribute("height", str(int(20))) + svgSingleSwatch.setAttribute("fill", "url(#"+swatchName+")") + svgSingleSwatch.setAttribute("id", "swatch"+swatchName) + svgSwatches.appendChild(svgSingleSwatch) + Column += 1 + if (Column >= self.currentPalette.columnCount()): + Column = 0 + Row +=1 + +groupNames = self.currentPalette.groupNames() +for groupName in groupNames: + Column=0 + Row+=1 + groupTitle = svgDoc.createElement("text") + groupTitle.setAttribute("x", str(int(Column*20))) + groupTitle.setAttribute("y", str(int(Row*20)+15)) + groupTitle.appendChild(svgDoc.createTextNode(groupName)) + svgSwatches.appendChild(groupTitle) + Row+=1 + colorCount = self.currentPalette.colorsCountGroup(groupName) + for i in range(colorCount): + entry = self.currentPalette.colorSetEntryFromGroup(i, groupName) + color = self.currentPalette.colorForEntry(entry) + iccColor = "icc-color("+color.colorProfile() + for c in range(len(color.componentsOrdered())-1): + iccColor = iccColor+","+str(color.componentsOrdered()[c]) + iccColor = iccColor+")" + #convert to sRGB + color.setColorSpace("RGBA", "U8", "sRGB built-in") + red = max(min(int(color.componentsOrdered()[0]*255), 255), 0) + green = max(min(int(color.componentsOrdered()[1]*255), 255), 0) + blue = max(min(int(color.componentsOrdered()[2]*255), 255), 0) + hexcode = "#"+str(format(red, '02x'))+str(format(green, '02x'))+str(format(blue, '02x')) + + swatchName = groupName+str(i)+"-"+entry.name + swatchName = swatchName.replace(" ", "-") + swatchMain = svgDoc.createElement("linearGradient") + swatchMain.setAttribute("osb:paint", "solid") + swatchMain.setAttribute("id", swatchName) + swatchSub = svgDoc.createElement("stop") + swatchSub.setAttribute("style", "stop-color: "+hexcode+" "+iccColor+";stop-opacity:1;") + swatchMain.appendChild(swatchSub) + svgDefs.appendChild(swatchMain) + svgSingleSwatch = svgDoc.createElement("rect") + svgSingleSwatch.setAttribute("x", str(int(Column*20))) + svgSingleSwatch.setAttribute("y", str(int(Row*20))) + svgSingleSwatch.setAttribute("width", str(int(20))) + svgSingleSwatch.setAttribute("height", str(int(20))) + svgSingleSwatch.setAttribute("fill", "url(#"+swatchName+")") + svgSingleSwatch.setAttribute("id", "swatch"+swatchName) + svgSwatches.appendChild(svgSingleSwatch) + Column += 1 + if (Column >= self.currentPalette.columnCount()): + Column = 0 + Row +=1 + +svgBaseElement.appendChild(svgDefs) +svgBaseElement.appendChild(svgSwatches) +svgBaseElement.setAttribute("viewBox", "0 0 "+str(self.currentPalette.columnCount()*20)+" "+str(int(Row*20))) +svgDoc.appendChild(svgBaseElement) +svgFile.write(svgDoc.toString()) +svgFile.close() + + diff --git a/plugins/extensions/pykrita/sip/krita/ManagedColor.sip b/plugins/extensions/pykrita/sip/krita/ManagedColor.sip index 8e7a96a549..5d8f9a580c 100644 --- a/plugins/extensions/pykrita/sip/krita/ManagedColor.sip +++ b/plugins/extensions/pykrita/sip/krita/ManagedColor.sip @@ -1,23 +1,24 @@ class ManagedColor : QObject { %TypeHeaderCode #include "ManagedColor.h" %End ManagedColor(const Palette & __0); public: ManagedColor(const QString &colorModel, const QString &colorDepth, const QString &colorProfile, QObject *parent = 0); bool operator==(const ManagedColor &other) const; QColor colorForCanvas(Canvas *canvas) const; QString colorDepth() const; QString colorModel() const; QString colorProfile() const; bool setColorProfile(const QString &colorProfile); bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile); QVector components() const; + QVector componentsOrdered() const; void setComponents(const QVector &values); QString toXML() const; void fromXML(const QString &xml); QString toQString(); private: };