Commit 1bcf68fc authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fixed a crash in Color Curves Filter

There is no need to regenerate transfers every time and
in the multithreaded evnvironment. Just do it in a single-threaded part
of the process when the configuration is generated.

I also did the same changes to the Brightnesss-Contrast Filter, bacause
it looks also vulnerable, although I couldn't reproduce the crash there.

BUG:317811,317939,312996
parent 048c141f
......@@ -24,7 +24,6 @@
#include <QList>
#include <QSharedData>
#include <QStringList>
#include <QReadWriteLock>
template <typename T>
class KisTridiagonalSystem
......@@ -252,7 +251,6 @@ struct KisCubicCurve::Data : public QSharedData {
~Data() {
}
QReadWriteLock mutex;
mutable KisCubicSpline<QPointF, qreal> spline;
QList<QPointF> points;
mutable bool validSpline;
......@@ -288,7 +286,7 @@ void KisCubicCurve::Data::keepSorted()
}
qreal KisCubicCurve::Data::value(qreal x)
{
{
updateSpline();
/* Automatically extend non-existing parts of the curve
* (e.g. before the first point) and cut off big y-values
......@@ -361,87 +359,62 @@ bool KisCubicCurve::operator==(const KisCubicCurve& curve) const
}
qreal KisCubicCurve::value(qreal x) const
{
d->data->mutex.lockForWrite();
{
qreal value = d->data->value(x);
d->data->mutex.unlock();
return value;
}
QList<QPointF> KisCubicCurve::points() const
{
{
return d->data->points;
}
void KisCubicCurve::setPoints(const QList<QPointF>& points)
{
d->data->mutex.lockForWrite();
d->data.detach();
d->data->points = points;
d->data->invalidate();
d->data->mutex.unlock();
}
void KisCubicCurve::setPoint(int idx, const QPointF& point)
{
d->data->mutex.lockForWrite();
d->data.detach();
d->data->points[idx] = point;
d->data->keepSorted();
d->data->invalidate();
d->data->mutex.unlock();
}
int KisCubicCurve::addPoint(const QPointF& point)
{
d->data->mutex.lockForWrite();
d->data.detach();
d->data->points.append(point);
d->data->keepSorted();
d->data->invalidate();
d->data->mutex.unlock();
return d->data->points.indexOf(point);
}
void KisCubicCurve::removePoint(int idx)
{
d->data->mutex.lockForWrite();
d->data.detach();
d->data->points.removeAt(idx);
d->data->invalidate();
d->data->mutex.unlock();
}
QString KisCubicCurve::toString() const
{
QString sCurve;
if(d->data->points.count() < 1)
return sCurve;
d->data->mutex.lockForWrite();
foreach(const QPointF & pair, d->data->points) {
sCurve += QString::number(pair.x());
sCurve += ',';
sCurve += QString::number(pair.y());
sCurve += ';';
}
d->data->mutex.unlock();
return sCurve;
}
......@@ -464,24 +437,12 @@ void KisCubicCurve::fromString(const QString& string)
const QVector<quint16> KisCubicCurve::uint16Transfer(int size) const
{
d->data->mutex.lockForWrite();
d->data->updateTransfer<quint16, int>(&d->data->u16Transfer, d->data->validU16Transfer, 0x0, 0xFFFF, size);
QVector<quint16> u16Transfer = d->data->u16Transfer;
d->data->mutex.unlock();
return u16Transfer;
return d->data->u16Transfer;
}
const QVector<qreal> KisCubicCurve::floatTransfer(int size) const
{
d->data->mutex.lockForWrite();
d->data->updateTransfer<qreal, qreal>(&d->data->fTransfer, d->data->validFTransfer, 0.0, 1.0, size);
QVector<qreal> fTransfer = d->data->fTransfer;
d->data->mutex.unlock();
return fTransfer;
return d->data->fTransfer;
}
......@@ -62,6 +62,27 @@ void KisBrightnessContrastFilterConfiguration::fromLegacyXML(const QDomElement&
fromXML(root);
}
void KisBrightnessContrastFilterConfiguration::updateTransfer()
{
m_transfer = m_curve.uint16Transfer();
}
void KisBrightnessContrastFilterConfiguration::setCurve(const KisCubicCurve &curve)
{
m_curve = curve;
updateTransfer();
}
const QVector<quint16>& KisBrightnessContrastFilterConfiguration::transfer() const
{
return m_transfer;
}
const KisCubicCurve& KisBrightnessContrastFilterConfiguration::curve() const
{
return m_curve;
}
void KisBrightnessContrastFilterConfiguration::fromXML(const QDomElement& root)
{
KisCubicCurve curve;
......@@ -92,11 +113,6 @@ void KisBrightnessContrastFilterConfiguration::fromXML(const QDomElement& root)
setCurve(curve);
}
void KisBrightnessContrastFilterConfiguration::setCurve(const KisCubicCurve &curve)
{
m_curve = curve;
}
/**
* Inherited from KisPropertiesConfiguration
*/
......@@ -167,7 +183,7 @@ KoColorTransformation* KisBrightnessContrastFilter::createTransformation(const K
const KisBrightnessContrastFilterConfiguration* configBC = dynamic_cast<const KisBrightnessContrastFilterConfiguration*>(config);
if (!configBC) return 0;
KoColorTransformation * adjustment = cs->createBrightnessContrastAdjustment(configBC->m_curve.uint16Transfer().data());
KoColorTransformation * adjustment = cs->createBrightnessContrastAdjustment(configBC->transfer().constData());
return adjustment;
}
......@@ -241,8 +257,7 @@ KisBrightnessContrastConfigWidget::KisBrightnessContrastConfigWidget(QWidget * p
KisBrightnessContrastFilterConfiguration * KisBrightnessContrastConfigWidget::configuration() const
{
KisBrightnessContrastFilterConfiguration * cfg = new KisBrightnessContrastFilterConfiguration();
cfg->m_curve = m_page->curveWidget->curve();
cfg->setCurve(m_page->curveWidget->curve());
return cfg;
}
......@@ -250,7 +265,7 @@ void KisBrightnessContrastConfigWidget::setConfiguration(const KisPropertiesConf
{
const KisBrightnessContrastFilterConfiguration * cfg = dynamic_cast<const KisBrightnessContrastFilterConfiguration *>(config);
Q_ASSERT(cfg);
m_page->curveWidget->setCurve(cfg->m_curve);
m_page->curveWidget->setCurve(cfg->curve());
}
#include "kis_brightness_contrast_filter.moc"
......
......@@ -61,11 +61,17 @@ public:
KisBrightnessContrastFilterConfiguration();
virtual ~KisBrightnessContrastFilterConfiguration();
public:
KisCubicCurve m_curve;
protected:
void setCurve(const KisCubicCurve &curve);
const QVector<quint16>& transfer() const;
const KisCubicCurve& curve() const;
private:
void updateTransfer();
private:
KisCubicCurve m_curve;
QVector<quint16> m_transfer;
};
/**
......
......@@ -237,7 +237,7 @@ void KisPerChannelConfigWidget::setConfiguration(const KisPropertiesConfiguratio
if (!cfg)
return;
if (cfg->m_curves.size() == 0) {
if (cfg->curves().size() == 0) {
/**
* HACK ALERT: our configuration factory generates
* default configuration with nTransfers==0.
......@@ -246,11 +246,11 @@ void KisPerChannelConfigWidget::setConfiguration(const KisPropertiesConfiguratio
KisPerChannelFilterConfiguration::initDefaultCurves(m_curves,
m_dev->colorSpace()->colorChannelCount());
} else if (cfg->m_curves.size() != int(m_dev->colorSpace()->colorChannelCount())) {
} else if (cfg->curves().size() != int(m_dev->colorSpace()->colorChannelCount())) {
return;
} else {
for (int ch = 0; ch < cfg->m_curves.size(); ch++)
m_curves[ch] = cfg->m_curves[ch];
for (int ch = 0; ch < cfg->curves().size(); ch++)
m_curves[ch] = cfg->curves()[ch];
}
m_page->curveWidget->setCurve(m_curves[m_activeCh]);
......@@ -262,7 +262,7 @@ KisPerChannelFilterConfiguration::KisPerChannelFilterConfiguration(int nCh)
: KisFilterConfiguration("perchannel", 1)
{
initDefaultCurves(m_curves, nCh);
oldCs = 0;
updateTransfers();
}
KisPerChannelFilterConfiguration::~KisPerChannelFilterConfiguration()
......@@ -271,14 +271,15 @@ KisPerChannelFilterConfiguration::~KisPerChannelFilterConfiguration()
bool KisPerChannelFilterConfiguration::isCompatible(const KisPaintDeviceSP dev) const
{
if (!oldCs) return false;
return *dev->colorSpace() == *oldCs;
return (int)dev->colorSpace()->colorChannelCount() == m_curves.size();
}
void KisPerChannelFilterConfiguration::setCurves(QList<KisCubicCurve> &curves)
{
m_curves.clear();
m_curves = curves;
updateTransfers();
}
void KisPerChannelFilterConfiguration::initDefaultCurves(QList<KisCubicCurve> &curves, int nCh)
......@@ -289,6 +290,26 @@ void KisPerChannelFilterConfiguration::initDefaultCurves(QList<KisCubicCurve> &c
}
}
void KisPerChannelFilterConfiguration::updateTransfers()
{
m_transfers.resize(m_curves.size());
for (int i = 0; i < m_curves.size(); i++) {
m_transfers[i] = m_curves[i].uint16Transfer();
}
}
const QVector<QVector<quint16> >&
KisPerChannelFilterConfiguration::transfers() const
{
return m_transfers;
}
const QList<KisCubicCurve>&
KisPerChannelFilterConfiguration::curves() const
{
return m_curves;
}
void KisPerChannelFilterConfiguration::fromLegacyXML(const QDomElement& root)
{
fromXML(root);
......@@ -397,17 +418,21 @@ KisFilterConfiguration * KisPerChannelFilter::factoryConfiguration(const KisPain
KoColorTransformation* KisPerChannelFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfiguration* config) const
{
KisPerChannelFilterConfiguration* configBC =
const_cast<KisPerChannelFilterConfiguration*>(dynamic_cast<const KisPerChannelFilterConfiguration*>(config)); // Somehow, this shouldn't happen
const KisPerChannelFilterConfiguration* configBC =
dynamic_cast<const KisPerChannelFilterConfiguration*>(config); // Somehow, this shouldn't happen
Q_ASSERT(configBC);
if (configBC->m_curves.size() != int(cs->colorChannelCount())) {
const QVector<QVector<quint16> > &originalTransfers =
configBC->transfers();
if (originalTransfers.size() != int(cs->colorChannelCount())) {
// We got an illegal number of colorchannels.KisFilter
return 0;
}
const quint16** transfers = new const quint16*[configBC->m_curves.size()];
for(int i = 0; i < configBC->m_curves.size(); ++i) {
transfers[i] = configBC->m_curves[i].uint16Transfer().constData();
const quint16** transfers = new const quint16*[configBC->curves().size()];
for(int i = 0; i < originalTransfers.size(); ++i) {
transfers[i] = originalTransfers[i].constData();
}
KoColorTransformation* t = cs->createPerChannelAdjustment(transfers);
delete transfers;
......
......@@ -60,10 +60,15 @@ public:
static inline void initDefaultCurves(QList<KisCubicCurve> &curves, int nCh);
bool isCompatible(const KisPaintDeviceSP) const;
public:
const QVector<QVector<quint16> >& transfers() const;
const QList<KisCubicCurve>& curves() const;
private:
QList<KisCubicCurve> m_curves;
const KoColorSpace* oldCs;
private:
void updateTransfers();
private:
QVector<QVector<quint16> > m_transfers;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment