diff --git a/libs/ui/tool/kis_tool_paint.h b/libs/ui/tool/kis_tool_paint.h --- a/libs/ui/tool/kis_tool_paint.h +++ b/libs/ui/tool/kis_tool_paint.h @@ -193,7 +193,6 @@ bool isPickingAction(AlternateAction action); - struct PickingJob { PickingJob() {} PickingJob(QPointF _documentPixel, diff --git a/libs/ui/tool/kis_tool_paint.cc b/libs/ui/tool/kis_tool_paint.cc --- a/libs/ui/tool/kis_tool_paint.cc +++ b/libs/ui/tool/kis_tool_paint.cc @@ -383,8 +383,14 @@ KisPaintDeviceSP device = fromCurrentNode ? currentNode()->projection() : image()->projection(); + //Used for color picker blending. + KoColor currentColor = canvas()->resourceManager()->foregroundColor(); + if( pickingJob.action == PickBgNode || pickingJob.action == PickBgImage ){ + currentColor = canvas()->resourceManager()->backgroundColor(); + } + image()->addJob(m_pickerStrokeId, - new KisColorPickerStrokeStrategy::Data(device, imagePoint)); + new KisColorPickerStrokeStrategy::Data(device, imagePoint, currentColor)); } void KisToolPaint::beginAlternateAction(KoPointerEvent *event, AlternateAction action) diff --git a/libs/ui/tool/kis_tool_utils.h b/libs/ui/tool/kis_tool_utils.h --- a/libs/ui/tool/kis_tool_utils.h +++ b/libs/ui/tool/kis_tool_utils.h @@ -37,6 +37,7 @@ bool normaliseValues; bool sampleMerged; int radius; + int blend; void save(bool defaultActivation = true) const; void load(bool defaultActivation = true); @@ -47,7 +48,7 @@ /** * return the color at the given position on the given paint device. */ -bool KRITAUI_EXPORT pick(KisPaintDeviceSP dev, const QPoint& pos, KoColor *color, int radius = 1); +bool KRITAUI_EXPORT pick(KisPaintDeviceSP dev, const QPoint& pos, KoColor *color, KoColor *previousColor = nullptr, int radius = 1, int blend = 255); /** * Recursively search a node with a non-transparent pixel diff --git a/libs/ui/tool/kis_tool_utils.cpp b/libs/ui/tool/kis_tool_utils.cpp --- a/libs/ui/tool/kis_tool_utils.cpp +++ b/libs/ui/tool/kis_tool_utils.cpp @@ -32,11 +32,12 @@ namespace KisToolUtils { - bool pick(KisPaintDeviceSP dev, const QPoint& pos, KoColor *color, int radius) + bool pick(KisPaintDeviceSP dev, const QPoint& pos, KoColor *color, KoColor *previousColor, int radius, int blend) { KIS_ASSERT(dev); KoColor pickedColor; + // Ctrl picker sampling radius. if (radius <= 1) { dev->pixel(pos.x(), pos.y(), &pickedColor); } else { @@ -64,6 +65,19 @@ const quint8** cpixels = const_cast(pixels.constData()); cs->mixColorsOp()->mixColors(cpixels, pixels.size(), pickedColor.data()); } + + // Ctrl picker color blending. + if (previousColor && blend<255) { + const quint8* colors[2]; + colors[0] = previousColor->data(); + colors[1] = pickedColor.data(); + qint16 weights[2]; + weights[0] = 255-blend; + weights[1] = blend; + + const KoMixColorsOp * mixOp = dev->colorSpace()->mixColorsOp(); + mixOp->mixColors(colors, weights, 2, pickedColor.data()); + } pickedColor.convertTo(dev->compositionSourceColorSpace()); @@ -148,6 +162,7 @@ , normaliseValues(false) , sampleMerged(true) , radius(1) + , blend(255) { } @@ -165,6 +180,7 @@ props.setProperty("normaliseValues", normaliseValues); props.setProperty("sampleMerged", sampleMerged); props.setProperty("radius", radius); + props.setProperty("blend", blend); KConfigGroup config = KSharedConfig::openConfig()->group(CONFIG_GROUP_NAME); @@ -184,6 +200,7 @@ normaliseValues = props.getBool("normaliseValues", false); sampleMerged = props.getBool("sampleMerged", !defaultActivation ? false : true); radius = props.getInt("radius", 1); + blend = props.getInt("blend", 255); } } diff --git a/libs/ui/tool/strokes/kis_color_picker_stroke_strategy.h b/libs/ui/tool/strokes/kis_color_picker_stroke_strategy.h --- a/libs/ui/tool/strokes/kis_color_picker_stroke_strategy.h +++ b/libs/ui/tool/strokes/kis_color_picker_stroke_strategy.h @@ -23,9 +23,7 @@ #include #include "kis_simple_stroke_strategy.h" #include "kis_lod_transform.h" - -class KoColor; - +#include "KoColor.h" class KisColorPickerStrokeStrategy : public QObject, public KisSimpleStrokeStrategy { @@ -33,19 +31,20 @@ public: class Data : public KisStrokeJobData { public: - Data(KisPaintDeviceSP _dev, const QPoint _pt) - : dev(_dev), pt(_pt) + Data(KisPaintDeviceSP _dev, const QPoint _pt, KoColor _currentColor) + : dev(_dev), pt(_pt), currentColor(_currentColor) {} KisStrokeJobData* createLodClone(int levelOfDetail) override { KisLodTransform t(levelOfDetail); const QPoint realPoint = t.map(pt); - return new Data(dev, realPoint); + return new Data(dev, realPoint, currentColor); } KisPaintDeviceSP dev; QPoint pt; + KoColor currentColor; //Used for color picked blending. }; public: KisColorPickerStrokeStrategy(int lod = 0); diff --git a/libs/ui/tool/strokes/kis_color_picker_stroke_strategy.cpp b/libs/ui/tool/strokes/kis_color_picker_stroke_strategy.cpp --- a/libs/ui/tool/strokes/kis_color_picker_stroke_strategy.cpp +++ b/libs/ui/tool/strokes/kis_color_picker_stroke_strategy.cpp @@ -34,6 +34,7 @@ bool shouldSkipWork; int radius = 1; + int blend = 255; }; KisColorPickerStrokeStrategy::KisColorPickerStrokeStrategy(int lod) @@ -46,6 +47,7 @@ config.load(); m_d->radius = qMax(1, qRound(config.radius * KisLodTransform::lodToScale(lod))); + m_d->blend = config.blend; } KisColorPickerStrokeStrategy::~KisColorPickerStrokeStrategy() @@ -60,7 +62,8 @@ KIS_ASSERT_RECOVER_RETURN(d); KoColor color; - bool result = KisToolUtils::pick(d->dev, d->pt, &color, m_d->radius); + KoColor previous = d->currentColor; + bool result = KisToolUtils::pick(d->dev, d->pt, &color, &previous, m_d->radius, m_d->blend); Q_UNUSED(result); emit sigColorUpdated(color); diff --git a/plugins/tools/basictools/kis_tool_colorpicker.h b/plugins/tools/basictools/kis_tool_colorpicker.h --- a/plugins/tools/basictools/kis_tool_colorpicker.h +++ b/plugins/tools/basictools/kis_tool_colorpicker.h @@ -69,6 +69,7 @@ bool normaliseValues; bool sampleMerged; int radius; + int blend; void save(ToolActivation activation) const; void load(ToolActivation activation); @@ -98,6 +99,7 @@ void slotSetNormaliseValues(bool); void slotSetAddPalette(bool); void slotChangeRadius(int); + void slotChangeBlend(int); void slotAddPalette(KoResource* resource); void slotSetColorSource(int value); diff --git a/plugins/tools/basictools/kis_tool_colorpicker.cc b/plugins/tools/basictools/kis_tool_colorpicker.cc --- a/plugins/tools/basictools/kis_tool_colorpicker.cc +++ b/plugins/tools/basictools/kis_tool_colorpicker.cc @@ -57,7 +57,6 @@ #include "kis_wrapped_rect.h" #include "kis_tool_utils.h" - namespace { // The location of the sample all visible layers in the combobox @@ -113,7 +112,6 @@ m_colorPickerDelayTimer.start(100); } - QScopedPointer > imageLocker; KisPaintDeviceSP dev; @@ -126,7 +124,8 @@ imageLocker.reset(new boost::lock_guard(*currentImage())); dev = currentImage()->projection(); } - + + // Color sampling radius. if (m_config->radius == 1) { QPoint realPos = pos.toPoint(); if (currentImage()->wrapAroundModePermitted()) { @@ -136,7 +135,6 @@ dev->pixel(realPos.x(), realPos.y(), &m_pickedColor); } else { - const KoColorSpace* cs = dev->colorSpace(); int pixelSize = cs->pixelSize(); @@ -161,7 +159,6 @@ } } - const quint8** cpixels = const_cast(pixels.constData()); cs->mixColorsOp()->mixColors(cpixels, pixels.size(), dstColor); @@ -170,6 +167,21 @@ delete[] dstColor; } + // Color blending. + if(m_config->blend < 255){ + KoColor previousColor = canvas()->resourceManager()->foregroundColor(); + + const quint8* colors[2]; + colors[0] = previousColor.data(); + colors[1] = m_pickedColor.data(); + qint16 weights[2]; + weights[0] = 255-m_config->blend; + weights[1] = m_config->blend; + + const KoMixColorsOp * mixOp = dev->colorSpace()->mixColorsOp(); + mixOp->mixColors(colors, weights, 2, m_pickedColor.data()); + } + m_pickedColor.convertTo(dev->compositionSourceColorSpace()); if (m_config->updateColor && @@ -204,7 +216,7 @@ } QPoint pos = convertToImagePixelCoordFloored(event); - // the color picking has to start in the visible part of the layer + // Color picking has to start in the visible part of the layer if (!currentImage()->bounds().contains(pos) && !currentImage()->wrapAroundModePermitted()) { event->ignore(); @@ -305,6 +317,8 @@ SLOT(slotSetAddPalette(bool))); connect(m_optionsWidget->radius, SIGNAL(valueChanged(int)), SLOT(slotChangeRadius(int))); + connect(m_optionsWidget->blend, SIGNAL(valueChanged(int)), + SLOT(slotChangeBlend(int))); connect(m_optionsWidget->cmbSources, SIGNAL(currentIndexChanged(int)), SLOT(slotSetColorSource(int))); @@ -335,6 +349,7 @@ m_optionsWidget->cmbSources->setCurrentIndex(SAMPLE_MERGED + !m_config->sampleMerged); m_optionsWidget->cbPalette->setChecked(m_config->addPalette); m_optionsWidget->radius->setValue(m_config->radius); + m_optionsWidget->blend->setValue(m_config->blend); } void KisToolColorPicker::setToForeground(bool newValue) @@ -370,6 +385,11 @@ m_config->radius = value; } +void KisToolColorPicker::slotChangeBlend(int value) +{ + m_config->blend = value; +} + void KisToolColorPicker::slotSetColorSource(int value) { m_config->sampleMerged = value == SAMPLE_MERGED; @@ -383,4 +403,3 @@ m_palettes.append(palette); } } - diff --git a/plugins/tools/basictools/wdgcolorpicker.ui b/plugins/tools/basictools/wdgcolorpicker.ui --- a/plugins/tools/basictools/wdgcolorpicker.ui +++ b/plugins/tools/basictools/wdgcolorpicker.ui @@ -14,7 +14,7 @@ Color Picker - + 2 @@ -32,7 +32,7 @@ - + 1 @@ -49,17 +49,23 @@ 0 - + - Sample radius: + Sample radius: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 1 + + + <nobr>Radius controls the color picker's sampling area.</nobr> Pixel colors within this radius are mixed together. + px @@ -81,7 +87,7 @@ - + 1 @@ -148,6 +154,48 @@ + + + + 1 + + + + + Blend: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + + + + + <nobr>Blending controls the percentage of color that is picked</nobr> and mixed with your current brush color. A full blending value picks colors completely, ignoring brush color. + + + 1 + + + 255 + + + 16 + + + 255 + + + Qt::Horizontal + + + + +