Changeset View
Changeset View
Standalone View
Standalone View
plugins/tools/basictools/kis_tool_colorpicker.cc
Context not available. | |||||
2 | * Copyright (c) 1999 Matthias Elter <me@kde.org> | 2 | * Copyright (c) 1999 Matthias Elter <me@kde.org> | ||
---|---|---|---|---|---|
3 | * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> | 3 | * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> | ||
4 | * Copyright (c) 2010 Lukáš Tvrdý <lukast.dev@gmail.com> | 4 | * Copyright (c) 2010 Lukáš Tvrdý <lukast.dev@gmail.com> | ||
5 | * Copyright (c) 2018 Emmet & Eoin O'Neill <emmetoneill.pdx@gmail.com> | ||||
5 | * | 6 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by | ||
Context not available. | |||||
19 | */ | 20 | */ | ||
20 | 21 | | |||
21 | #include "kis_tool_colorpicker.h" | 22 | #include "kis_tool_colorpicker.h" | ||
22 | #include <string.h> | | |||
23 | 23 | | |||
24 | #include <boost/thread/locks.hpp> | 24 | #include <boost/thread/locks.hpp> | ||
25 | | ||||
26 | #include <QPoint> | | |||
27 | #include <QLayout> | | |||
28 | #include <QCheckBox> | | |||
29 | #include <QComboBox> | | |||
30 | #include <QSpinBox> | | |||
31 | #include <QListWidget> | | |||
32 | #include <QList> | | |||
33 | #include <QWidget> | | |||
34 | #include <QVector> | | |||
35 | | ||||
36 | #include <ksharedconfig.h> | | |||
37 | #include <kconfiggroup.h> | | |||
38 | #include <klocalizedstring.h> | | |||
39 | | ||||
40 | #include <QMessageBox> | 25 | #include <QMessageBox> | ||
41 | | ||||
42 | #include "kis_layer.h" | | |||
43 | #include "kis_cursor.h" | 26 | #include "kis_cursor.h" | ||
44 | #include "kis_image.h" | 27 | #include "kis_image.h" | ||
45 | #include "kis_paint_device.h" | | |||
46 | #include "kis_properties_configuration.h" | | |||
47 | | ||||
48 | #include "KoPointerEvent.h" | 28 | #include "KoPointerEvent.h" | ||
49 | #include "KoCanvasBase.h" | 29 | #include "KoCanvasBase.h" | ||
50 | #include "kis_random_accessor_ng.h" | 30 | #include "kis_random_accessor_ng.h" | ||
51 | #include "KoColor.h" | | |||
52 | #include "KoResourceServerProvider.h" | 31 | #include "KoResourceServerProvider.h" | ||
53 | #include <resources/KoColorSet.h> | | |||
54 | #include <KoChannelInfo.h> | | |||
55 | #include <KoMixColorsOp.h> | 32 | #include <KoMixColorsOp.h> | ||
56 | | ||||
57 | #include "kis_wrapped_rect.h" | 33 | #include "kis_wrapped_rect.h" | ||
58 | #include "kis_tool_utils.h" | 34 | #include "kis_tool_utils.h" | ||
59 | 35 | | |||
60 | | ||||
61 | namespace | 36 | namespace | ||
62 | { | 37 | { | ||
63 | // The location of the sample all visible layers in the combobox | 38 | // GUI ComboBox index constants | ||
64 | const int SAMPLE_MERGED = 0; | 39 | const int SAMPLE_MERGED = 0; | ||
65 | } | 40 | } | ||
66 | 41 | | |||
67 | KisToolColorPicker::KisToolColorPicker(KoCanvasBase* canvas) | 42 | KisToolColorPicker::KisToolColorPicker(KoCanvasBase *canvas) | ||
68 | : KisTool(canvas, KisCursor::pickerCursor()), | 43 | : KisTool(canvas, KisCursor::pickerCursor()), | ||
69 | m_config(new KisToolUtils::ColorPickerConfig) | 44 | m_config(new KisToolUtils::ColorPickerConfig) | ||
70 | { | 45 | { | ||
Context not available. | |||||
81 | } | 56 | } | ||
82 | } | 57 | } | ||
83 | 58 | | |||
84 | void KisToolColorPicker::paint(QPainter& gc, const KoViewConverter &converter) | 59 | void KisToolColorPicker::paint(QPainter &gc, const KoViewConverter &converter) | ||
85 | { | 60 | { | ||
86 | Q_UNUSED(gc); | 61 | Q_UNUSED(gc); | ||
87 | Q_UNUSED(converter); | 62 | Q_UNUSED(converter); | ||
Context not available. | |||||
103 | KisTool::deactivate(); | 78 | KisTool::deactivate(); | ||
104 | } | 79 | } | ||
105 | 80 | | |||
106 | void KisToolColorPicker::pickColor(const QPointF& pos) | 81 | void KisToolColorPicker::pickColor(const QPointF &pos) | ||
107 | { | 82 | { | ||
108 | if (m_colorPickerDelayTimer.isActive()) { | 83 | if (m_colorPickerDelayTimer.isActive()) { | ||
109 | return; | 84 | return; | ||
Context not available. | |||||
113 | m_colorPickerDelayTimer.start(100); | 88 | m_colorPickerDelayTimer.start(100); | ||
114 | } | 89 | } | ||
115 | 90 | | |||
116 | 91 | QScopedPointer<boost::lock_guard<KisImage>> imageLocker; | |||
117 | QScopedPointer<boost::lock_guard<KisImage> > imageLocker; | | |||
118 | 92 | | |||
119 | KisPaintDeviceSP dev; | 93 | KisPaintDeviceSP dev; | ||
120 | 94 | | |||
Context not available. | |||||
126 | imageLocker.reset(new boost::lock_guard<KisImage>(*currentImage())); | 100 | imageLocker.reset(new boost::lock_guard<KisImage>(*currentImage())); | ||
127 | dev = currentImage()->projection(); | 101 | dev = currentImage()->projection(); | ||
128 | } | 102 | } | ||
129 | 103 | | |||
104 | // Color sampling radius. | ||||
130 | if (m_config->radius == 1) { | 105 | if (m_config->radius == 1) { | ||
131 | QPoint realPos = pos.toPoint(); | 106 | QPoint realPos = pos.toPoint(); | ||
132 | if (currentImage()->wrapAroundModePermitted()) { | 107 | if (currentImage()->wrapAroundModePermitted()) { | ||
Context not available. | |||||
136 | dev->pixel(realPos.x(), realPos.y(), &m_pickedColor); | 111 | dev->pixel(realPos.x(), realPos.y(), &m_pickedColor); | ||
137 | } | 112 | } | ||
138 | else { | 113 | else { | ||
139 | 114 | const KoColorSpace *cs = dev->colorSpace(); | |||
140 | const KoColorSpace* cs = dev->colorSpace(); | | |||
141 | int pixelSize = cs->pixelSize(); | 115 | int pixelSize = cs->pixelSize(); | ||
142 | 116 | | |||
143 | quint8* dstColor = new quint8[pixelSize]; | 117 | quint8* dstColor = new quint8[pixelSize]; | ||
Context not available. | |||||
161 | } | 135 | } | ||
162 | } | 136 | } | ||
163 | 137 | | |||
164 | 138 | const quint8 **cpixels = const_cast<const quint8**>(pixels.constData()); | |||
165 | const quint8** cpixels = const_cast<const quint8**>(pixels.constData()); | | |||
166 | cs->mixColorsOp()->mixColors(cpixels, pixels.size(), dstColor); | 139 | cs->mixColorsOp()->mixColors(cpixels, pixels.size(), dstColor); | ||
167 | 140 | | |||
168 | m_pickedColor = KoColor(dstColor, cs); | 141 | m_pickedColor = KoColor(dstColor, cs); | ||
Context not available. | |||||
170 | delete[] dstColor; | 143 | delete[] dstColor; | ||
171 | } | 144 | } | ||
172 | 145 | | |||
146 | // Color blending. | ||||
147 | if(m_config->blend < 100){ | ||||
148 | //Scale from 0..100% to 0..255 range for mixOp weights. | ||||
149 | quint8 blendScaled = static_cast<quint8>(m_config->blend * 2.55f); | ||||
150 | | ||||
151 | KoColor previousColor = canvas()->resourceManager()->foregroundColor(); | ||||
152 | | ||||
153 | const quint8 *colors[2]; | ||||
154 | colors[0] = previousColor.data(); | ||||
155 | colors[1] = m_pickedColor.data(); | ||||
156 | qint16 weights[2]; | ||||
157 | weights[0] = 255 - blendScaled; | ||||
158 | weights[1] = blendScaled; | ||||
159 | | ||||
160 | const KoMixColorsOp *mixOp = dev->colorSpace()->mixColorsOp(); | ||||
161 | mixOp->mixColors(colors, weights, 2, m_pickedColor.data()); | ||||
162 | } | ||||
163 | | ||||
173 | m_pickedColor.convertTo(dev->compositionSourceColorSpace()); | 164 | m_pickedColor.convertTo(dev->compositionSourceColorSpace()); | ||
174 | 165 | | |||
175 | if (m_config->updateColor && | 166 | if (m_config->updateColor && | ||
Context not available. | |||||
204 | } | 195 | } | ||
205 | 196 | | |||
206 | QPoint pos = convertToImagePixelCoordFloored(event); | 197 | QPoint pos = convertToImagePixelCoordFloored(event); | ||
207 | // the color picking has to start in the visible part of the layer | 198 | // Color picking has to start in the visible part of the layer | ||
208 | if (!currentImage()->bounds().contains(pos) && | 199 | if (!currentImage()->bounds().contains(pos) && | ||
209 | !currentImage()->wrapAroundModePermitted()) { | 200 | !currentImage()->wrapAroundModePermitted()) { | ||
210 | event->ignore(); | 201 | event->ignore(); | ||
Context not available. | |||||
235 | ent.color = m_pickedColor; | 226 | ent.color = m_pickedColor; | ||
236 | // We don't ask for a name, too intrusive here | 227 | // We don't ask for a name, too intrusive here | ||
237 | 228 | | |||
238 | KoColorSet* palette = m_palettes.at(m_optionsWidget->cmbPalette->currentIndex()); | 229 | KoColorSet *palette = m_palettes.at(m_optionsWidget->cmbPalette->currentIndex()); | ||
239 | palette->add(ent); | 230 | palette->add(ent); | ||
240 | 231 | | |||
241 | if (!palette->save()) { | 232 | if (!palette->save()) { | ||
Context not available. | |||||
244 | } | 235 | } | ||
245 | } | 236 | } | ||
246 | 237 | | |||
247 | | ||||
248 | struct PickedChannel { | 238 | struct PickedChannel { | ||
249 | QString name; | 239 | QString name; | ||
250 | QString valueText; | 240 | QString valueText; | ||
Context not available. | |||||
297 | specialSpacer->setFixedSize(0, 0); | 287 | specialSpacer->setFixedSize(0, 0); | ||
298 | m_optionsWidget->layout()->addWidget(specialSpacer); | 288 | m_optionsWidget->layout()->addWidget(specialSpacer); | ||
299 | 289 | | |||
290 | // Initialize blend KisSliderSpinBox | ||||
291 | m_optionsWidget->blend->setRange(0,100); | ||||
292 | | ||||
300 | updateOptionWidget(); | 293 | updateOptionWidget(); | ||
301 | 294 | | |||
302 | connect(m_optionsWidget->cbUpdateCurrentColor, SIGNAL(toggled(bool)), SLOT(slotSetUpdateColor(bool))); | 295 | connect(m_optionsWidget->cbUpdateCurrentColor, SIGNAL(toggled(bool)), SLOT(slotSetUpdateColor(bool))); | ||
Context not available. | |||||
305 | SLOT(slotSetAddPalette(bool))); | 298 | SLOT(slotSetAddPalette(bool))); | ||
306 | connect(m_optionsWidget->radius, SIGNAL(valueChanged(int)), | 299 | connect(m_optionsWidget->radius, SIGNAL(valueChanged(int)), | ||
307 | SLOT(slotChangeRadius(int))); | 300 | SLOT(slotChangeRadius(int))); | ||
301 | connect(m_optionsWidget->blend, SIGNAL(valueChanged(int)), | ||||
302 | SLOT(slotChangeBlend(int))); | ||||
308 | connect(m_optionsWidget->cmbSources, SIGNAL(currentIndexChanged(int)), | 303 | connect(m_optionsWidget->cmbSources, SIGNAL(currentIndexChanged(int)), | ||
309 | SLOT(slotSetColorSource(int))); | 304 | SLOT(slotSetColorSource(int))); | ||
310 | 305 | | |||
311 | KoResourceServer<KoColorSet>* srv = KoResourceServerProvider::instance()->paletteServer(); | 306 | KoResourceServer<KoColorSet> *srv = KoResourceServerProvider::instance()->paletteServer(); | ||
312 | 307 | | |||
313 | if (!srv) { | 308 | if (!srv) { | ||
314 | return m_optionsWidget; | 309 | return m_optionsWidget; | ||
Context not available. | |||||
335 | m_optionsWidget->cmbSources->setCurrentIndex(SAMPLE_MERGED + !m_config->sampleMerged); | 330 | m_optionsWidget->cmbSources->setCurrentIndex(SAMPLE_MERGED + !m_config->sampleMerged); | ||
336 | m_optionsWidget->cbPalette->setChecked(m_config->addPalette); | 331 | m_optionsWidget->cbPalette->setChecked(m_config->addPalette); | ||
337 | m_optionsWidget->radius->setValue(m_config->radius); | 332 | m_optionsWidget->radius->setValue(m_config->radius); | ||
333 | m_optionsWidget->blend->setValue(m_config->blend); | ||||
338 | } | 334 | } | ||
339 | 335 | | |||
340 | void KisToolColorPicker::setToForeground(bool newValue) | 336 | void KisToolColorPicker::setToForeground(bool newValue) | ||
Context not available. | |||||
370 | m_config->radius = value; | 366 | m_config->radius = value; | ||
371 | } | 367 | } | ||
372 | 368 | | |||
369 | void KisToolColorPicker::slotChangeBlend(int value) | ||||
370 | { | ||||
371 | m_config->blend = value; | ||||
372 | } | ||||
373 | | ||||
373 | void KisToolColorPicker::slotSetColorSource(int value) | 374 | void KisToolColorPicker::slotSetColorSource(int value) | ||
374 | { | 375 | { | ||
375 | m_config->sampleMerged = value == SAMPLE_MERGED; | 376 | m_config->sampleMerged = value == SAMPLE_MERGED; | ||
376 | } | 377 | } | ||
377 | 378 | | |||
378 | void KisToolColorPicker::slotAddPalette(KoResource* resource) | 379 | void KisToolColorPicker::slotAddPalette(KoResource *resource) | ||
379 | { | 380 | { | ||
380 | KoColorSet* palette = dynamic_cast<KoColorSet*>(resource); | 381 | KoColorSet *palette = dynamic_cast<KoColorSet*>(resource); | ||
381 | if (palette) { | 382 | if (palette) { | ||
382 | m_optionsWidget->cmbPalette->addSqueezedItem(palette->name()); | 383 | m_optionsWidget->cmbPalette->addSqueezedItem(palette->name()); | ||
383 | m_palettes.append(palette); | 384 | m_palettes.append(palette); | ||
384 | } | 385 | } | ||
385 | } | 386 | } | ||
386 | | ||||
Context not available. |