diff --git a/libs/image/filter/kis_filter_category_ids.h b/libs/image/filter/kis_filter_category_ids.h --- a/libs/image/filter/kis_filter_category_ids.h +++ b/libs/image/filter/kis_filter_category_ids.h @@ -28,6 +28,7 @@ extern const KoID KRITAIMAGE_EXPORT FiltersCategoryArtisticId; extern const KoID KRITAIMAGE_EXPORT FiltersCategoryBlurId; extern const KoID KRITAIMAGE_EXPORT FiltersCategoryColorId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryDetailId; extern const KoID KRITAIMAGE_EXPORT FiltersCategoryEdgeDetectionId; extern const KoID KRITAIMAGE_EXPORT FiltersCategoryEmbossId; extern const KoID KRITAIMAGE_EXPORT FiltersCategoryEnhanceId; diff --git a/libs/image/filter/kis_filter_category_ids.cpp b/libs/image/filter/kis_filter_category_ids.cpp --- a/libs/image/filter/kis_filter_category_ids.cpp +++ b/libs/image/filter/kis_filter_category_ids.cpp @@ -24,6 +24,7 @@ const KoID FiltersCategoryAdjustId("adjust_filters", ki18n("Adjust")); const KoID FiltersCategoryArtisticId("artistic_filters", ki18n("Artistic")); const KoID FiltersCategoryBlurId("blur_filters", ki18n("Blur")); +const KoID FiltersCategoryDetailId("detail_filters", ki18n("Details")); const KoID FiltersCategoryColorId("color_filters", ki18n("Colors")); const KoID FiltersCategoryEdgeDetectionId("edge_filters", ki18n("Edge Detection")); const KoID FiltersCategoryEmbossId("emboss_filters", ki18n("Emboss")); diff --git a/plugins/filters/CMakeLists.txt b/plugins/filters/CMakeLists.txt --- a/plugins/filters/CMakeLists.txt +++ b/plugins/filters/CMakeLists.txt @@ -3,6 +3,7 @@ add_subdirectory( colors ) add_subdirectory( colorsfilters ) add_subdirectory( convolutionfilters ) +add_subdirectory( details ) add_subdirectory( embossfilter ) add_subdirectory( example ) add_subdirectory( fastcolortransfer ) diff --git a/plugins/filters/details/CMakeLists.txt b/plugins/filters/details/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/plugins/filters/details/CMakeLists.txt @@ -0,0 +1,15 @@ +set(kritahighpassfilter_SOURCES + highpass.cpp + kis_wdg_highpass.cpp + kis_highpass_filter.cpp + ) + +ki18n_wrap_ui(kritahighpassfilter_SOURCES + wdghighpass.ui + ) + +add_library(kritahighpassfilter MODULE ${kritahighpassfilter_SOURCES}) + +target_link_libraries(kritahighpassfilter kritaui) + +install(TARGETS kritahighpassfilter DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/filters/details/highpass.h b/plugins/filters/details/highpass.h new file mode 100644 --- /dev/null +++ b/plugins/filters/details/highpass.h @@ -0,0 +1,35 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2019 Miguel Lopez + * + * 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. + */ + +#ifndef _HIGHPASS_PLUGIN_H_ +#define _HIGHPASS_PLUGIN_H_ + +#include +#include + +class HighPassPlugin : public QObject +{ + Q_OBJECT +public: + HighPassPlugin(QObject *parent, const QVariantList &); + ~HighPassPlugin() override; +}; + +#endif diff --git a/plugins/filters/details/highpass.cpp b/plugins/filters/details/highpass.cpp new file mode 100644 --- /dev/null +++ b/plugins/filters/details/highpass.cpp @@ -0,0 +1,41 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2019 Miguel Lopez + * + * 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 "highpass.h" +#include + +#include "kis_highpass_filter.h" + +#include + +K_PLUGIN_FACTORY_WITH_JSON(HighPassPluginFactory, "kritahighpassfilter.json", registerPlugin();) + +HighPassPlugin::HighPassPlugin(QObject *parent, const QVariantList &) + : QObject(parent) +{ + KisFilterRegistry::instance()->add(new KisHighPassFilter()); + +} + +HighPassPlugin::~HighPassPlugin() +{ +} + +#include "highpass.moc" diff --git a/plugins/filters/details/kis_highpass_filter.h b/plugins/filters/details/kis_highpass_filter.h new file mode 100644 --- /dev/null +++ b/plugins/filters/details/kis_highpass_filter.h @@ -0,0 +1,57 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2019 Miguel Lopez + * + * 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. + */ + +#ifndef KIS_HIGHPASS_FILTER_H +#define KIS_HIGHPASS_FILTER_H + +#include "filter/kis_filter.h" + +class KisHighPassFilter : public KisFilter +{ +public: + + KisHighPassFilter(); + + void processImpl(KisPaintDeviceSP device, + const QRect& applyRect, + const KisFilterConfigurationSP config, + KoUpdater* progressUpdater + ) const override; + + static inline KoID id() { + return KoID("highpass", i18n("High Pass")); + } + + KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const override; + KisFilterConfigurationSP factoryConfiguration() const override; + + QRect changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const override; + QRect neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const override; + +private: + + void processRaw(KisPaintDeviceSP device, + const QRect &rect, + qreal weights[1], + qreal factor, + const QBitArray &channelFlags, KoUpdater *progressUpdater) const; +}; + +#endif diff --git a/plugins/filters/details/kis_highpass_filter.cpp b/plugins/filters/details/kis_highpass_filter.cpp new file mode 100644 --- /dev/null +++ b/plugins/filters/details/kis_highpass_filter.cpp @@ -0,0 +1,168 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2019 Miguel Lopez + * + * 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 //MSVC requires that Vc come first +#include "kis_highpass_filter.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kis_lod_transform.h" + +#include "kis_wdg_highpass.h" +#include "ui_wdghighpass.h" +#include "KoColorSpaceTraits.h" +#include + + +KisHighPassFilter::KisHighPassFilter() : KisFilter(id(), FiltersCategoryDetailId, i18n("&High Pass...")) +{ + setSupportsPainting(true); + setSupportsAdjustmentLayers(true); + setSupportsThreading(true); + + /** + * Officially Unsharp Mask doesn't support LoD, because it + * generates subtle artifacts when the unsharp radius is smaller + * than current zoom level. But LoD devices can still appear when + * the filter is used in Adjustment Layer. So the actual LoD is + * still counted on. + */ + setSupportsLevelOfDetail(false); + setColorSpaceIndependence(FULLY_INDEPENDENT); +} + +KisConfigWidget * KisHighPassFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const +{ + return new KisWdgHighPass(parent); +} + +KisFilterConfigurationSP KisHighPassFilter::factoryConfiguration() const +{ + KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); + config->setProperty("blurAmount", 1); + return config; +} + +void KisHighPassFilter::processImpl(KisPaintDeviceSP device, + const QRect& applyRect, + const KisFilterConfigurationSP _config, + KoUpdater* progressUpdater + ) const +{ + + QPointer filterUpdater = 0; + QPointer convolutionUpdater = 0; + QScopedPointer updater; + + if (progressUpdater) { + updater.reset(new KoProgressUpdater(progressUpdater)); + updater->start(100, i18n("High Pass Mask")); + // Two sub-sub tasks that each go from 0 to 100. + convolutionUpdater = updater->startSubtask(); + filterUpdater = updater->startSubtask(); + } + + KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); + + QVariant value; + + KisLodTransformScalar t(device); + + const qreal blurAmount = t.scale(config->getProperty("blurAmount", value) ? value.toDouble() : 1.0); + + QBitArray channelFlags = config->channelFlags(); + KisGaussianKernel::applyGaussian(device, applyRect, + blurAmount, blurAmount, + channelFlags, + convolutionUpdater); + + qreal weights[2]; + qreal factor = 128; + + weights[0] = -factor * (1. - 1); + weights[1] = 128; + + { + processRaw(device, applyRect, weights, factor, channelFlags, filterUpdater); + } +} + +void KisHighPassFilter::processRaw(KisPaintDeviceSP device, + const QRect &rect, + qreal weights[2], + qreal factor, + const QBitArray &channelFlags, + KoUpdater *progressUpdater) const +{ + const KoColorSpace *cs = device->colorSpace(); + const int pixelSize = cs->pixelSize(); + KoConvolutionOp * convolutionOp = cs->convolutionOp(); + KoColorTransformation * createInvertTransformation = cs->createInvertTransformation(); + KoMixColorsOp * mixColorsOp = cs->mixColorsOp(); + + quint8 *colors[2]; + colors[0] = new quint8[pixelSize]; + colors[1] = new quint8[pixelSize]; + + KisSequentialIteratorProgress dstIt(device, rect, progressUpdater); + + while (dstIt.nextPixel()) { + { + memcpy(colors[0], dstIt.oldRawData(), pixelSize); + memcpy(colors[1], dstIt.rawDataConst(), pixelSize); + convolutionOp->convolveColors(colors, weights, dstIt.rawData(), factor, 0, 2, channelFlags); + createInvertTransformation->transform(dstIt.rawDataConst(), dstIt.rawData(),1); + mixColorsOp->mixColors(dstIt.oldRawData(),2,dstIt.rawData()); + } + } + + delete[] colors[0]; + delete[] colors[1]; +} + +QRect KisHighPassFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const +{ + KisLodTransformScalar t(lod); + + QVariant value; + const qreal blurAmount = t.scale(config->getProperty("blurAmount", value) ? value.toDouble() : 1.0); + + return rect.adjusted(-blurAmount * 2, -blurAmount * 2, blurAmount * 2, blurAmount * 2); +} + +QRect KisHighPassFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const +{ + KisLodTransformScalar t(lod); + + QVariant value; + const qreal blurAmount = t.scale(config->getProperty("blurAmount", value) ? value.toDouble() : 1.0); + + return rect.adjusted( -blurAmount, -blurAmount, blurAmount, blurAmount); +} diff --git a/plugins/filters/details/kis_wdg_highpass.h b/plugins/filters/details/kis_wdg_highpass.h new file mode 100644 --- /dev/null +++ b/plugins/filters/details/kis_wdg_highpass.h @@ -0,0 +1,43 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2019 Miguel Lopez + * + * 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. + */ + +#ifndef _KIS_WDG_HIGHPASS_H_ +#define _KIS_WDG_HIGHPASS_H_ + +#include + +class Ui_WdgHighPass; + +class KisWdgHighPass : public KisConfigWidget +{ + Q_OBJECT +public: + KisWdgHighPass(QWidget * parent); + ~KisWdgHighPass() override; + inline const Ui_WdgHighPass* widget() const { + return m_widget; + } + void setConfiguration(const KisPropertiesConfigurationSP) override; + KisPropertiesConfigurationSP configuration() const override; +private: + Ui_WdgHighPass* m_widget; +}; + +#endif diff --git a/plugins/filters/details/kis_wdg_highpass.cpp b/plugins/filters/details/kis_wdg_highpass.cpp new file mode 100644 --- /dev/null +++ b/plugins/filters/details/kis_wdg_highpass.cpp @@ -0,0 +1,57 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2019 Miguel Lopez + * + * 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_wdg_highpass.h" +#include +#include + +#include +#include +#include + +#include "ui_wdghighpass.h" + +KisWdgHighPass::KisWdgHighPass(QWidget * parent) : KisConfigWidget(parent) +{ + m_widget = new Ui_WdgHighPass(); + m_widget->setupUi(this); + + connect(widget()->doubleblurAmount, SIGNAL(valueChanged(double)), SIGNAL(sigConfigurationItemChanged())); +} + +KisWdgHighPass::~KisWdgHighPass() +{ + delete m_widget; +} + +void KisWdgHighPass::setConfiguration(const KisPropertiesConfigurationSP config) +{ + QVariant value; + widget()->doubleblurAmount->setValue((config->getProperty("blurAmount", value)) ? value.toDouble() : 1.0); +} + +KisPropertiesConfigurationSP KisWdgHighPass::configuration() const +{ + KisFilterConfigurationSP config = new KisFilterConfiguration("highpass", 1); + config->setProperty("blurAmount", widget()->doubleblurAmount->value()); + return config; +} + + diff --git a/plugins/filters/details/kritahighpassfilter.json b/plugins/filters/details/kritahighpassfilter.json new file mode 100644 --- /dev/null +++ b/plugins/filters/details/kritahighpassfilter.json @@ -0,0 +1,9 @@ +{ + "Id": "Detail Filters (Extension)", + "Type": "Service", + "X-KDE-Library": "kritahighpassfilter", + "X-KDE-ServiceTypes": [ + "Krita/Filter" + ], + "X-Krita-Version": "28" +} diff --git a/plugins/filters/details/wdghighpass.ui b/plugins/filters/details/wdghighpass.ui new file mode 100644 --- /dev/null +++ b/plugins/filters/details/wdghighpass.ui @@ -0,0 +1,89 @@ + + + WdgHighPass + + + + 0 + 0 + 331 + 167 + + + + + + + + 0 + 0 + + + + Radius: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + 250.000000000000000 + + + 1.000000000000000 + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 21 + + + + + + + + + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
+ + +