/* Copyright (c) 2008-2024 Jan W. Krieger () This software is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License (LGPL) for more details. You should have received a copy of the GNU Lesser General Public License (LGPL) along with this program. If not, see . */ #include "jkqtcommon/jkqtpbasicimagetools.h" #include #include #include #include #include #ifdef QT_XML_LIB # include #endif #if (QT_VERSION>=QT_VERSION_CHECK(6, 0, 0)) #include #include #else #include #endif const int JKQTPImageTools::PALETTE_ICON_WIDTH = 64; const int JKQTPImageTools::PALETTE_IMAGEICON_HEIGHT = 64; const int JKQTPImageTools::LUTSIZE = 256; const int JKQTPImageTools::NDEFAULTSTEPS = 5; QMap JKQTPImageTools::global_jkqtpimagetools_lutstore = JKQTPImageTools::getDefaultLUTs(); int JKQTPImageTools::global_next_userpalette = JKQTPMathImageFIRST_REGISTERED_USER_PALETTE; QReadWriteLock JKQTPImageTools::lutMutex; QStringList JKQTPImageTools::getPredefinedPalettesGlobalList = QStringList(); QStringList JKQTPImageTools::getPredefinedPalettesMachineReadableGlobalList = QStringList(); QMap JKQTPImageTools::getDefaultLUTs() { QMap lutstore; { const auto palette=JKQTPMathImageDefault_STEP; const QString palN="jkqtplotterdefault_step"; const QString palNT=QObject::tr("steps: JKQTPlotter Default"); lutstore[palette]=JKQTPImageTools::LUTData(palN, palNT); JKQTPPaletteList lst; lst< float { return (382.5 - 1020.0 * std::abs(v - 0.75))/255.0; }; const auto fG= [](float v) -> float { return (382.5 - 1020.0 * std::abs(v - 0.5))/255.0; }; const auto fB= [](float v) -> float { return (382.5 - 1020.0 * std::abs(v - 0.25))/255.0; }; const auto& normLUT=lutstore[JKQTPMathImageMATLAB]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "Matlab", QObject::tr("Matlab")); lutstore[JKQTPMathImageINVERTED_MATLAB]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invMatlab", QObject::tr("inv. Matlab")); } { const auto fR= [](float v) -> float { return (796.875*v - 199.21875)/255.0; }; const auto fG= [](float v) -> float { return std::sin(JKQTPSTATISTICS_PI*v); }; const auto fB= [](float v) -> float { return (255.0 - 765.0 * v)/255.0; }; const auto& normLUT=lutstore[JKQTPMathImageRYGB]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "RYGB", QObject::tr("RYGB")); lutstore[JKQTPMathImageINVERTED_RYGB]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invRYGB", QObject::tr("inv. RYGB")); } { const auto& normLUT=lutstore[JKQTPMathImageHSV]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT([](float v)->QRgb { const int h = static_cast(floor(6.0*v)); const double f = 6*v-double(h); switch (h) { case 0: return qRgb(255, static_cast(255.0*f), 0); case 1: return qRgb(static_cast(255.0*(1-f)), 255, 0); case 2: return qRgb(0, 255, static_cast(255.0*f)); case 3: return qRgb(0, static_cast(255.0*(1-f)), 255); case 4: return qRgb(static_cast(255.0*f), 0, 255); case 5: return qRgb(255, 0, static_cast(255.0*(1-f))); case 6: return qRgb(255, static_cast(255.0*f), 0); default: return qRgb(0,0,0); } }), "HSV", QObject::tr("HSV")); lutstore[JKQTPMathImageINVERTED_HSV]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invHSV", QObject::tr("inv. HSV")); } { const auto fR= [](float v) -> float { return std::abs(2.0*v-0.5); }; const auto fG= [](float v) -> float { return sin(JKQTPSTATISTICS_PI*v); }; const auto fB= [](float v) -> float { return cos(0.5*JKQTPSTATISTICS_PI*v); }; const auto& normLUT=lutstore[JKQTPMathImageRAINBOW]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "rainbow", QObject::tr("rainbow")); lutstore[JKQTPMathImageINVERTED_RAINBOW]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invrainbow", QObject::tr("inv. rainbow")); } { const auto fR= [](float v) -> float { return 765.0*v/255.0; }; const auto fG= [](float v) -> float { return (765.0*v-255.0)/255.0; }; const auto fB= [](float v) -> float { return (765.0*v-510.0)/255.0; }; const auto& normLUT=lutstore[JKQTPMathImageHOT]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "AFMhot", QObject::tr("AFM hot")); lutstore[JKQTPMathImageINVERTED_HOT]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invAFMhot", QObject::tr("inv. AFM hot")); } { const auto fR= [](float v) -> float { return (765.0*v-510.0)/255.0; }; const auto fG= [](float v) -> float { return (std::abs(382.5*v-127.5))/255.0; }; const auto fB= [](float v) -> float { return v; }; const auto& normLUT=lutstore[JKQTPMathImageOCEAN]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "ocean", QObject::tr("ocean")); lutstore[JKQTPMathImageINVERTED_OCEAN]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invocean", QObject::tr("inv. ocean")); } { const auto fR= [](float v) -> float { return v/0.32-0.78125; }; const auto fG= [](float v) -> float { return 2.0*v-0.84; }; const auto fB= [](float v) -> float { double b = 4.0*v; if (b>1 || b<0) b = -2.0*v+1.84; if (b>1 || b<0) b = v/0.08-11.5; if (b>1 || b<0) b=1; return b; }; const auto& normLUT=lutstore[JKQTPMathImageBLUEMAGENTAYELLOW]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "BlMaYe", QObject::tr("blue-magenta-yellow")); lutstore[JKQTPMathImageINVERTED_BLUEMAGENTAYELLOW]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "YeMaBl", QObject::tr("yellow-magenta-blue")); } { const auto fR= [](float v) -> float { return sqrt(sqrt(v)); }; const auto fG= [](float v) -> float { return sin(JKQTPSTATISTICS_PI/2.0*v); }; const auto fB= [](float v) -> float { return cos(JKQTPSTATISTICS_PI/2.0*v); }; const auto& normLUT=lutstore[JKQTPMathImageBLUEYELLOW]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "BlYe", QObject::tr("blue-yellow")); lutstore[JKQTPMathImageINVERTED_BLUEYELLOW]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "YeBl", QObject::tr("yellow-blue")); } { const auto fR= [](float v) -> float { return ((v < 0.5) ? 128.0*sin(JKQTPSTATISTICS_PI*(2.0*v-0.5))+128.0 : 255.0)/255.0; }; const auto fG= [](float v) -> float { return ((v < 0.5) ? 512.0*v+128.0 : 512.0-512.0*v)/255.0; }; const auto fB= [](float ) -> float { return 0.0; }; const auto& normLUT=lutstore[JKQTPMathImageTRAFFICLIGHT]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "Trafficlight", QObject::tr("Trafficlight")); lutstore[JKQTPMathImageINVERTED_TRAFFICLIGHT]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invtrafficlight", QObject::tr("inv. Trafficlight")); } { const auto fR= [](float v) -> float { return sqrt(v); }; const auto fG= [](float v) -> float { return v*v*v; }; const auto fB= [](float v) -> float { return sin(2.0*JKQTPSTATISTICS_PI*v); }; const auto& normLUT=lutstore[JKQTPMathImageBLACKBLUEREDYELLOW]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "BBlRdYe", QObject::tr("black-blue-red-yellow")); lutstore[JKQTPMathImageYELLOWREDBLUEBLACK]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "YeRdBlB", QObject::tr("yellow-red-blue-black")); } { const auto fR= [](float v) -> float { return v; }; const auto fG= [](float v) -> float { return fabs(v-0.5); }; const auto fB= [](float v) -> float { return v*v*v*v; }; const auto& normLUT=lutstore[JKQTPMathImageGREENREDVIOLET]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "GnRdVi", QObject::tr("green-red-violet")); lutstore[JKQTPMathImageVIOLETREDGREEN]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "ViRdGn", QObject::tr("violet-red-green")); } { const auto fR= [](float v) -> float { return v/0.32-0.78125; }; const auto fG= [](float v) -> float { return v/0.32-0.78125; }; const auto fB= [](float v) -> float { return (v<0.25)?4*v:(v<0.42)?1.0:(v<0.92)?-2.0*v+1.84:v/0.08-11.5; }; const auto& normLUT=lutstore[JKQTPMathImageBLACKBLUEWHITEYELLOWWHITE]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUT(fR, fG, fB), "BWprint", QObject::tr("black-blue-white-yellow-white")); lutstore[JKQTPMathImageWHITEYELLOWWHITEBLUEBLACK]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invBWprint", QObject::tr("white-yellow-white-blue-black")); } { JKQTPPaletteList lst { jkqtp_qRgbOpaque(0xB2182B), jkqtp_qRgbOpaque(0xD6604D), jkqtp_qRgbOpaque(0xF4A582), jkqtp_qRgbOpaque(0xFDDBC7), jkqtp_qRgbOpaque(0xD1E5F0), jkqtp_qRgbOpaque(0x92C5DE), jkqtp_qRgbOpaque(0x4393C3), jkqtp_qRgbOpaque(0x2166AC) }; const auto& normLUT=lutstore[JKQTPMathImageREDWHITEBLUE]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "redwhiteblue", QObject::tr("red-white-blue (diverging)")); const auto& normStepLUT=lutstore[JKQTPMathImageREDWHITEBLUE_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTColorsOnlySteps(lst), "stepsredwhiteblue", QObject::tr("steps: red-white-blue (diverging)")); lutstore[JKQTPMathImageBLUEWHITERED]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "bluewhitered", QObject::tr("blue-white-red (diverging)")); lutstore[JKQTPMathImageBLUEWHITERED_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsbluewhitered", QObject::tr("steps: blue-white-red (diverging)")); } { JKQTPPaletteList lst { QColor(165,0,38), QColor(253,254,194), QColor(49,54,149) }; const auto& normLUT=lutstore[JKQTPMathImageREDYELLOWBLUE]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "redyellowblue", QObject::tr("red-yellow-blue (diverging)")); const auto& normStepLUT=lutstore[JKQTPMathImageREDYELLOWBLUE_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst,9), "stepsredyellowblue", QObject::tr("steps: red-yellow-blue (diverging)")); lutstore[JKQTPMathImageBLUEYELLOWRED]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "blueyellowred", QObject::tr("blue-yellow-red (diverging)")); lutstore[JKQTPMathImageBLUEYELLOWRED_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsblueyellowred", QObject::tr("steps: blue-yellow-red (diverging)")); } { JKQTPPaletteList lst { QColor(49,54,149), QColor(253,254,194), QColor(0,104,55) }; const auto& normLUT=lutstore[JKQTPMathImageRD_Yn_GN]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "RdYnGn", QObject::tr("red-yellow-green (diverging)")); const auto& normStepLUT=lutstore[JKQTPMathImageRD_Yn_GN_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst,9), "stepsRdYnGn", QObject::tr("steps: red-yellow-green (diverging)")); lutstore[JKQTPMathImageGN_Yn_RD]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "GnYnRd", QObject::tr("green-yellow-red (diverging)")); lutstore[JKQTPMathImageGN_Yn_RD_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsGnYnRd", QObject::tr("steps: green-yellow-red (diverging)")); } { const JKQTPPaletteList lst= { jkqtp_qRgbOpaque(0x8C510A), jkqtp_qRgbOpaque(0xBF812D), jkqtp_qRgbOpaque(0xDFC27D), jkqtp_qRgbOpaque(0xF6E8C3), jkqtp_qRgbOpaque(0xC7EAE5), jkqtp_qRgbOpaque(0x80CDC1), jkqtp_qRgbOpaque(0x35978F), jkqtp_qRgbOpaque(0x01665E) }; const auto& normLUT=lutstore[JKQTPMathImageBR_GR]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "BrGr", QObject::tr("brown-white-green (diverging)")); lutstore[JKQTPMathImageBR_GR].legacyNames<<"BrBG"; const auto& normStepLUT=lutstore[JKQTPMathImageBR_GR_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTColorsOnlySteps(lst), "stepsBrGr", QObject::tr("steps: brown-white-green (diverging)")); lutstore[JKQTPMathImageBR_GR_STEP].legacyNames<<"stepsBrBG"; lutstore[JKQTPMathImageGR_BR]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "GrBr", QObject::tr("green-white-brown (diverging)")); lutstore[JKQTPMathImageGR_BR_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsGrBr", QObject::tr("steps: green-white-brown (diverging)")); } { const JKQTPPaletteList lst= { jkqtp_qRgbOpaque(0xB35806), jkqtp_qRgbOpaque(0xE08214), jkqtp_qRgbOpaque(0xFDB863), jkqtp_qRgbOpaque(0xFEE0B6), jkqtp_qRgbOpaque(0xF7F7F7), jkqtp_qRgbOpaque(0xD8DAEB), jkqtp_qRgbOpaque(0xB2ABD2), jkqtp_qRgbOpaque(0x8073AC), jkqtp_qRgbOpaque(0x542788) }; const auto& normLUT=lutstore[JKQTPMathImageOR_PU]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "OrPu", QObject::tr("orange-white-purple (diverging)")); const auto& normStepLUT=lutstore[JKQTPMathImageOR_PU_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTColorsOnlySteps(lst), "stepsOrPu", QObject::tr("steps: orange-white-purple (diverging)")); lutstore[JKQTPMathImagePU_OR]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "PuOr", QObject::tr("purple-white-orange (diverging)")); lutstore[JKQTPMathImagePU_OR_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsPuOr", QObject::tr("steps: purple-white-orange (diverging)")); } { const JKQTPPaletteList lst= { jkqtp_qRgbOpaque(0xFFFFD9), jkqtp_qRgbOpaque(0xEDF8B1), jkqtp_qRgbOpaque(0xC7E9B4), jkqtp_qRgbOpaque(0x7FCDBB), jkqtp_qRgbOpaque(0x41B6C4), jkqtp_qRgbOpaque(0x1D91C0), jkqtp_qRgbOpaque(0x225EA8), jkqtp_qRgbOpaque(0x253494), jkqtp_qRgbOpaque(0x081D58) }; const auto& normLUT=lutstore[JKQTPMathImageYL_GN_BU]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "YeGnBu", QObject::tr("yellow-green-blue")); const auto& normStepLUT=lutstore[JKQTPMathImageYL_GN_BU_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTColorsOnlySteps(lst), "stepsYeGnBu", QObject::tr("steps: yellow-green-blue")); lutstore[JKQTPMathImageBU_GN_YL]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "BlGnYe", QObject::tr("blue-green-yellow")); lutstore[JKQTPMathImageBU_GN_YL_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsBlGnYe", QObject::tr("steps: blue-green-yellow")); } { const JKQTPPaletteList lst= { jkqtp_qRgbOpaque(0xF7FCF0), jkqtp_qRgbOpaque(0xE0F3DB), jkqtp_qRgbOpaque(0xCCEBC5), jkqtp_qRgbOpaque(0xA8DDB5), jkqtp_qRgbOpaque(0x7BCCC4), jkqtp_qRgbOpaque(0x4EB3D3), jkqtp_qRgbOpaque(0x2B8CBE), jkqtp_qRgbOpaque(0x0868AC), jkqtp_qRgbOpaque(0x084081) }; const auto& normLUT=lutstore[JKQTPMathImageBU_GN]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "bluegreen", QObject::tr("blue-green-white")); const auto& normStepLUT=lutstore[JKQTPMathImageBU_GN_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTColorsOnlySteps(lst), "stepsBlGn", QObject::tr("steps: blue-green-white")); lutstore[JKQTPMathImageGN_BU]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "BlGnYe", QObject::tr("white-green-blue")); lutstore[JKQTPMathImageGN_BU_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsBlGnYe", QObject::tr("steps: white-green-blue")); } { const JKQTPPaletteList lst= { QColor("blue"), QColor("green"), QColor("red") }; const auto& normLUT=lutstore[JKQTPMathImageBlueGreenRed]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "BlGnRd", QObject::tr("blue-green-red")); lutstore[JKQTPMathImageBlueGreenRed].legacyNames<<"bluegreenred"; lutstore[JKQTPMathImageRedGreenBlue]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "RdGnBu", QObject::tr("red-green-blue")); lutstore[JKQTPMathImageRedGreenBlue].legacyNames<<"redgreenblue"; } { const JKQTPPaletteList lst= { QColor("magenta"), QColor("yellow") }; const auto& normLUT=lutstore[JKQTPMathImageMagentaYellow]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "magentayellow", QObject::tr("magenta-yellow")); lutstore[JKQTPMathImageYellowMagenta]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "yellowmagenta", QObject::tr("yellow-magenta")); } { const JKQTPPaletteList lst= { QColor("red"), QColor("blue") }; const auto& normLUT=lutstore[JKQTPMathImageRedBlue]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "redblue", QObject::tr("red-blue")); lutstore[JKQTPMathImageBlueRed]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "bluered", QObject::tr("blue-red")); } { const JKQTPPaletteList lst= { QColor(142,1,82), QColor(246,246,246), QColor(39,100,25) }; const auto& normLUT=lutstore[JKQTPMathImagePI_W_GR]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "PiWGr", QObject::tr("pink-white-green (diverging)")); const auto& normStepLUT=lutstore[JKQTPMathImagePI_W_GR_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst,9), "stepsPiWGr", QObject::tr("steps: pink-white-green (diverging)")); lutstore[JKQTPMathImageGR_W_PI]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "GrWPi", QObject::tr("green-wite-pink (diverging)")); lutstore[JKQTPMathImageGR_W_PI_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsGrWPi", QObject::tr("steps: green-wite-pink (diverging)")); } { const JKQTPPaletteList lst= { QColor(103,0,31), QColor(254,254,254), QColor(26,26,26) }; const auto& normLUT=lutstore[JKQTPMathImageRD_W_GY]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "RdWGy", QObject::tr("red-white-gray (diverging)")); const auto& normStepLUT=lutstore[JKQTPMathImageRD_W_GY_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst,9), "stepsRdWGy", QObject::tr("steps: red-white-gray (diverging)")); lutstore[JKQTPMathImageGY_W_RD]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "GyWRd", QObject::tr("gray-white-red (diverging)")); lutstore[JKQTPMathImageGY_W_RD_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsGyWRd", QObject::tr("steps: gray-wite-red (diverging)")); } { const JKQTPPaletteList lst= { QColor(58,76,192), QColor(220,220,220), QColor(179,3,38) }; const auto& normLUT=lutstore[JKQTPMathImageCoolwarm]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "coolwarm", QObject::tr("coolwarm (diverging)")); const auto& normStepLUT=lutstore[JKQTPMathImageCoolwarm_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst,9), "stepscoolwarm", QObject::tr("steps: coolwarm (diverging)")); lutstore[JKQTPMathImageINVERTED_Coolwarm]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invcoolwarm", QObject::tr("inv. coolwarm (diverging)")); lutstore[JKQTPMathImageINVERTED_Coolwarm_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsinvcoolwarm", QObject::tr("steps: inv. coolwarm (diverging)")); } { const JKQTPPaletteList lst= { QColor::fromRgbF(0.0f, 0.0f, 0.3f), QColor::fromRgbF(0.0f, 0.0f, 1.0f), QColor::fromRgbF(1.0f, 1.0f, 1.0f), QColor::fromRgbF(1.0f, 0.0f, 0.0f), QColor::fromRgbF(0.5f, 0.0f, 0.0f) }; const auto& normLUT=lutstore[JKQTPMathImageSeismic]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "seismic", QObject::tr("seismic")); const auto& normStepLUT=lutstore[JKQTPMathImageSeismic_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTColorsOnlySteps(lst), "stepsseismic", QObject::tr("steps: seismic")); lutstore[JKQTPMathImageSeismic_STEP].legacyNames<<"seismic_step"; lutstore[JKQTPMathImageINVERTED_Seismic]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invseismic", QObject::tr("inv. seismic")); lutstore[JKQTPMathImageINVERTED_Seismic_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsinvseismic", QObject::tr("steps: inv. seismic")); } { JKQTPPaletteList lst; lst<(0.00, QColor::fromRgbF(0.2f, 0.2f, 0.6f).rgb()); lst<(0.15, QColor::fromRgbF(0.0f, 0.6f, 1.0f).rgb()); lst<(0.25, QColor::fromRgbF(0.0f, 0.8f, 0.4f).rgb()); lst<(0.50, QColor::fromRgbF(1.0f, 1.0f, 0.6f).rgb()); lst<(0.75, QColor::fromRgbF(0.5f, 0.36f, 0.33f).rgb()); lst<(1.00, QColor::fromRgbF(1.0f, 1.0f, 1.0f).rgb()); const auto& normLUT=lutstore[JKQTPMathImageTerrain]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTLinInterpolate(lst), "terrain", QObject::tr("terrain")); const auto& normStepLUT=lutstore[JKQTPMathImageTerrain_STEP]=JKQTPImageTools::LUTData(JKQTPBuildColorPaletteLUTColorsOnlySteps(lst), "stepsterrain", QObject::tr("steps: terrain")); lutstore[JKQTPMathImageTerrain_STEP].legacyNames<<"terrain_step"; lutstore[JKQTPMathImageINVERTED_Terrain]=JKQTPImageTools::LUTData(jkqtp_reversed(normLUT.lut), "invterrain", QObject::tr("inv. terrain")); lutstore[JKQTPMathImageINVERTED_Terrain_STEP]=JKQTPImageTools::LUTData(jkqtp_reversed(normStepLUT.lut), "stepsinvterrain", QObject::tr("steps: inv. terrain")); } { QList lstR,lstG,lstB; lstR< lstR,lstG,lstB; lstR< lstR,lstG,lstB; lstR< lstR,lstG,lstB; lstR< &s1, const QPair &s2) { return s1.first itemsR, QList itemsG, QList itemsB, int lut_size) { std::sort(itemsR.begin(), itemsR.end(), JKQTPBuildColorPaletteLUTLinSegLessThan); std::sort(itemsG.begin(), itemsG.end(), JKQTPBuildColorPaletteLUTLinSegLessThan); std::sort(itemsB.begin(), itemsB.end(), JKQTPBuildColorPaletteLUTLinSegLessThan); return JKQTPBuildColorPaletteLUTLinSegmentsSorted(itemsR, itemsG, itemsB, lut_size); } JKQTPImageTools::LUTType JKQTPBuildColorPaletteLUTLinSegmentsSorted(const QList &itemsR, const QList &itemsG, const QList &itemsB, int lut_size) { JKQTPImageTools::LUTType lut(lut_size, qRgb(255,255,255)); if (itemsR.size()<=0 && itemsG.size()<=0 && itemsB.size()<=0) return lut; auto buildChannel=[](JKQTPImageTools::LUTType& lut, const QList &items, int channel) { if (items.size()==1) { for (int i=0; i(lut.size()-2); double v=dmin; int j1=0; for (int i=0; i(static_cast(items[j2].colval_endprevious-items[j1].colval_startnext)*local_relV); JKQTPSetColorChannel(lut[i], channel, jkqtp_bounded(0, newCol, 255)); //qDebug()<<"i="< lut[i]=0x"<=items[j1].position && v>=items[j2].position && j1(0, items.last().colval_endprevious, 255)); } }; buildChannel(lut, itemsR, 0); buildChannel(lut, itemsG, 1); buildChannel(lut, itemsB, 2); return lut; } JKQTPImageTools::LUTType JKQTPBuildColorPaletteLUTLinInterpolateSorted(const JKQTPPaletteList &items, int lut_size) { JKQTPImageTools::LUTType lut(lut_size, 0); if (items.size()<=1) return lut; double dmin=items.first().first; double dmax=items.last().first; double delta=(dmax-dmin)/static_cast(lut_size-2); double v=dmin; int j1=0; for (int i=0; i(r), static_cast(g), static_cast(b)); v+=delta; // advance over items, if v crosses items[j2].first while (v>=items[j1].first && v>=items[j2].first && j1=items[j+1].first) j++; } if (i<=lut_size) lut[i]=qRgb(static_cast(r), static_cast(g), static_cast(b)); i++; } return lut; } JKQTPImageTools::LUTType JKQTPBuildColorPaletteLUTLinInterpolate(const QMap &items, int lut_size) { JKQTPPaletteList itemsi; for (auto it=items.begin(); it!=items.end(); ++it) { itemsi.append(QPair(it.key(), it.value())); } return JKQTPBuildColorPaletteLUTLinInterpolateSorted(itemsi, lut_size); } JKQTPImageTools::LUTType JKQTPBuildColorPaletteLUT(const QMap &items, int lut_size) { JKQTPPaletteList itemsi; for (auto it=items.begin(); it!=items.end(); ++it) { itemsi.append(QPair(it.key(), it.value())); } return JKQTPBuildColorPaletteLUTSorted(itemsi, lut_size); } double JKQTPImagePlot_QStringToDouble(QString value) { QString v=value; if (value.contains(',')) { v=value.replace(',', '.'); } QLocale loc=QLocale::c(); loc.setNumberOptions(QLocale::OmitGroupSeparator); return loc.toDouble(v) ; } JKQTPImageTools::LUTType JKQTPBuildColorPaletteLUTBySubsampling(const JKQTPImageTools::LUTType &lut, int lut_size) { JKQTPImageTools::LUTType out; out.reserve(lut_size); for (int i=0; i(0, i*(lut.size()-1)/lut_size, lut.size()-1); out.append(lut[step]); } return out; } template bool JKQTPImagePlot_QPairCompareFirst(const QPair &s1, const QPair &s2) { return s1.first < s2.first; } QStringList JKQTPImageTools::getPredefinedPalettes() { QReadLocker lock(&JKQTPImageTools::lutMutex); if (getPredefinedPalettesGlobalList.size()!=JKQTPImageTools::global_jkqtpimagetools_lutstore.size()) { lock.unlock(); QWriteLocker lock(&JKQTPImageTools::lutMutex); if (getPredefinedPalettesGlobalList.size()!=JKQTPImageTools::global_jkqtpimagetools_lutstore.size()) { getPredefinedPalettesGlobalList.clear(); for (auto it=JKQTPImageTools::global_jkqtpimagetools_lutstore.begin(); it!=JKQTPImageTools::global_jkqtpimagetools_lutstore.end(); ++it) { if (it.key()>=0 && it.key()<=JKQTPMathImageLAST_POSSIBLE_REGISTERED_USER_PALETTE) { if (it.value().nameT.size()!=0) getPredefinedPalettesGlobalList<=0) { if (it.value().name.size()!=0) getPredefinedPalettesMachineReadableGlobalList<(p)); else { if (it.value().name.size()>0) return it.value().name; else return QString::number(static_cast(p)); } } QString JKQTPImageTools::JKQTPMathImageColorPalette2StringHumanReadable(JKQTPMathImageColorPalette p) { QReadLocker lock(&JKQTPImageTools::lutMutex); auto it=JKQTPImageTools::global_jkqtpimagetools_lutstore.find(p); if (it==JKQTPImageTools::global_jkqtpimagetools_lutstore.end()) return QString::number(static_cast(p)); else { if (it.value().nameT.size()>0) return it.value().nameT; else if (it.value().name.size()>0) return it.value().name; else return QString::number(static_cast(p)); } } JKQTPMathImageColorPalette JKQTPImageTools::String2JKQTPMathImageColorPalette(const QString &p) { QReadLocker lock(&JKQTPImageTools::lutMutex); for (auto it=JKQTPImageTools::global_jkqtpimagetools_lutstore.begin(); it!=JKQTPImageTools::global_jkqtpimagetools_lutstore.end(); ++it) { if (QString::compare(p, it.value().name, Qt::CaseInsensitive)==0) { return static_cast(it.key()); } for (const auto& ln: it.value().legacyNames) { if (QString::compare(p, ln, Qt::CaseInsensitive)==0) { return static_cast(it.key()); } } } for (auto it=JKQTPImageTools::global_jkqtpimagetools_lutstore.begin(); it!=JKQTPImageTools::global_jkqtpimagetools_lutstore.end(); ++it) { if (QString::compare(p, it.value().nameT, Qt::CaseInsensitive)==0) { return static_cast(it.key()); } } bool ok=false; JKQTPMathImageColorPalette res = static_cast(p.toInt(&ok)); if (!ok) return JKQTPMathImageMATLAB; else return res; } const JKQTPImageTools::LUTType& JKQTPImageTools::getLUTforPalette(const QMap& lutstore, JKQTPMathImageColorPalette palette) { static JKQTPImageTools::LUTType empty(JKQTPImageTools::LUTSIZE, 0); auto it=lutstore.find(static_cast(palette)); if (it==lutstore.end()) { return empty; } else { return it.value().lut; } } QImage JKQTPImageTools::GetPaletteImage(int i, int width) { return JKQTPImageTools::GetPaletteImage(i, width, 1); } QImage JKQTPImageTools::GetPaletteImage(int i, int width, int height) { QImage img; const int NPixels=jkqtp_bounded(width*height); QVector pic(NPixels,0); for (int j=0; j(pic.data(), width, height, img, static_cast(i), Qt::black, Qt::black); return img; } QImage JKQTPImageTools::GetPaletteImage(JKQTPMathImageColorPalette palette, int width) { return JKQTPImageTools::GetPaletteImage(static_cast(palette), width); } QImage JKQTPImageTools::GetPaletteImage(JKQTPMathImageColorPalette palette, int width, int height) { return JKQTPImageTools::GetPaletteImage(static_cast(palette), width, height); } QImage JKQTPImageTools::GetPaletteImage(const JKQTPImageTools::LUTType& lut, int width) { QImage img; QVector pic(width); for (int j=0; j(pic.data(), pic.size(), 1, img, lut, Qt::black, Qt::black); return img; } QIcon JKQTPImageTools::GetPaletteIcon(int i) { const QImage img=JKQTPImageTools::GetPaletteImage(i, JKQTPImageTools::PALETTE_ICON_WIDTH); QPixmap pix(JKQTPImageTools::PALETTE_ICON_WIDTH,8); const QRect r(0,0,JKQTPImageTools::PALETTE_ICON_WIDTH-1,7); QPainter p(&pix); p.drawImage(r, img); p.setPen(QPen(QColor("black"))); p.drawRect(r); p.end(); return QIcon(pix); } QIcon JKQTPImageTools::GetPaletteIcon(JKQTPMathImageColorPalette palette) { return JKQTPImageTools::GetPaletteIcon(static_cast(palette)); } const JKQTPImageTools::LUTType &JKQTPImageTools::getLUTforPalette(JKQTPMathImageColorPalette palette) { return getLUTforPalette(JKQTPImageTools::global_jkqtpimagetools_lutstore, palette); } QVector JKQTPImageTools::getColorsforPalette(JKQTPMathImageColorPalette palette) { QVector cols; const auto& lut=JKQTPImageTools::getLUTforPalette(palette); cols.reserve(lut.size()); std::for_each(lut.begin(), lut.end(), [&](QRgb c) { cols.push_back(c); }); return cols; } int JKQTPImageTools::registerPalette(const QString &name, const JKQTPImageTools::LUTType &paletteLut, const QString &nameT) { QWriteLocker lock(&JKQTPImageTools::lutMutex); int id=JKQTPImageTools::global_next_userpalette++; JKQTPImageTools::global_jkqtpimagetools_lutstore[id].name=name; JKQTPImageTools::global_jkqtpimagetools_lutstore[id].nameT=((nameT.size()>0)?nameT:name); JKQTPImageTools::global_jkqtpimagetools_lutstore[id].lut=paletteLut; return id; } QVector JKQTPImageTools::registerPalettesFromFile(const QString &filename, bool interpolatePalette) { QVector ids; QString ext=QFileInfo(filename).suffix().toLower(); if (ext=="rgb" || ext=="pal" || ext=="csv") { QFile file(filename); if (file.open(QIODevice::ReadOnly|QIODevice::Text)) { QString txt=file.readAll(); QStringList slt=txt.split('\n'); bool has4=false; bool rgb255=false; JKQTPPaletteList pal; #if (QT_VERSION>=QT_VERSION_CHECK(6, 0, 0)) QRegularExpression rx3("\\s*([0-9eE.+-]+)\\s*([,\\t ])\\s*([0-9eE.+-]+)\\s*\\2\\s*([0-9eE.+-]+)\\s*", QRegularExpression::CaseInsensitiveOption|QRegularExpression::InvertedGreedinessOption); QRegularExpression rx4("\\s*([0-9eE.+-]+)\\s*([,\\t ])\\s*([0-9eE.+-]+)\\s*\\2\\s*([0-9eE.+-]+)\\s*\\2\\s*([0-9eE.+-]+)\\s*", QRegularExpression::CaseInsensitiveOption|QRegularExpression::InvertedGreedinessOption); #else QRegExp rx3("\\s*([0-9eE.+-]+)\\s*([,\\t ])\\s*([0-9eE.+-]+)\\s*\\2\\s*([0-9eE.+-]+)\\s*", Qt::CaseInsensitive); rx3.setMinimal(false); QRegExp rx4("\\s*([0-9eE.+-]+)\\s*([,\\t ])\\s*([0-9eE.+-]+)\\s*\\2\\s*([0-9eE.+-]+)\\s*\\2\\s*([0-9eE.+-]+)\\s*", Qt::CaseInsensitive); rx4.setMinimal(false); #endif // determine format for (int i=slt.size()-1; i>=0; i--) { slt[i]=slt[i].trimmed(); #if (QT_VERSION>=QT_VERSION_CHECK(6, 0, 0)) const auto m4=rx4.match(slt[i]); const auto m3=rx3.match(slt[i]); if (m4.hasMatch()) { const double r=JKQTPImagePlot_QStringToDouble(m4.captured(3)); const double g=JKQTPImagePlot_QStringToDouble(m4.captured(4)); const double b=JKQTPImagePlot_QStringToDouble(m4.captured(5)); #else if (rx4.indexIn(slt[i])>=0) { const double r=JKQTPImagePlot_QStringToDouble(rx4.cap(3)); const double g=JKQTPImagePlot_QStringToDouble(rx4.cap(4)); const double b=JKQTPImagePlot_QStringToDouble(rx4.cap(5)); #endif has4=true; if (r>1.0 || g>1.0 || b>1.0) { rgb255=true; } #if (QT_VERSION>=QT_VERSION_CHECK(6, 0, 0)) } else if (m3.hasMatch()) { const double r=JKQTPImagePlot_QStringToDouble(m3.captured(1)); const double g=JKQTPImagePlot_QStringToDouble(m3.captured(3)); const double b=JKQTPImagePlot_QStringToDouble(m3.captured(4)); #else } else if (rx3.indexIn(slt[i])>=0) { double r=JKQTPImagePlot_QStringToDouble(rx3.cap(1)); double g=JKQTPImagePlot_QStringToDouble(rx3.cap(3)); double b=JKQTPImagePlot_QStringToDouble(rx3.cap(4)); #endif has4=false; if (r>1.0 || g>1.0 || b>1.0) { rgb255=true; } } else { slt.removeAt(i); } } // read data bool ok=true; for (int i=0; i=QT_VERSION_CHECK(6, 0, 0)) const auto m4=rx4.match(slt[i]); const auto m3=rx3.match(slt[i]); if (has4 && m4.hasMatch()) { x=JKQTPImagePlot_QStringToDouble(m4.captured(1)); r=JKQTPImagePlot_QStringToDouble(m4.captured(3)); g=JKQTPImagePlot_QStringToDouble(m4.captured(4)); b=JKQTPImagePlot_QStringToDouble(m4.captured(5)); } else if (!has4 && m3.hasMatch()) { x=i; r=JKQTPImagePlot_QStringToDouble(m3.captured(1)); g=JKQTPImagePlot_QStringToDouble(m3.captured(3)); b=JKQTPImagePlot_QStringToDouble(m3.captured(4)); #else if (has4 && rx4.indexIn(slt[i])>=0) { x=JKQTPImagePlot_QStringToDouble(rx4.cap(1)); r=JKQTPImagePlot_QStringToDouble(rx4.cap(3)); g=JKQTPImagePlot_QStringToDouble(rx4.cap(4)); b=JKQTPImagePlot_QStringToDouble(rx4.cap(5)); } else if (!has4 && rx3.indexIn(slt[i])>=0) { x=i; r=JKQTPImagePlot_QStringToDouble(rx3.cap(1)); g=JKQTPImagePlot_QStringToDouble(rx3.cap(3)); b=JKQTPImagePlot_QStringToDouble(rx3.cap(4)); //qDebug()<(x, qRgb(qBound(0,static_cast(round(255*r)), 255), qBound(0,static_cast(round(255*g)), 255), qBound(0,static_cast(round(255*b)), 255))); } else { pal<(x, qRgb(qBound(0,static_cast(round(r)), 255), qBound(0,static_cast(round(g)), 255), qBound(0,static_cast(round(b)), 255))); } } } if (ok && pal.size()>1) { if (interpolatePalette) ids<(round(255*r)), 255), qBound(0,static_cast(round(255*g)), 255), qBound(0,static_cast(round(255*b)), 255))); e = e.nextSiblingElement("Point"); } if (pal.size()>1) { if (interpolatePalette) ids<(0, y1*255.0, 255), jkqtp_boundedRoundTo(0, y2*255.0, 255)); } JKQTPColorPaletteSingleColorLinSegment::JKQTPColorPaletteSingleColorLinSegment(): position(0), colval_endprevious(0), colval_startnext(0) { } JKQTPMathImageModifierMode StringToModifierMode(const QString &mode) { QString m=mode.toLower(); if (m=="value" ) return JKQTPMathImageModifierMode::ModifyValue; if (m=="saturation" ) return JKQTPMathImageModifierMode::ModifySaturation; if (m=="alpha" ) return JKQTPMathImageModifierMode::ModifyAlpha; if (m=="luminance" ) return JKQTPMathImageModifierMode::ModifyLuminance; if (m=="hue" ) return JKQTPMathImageModifierMode::ModifyHue; return JKQTPMathImageModifierMode::ModifyNone; } QString ModifierModeToString(const JKQTPMathImageModifierMode &mode) { if (mode==JKQTPMathImageModifierMode::ModifyValue) return "value"; if (mode==JKQTPMathImageModifierMode::ModifySaturation) return "saturation"; if (mode==JKQTPMathImageModifierMode::ModifyAlpha) return "alpha"; if (mode==JKQTPMathImageModifierMode::ModifyLuminance) return "luminance"; if (mode==JKQTPMathImageModifierMode::ModifyHue) return "hue"; return "none"; } void JKQTPModifyImage(QImage &img, JKQTPMathImageModifierMode modifierMode, const void *dataModifier, JKQTPMathImageDataType datatypeModifier, int Nx, int Ny, double internalModifierMin, double internalModifierMax) { if (!dataModifier) return; //getModifierMinMax(internalModifierMin, internalModifierMax); if (modifierMode!=JKQTPMathImageModifierMode::ModifyNone) { JKQTPRGBMathImageRGBMode rgbModMode=JKQTPRGBMathImageModeRGBMode; int modChannel=3; if (modifierMode==JKQTPMathImageModifierMode::ModifyValue) { modChannel=2; rgbModMode=JKQTPRGBMathImageModeHSVMode; } else if (modifierMode==JKQTPMathImageModifierMode::ModifySaturation) { modChannel=1; rgbModMode=JKQTPRGBMathImageModeHSVMode; } else if (modifierMode==JKQTPMathImageModifierMode::ModifyAlpha) { modChannel=3; rgbModMode=JKQTPRGBMathImageModeRGBMode; } else if (modifierMode==JKQTPMathImageModifierMode::ModifyLuminance) { modChannel=2; rgbModMode=JKQTPRGBMathImageModeHSLMode; } else if (modifierMode==JKQTPMathImageModifierMode::ModifyHue) { modChannel=0; rgbModMode=JKQTPRGBMathImageModeHSLMode; } //qDebug()<<"mod: "<(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; case JKQTPMathImageDataType::FloatArray: JKQTPImagePlot_array2RGBimage(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; case JKQTPMathImageDataType::UInt8Array: JKQTPImagePlot_array2RGBimage(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; case JKQTPMathImageDataType::UInt16Array: JKQTPImagePlot_array2RGBimage(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; case JKQTPMathImageDataType::UInt32Array: JKQTPImagePlot_array2RGBimage(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; case JKQTPMathImageDataType::UInt64Array: JKQTPImagePlot_array2RGBimage(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; case JKQTPMathImageDataType::Int8Array: JKQTPImagePlot_array2RGBimage(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; case JKQTPMathImageDataType::Int16Array: JKQTPImagePlot_array2RGBimage(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; case JKQTPMathImageDataType::Int32Array: JKQTPImagePlot_array2RGBimage(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; case JKQTPMathImageDataType::Int64Array: JKQTPImagePlot_array2RGBimage(static_cast(dataModifier), Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break; } } } JKQTPImageTools::LUTType JKQTPModifyLUT(JKQTPImageTools::LUTType lut, std::function f) { int i=0; for (auto& c: lut) { c=f(i, c); i++; } return lut; } JKQTPImageTools::LUTType JKQTPModifyLUT(JKQTPImageTools::LUTType lut, std::function f) { for (auto& c: lut) { c=f(c); } return lut; } JKQTPImageTools::LUTType JKQTPCreateGreensCubeHelixLUT(float start, float rotation, float gamma, int lutsize, float lambda_min, float lambda_max, float saturation_min, float saturation_max) { JKQTPImageTools::LUTType res; for (int i=0; i(i)/static_cast(lutsize-1)*(lambda_max-lambda_min); const float sat=saturation_min+static_cast(i)/static_cast(lutsize-1)*(saturation_max-saturation_min); const float lambda_gamma=pow(lambda, gamma); const float phi=2.0*JKQTPSTATISTICS_PI*(start/3.0+rotation*lambda); const float cosphi=cos(phi); const float sinphi=sin(phi); const float amplitude=sat*lambda_gamma*(1-lambda_gamma)/2.0; const float R=lambda_gamma + amplitude*(-0.14861*cosphi+1.78277*sinphi); const float G=lambda_gamma + amplitude*(-0.29227*cosphi-0.90649*sinphi); const float B=lambda_gamma + amplitude*(1.972940*cosphi+0.0*sinphi); res<(0.0,R,1.0), jkqtp_bounded(0.0,G,1.0), jkqtp_bounded(0.0,B,1.0)).rgb(); } return res; } JKQTPImageTools::LUTType JKQTPBuildColorPaletteLUT(const std::function &palFunc, int lut_size, float vMin, float vMax) { JKQTPImageTools::LUTType res; const float delta=(vMax-vMin)/static_cast(lut_size-1); for (int i=0; i(i)*delta; res< &rFunc, const std::function &gFunc, const std::function &bFunc, int lut_size, float vMin, float vMax) { return JKQTPBuildColorPaletteLUT([&rFunc, &gFunc, &bFunc](float v) { return QColor::fromRgbF(jkqtp_bounded(0.0, rFunc(v), 1.0), jkqtp_bounded(0.0, gFunc(v), 1.0), jkqtp_bounded(0.0, bFunc(v), 1.0)).rgba(); }, lut_size, vMin, vMax); } JKQTPImageTools::LUTType JKQTPBuildColorPaletteLUT(const std::function &rFunc, const std::function &gFunc, const std::function &aFunc, const std::function &bFunc, int lut_size, float vMin, float vMax) { return JKQTPBuildColorPaletteLUT([&rFunc, &gFunc, &bFunc, &aFunc](float v) { return QColor::fromRgbF(jkqtp_bounded(0.0, rFunc(v), 1.0), jkqtp_bounded(0.0, gFunc(v), 1.0), jkqtp_bounded(0.0, bFunc(v), 1.0), jkqtp_bounded(0.0, aFunc(v), 1.0)).rgba(); }, lut_size, vMin, vMax); }