diff --git a/libs/image/kis_properties_configuration.cc b/libs/image/kis_properties_configuration.cc index ade808b394..9b9e682770 100644 --- a/libs/image/kis_properties_configuration.cc +++ b/libs/image/kis_properties_configuration.cc @@ -1,328 +1,331 @@ /* * Copyright (c) 2006 Boudewijn Rempt * Copyright (c) 2007,2010 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_properties_configuration.h" #include #include #include #include "kis_image.h" #include "kis_transaction.h" #include "kis_undo_adapter.h" #include "kis_painter.h" #include "kis_selection.h" #include "KoID.h" #include "kis_types.h" #include #include struct Q_DECL_HIDDEN KisPropertiesConfiguration::Private { QMap properties; QStringList notSavedProperties; }; KisPropertiesConfiguration::KisPropertiesConfiguration() : d(new Private) { } KisPropertiesConfiguration::~KisPropertiesConfiguration() { delete d; } KisPropertiesConfiguration::KisPropertiesConfiguration(const KisPropertiesConfiguration& rhs) : KisSerializableConfiguration(rhs) , d(new Private(*rhs.d)) { } KisPropertiesConfiguration &KisPropertiesConfiguration::operator=(const KisPropertiesConfiguration &rhs) { if (&rhs != this) { *d = *rhs.d; } return *this; } bool KisPropertiesConfiguration::fromXML(const QString & xml, bool clear) { if (clear) { clearProperties(); } QDomDocument doc; bool retval = doc.setContent(xml); if (retval) { QDomElement e = doc.documentElement(); fromXML(e); } return retval; } void KisPropertiesConfiguration::fromXML(const QDomElement& e) { QDomNode n = e.firstChild(); while (!n.isNull()) { // We don't nest elements in filter configuration. For now... QDomElement e = n.toElement(); if (!e.isNull()) { if (e.tagName() == "param") { // If the file contains the new type parameter introduced in Krita act on it // Else invoke old behaviour if(e.attributes().contains("type")) { QString type = e.attribute("type"); QString name = e.attribute("name"); QString value = e.text(); if(type == "bytearray") { d->properties[name] = QVariant(QByteArray::fromBase64(value.toLatin1())); } else d->properties[name] = value; } else d->properties[e.attribute("name")] = QVariant(e.text()); } } n = n.nextSibling(); } //dump(); } void KisPropertiesConfiguration::toXML(QDomDocument& doc, QDomElement& root) const { QMap::Iterator it; for (it = d->properties.begin(); it != d->properties.end(); ++it) { if(d->notSavedProperties.contains(it.key())) { continue; } QDomElement e = doc.createElement("param"); e.setAttribute("name", QString(it.key().toLatin1())); QString type = "string"; QVariant v = it.value(); QDomText text; if (v.type() == QVariant::UserType && v.userType() == qMetaTypeId()) { text = doc.createCDATASection(v.value().toString()); } else if (v.type() == QVariant::UserType && v.userType() == qMetaTypeId()) { QDomDocument doc = QDomDocument("color"); QDomElement root = doc.createElement("color"); doc.appendChild(root); v.value().toXML(doc, root); text = doc.createCDATASection(doc.toString()); type = "color"; } else if(v.type() == QVariant::String ) { text = doc.createCDATASection(v.toString()); // XXX: Unittest this! type = "string"; } else if(v.type() == QVariant::ByteArray ) { text = doc.createTextNode(QString::fromLatin1(v.toByteArray().toBase64())); // Arbitrary Data type = "bytearray"; } else { text = doc.createTextNode(v.toString()); type = "internal"; } e.setAttribute("type", type); e.appendChild(text); root.appendChild(e); } } QString KisPropertiesConfiguration::toXML() const { QDomDocument doc = QDomDocument("params"); QDomElement root = doc.createElement("params"); doc.appendChild(root); toXML(doc, root); return doc.toString(); } bool KisPropertiesConfiguration::hasProperty(const QString& name) const { return d->properties.contains(name); } void KisPropertiesConfiguration::setProperty(const QString & name, const QVariant & value) { if (d->properties.find(name) == d->properties.end()) { d->properties.insert(name, value); } else { d->properties[name] = value; } } bool KisPropertiesConfiguration::getProperty(const QString & name, QVariant & value) const { if (d->properties.find(name) == d->properties.end()) { return false; } else { value = d->properties[name]; return true; } } QVariant KisPropertiesConfiguration::getProperty(const QString & name) const { if (d->properties.find(name) == d->properties.end()) { return QVariant(); } else { return d->properties[name]; } } int KisPropertiesConfiguration::getInt(const QString & name, int def) const { QVariant v = getProperty(name); if (v.isValid()) return v.toInt(); else return def; } double KisPropertiesConfiguration::getDouble(const QString & name, double def) const { QVariant v = getProperty(name); if (v.isValid()) return v.toDouble(); else return def; } float KisPropertiesConfiguration::getFloat(const QString & name, float def) const { QVariant v = getProperty(name); if (v.isValid()) return (float)v.toDouble(); else return def; } bool KisPropertiesConfiguration::getBool(const QString & name, bool def) const { QVariant v = getProperty(name); if (v.isValid()) return v.toBool(); else return def; } QString KisPropertiesConfiguration::getString(const QString & name, const QString & def) const { QVariant v = getProperty(name); if (v.isValid()) return v.toString(); else return def; } KisCubicCurve KisPropertiesConfiguration::getCubicCurve(const QString & name, const KisCubicCurve & curve) const { QVariant v = getProperty(name); if (v.isValid()) { if (v.type() == QVariant::UserType && v.userType() == qMetaTypeId()) { return v.value(); } else { KisCubicCurve c; c.fromString(v.toString()); return c; } } else return curve; } KoColor KisPropertiesConfiguration::getColor(const QString& name, const KoColor& color) const { QVariant v = getProperty(name); if (v.isValid()) { if (v.type() == QVariant::UserType && v.userType() == qMetaTypeId()) { return v.value(); } else { QDomDocument doc; doc.setContent(v.toString()); QDomElement e = doc.documentElement().firstChild().toElement(); - return KoColor::fromXML(e, Integer16BitsColorDepthID.id()); + bool ok; + KoColor c = KoColor::fromXML(e, Integer16BitsColorDepthID.id(), &ok); + if (ok) { + return c; + } } - } else { - return color; } + return color; } void KisPropertiesConfiguration::dump() const { QMap::Iterator it; for (it = d->properties.begin(); it != d->properties.end(); ++it) { dbgKrita << it.key() << " = " << it.value(); } } void KisPropertiesConfiguration::clearProperties() { d->properties.clear(); } void KisPropertiesConfiguration::setPropertyNotSaved(const QString& name) { d->notSavedProperties.append(name); } QMap KisPropertiesConfiguration::getProperties() const { return d->properties; } void KisPropertiesConfiguration::removeProperty(const QString & name) { d->properties.remove(name); } // --- factory --- struct Q_DECL_HIDDEN KisPropertiesConfigurationFactory::Private { }; KisPropertiesConfigurationFactory::KisPropertiesConfigurationFactory() : d(new Private) { } KisPropertiesConfigurationFactory::~KisPropertiesConfigurationFactory() { delete d; } KisSerializableConfigurationSP KisPropertiesConfigurationFactory::createDefault() { return new KisPropertiesConfiguration(); } KisSerializableConfigurationSP KisPropertiesConfigurationFactory::create(const QDomElement& e) { KisPropertiesConfigurationSP pc = new KisPropertiesConfiguration(); pc->fromXML(e); return pc; } diff --git a/libs/pigment/KoColor.cpp b/libs/pigment/KoColor.cpp index b5973762b0..5ab7e9e9a3 100644 --- a/libs/pigment/KoColor.cpp +++ b/libs/pigment/KoColor.cpp @@ -1,336 +1,345 @@ /* * Copyright (c) 2005 Boudewijn Rempt * Copyright (C) 2007 Thomas Zander * Copyright (C) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "KoColor.h" #include #include #include "DebugPigment.h" #include "KoColorModelStandardIds.h" #include "KoColorProfile.h" #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "KoChannelInfo.h" class Q_DECL_HIDDEN KoColor::Private { public: Private() : data(0), colorSpace(0) {} ~Private() { delete [] data; } quint8 * data; const KoColorSpace * colorSpace; }; KoColor::KoColor() : d(new Private()) { d->colorSpace = KoColorSpaceRegistry::instance()->rgb16(0); d->data = new quint8[d->colorSpace->pixelSize()]; d->colorSpace->fromQColor(Qt::black, d->data); d->colorSpace->setOpacity(d->data, OPACITY_OPAQUE_U8, 1); } KoColor::KoColor(const KoColorSpace * colorSpace) : d(new Private()) { Q_ASSERT(colorSpace); d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); d->data = new quint8[d->colorSpace->pixelSize()]; memset(d->data, 0, d->colorSpace->pixelSize()); } KoColor::~KoColor() { delete d; } KoColor::KoColor(const QColor & color, const KoColorSpace * colorSpace) : d(new Private()) { Q_ASSERT(color.isValid()); Q_ASSERT(colorSpace); d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); d->data = new quint8[colorSpace->pixelSize()]; memset(d->data, 0, d->colorSpace->pixelSize()); d->colorSpace->fromQColor(color, d->data); } KoColor::KoColor(const quint8 * data, const KoColorSpace * colorSpace) : d(new Private()) { Q_ASSERT(colorSpace); Q_ASSERT(data); d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); d->data = new quint8[colorSpace->pixelSize()]; memset(d->data, 0, d->colorSpace->pixelSize()); memmove(d->data, data, colorSpace->pixelSize()); } KoColor::KoColor(const KoColor &src, const KoColorSpace * colorSpace) : d(new Private()) { Q_ASSERT(colorSpace); d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); d->data = new quint8[colorSpace->pixelSize()]; memset(d->data, 0, d->colorSpace->pixelSize()); src.colorSpace()->convertPixelsTo(src.d->data, d->data, colorSpace, 1, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); } KoColor::KoColor(const KoColor & rhs) : d(new Private()) { d->colorSpace = rhs.colorSpace(); Q_ASSERT(*d->colorSpace == *KoColorSpaceRegistry::instance()->permanentColorspace(d->colorSpace)); if (d->colorSpace && rhs.d->data) { d->data = new quint8[d->colorSpace->pixelSize()]; memcpy(d->data, rhs.d->data, d->colorSpace->pixelSize()); } } KoColor & KoColor::operator=(const KoColor & rhs) { if (this == &rhs) return *this; delete [] d->data; d->data = 0; d->colorSpace = rhs.colorSpace(); if (rhs.d->colorSpace && rhs.d->data) { Q_ASSERT(d->colorSpace == KoColorSpaceRegistry::instance()->permanentColorspace(d->colorSpace)); // here we want to do a check on pointer, since d->colorSpace is supposed to already be a permanent one d->data = new quint8[d->colorSpace->pixelSize()]; memcpy(d->data, rhs.d->data, d->colorSpace->pixelSize()); } return * this; } bool KoColor::operator==(const KoColor &other) const { if (*colorSpace() != *other.colorSpace()) return false; return memcmp(d->data, other.d->data, d->colorSpace->pixelSize()) == 0; } void KoColor::convertTo(const KoColorSpace * cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) { //dbgPigment <<"Our colormodel:" << d->colorSpace->id().name() // << ", new colormodel: " << cs->id().name() << "\n"; if (*d->colorSpace == *cs) return; quint8 * data = new quint8[cs->pixelSize()]; memset(data, 0, cs->pixelSize()); d->colorSpace->convertPixelsTo(d->data, data, cs, 1, renderingIntent, conversionFlags); delete [] d->data; d->data = data; d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(cs); } void KoColor::convertTo(const KoColorSpace * cs) { convertTo(cs, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); } void KoColor::setProfile(const KoColorProfile *profile) { const KoColorSpace *dstColorSpace = KoColorSpaceRegistry::instance()->colorSpace(colorSpace()->colorModelId().id(), colorSpace()->colorDepthId().id(), profile); if (!dstColorSpace) return; d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(dstColorSpace); } void KoColor::setColor(const quint8 * data, const KoColorSpace * colorSpace) { Q_ASSERT(data); Q_ASSERT(colorSpace); if(d->colorSpace->pixelSize() != colorSpace->pixelSize()) { delete [] d->data; d->data = new quint8[colorSpace->pixelSize()]; } memcpy(d->data, data, colorSpace->pixelSize()); d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); } // To save the user the trouble of doing color->colorSpace()->toQColor(color->data(), &c, &a, profile void KoColor::toQColor(QColor *c) const { Q_ASSERT(c); if (d->colorSpace && d->data) { d->colorSpace->toQColor(d->data, c); } } QColor KoColor::toQColor() const { QColor c; toQColor(&c); return c; } void KoColor::fromQColor(const QColor& c) const { if (d->colorSpace && d->data) { d->colorSpace->fromQColor(c, d->data); } } #ifndef NDEBUG void KoColor::dump() const { dbgPigment <<"KoColor (" << this <<")," << d->colorSpace->id() <<""; QList channels = d->colorSpace->channels(); QList::const_iterator begin = channels.constBegin(); QList::const_iterator end = channels.constEnd(); for (QList::const_iterator it = begin; it != end; ++it) { KoChannelInfo * ch = (*it); // XXX: setNum always takes a byte. if (ch->size() == sizeof(quint8)) { // Byte dbgPigment <<"Channel (byte):" << ch->name() <<":" << QString().setNum(d->data[ch->pos()]) <<""; } else if (ch->size() == sizeof(quint16)) { // Short (may also by an nvidia half) dbgPigment <<"Channel (short):" << ch->name() <<":" << QString().setNum(*((const quint16 *)(d->data+ch->pos()))) <<""; } else if (ch->size() == sizeof(quint32)) { // Integer (may also be float... Find out how to distinguish these!) dbgPigment <<"Channel (int):" << ch->name() <<":" << QString().setNum(*((const quint32 *)(d->data+ch->pos()))) <<""; } } } #endif void KoColor::fromKoColor(const KoColor& src) { src.colorSpace()->convertPixelsTo(src.d->data, d->data, colorSpace(), 1, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); } const KoColorProfile *KoColor::profile() const { return d->colorSpace->profile(); } quint8 * KoColor::data() { return d->data; } const quint8 * KoColor::data() const { return d->data; } const KoColorSpace * KoColor::colorSpace() const { return d->colorSpace; } void KoColor::toXML(QDomDocument& doc, QDomElement& colorElt) const { d->colorSpace->colorToXML(d->data, doc, colorElt); } void KoColor::setOpacity(quint8 alpha) { d->colorSpace->setOpacity(d->data, alpha, 1); } void KoColor::setOpacity(qreal alpha) { d->colorSpace->setOpacity(d->data, alpha, 1); } quint8 KoColor::opacityU8() const { return d->colorSpace->opacityU8(d->data); } qreal KoColor::opacityF() const { return d->colorSpace->opacityF(d->data); } -KoColor KoColor::fromXML(const QDomElement& elt, const QString & bitDepthId) +KoColor KoColor::fromXML(const QDomElement& elt, const QString& bitDepthId) { + bool ok; + return fromXML(elt, bitDepthId, &ok); +} + +KoColor KoColor::fromXML(const QDomElement& elt, const QString& bitDepthId, bool* ok) +{ + *ok = true; QString modelId; if (elt.tagName() == "CMYK") { modelId = CMYKAColorModelID.id(); } else if (elt.tagName() == "RGB") { modelId = RGBAColorModelID.id(); } else if (elt.tagName() == "sRGB") { modelId = RGBAColorModelID.id(); } else if (elt.tagName() == "Lab") { modelId = LABAColorModelID.id(); } else if (elt.tagName() == "XYZ") { modelId = XYZAColorModelID.id(); } else if (elt.tagName() == "Gray") { modelId = GrayAColorModelID.id(); } else if (elt.tagName() == "YCbCr") { modelId = YCbCrAColorModelID.id(); } QString profileName; if (elt.tagName() != "sRGB") { profileName = elt.attribute("space", ""); if (!KoColorSpaceRegistry::instance()->profileByName(profileName)) { profileName.clear(); } } const KoColorSpace* cs = KoColorSpaceRegistry::instance()->colorSpace(modelId, bitDepthId, profileName); if (cs == 0) { QList list = KoColorSpaceRegistry::instance()->colorDepthList(modelId, KoColorSpaceRegistry::AllColorSpaces); if (!list.empty()) { cs = KoColorSpaceRegistry::instance()->colorSpace(modelId, list[0].id(), profileName); } } if (cs) { KoColor c(cs); + // TODO: Provide a way for colorFromXML() to notify the caller if parsing failed. Currently it returns default values on failure. cs->colorFromXML(c.data(), elt); return c; } else { + *ok = false; return KoColor(); } } QString KoColor::toQString(const KoColor &color) { QStringList ls; Q_FOREACH (KoChannelInfo *channel, KoChannelInfo::displayOrderSorted(color.colorSpace()->channels())) { int realIndex = KoChannelInfo::displayPositionToChannelIndex(channel->displayPosition(), color.colorSpace()->channels()); ls << channel->name(); ls << color.colorSpace()->channelValueText(color.data(), realIndex); } return ls.join(" "); } diff --git a/libs/pigment/KoColor.h b/libs/pigment/KoColor.h index 214c20a137..24c4d28ef6 100644 --- a/libs/pigment/KoColor.h +++ b/libs/pigment/KoColor.h @@ -1,179 +1,193 @@ /* * Copyright (c) 2005 Boudewijn Rempt * Copyright (C) 2007 Thomas Zander * * 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 KOCOLOR_H #define KOCOLOR_H #include #include #include "kritapigment_export.h" #include "KoColorConversionTransformation.h" #include class QDomDocument; class QDomElement; class KoColorProfile; class KoColorSpace; /** * A KoColor describes a color in a certain colorspace. The color is stored in a buffer * that can be manipulated by the function of the color space. */ class KRITAPIGMENT_EXPORT KoColor : public boost::equality_comparable { public: /// Create an empty KoColor. It will be valid, but also black and transparent KoColor(); ~KoColor(); /// Create a null KoColor. It will be valid, but all channels will be set to 0 explicit KoColor(const KoColorSpace * colorSpace); /// Create a KoColor from a QColor. The QColor is immediately converted to native. The QColor /// is assumed to have the current monitor profile. KoColor(const QColor & color, const KoColorSpace * colorSpace); /// Create a KoColor using a native color strategy. The data is copied. KoColor(const quint8 * data, const KoColorSpace * colorSpace); /// Create a KoColor by converting src into another colorspace KoColor(const KoColor &src, const KoColorSpace * colorSpace); /// Copy constructor -- deep copies the colors. KoColor(const KoColor & rhs); /** * assignment operator to copy the data from the param color into this one. * @param other the color we are going to copy * @return this color */ KoColor &operator=(const KoColor &other); bool operator==(const KoColor &other) const; /// return the current colorSpace const KoColorSpace * colorSpace() const; /// return the current profile const KoColorProfile *profile() const; /// Convert this KoColor to the specified colorspace. If the specified colorspace is the /// same as the original colorspace, do nothing. Returns the converted KoColor. void convertTo(const KoColorSpace * cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags); void convertTo(const KoColorSpace * cs); /// assign new profile without converting pixel data void setProfile(const KoColorProfile *profile); - /// Replace the existing color data, and colorspace with the specified data. /// The data is copied. void setColor(const quint8 * data, const KoColorSpace * colorSpace = 0); /// Convert the color from src and replace the value of the current color with the converted data. /// Don't convert the color if src and this have the same colorspace. void fromKoColor(const KoColor& src); /// a convenience method for the above. void toQColor(QColor *c) const; /// a convenience method for the above. QColor toQColor() const; /** * Convenient function to set the opacity of the color. */ void setOpacity(quint8 alpha); void setOpacity(qreal alpha); /** * Convenient function that return the opacity of the color */ quint8 opacityU8() const; qreal opacityF() const; /// Convenient function for converting from a QColor void fromQColor(const QColor& c) const; /** * @return the buffer associated with this color object to be used with the * transformation object created by the color space of this KoColor * or to copy to a different buffer from the same color space */ quint8 * data(); /** * @return the buffer associated with this color object to be used with the * transformation object created by the color space of this KoColor * or to copy to a different buffer from the same color space */ const quint8 * data() const; /** * Serialize this color following Create's swatch color specification available * at http://create.freedesktop.org/wiki/index.php/Swatches_-_colour_file_format * * This function doesn't create the element but rather the , * , ... elements. It is assumed that colorElt is the * element. * * @param colorElt root element for the serialization, it is assumed that this * element is * @param doc is the document containing colorElt */ void toXML(QDomDocument& doc, QDomElement& colorElt) const; /** * Unserialize a color following Create's swatch color specification available * at http://create.freedesktop.org/wiki/index.php/Swatches_-_colour_file_format * * @param elt the element to unserialize (, , ) * @param bitDepthId the bit depth is unspecified by the spec, this allow to select * a preferred bit depth for creating the KoColor object (if that * bit depth isn't available, this function will randomly select * an other bit depth) * @return the unserialize color, or an empty color object if the function failed * to unserialize the color */ static KoColor fromXML(const QDomElement& elt, const QString & bitDepthId); + /** + * Unserialize a color following Create's swatch color specification available + * at http://create.freedesktop.org/wiki/index.php/Swatches_-_colour_file_format + * + * @param elt the element to unserialize (, , ) + * @param bitDepthId the bit depth is unspecified by the spec, this allow to select + * a preferred bit depth for creating the KoColor object (if that + * bit depth isn't available, this function will randomly select + * an other bit depth) + * @param ok If a an error occurs, *ok is set to false; otherwise it's set to true + * @return the unserialize color, or an empty color object if the function failed + * to unserialize the color + */ + static KoColor fromXML(const QDomElement& elt, const QString & bitDepthId, bool* ok); + /** * @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. */ static QString toQString(const KoColor &color); #ifndef NODEBUG /// use qDebug calls to print internal info void dump() const; #endif private: class Private; Private * const d; }; Q_DECLARE_METATYPE(KoColor) #endif diff --git a/plugins/impex/jpeg/kis_jpeg_export.cc b/plugins/impex/jpeg/kis_jpeg_export.cc index c6d74f926a..03b97fe70a 100644 --- a/plugins/impex/jpeg/kis_jpeg_export.cc +++ b/plugins/impex/jpeg/kis_jpeg_export.cc @@ -1,223 +1,233 @@ /* * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_jpeg_export.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_jpeg_converter.h" class KisExternalLayer; K_PLUGIN_FACTORY_WITH_JSON(KisJPEGExportFactory, "krita_jpeg_export.json", registerPlugin();) KisJPEGExport::KisJPEGExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KisJPEGExport::~KisJPEGExport() { } KisImportExportFilter::ConversionStatus KisJPEGExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration) { KisImageSP image = document->savingImage(); Q_CHECK_PTR(image); // An extra option to pass to the config widget to set the state correctly, this isn't saved const KoColorSpace* cs = image->projection()->colorSpace(); bool sRGB = cs->profile()->name().contains(QLatin1String("srgb"), Qt::CaseInsensitive); configuration->setProperty("is_sRGB", sRGB); KisJPEGOptions options; options.progressive = configuration->getBool("progressive", false); options.quality = configuration->getInt("quality", 80); options.forceSRGB = configuration->getBool("forceSRGB", false); options.saveProfile = configuration->getBool("saveProfile", true); options.optimize = configuration->getBool("optimize", true); options.smooth = configuration->getInt("smoothing", 0); options.baseLineJPEG = configuration->getBool("baseline", true); options.subsampling = configuration->getInt("subsampling", 0); options.exif = configuration->getBool("exif", true); options.iptc = configuration->getBool("iptc", true); options.xmp = configuration->getBool("xmp", true); - QStringList rgb = configuration->getString("transparencyFillcolor", "255,255,255").split(','); - options.transparencyFillColor = QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt()); + KoColor c(KoColorSpaceRegistry::instance()->rgb8()); + c.fromQColor(Qt::white); + options.transparencyFillColor = configuration->getColor("transparencyFillcolor", c).toQColor(); KisMetaData::FilterRegistryModel m; m.setEnabledFilters(configuration->getString("filters").split(",")); options.filters = m.enabledFilters(); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); KisJPEGConverter kpc(document, batchMode()); KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); KisExifInfoVisitor eIV; eIV.visit(image->rootLayer().data()); KisMetaData::Store* eI = 0; if (eIV.countPaintLayer() == 1) { eI = eIV.exifInfo(); } if (eI) { KisMetaData::Store* copy = new KisMetaData::Store(*eI); eI = copy; } KisImageBuilder_Result res = kpc.buildFile(io, l, options, eI); if (res == KisImageBuilder_RESULT_OK) { delete eI; return KisImportExportFilter::OK; } delete eI; dbgFile << " Result =" << res; return KisImportExportFilter::InternalError; } KisPropertiesConfigurationSP KisJPEGExport::defaultConfiguration(const QByteArray &/*from*/, const QByteArray &/*to*/) const { KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(); cfg->setProperty("progressive", false); cfg->setProperty("quality", 80); cfg->setProperty("forceSRGB", false); cfg->setProperty("saveProfile", true); cfg->setProperty("optimize", true); cfg->setProperty("smoothing", 0); cfg->setProperty("baseline", true); cfg->setProperty("subsampling", 0); cfg->setProperty("exif", true); cfg->setProperty("iptc", true); cfg->setProperty("xmp", true); - cfg->setProperty("transparencyFillcolor", QString("255,255,255")); + + KoColor fill_color(KoColorSpaceRegistry::instance()->rgb8()); + fill_color = KoColor(); + fill_color.fromQColor(Qt::white); + QVariant v; + v.setValue(fill_color); + + cfg->setProperty("transparencyFillcolor", v); cfg->setProperty("filters", ""); return cfg; } KisConfigWidget *KisJPEGExport::createConfigurationWidget(QWidget *parent, const QByteArray &/*from*/, const QByteArray &/*to*/) const { return new KisWdgOptionsJPEG(parent); } void KisJPEGExport::initializeCapabilities() { addCapability(KisExportCheckRegistry::instance()->get("sRGBProfileCheck")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("ExifCheck")->create(KisExportCheckBase::SUPPORTED)); QList > supportedColorModels; supportedColorModels << QPair() << QPair(RGBAColorModelID, Integer8BitsColorDepthID) << QPair(GrayAColorModelID, Integer8BitsColorDepthID) << QPair(CMYKAColorModelID, Integer8BitsColorDepthID); addSupportedColorModels(supportedColorModels, "JPEG"); } KisWdgOptionsJPEG::KisWdgOptionsJPEG(QWidget *parent) : KisConfigWidget(parent) { setupUi(this); metaDataFilters->setModel(&m_filterRegistryModel); qualityLevel->setRange(0, 100, 0); qualityLevel->setSuffix("%"); smoothLevel->setRange(0, 100, 0); smoothLevel->setSuffix("%"); } void KisWdgOptionsJPEG::setConfiguration(const KisPropertiesConfigurationSP cfg) { progressive->setChecked(cfg->getBool("progressive", false)); qualityLevel->setValue(cfg->getInt("quality", 80)); optimize->setChecked(cfg->getBool("optimize", true)); smoothLevel->setValue(cfg->getInt("smoothing", 0)); baseLineJPEG->setChecked(cfg->getBool("baseline", true)); subsampling->setCurrentIndex(cfg->getInt("subsampling", 0)); exif->setChecked(cfg->getBool("exif", true)); iptc->setChecked(cfg->getBool("iptc", true)); xmp->setChecked(cfg->getBool("xmp", true)); chkForceSRGB->setVisible(cfg->getBool("is_sRGB")); chkForceSRGB->setChecked(cfg->getBool("forceSRGB", false)); chkSaveProfile->setChecked(cfg->getBool("saveProfile", true)); - QStringList rgb = cfg->getString("transparencyFillcolor", "255,255,255").split(','); KoColor background(KoColorSpaceRegistry::instance()->rgb8()); background.fromQColor(Qt::white); bnTransparencyFillColor->setDefaultColor(background); - background.fromQColor(QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt())); - bnTransparencyFillColor->setColor(background); + bnTransparencyFillColor->setColor(cfg->getColor("transparencyFillcolor", background)); m_filterRegistryModel.setEnabledFilters(cfg->getString("filters").split(',')); } KisPropertiesConfigurationSP KisWdgOptionsJPEG::configuration() const { KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(); + + QVariant transparencyFillcolor; + transparencyFillcolor.setValue(bnTransparencyFillColor->color()); + cfg->setProperty("progressive", progressive->isChecked()); cfg->setProperty("quality", (int)qualityLevel->value()); cfg->setProperty("forceSRGB", chkForceSRGB->isChecked()); cfg->setProperty("saveProfile", chkSaveProfile->isChecked()); cfg->setProperty("optimize", optimize->isChecked()); cfg->setProperty("smoothing", (int)smoothLevel->value()); cfg->setProperty("baseline", baseLineJPEG->isChecked()); cfg->setProperty("subsampling", subsampling->currentIndex()); cfg->setProperty("exif", exif->isChecked()); cfg->setProperty("iptc", iptc->isChecked()); cfg->setProperty("xmp", xmp->isChecked()); - QColor c = bnTransparencyFillColor->color().toQColor(); - cfg->setProperty("transparencyFillcolor", QString("%1,%2,%3").arg(c.red()).arg(c.green()).arg(c.blue())); + cfg->setProperty("transparencyFillcolor", transparencyFillcolor); + QString enabledFilters; Q_FOREACH (const KisMetaData::Filter* filter, m_filterRegistryModel.enabledFilters()) { enabledFilters = enabledFilters + filter->id() + ','; } cfg->setProperty("filters", enabledFilters); return cfg; } #include diff --git a/plugins/impex/png/kis_png_export.cc b/plugins/impex/png/kis_png_export.cc index 9914f51d93..015dbe0d08 100644 --- a/plugins/impex/png/kis_png_export.cc +++ b/plugins/impex/png/kis_png_export.cc @@ -1,225 +1,232 @@ /* * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_png_export.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_png_converter.h" #include K_PLUGIN_FACTORY_WITH_JSON(KisPNGExportFactory, "krita_png_export.json", registerPlugin();) KisPNGExport::KisPNGExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KisPNGExport::~KisPNGExport() { } bool hasVisibleWidgets() { QWidgetList wl = QApplication::allWidgets(); Q_FOREACH (QWidget* w, wl) { if (w->isVisible() && strcmp(w->metaObject()->className(), "QDesktopWidget")) { dbgFile << "Widget " << w << " " << w->objectName() << " " << w->metaObject()->className() << " is visible"; return true; } } return false; } KisImportExportFilter::ConversionStatus KisPNGExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration) { KisImageSP image = document->savingImage(); KisPNGOptions options; options.alpha = configuration->getBool("alpha", true); options.interlace = configuration->getBool("interlaced", false); options.compression = configuration->getInt("compression", 3); options.tryToSaveAsIndexed = configuration->getBool("indexed", false); - QStringList rgb = configuration->getString("transparencyFillcolor", "255,255,255").split(','); - options.transparencyFillColor = QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt()); + KoColor c(KoColorSpaceRegistry::instance()->rgb8()); + c.fromQColor(Qt::white); + options.transparencyFillColor = configuration->getColor("transparencyFillcolor", c).toQColor(); options.saveSRGBProfile = configuration->getBool("saveSRGBProfile", false); options.forceSRGB = configuration->getBool("forceSRGB", true); vKisAnnotationSP_it beginIt = image->beginAnnotations(); vKisAnnotationSP_it endIt = image->endAnnotations(); KisExifInfoVisitor eIV; eIV.visit(image->rootLayer().data()); KisMetaData::Store *eI = 0; if (eIV.countPaintLayer() == 1) { eI = eIV.exifInfo(); } if (eI) { KisMetaData::Store* copy = new KisMetaData::Store(*eI); eI = copy; } KisPNGConverter pngConverter(document); KisImageBuilder_Result res = pngConverter.buildFile(io, image->bounds(), image->xRes(), image->yRes(), image->projection(), beginIt, endIt, options, eI); if (res == KisImageBuilder_RESULT_OK) { delete eI; return KisImportExportFilter::OK; } delete eI; dbgFile << " Result =" << res; return KisImportExportFilter::InternalError; } KisPropertiesConfigurationSP KisPNGExport::defaultConfiguration(const QByteArray &, const QByteArray &) const { KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(); cfg->setProperty("alpha", true); cfg->setProperty("indexed", false); cfg->setProperty("compression", 3); cfg->setProperty("interlaced", false); - cfg->setProperty("transparencyFillcolor", QString("255,255,255")); + + KoColor fill_color(KoColorSpaceRegistry::instance()->rgb8()); + fill_color = KoColor(); + fill_color.fromQColor(Qt::white); + QVariant v; + v.setValue(fill_color); + + cfg->setProperty("transparencyFillcolor", v); cfg->setProperty("saveSRGBProfile", false); cfg->setProperty("forceSRGB", true); return cfg; } KisConfigWidget *KisPNGExport::createConfigurationWidget(QWidget *parent, const QByteArray &, const QByteArray &) const { return new KisWdgOptionsPNG(parent); } void KisPNGExport::initializeCapabilities() { addCapability(KisExportCheckRegistry::instance()->get("sRGBProfileCheck")->create(KisExportCheckBase::SUPPORTED)); QList > supportedColorModels; supportedColorModels << QPair() << QPair(RGBAColorModelID, Integer8BitsColorDepthID) << QPair(RGBAColorModelID, Integer16BitsColorDepthID) << QPair(GrayAColorModelID, Integer8BitsColorDepthID) << QPair(GrayAColorModelID, Integer16BitsColorDepthID); addSupportedColorModels(supportedColorModels, "PNG"); } void KisWdgOptionsPNG::setConfiguration(const KisPropertiesConfigurationSP cfg) { // the export manager should have prepared some info for us! KIS_SAFE_ASSERT_RECOVER_NOOP(cfg->hasProperty(KisImportExportFilter::ImageContainsTransparencyTag)); KIS_SAFE_ASSERT_RECOVER_NOOP(cfg->hasProperty(KisImportExportFilter::ColorModelIDTag)); KIS_SAFE_ASSERT_RECOVER_NOOP(cfg->hasProperty(KisImportExportFilter::sRGBTag)); const bool isThereAlpha = cfg->getBool(KisImportExportFilter::ImageContainsTransparencyTag); alpha->setChecked(cfg->getBool("alpha", isThereAlpha) && isThereAlpha); alpha->setEnabled(isThereAlpha); bnTransparencyFillColor->setEnabled(!alpha->isChecked()); if (cfg->getString(KisImportExportFilter::ColorModelIDTag) == RGBAColorModelID.id()) { tryToSaveAsIndexed->setVisible(true); if (alpha->isChecked()) { tryToSaveAsIndexed->setChecked(false); } else { tryToSaveAsIndexed->setChecked(cfg->getBool("indexed", false)); } } else { tryToSaveAsIndexed->setVisible(false); } interlacing->setChecked(cfg->getBool("interlaced", false)); compressionLevel->setValue(cfg->getInt("compression", 3)); - compressionLevel->setRange(1, 9 , 0); + compressionLevel->setRange(1, 9, 0); tryToSaveAsIndexed->setVisible(!isThereAlpha); const bool sRGB = cfg->getBool(KisImportExportFilter::sRGBTag, false); chkSRGB->setEnabled(sRGB); chkSRGB->setChecked(cfg->getBool("saveSRGBProfile", true)); chkForceSRGB->setEnabled(!sRGB); chkForceSRGB->setChecked(cfg->getBool("forceSRGB", false)); - QStringList rgb = cfg->getString("transparencyFillcolor", "255,255,255").split(','); - KoColor c(KoColorSpaceRegistry::instance()->rgb8()); - c.fromQColor(Qt::white); - bnTransparencyFillColor->setDefaultColor(c); - c.fromQColor(QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt())); - bnTransparencyFillColor->setColor(c); - + KoColor background(KoColorSpaceRegistry::instance()->rgb8()); + background.fromQColor(Qt::white); + bnTransparencyFillColor->setDefaultColor(background); + bnTransparencyFillColor->setColor(cfg->getColor("transparencyFillcolor", background)); } KisPropertiesConfigurationSP KisWdgOptionsPNG::configuration() const { KisPropertiesConfigurationSP cfg(new KisPropertiesConfiguration()); bool alpha = this->alpha->isChecked(); bool interlace = interlacing->isChecked(); int compression = (int)compressionLevel->value(); bool tryToSaveAsIndexed = this->tryToSaveAsIndexed->isChecked(); - QColor c = bnTransparencyFillColor->color().toQColor(); bool saveSRGB = chkSRGB->isChecked(); bool forceSRGB = chkForceSRGB->isChecked(); + QVariant transparencyFillcolor; + transparencyFillcolor.setValue(bnTransparencyFillColor->color()); + cfg->setProperty("alpha", alpha); cfg->setProperty("indexed", tryToSaveAsIndexed); cfg->setProperty("compression", compression); cfg->setProperty("interlaced", interlace); - cfg->setProperty("transparencyFillcolor", QString("%1,%2,%3").arg(c.red()).arg(c.green()).arg(c.blue())); + cfg->setProperty("transparencyFillcolor", transparencyFillcolor); cfg->setProperty("saveSRGBProfile", saveSRGB); cfg->setProperty("forceSRGB", forceSRGB); return cfg; } void KisWdgOptionsPNG::on_alpha_toggled(bool checked) { bnTransparencyFillColor->setEnabled(!checked); } #include "kis_png_export.moc"