File indexing completed on 2024-12-22 04:15:19

0001 /*
0002  * This file is part of Krita
0003  *
0004  * SPDX-FileCopyrightText: 2019 Miguel Lopez <reptillia39@live.com>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "gaussianhighpass_filter.h"
0010 #include <QBitArray>
0011 
0012 #include <KoColorSpace.h>
0013 #include <KoChannelInfo.h>
0014 #include <KoColor.h>
0015 #include <kis_painter.h>
0016 #include <kis_paint_device.h>
0017 #include <kis_paint_layer.h>
0018 #include <kis_group_layer.h>
0019 
0020 #include <kis_mask_generator.h>
0021 #include <kis_gaussian_kernel.h>
0022 #include <filter/kis_filter_category_ids.h>
0023 #include <filter/kis_filter_configuration.h>
0024 #include <kis_processing_information.h>
0025 #include <KoProgressUpdater.h>
0026 #include <KoUpdater.h>
0027 #include <KoMixColorsOp.h>
0028 #include "kis_lod_transform.h"
0029 #include <KoCompositeOpRegistry.h>
0030 
0031 #include "wdg_gaussianhighpass.h"
0032 #include "ui_wdggaussianhighpass.h"
0033 #include "KoColorSpaceTraits.h"
0034 #include <KisSequentialIteratorProgress.h>
0035 
0036 
0037 KisGaussianHighPassFilter::KisGaussianHighPassFilter() : KisFilter(id(), FiltersCategoryEdgeDetectionId, i18n("&Gaussian High Pass..."))
0038 {
0039     setSupportsPainting(true);
0040     setSupportsAdjustmentLayers(true);
0041     setSupportsThreading(true);
0042     setSupportsLevelOfDetail(true);
0043     setColorSpaceIndependence(FULLY_INDEPENDENT);
0044 }
0045 
0046 KisConfigWidget * KisGaussianHighPassFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP, bool /* useForMasks */) const
0047 {
0048     return new KisWdgGaussianHighPass(parent);
0049 }
0050 
0051 KisFilterConfigurationSP KisGaussianHighPassFilter::defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const
0052 {
0053     KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
0054     config->setProperty("blurAmount", 1);
0055     return config;
0056 }
0057 
0058 void KisGaussianHighPassFilter::processImpl(KisPaintDeviceSP device,
0059                                    const QRect& applyRect,
0060                                    const KisFilterConfigurationSP config,
0061                                    KoUpdater *
0062                                    ) const
0063 {
0064     QPointer<KoUpdater> convolutionUpdater = 0;
0065     KIS_SAFE_ASSERT_RECOVER_RETURN(config);
0066 
0067     QVariant value;
0068     KisLodTransformScalar t(device);
0069     const qreal blurAmount = t.scale(config->getProperty("blurAmount", value) ? value.toDouble() : 1.0);
0070     QBitArray channelFlags = config->channelFlags();
0071 
0072     const QRect gaussNeedRect = this->neededRect(applyRect, config, device->defaultBounds()->currentLevelOfDetail());
0073 
0074     KisCachedPaintDevice::Guard d1(device, m_cachedPaintDevice);
0075     KisPaintDeviceSP blur = d1.device();
0076     KisPainter::copyAreaOptimizedOldData(gaussNeedRect.topLeft(), device, blur, gaussNeedRect);
0077     KisGaussianKernel::applyGaussian(blur, applyRect,
0078                                      blurAmount, blurAmount,
0079                                      channelFlags,
0080                                      convolutionUpdater,
0081                                      true); // make sure we create an internal transaction on temp device
0082     
0083     KisPainter painter(device);
0084     painter.setCompositeOpId(COMPOSITE_GRAIN_EXTRACT);
0085     painter.bitBlt(applyRect.topLeft(), blur, applyRect);
0086     painter.end();
0087 }
0088 
0089 
0090 QRect KisGaussianHighPassFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const
0091 {
0092     KisLodTransformScalar t(lod);
0093 
0094     QVariant value;
0095 
0096     const int halfSize = config->getProperty("blurAmount", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5;
0097 
0098     return rect.adjusted( -halfSize * 2, -halfSize * 2, halfSize * 2, halfSize * 2);
0099 }
0100 
0101 QRect KisGaussianHighPassFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const
0102 {
0103     KisLodTransformScalar t(lod);
0104 
0105     QVariant value;
0106 
0107     const int halfSize = config->getProperty("blurAmount", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5;
0108 
0109     return rect.adjusted( -halfSize, -halfSize, halfSize, halfSize);
0110 }