QPointF KisVisualColorSelectorShape::convertKoColorToShapeCoordinate(KoColor c) { ////qDebug() << this << ">>>>>>>>> convertKoColorToShapeCoordinate()"; if (c.colorSpace() != m_d->colorSpace) { c.convertTo(m_d->colorSpace); } QVector <float> channelValues (m_d->currentColor.colorSpace()->channelCount()); channelValues.fill(1.0); m_d->colorSpace->normalisedChannelsValue(c.data(), channelValues); QVector <float> channelValuesDisplay = channelValues; QVector <qreal> maxvalue(c.colorSpace()->channelCount()); maxvalue.fill(1.0); if (m_d->displayRenderer && (m_d->colorSpace->colorDepthId() == Float16BitsColorDepthID || m_d->colorSpace->colorDepthId() == Float32BitsColorDepthID || m_d->colorSpace->colorDepthId() == Float64BitsColorDepthID) && m_d->colorSpace->colorModelId() != LABAColorModelID && m_d->colorSpace->colorModelId() != CMYKAColorModelID) { for (int ch = 0; ch<maxvalue.size(); ch++) { KoChannelInfo *channel = m_d->colorSpace->channels()[ch]; maxvalue[ch] = m_d->displayRenderer->maxVisibleFloatValue(channel); channelValues[ch] = channelValues[ch]/(maxvalue[ch]); channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(ch, m_d->colorSpace->channels())] = channelValues[ch]; } } else { for (int i =0; i<channelValues.size();i++) { channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(i, m_d->colorSpace->channels())] = qBound((float)0.0,channelValues[i], (float)1.0); } } QPointF coordinates(0.0,0.0); qreal huedivider = 1.0; qreal huedivider2 = 1.0; if (m_d->channel1==0) { huedivider = 360.0; } if (m_d->channel2==0) { huedivider2 = 360.0; } if (m_d->model != ColorModel::Channel && c.colorSpace()->colorModelId().id() == "RGBA") { if (c.colorSpace()->colorModelId().id() == "RGBA") { if (m_d->model == ColorModel::HSV){ QVector <float> inbetween(3); RGBToHSV(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); coordinates.setX(inbetween[m_d->channel1]/huedivider); if (m_d->dimension == Dimensions::twodimensional) { coordinates.setY(inbetween[m_d->channel2]/huedivider2); } } else if (m_d->model == ColorModel::HSL) { QVector <float> inbetween(3); RGBToHSL(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); coordinates.setX(inbetween[m_d->channel1]/huedivider); if (m_d->dimension == Dimensions::twodimensional) { coordinates.setY(inbetween[m_d->channel2]/huedivider2); } } else if (m_d->model == ColorModel::HSI) { QVector <qreal> chan2 = convertvectorfloatToqreal(channelValuesDisplay); QVector <qreal> inbetween(3); RGBToHSI(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); inbetween = getHSX(inbetween); coordinates.setX(inbetween[m_d->channel1]); if (m_d->dimension == Dimensions::twodimensional) { coordinates.setY(inbetween[m_d->channel2]); } } else if (m_d->model == ColorModel::HSY) { QVector <qreal> luma = m_d->colorSpace->lumaCoefficients(); QVector <qreal> chan2 = convertvectorfloatToqreal(channelValuesDisplay); QVector <qreal> inbetween(3); RGBToHSY(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2], luma[0], luma[1], luma[2]); inbetween = getHSX(inbetween); coordinates.setX(inbetween[m_d->channel1]); if (m_d->dimension == Dimensions::twodimensional) { coordinates.setY(inbetween[m_d->channel2]); } } } } else { coordinates.setX(qBound((float)0.0, channelValuesDisplay[m_d->channel1], (float)1.0)); if (m_d->dimension == Dimensions::twodimensional) { coordinates.setY(qBound((float)0.0, channelValuesDisplay[m_d->channel2], (float)1.0)); } } return coordinates; }
void RgbF16ColorSpace::toHSY(QVector <double> channelValues, qreal *hue, qreal *sat, qreal *luma) const { RGBToHSY(channelValues[0],channelValues[1],channelValues[2], hue, sat, luma, lumaCoefficients()[0], lumaCoefficients()[1], lumaCoefficients()[2]); }
KoColor KisVisualColorSelectorShape::convertShapeCoordinateToKoColor(QPointF coordinates, bool cursor) { //qDebug() << this << ">>>>>>>>> convertShapeCoordinateToKoColor()" << coordinates; KoColor c = m_d->currentColor; QVector <float> channelValues (c.colorSpace()->channelCount()); channelValues.fill(1.0); c.colorSpace()->normalisedChannelsValue(c.data(), channelValues); QVector <float> channelValuesDisplay = channelValues; QVector <qreal> maxvalue(c.colorSpace()->channelCount()); maxvalue.fill(1.0); if (m_d->displayRenderer && (m_d->colorSpace->colorDepthId() == Float16BitsColorDepthID || m_d->colorSpace->colorDepthId() == Float32BitsColorDepthID || m_d->colorSpace->colorDepthId() == Float64BitsColorDepthID) && m_d->colorSpace->colorModelId() != LABAColorModelID && m_d->colorSpace->colorModelId() != CMYKAColorModelID) { for (int ch = 0; ch < maxvalue.size(); ch++) { KoChannelInfo *channel = m_d->colorSpace->channels()[ch]; maxvalue[ch] = m_d->displayRenderer->maxVisibleFloatValue(channel); channelValues[ch] = channelValues[ch]/(maxvalue[ch]); channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(ch, m_d->colorSpace->channels())] = channelValues[ch]; } } else { for (int i =0; i < channelValues.size();i++) { channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(i, m_d->colorSpace->channels())] = qBound((float)0.0,channelValues[i], (float)1.0); } } qreal huedivider = 1.0; qreal huedivider2 = 1.0; if (m_d->channel1 == 0) { huedivider = 360.0; } if (m_d->channel2 == 0) { huedivider2 = 360.0; } if (m_d->model != ColorModel::Channel && c.colorSpace()->colorModelId().id() == "RGBA") { if (m_d->model == ColorModel::HSV) { /* * RGBToHSV has a undefined hue possibility. This means that hue will be -1. * This can be annoying for dealing with a selector, but I understand it is being * used for the KoColorSelector... For now implement a qMax here. */ QVector <float> inbetween(3); RGBToHSV(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); inbetween[m_d->channel1] = coordinates.x()*huedivider; if (m_d->dimension == Dimensions::twodimensional) { inbetween[m_d->channel2] = coordinates.y()*huedivider2; } if (cursor) { setHSX(convertvectorfloatToqreal(inbetween)); Q_EMIT sigHSXchange(); } HSVToRGB(qMax(inbetween[0],(float)0.0), inbetween[1], inbetween[2], &channelValuesDisplay[0], &channelValuesDisplay[1], &channelValuesDisplay[2]); } else if (m_d->model == ColorModel::HSL) { /* * HSLToRGB can give negative values on the grey. I fixed the fromNormalisedChannel function to clamp, * but you might want to manually clamp for floating point values. */ QVector <float> inbetween(3); RGBToHSL(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); inbetween[m_d->channel1] = fmod(coordinates.x()*huedivider, 360.0); if (m_d->dimension == Dimensions::twodimensional) { inbetween[m_d->channel2] = coordinates.y()*huedivider2; } if (cursor) { setHSX(convertvectorfloatToqreal(inbetween)); Q_EMIT sigHSXchange(); } HSLToRGB(qMax(inbetween[0], (float)0.0), inbetween[1], inbetween[2], &channelValuesDisplay[0], &channelValuesDisplay[1], &channelValuesDisplay[2]); } else if (m_d->model == ColorModel::HSI) { /* * HSI is a modified HSY function. */ QVector <qreal> chan2 = convertvectorfloatToqreal(channelValuesDisplay); QVector <qreal> inbetween(3); RGBToHSI(chan2[0],chan2[1], chan2[2], &inbetween[0], &inbetween[1], &inbetween[2]); inbetween = getHSX(inbetween); inbetween[m_d->channel1] = coordinates.x(); if (m_d->dimension == Dimensions::twodimensional) { inbetween[m_d->channel2] = coordinates.y(); } if (cursor) { setHSX(inbetween); Q_EMIT sigHSXchange(); } HSIToRGB(inbetween[0], inbetween[1], inbetween[2],&chan2[0],&chan2[1], &chan2[2]); channelValuesDisplay = convertvectorqrealTofloat(chan2); } else /*if (m_d->model == ColorModel::HSY)*/ { /* * HSY is pretty slow to render due being a pretty over-the-top function. * Might be worth investigating whether HCY can be used instead, but I have had * some weird results with that. */ QVector <qreal> luma= m_d->colorSpace->lumaCoefficients(); QVector <qreal> chan2 = convertvectorfloatToqreal(channelValuesDisplay); QVector <qreal> inbetween(3); RGBToHSY(chan2[0],chan2[1], chan2[2], &inbetween[0], &inbetween[1], &inbetween[2], luma[0], luma[1], luma[2]); inbetween = getHSX(inbetween); inbetween[m_d->channel1] = coordinates.x(); if (m_d->dimension == Dimensions::twodimensional) { inbetween[m_d->channel2] = coordinates.y(); } if (cursor) { setHSX(inbetween); Q_EMIT sigHSXchange(); } HSYToRGB(inbetween[0], inbetween[1], inbetween[2],&chan2[0],&chan2[1], &chan2[2], luma[0], luma[1], luma[2]); channelValuesDisplay = convertvectorqrealTofloat(chan2); } } else { channelValuesDisplay[m_d->channel1] = coordinates.x(); if (m_d->dimension == Dimensions::twodimensional) { channelValuesDisplay[m_d->channel2] = coordinates.y(); } } for (int i=0; i<channelValues.size();i++) { channelValues[i] = channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(i, m_d->colorSpace->channels())]*(maxvalue[i]); } c.colorSpace()->fromNormalisedChannelsValue(c.data(), channelValues); return c; }