File indexing completed on 2024-06-16 04:16:38
0001 /* 0002 * This file is part of Krita 0003 * 0004 * SPDX-FileCopyrightText: 2005 C. Boemann <cbo@boemann.dk> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "kis_perchannel_filter.h" 0010 0011 #include <Qt> 0012 #include <QLayout> 0013 #include <QPixmap> 0014 #include <QPainter> 0015 #include <QLabel> 0016 #include <QComboBox> 0017 #include <QDomDocument> 0018 #include <QHBoxLayout> 0019 0020 #include "KoChannelInfo.h" 0021 #include "KoBasicHistogramProducers.h" 0022 #include "KoColorModelStandardIds.h" 0023 #include "KoColorSpace.h" 0024 #include "KoColorTransformation.h" 0025 #include "KoCompositeColorTransformation.h" 0026 #include "KoCompositeOp.h" 0027 #include "KoID.h" 0028 0029 #include "kis_signals_blocker.h" 0030 0031 #include "kis_bookmarked_configuration_manager.h" 0032 #include "kis_config_widget.h" 0033 #include <filter/kis_filter_configuration.h> 0034 #include <kis_selection.h> 0035 #include <kis_paint_device.h> 0036 #include <kis_processing_information.h> 0037 0038 #include "kis_histogram.h" 0039 #include "kis_painter.h" 0040 #include "widgets/kis_curve_widget.h" 0041 #include <KisGlobalResourcesInterface.h> 0042 0043 #include "kis_multichannel_utils.h" 0044 0045 KisPerChannelConfigWidget::KisPerChannelConfigWidget(QWidget * parent, KisPaintDeviceSP dev, Qt::WindowFlags f) 0046 : KisMultiChannelConfigWidget(parent, dev, f) 0047 { 0048 init(); 0049 0050 // These are not used by this filter, 0051 // but the dialog is shared with KisCrossChannelFilter 0052 m_page->lblDriverChannel->hide(); 0053 m_page->cmbDriverChannel->hide(); 0054 } 0055 0056 KisPerChannelConfigWidget::~KisPerChannelConfigWidget() 0057 {} 0058 0059 #define BITS_PER_BYTE 8 0060 #define pwr2(p) (1<<p) 0061 void KisPerChannelConfigWidget::updateChannelControls() 0062 { 0063 // Getting range accepted by channel 0064 VirtualChannelInfo ¤tVChannel = m_virtualChannels[m_activeVChannel]; 0065 0066 KoChannelInfo::enumChannelValueType valueType = currentVChannel.valueType(); 0067 0068 int order = BITS_PER_BYTE * currentVChannel.channelSize(); 0069 int maxValue = pwr2(order); 0070 int min; 0071 int max; 0072 0073 m_curveControlsManager.reset(); 0074 0075 switch (valueType) { 0076 case KoChannelInfo::UINT8: 0077 case KoChannelInfo::UINT16: 0078 case KoChannelInfo::UINT32: 0079 min = 0; 0080 max = maxValue - 1; 0081 break; 0082 case KoChannelInfo::INT8: 0083 case KoChannelInfo::INT16: 0084 min = -maxValue / 2; 0085 max = maxValue / 2 - 1; 0086 break; 0087 case KoChannelInfo::FLOAT16: 0088 case KoChannelInfo::FLOAT32: 0089 case KoChannelInfo::FLOAT64: 0090 default: 0091 //Hack Alert: should be changed to float 0092 if (m_dev->colorSpace()->colorModelId() == LABAColorModelID || m_dev->colorSpace()->colorModelId() == CMYKAColorModelID) { 0093 if (m_dev->colorSpace()->channelCount() > m_activeVChannel) { 0094 const QList<KoChannelInfo*> channels = m_dev->colorSpace()->channels(); 0095 min = channels[m_activeVChannel]->getUIMin(); 0096 max = channels[m_activeVChannel]->getUIMax(); 0097 } else { 0098 // it must be "Hue", "Saturation" or other "channel" that isn't actually accessible in the color space 0099 min = 0; 0100 // specific number apparently doesn't matter, 0101 // if there is 255, it will work just fine, too 0102 max = 100; 0103 } 0104 } else { 0105 min = 0; 0106 max = 100; 0107 } 0108 break; 0109 } 0110 0111 m_curveControlsManager.reset(new KisCurveWidgetControlsManagerInt(m_page->curveWidget, 0112 m_page->intIn, m_page->intOut, min, max, min, max)); 0113 } 0114 0115 0116 KisPropertiesConfigurationSP KisPerChannelConfigWidget::configuration() const 0117 { 0118 int numChannels = m_virtualChannels.size(); 0119 KisPropertiesConfigurationSP cfg = new KisPerChannelFilterConfiguration(numChannels, KisGlobalResourcesInterface::instance()); 0120 0121 KIS_ASSERT_RECOVER(m_activeVChannel < m_curves.size()) { return cfg; } 0122 0123 m_curves[m_activeVChannel] = m_page->curveWidget->curve(); 0124 static_cast<KisPerChannelFilterConfiguration*>(cfg.data())->setCurves(m_curves); 0125 0126 return cfg; 0127 } 0128 0129 KisPropertiesConfigurationSP KisPerChannelConfigWidget::getDefaultConfiguration() 0130 { 0131 return new KisPerChannelFilterConfiguration(m_virtualChannels.size(), KisGlobalResourcesInterface::instance()); 0132 } 0133 0134 KisPerChannelFilterConfiguration::KisPerChannelFilterConfiguration(int channelCount, KisResourcesInterfaceSP resourcesInterface) 0135 : KisMultiChannelFilterConfiguration(channelCount, "perchannel", 1, resourcesInterface) 0136 { 0137 init(); 0138 } 0139 0140 KisPerChannelFilterConfiguration::KisPerChannelFilterConfiguration(const KisPerChannelFilterConfiguration &rhs) 0141 : KisMultiChannelFilterConfiguration(rhs) 0142 { 0143 } 0144 0145 KisPerChannelFilterConfiguration::~KisPerChannelFilterConfiguration() 0146 { 0147 } 0148 0149 KisFilterConfigurationSP KisPerChannelFilterConfiguration::clone() const 0150 { 0151 return new KisPerChannelFilterConfiguration(*this); 0152 } 0153 0154 KisCubicCurve KisPerChannelFilterConfiguration::getDefaultCurve() 0155 { 0156 return KisCubicCurve(); 0157 } 0158 0159 // KisPerChannelFilter 0160 0161 KisPerChannelFilter::KisPerChannelFilter() : KisMultiChannelFilter(id(), i18n("&Color Adjustment curves...")) 0162 { 0163 setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M)); 0164 } 0165 0166 KisConfigWidget * KisPerChannelFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool) const 0167 { 0168 return new KisPerChannelConfigWidget(parent, dev); 0169 } 0170 0171 KisFilterConfigurationSP KisPerChannelFilter::factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const 0172 { 0173 return new KisPerChannelFilterConfiguration(0, resourcesInterface); 0174 } 0175 0176 KoColorTransformation* KisPerChannelFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const 0177 { 0178 const KisPerChannelFilterConfiguration* configBC = 0179 dynamic_cast<const KisPerChannelFilterConfiguration*>(config.data()); // Somehow, this shouldn't happen 0180 Q_ASSERT(configBC); 0181 0182 QList<bool> isIdentityList; 0183 for (const KisCubicCurve &curve : configBC->curves()) { 0184 isIdentityList.append(curve.isIdentity()); 0185 } 0186 0187 return KisMultiChannelUtils::createPerChannelTransformationFromTransfers(cs, configBC->transfers(), isIdentityList); 0188 }