File indexing completed on 2024-05-26 04:33:03

0001 /*
0002  * This file is part of Krita
0003  *
0004  * SPDX-FileCopyrightText: 2004 Cyrille Berger <cberger@cberger.net>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "colorsfilters.h"
0010 
0011 
0012 #include <math.h>
0013 
0014 #include <stdlib.h>
0015 #include <string.h>
0016 
0017 #include <QSlider>
0018 #include <QPoint>
0019 #include <QColor>
0020 
0021 #include <klocalizedstring.h>
0022 
0023 #include <kis_debug.h>
0024 #include <kpluginfactory.h>
0025 
0026 #include "KoBasicHistogramProducers.h"
0027 #include <KoColorSpace.h>
0028 #include <KoColorTransformation.h>
0029 #include <filter/kis_filter_category_ids.h>
0030 #include <filter/kis_filter_configuration.h>
0031 #include <kis_paint_device.h>
0032 #include <kis_processing_information.h>
0033 #include <KisDocument.h>
0034 #include <kis_image.h>
0035 #include <kis_layer.h>
0036 #include <kis_global.h>
0037 #include <kis_types.h>
0038 #include <kis_selection.h>
0039 #include <kis_histogram.h>
0040 #include <filter/kis_filter_registry.h>
0041 #include <kis_painter.h>
0042 #include <KoUpdater.h>
0043 #include <KoColorSpaceConstants.h>
0044 #include <KoCompositeOp.h>
0045 #include <KisSequentialIteratorProgress.h>
0046 
0047 
0048 #include "kis_hsv_adjustment_filter.h"
0049 #include "kis_perchannel_filter.h"
0050 #include "kis_cross_channel_filter.h"
0051 #include "kis_color_balance_filter.h"
0052 #include "kis_desaturate_filter.h"
0053 
0054 K_PLUGIN_FACTORY_WITH_JSON(ColorsFiltersFactory, "kritacolorsfilter.json", registerPlugin<ColorsFilters>();)
0055 
0056 ColorsFilters::ColorsFilters(QObject *parent, const QVariantList &)
0057         : QObject(parent)
0058 {
0059     KisFilterRegistry * manager = KisFilterRegistry::instance();
0060     manager->add(new KisAutoContrast());
0061     manager->add(new KisPerChannelFilter());
0062     manager->add(new KisCrossChannelFilter());
0063     manager->add(new KisDesaturateFilter());
0064     manager->add(new KisHSVAdjustmentFilter());
0065     manager->add(new KisColorBalanceFilter());
0066 
0067 }
0068 
0069 ColorsFilters::~ColorsFilters()
0070 {
0071 }
0072 
0073 
0074 //==================================================================
0075 
0076 
0077 KisAutoContrast::KisAutoContrast() : KisFilter(id(), FiltersCategoryAdjustId, i18n("&Auto Contrast"))
0078 {
0079     setSupportsPainting(false);
0080     setSupportsThreading(false);
0081     setSupportsAdjustmentLayers(false);
0082     setColorSpaceIndependence(TO_LAB16);
0083     setShowConfigurationWidget(false);
0084 }
0085 
0086 void KisAutoContrast::processImpl(KisPaintDeviceSP device,
0087                                   const QRect& applyRect,
0088                                   const KisFilterConfigurationSP config,
0089                                   KoUpdater* progressUpdater) const
0090 {
0091     Q_ASSERT(device != 0);
0092     Q_UNUSED(config);
0093     // initialize
0094     KoHistogramProducer *producer = new KoGenericLabHistogramProducer();
0095     KisHistogram histogram(device, applyRect, producer, LINEAR);
0096     int minvalue = int(255 * histogram.calculations().getMin() + 0.5);
0097     int maxvalue = int(255 * histogram.calculations().getMax() + 0.5);
0098 
0099     if (maxvalue > 255)
0100         maxvalue = 255;
0101 
0102     histogram.setChannel(0);
0103     int twoPercent = int(0.005 * histogram.calculations().getCount());
0104     int pixCount = 0;
0105     int binnum = 0;
0106 
0107     while (binnum < histogram.producer()->numberOfBins()) {
0108         pixCount += histogram.getValue(binnum);
0109         if (pixCount > twoPercent) {
0110             minvalue = binnum;
0111             break;
0112         }
0113         binnum++;
0114     }
0115     pixCount = 0;
0116     binnum = histogram.producer()->numberOfBins() - 1;
0117     while (binnum > 0) {
0118         pixCount += histogram.getValue(binnum);
0119         if (pixCount > twoPercent) {
0120             maxvalue = binnum;
0121             break;
0122         }
0123         binnum--;
0124     }
0125     // build the transferfunction
0126     int diff = maxvalue - minvalue;
0127 
0128     QScopedArrayPointer<quint16> transfer(new quint16[256]);
0129     for (int i = 0; i < 255; i++)
0130         transfer[i] = 0xFFFF;
0131 
0132     if (diff != 0) {
0133         for (int i = 0; i < minvalue; i++)
0134             transfer[i] = 0x0;
0135         for (int i = minvalue; i < maxvalue; i++) {
0136             qint32 val = int((0xFFFF * (i - minvalue)) / diff);
0137             if (val > 0xFFFF)
0138                 val = 0xFFFF;
0139             if (val < 0)
0140                 val = 0;
0141 
0142             transfer[i] = val;
0143         }
0144         for (int i = maxvalue; i < 256; i++)
0145             transfer[i] = 0xFFFF;
0146     }
0147     // apply
0148     QScopedPointer<KoColorTransformation> adj(device->colorSpace()->createBrightnessContrastAdjustment(transfer.data()));
0149     KIS_SAFE_ASSERT_RECOVER_RETURN(adj);
0150 
0151     KisSequentialIteratorProgress it(device, applyRect, progressUpdater);
0152 
0153     quint32 npix = it.nConseqPixels();
0154     while(it.nextPixels(npix)) {
0155 
0156         // adjust
0157         npix = it.nConseqPixels();
0158         adj->transform(it.oldRawData(), it.rawData(), npix);
0159     }
0160 }
0161 
0162 #include "colorsfilters.moc"