diff --git a/doc/colormap-cool-warm-bent.png b/doc/colormap-cool-warm-bent.png new file mode 100644 index 000000000..364568d31 Binary files /dev/null and b/doc/colormap-cool-warm-bent.png differ diff --git a/doc/colormap-cool-warm-smooth.png b/doc/colormap-cool-warm-smooth.png new file mode 100644 index 000000000..c91428c8d Binary files /dev/null and b/doc/colormap-cool-warm-smooth.png differ diff --git a/doc/generated/colormaps.cpp b/doc/generated/colormaps.cpp index d0e24f05d..0c9ceb9d0 100644 --- a/doc/generated/colormaps.cpp +++ b/doc/generated/colormaps.cpp @@ -48,7 +48,9 @@ int main() { std::make_pair(DebugTools::ColorMap::magma(), "colormap-magma.png"), std::make_pair(DebugTools::ColorMap::plasma(), "colormap-plasma.png"), std::make_pair(DebugTools::ColorMap::inferno(), "colormap-inferno.png"), - std::make_pair(DebugTools::ColorMap::viridis(), "colormap-viridis.png") + std::make_pair(DebugTools::ColorMap::viridis(), "colormap-viridis.png"), + std::make_pair(DebugTools::ColorMap::coolWarmSmooth(), "colormap-cool-warm-smooth.png"), + std::make_pair(DebugTools::ColorMap::coolWarmBent(), "colormap-cool-warm-bent.png") }) { constexpr Vector2i OutputSize{256, 12}; CORRADE_INTERNAL_ASSERT(image.first.size() == std::size_t(OutputSize.x())); diff --git a/src/Magnum/DebugTools/ColorMap.cpp b/src/Magnum/DebugTools/ColorMap.cpp index bb0c694d7..b5b64ff41 100644 --- a/src/Magnum/DebugTools/ColorMap.cpp +++ b/src/Magnum/DebugTools/ColorMap.cpp @@ -373,11 +373,149 @@ constexpr UnsignedByte Viridis[][3] = { {246, 230, 31}, {248, 230, 33}, {250, 230, 34}, {253, 231, 36} }; +/* Generated with Implementation/cool-warm.py */ +constexpr UnsignedByte CoolWarmSmooth[][3] = { + { 85, 72, 193}, { 86, 74, 194}, { 88, 76, 196}, { 89, 78, 198}, + { 90, 79, 199}, { 91, 81, 201}, { 92, 83, 202}, { 93, 85, 204}, + { 94, 87, 205}, { 95, 88, 207}, { 96, 90, 208}, { 97, 92, 209}, + { 98, 94, 211}, { 99, 95, 212}, {100, 97, 214}, {102, 99, 215}, + {103, 101, 216}, {104, 102, 218}, {105, 104, 219}, {106, 106, 220}, + {107, 107, 221}, {108, 109, 223}, {109, 111, 224}, {110, 113, 225}, + {111, 114, 226}, {112, 116, 227}, {113, 118, 228}, {115, 119, 230}, + {116, 121, 231}, {117, 123, 232}, {118, 124, 233}, {119, 126, 234}, + {120, 127, 235}, {121, 129, 236}, {122, 131, 237}, {123, 132, 238}, + {125, 134, 238}, {126, 135, 239}, {127, 137, 240}, {128, 139, 241}, + {129, 140, 242}, {130, 142, 243}, {131, 143, 243}, {132, 145, 244}, + {133, 146, 245}, {135, 148, 246}, {136, 149, 246}, {137, 151, 247}, + {138, 152, 248}, {139, 154, 248}, {140, 155, 249}, {141, 157, 249}, + {142, 158, 250}, {144, 160, 250}, {145, 161, 251}, {146, 162, 251}, + {147, 164, 252}, {148, 165, 252}, {149, 166, 253}, {150, 168, 253}, + {151, 169, 253}, {153, 170, 254}, {154, 172, 254}, {155, 173, 254}, + {156, 174, 254}, {157, 176, 255}, {158, 177, 255}, {159, 178, 255}, + {160, 179, 255}, {162, 181, 255}, {163, 182, 255}, {164, 183, 255}, + {165, 184, 255}, {166, 185, 255}, {167, 186, 255}, {168, 187, 255}, + {169, 189, 255}, {171, 190, 255}, {172, 191, 255}, {173, 192, 255}, + {174, 193, 255}, {175, 194, 255}, {176, 195, 255}, {177, 196, 254}, + {178, 197, 254}, {179, 198, 254}, {180, 199, 253}, {182, 200, 253}, + {183, 201, 253}, {184, 201, 252}, {185, 202, 252}, {186, 203, 252}, + {187, 204, 251}, {188, 205, 251}, {189, 206, 250}, {190, 206, 250}, + {191, 207, 249}, {192, 208, 249}, {193, 209, 248}, {194, 209, 247}, + {195, 210, 247}, {196, 211, 246}, {197, 211, 245}, {198, 212, 245}, + {199, 212, 244}, {200, 213, 243}, {201, 214, 242}, {202, 214, 242}, + {203, 215, 241}, {204, 215, 240}, {205, 216, 239}, {206, 216, 238}, + {207, 217, 237}, {208, 217, 236}, {209, 217, 235}, {210, 218, 234}, + {211, 218, 233}, {212, 218, 232}, {213, 219, 231}, {214, 219, 230}, + {214, 219, 229}, {215, 220, 228}, {216, 220, 227}, {217, 220, 226}, + {218, 220, 225}, {219, 220, 224}, {219, 220, 222}, {220, 221, 221}, + {221, 220, 220}, {222, 220, 219}, {223, 220, 217}, {224, 219, 216}, + {225, 219, 214}, {226, 218, 213}, {227, 217, 211}, {227, 217, 210}, + {228, 216, 209}, {229, 216, 207}, {230, 215, 206}, {231, 214, 204}, + {231, 214, 203}, {232, 213, 201}, {233, 212, 200}, {233, 211, 198}, + {234, 211, 197}, {235, 210, 195}, {235, 209, 194}, {236, 208, 192}, + {236, 207, 190}, {237, 207, 189}, {237, 206, 187}, {238, 205, 186}, + {238, 204, 184}, {239, 203, 183}, {239, 202, 181}, {240, 201, 180}, + {240, 200, 178}, {240, 199, 177}, {241, 198, 175}, {241, 197, 173}, + {241, 196, 172}, {242, 195, 170}, {242, 194, 169}, {242, 193, 167}, + {242, 191, 166}, {243, 190, 164}, {243, 189, 162}, {243, 188, 161}, + {243, 187, 159}, {243, 185, 158}, {243, 184, 156}, {243, 183, 154}, + {243, 182, 153}, {243, 180, 151}, {243, 179, 150}, {243, 178, 148}, + {243, 176, 147}, {243, 175, 145}, {243, 174, 143}, {243, 172, 142}, + {243, 171, 140}, {243, 169, 139}, {243, 168, 137}, {242, 167, 136}, + {242, 165, 134}, {242, 164, 133}, {242, 162, 131}, {241, 161, 129}, + {241, 159, 128}, {241, 158, 126}, {240, 156, 125}, {240, 154, 123}, + {240, 153, 122}, {239, 151, 120}, {239, 150, 119}, {238, 148, 117}, + {238, 146, 116}, {237, 145, 114}, {237, 143, 113}, {236, 141, 111}, + {236, 140, 110}, {235, 138, 108}, {235, 136, 107}, {234, 134, 105}, + {234, 133, 104}, {233, 131, 102}, {232, 129, 101}, {232, 127, 99}, + {231, 126, 98}, {230, 124, 97}, {229, 122, 95}, {229, 120, 94}, + {228, 118, 92}, {227, 116, 91}, {226, 114, 89}, {225, 112, 88}, + {224, 111, 87}, {224, 109, 85}, {223, 107, 84}, {222, 105, 83}, + {221, 103, 81}, {220, 101, 80}, {219, 99, 78}, {218, 97, 77}, + {217, 95, 76}, {216, 93, 75}, {215, 91, 73}, {214, 88, 72}, + {213, 86, 71}, {212, 84, 69}, {210, 82, 68}, {209, 80, 67}, + {208, 78, 66}, {207, 75, 64}, {206, 73, 63}, {205, 71, 62}, + {203, 68, 61}, {202, 66, 59}, {201, 64, 58}, {200, 61, 57}, + {198, 59, 56}, {197, 56, 55}, {196, 54, 54}, {194, 51, 52}, + {193, 48, 51}, {192, 45, 50}, {190, 42, 49}, {189, 39, 48}, + {187, 36, 47}, {186, 33, 46}, {185, 29, 45}, {183, 25, 44}, + {182, 20, 43}, {180, 15, 41}, {179, 8, 40}, {177, 1, 39} +}; + +/* Generated with Implementation/cool-warm.py */ +constexpr UnsignedByte CoolWarmBent[][3] = { + { 85, 72, 193}, { 86, 74, 194}, { 87, 75, 194}, { 88, 77, 195}, + { 88, 78, 196}, { 89, 79, 196}, { 90, 81, 197}, { 90, 82, 197}, + { 91, 84, 198}, { 92, 85, 199}, { 93, 87, 199}, { 94, 88, 200}, + { 94, 90, 200}, { 95, 91, 201}, { 96, 92, 202}, { 97, 94, 202}, + { 98, 95, 203}, { 98, 97, 203}, { 99, 98, 204}, {100, 99, 204}, + {101, 101, 205}, {102, 102, 206}, {103, 104, 206}, {104, 105, 207}, + {104, 106, 207}, {105, 108, 208}, {106, 109, 208}, {107, 110, 209}, + {108, 112, 209}, {109, 113, 210}, {110, 115, 210}, {111, 116, 211}, + {112, 117, 211}, {113, 119, 212}, {114, 120, 212}, {115, 121, 213}, + {116, 123, 213}, {117, 124, 214}, {118, 125, 214}, {119, 127, 215}, + {120, 128, 215}, {121, 129, 215}, {122, 131, 216}, {123, 132, 216}, + {124, 134, 217}, {125, 135, 217}, {126, 136, 218}, {127, 138, 218}, + {128, 139, 218}, {129, 140, 219}, {130, 142, 219}, {132, 143, 220}, + {133, 144, 220}, {134, 146, 221}, {135, 147, 221}, {136, 148, 221}, + {137, 150, 222}, {138, 151, 222}, {140, 152, 222}, {141, 154, 223}, + {142, 155, 223}, {143, 156, 224}, {144, 158, 224}, {146, 159, 224}, + {147, 160, 225}, {148, 162, 225}, {149, 163, 225}, {151, 164, 226}, + {152, 166, 226}, {153, 167, 226}, {154, 168, 227}, {156, 170, 227}, + {157, 171, 227}, {158, 172, 228}, {160, 174, 228}, {161, 175, 228}, + {162, 176, 229}, {164, 177, 229}, {165, 179, 229}, {166, 180, 230}, + {168, 181, 230}, {169, 183, 230}, {170, 184, 230}, {172, 185, 231}, + {173, 187, 231}, {175, 188, 231}, {176, 189, 232}, {177, 191, 232}, + {179, 192, 232}, {180, 193, 232}, {182, 194, 233}, {183, 196, 233}, + {185, 197, 233}, {186, 198, 234}, {188, 200, 234}, {189, 201, 234}, + {191, 202, 234}, {192, 204, 235}, {194, 205, 235}, {195, 206, 235}, + {197, 207, 235}, {198, 209, 236}, {200, 210, 236}, {201, 211, 236}, + {203, 213, 236}, {205, 214, 237}, {206, 215, 237}, {208, 216, 237}, + {209, 218, 237}, {211, 219, 238}, {213, 220, 238}, {214, 221, 238}, + {216, 223, 238}, {217, 224, 239}, {219, 225, 239}, {221, 227, 239}, + {222, 228, 239}, {224, 229, 240}, {226, 230, 240}, {227, 232, 240}, + {229, 233, 240}, {231, 234, 241}, {233, 235, 241}, {234, 237, 241}, + {236, 238, 241}, {238, 239, 242}, {240, 240, 242}, {241, 242, 242}, + {242, 242, 241}, {242, 240, 239}, {241, 239, 237}, {241, 237, 235}, + {240, 236, 232}, {240, 234, 230}, {239, 233, 228}, {239, 231, 226}, + {239, 230, 224}, {238, 228, 221}, {238, 226, 219}, {237, 225, 217}, + {237, 223, 215}, {237, 222, 213}, {236, 220, 211}, {236, 219, 209}, + {235, 217, 207}, {235, 216, 205}, {234, 214, 203}, {234, 213, 200}, + {234, 211, 198}, {233, 210, 196}, {233, 208, 194}, {232, 207, 192}, + {232, 205, 190}, {231, 204, 188}, {231, 202, 186}, {231, 201, 184}, + {230, 199, 182}, {230, 198, 180}, {229, 196, 178}, {229, 195, 176}, + {228, 193, 175}, {228, 192, 173}, {228, 190, 171}, {227, 188, 169}, + {227, 187, 167}, {226, 185, 165}, {226, 184, 163}, {225, 182, 161}, + {225, 181, 159}, {224, 179, 158}, {224, 178, 156}, {224, 176, 154}, + {223, 175, 152}, {223, 173, 150}, {222, 171, 148}, {222, 170, 147}, + {221, 168, 145}, {221, 167, 143}, {220, 165, 141}, {220, 164, 140}, + {219, 162, 138}, {219, 161, 136}, {219, 159, 134}, {218, 157, 133}, + {218, 156, 131}, {217, 154, 129}, {217, 153, 128}, {216, 151, 126}, + {216, 149, 124}, {215, 148, 123}, {215, 146, 121}, {214, 145, 119}, + {214, 143, 118}, {213, 141, 116}, {213, 140, 115}, {212, 138, 113}, + {212, 137, 111}, {211, 135, 110}, {211, 133, 108}, {210, 132, 107}, + {210, 130, 105}, {209, 129, 104}, {209, 127, 102}, {208, 125, 101}, + {208, 124, 99}, {207, 122, 98}, {207, 120, 96}, {206, 119, 95}, + {206, 117, 93}, {205, 115, 92}, {205, 114, 91}, {204, 112, 89}, + {203, 110, 88}, {203, 109, 86}, {202, 107, 85}, {202, 105, 84}, + {201, 103, 82}, {201, 102, 81}, {200, 100, 80}, {200, 98, 78}, + {199, 96, 77}, {198, 95, 76}, {198, 93, 74}, {197, 91, 73}, + {197, 89, 72}, {196, 87, 71}, {196, 86, 69}, {195, 84, 68}, + {194, 82, 67}, {194, 80, 66}, {193, 78, 65}, {193, 76, 63}, + {192, 74, 62}, {191, 72, 61}, {191, 70, 60}, {190, 68, 59}, + {189, 66, 58}, {189, 64, 57}, {188, 62, 56}, {188, 59, 55}, + {187, 57, 54}, {186, 55, 53}, {186, 52, 52}, {185, 50, 50}, + {184, 47, 49}, {184, 45, 49}, {183, 42, 48}, {182, 39, 47}, + {182, 36, 46}, {181, 33, 45}, {181, 29, 44}, {180, 25, 43}, + {179, 21, 42}, {178, 15, 41}, {178, 8, 40}, {177, 1, 39} +}; + static_assert(sizeof(Turbo) == 256*3, ""); static_assert(sizeof(Magma) == 256*3, ""); static_assert(sizeof(Plasma) == 256*3, ""); static_assert(sizeof(Inferno) == 256*3, ""); static_assert(sizeof(Viridis) == 256*3, ""); +static_assert(sizeof(CoolWarmSmooth) == 256*3, ""); +static_assert(sizeof(CoolWarmBent) == 256*3, ""); } @@ -401,4 +539,12 @@ Containers::StaticArrayView<256, const Vector3ub> viridis() { return Containers::StaticArrayView<256, const Vector3ub>{reinterpret_cast(&Viridis[0][0])}; } +Containers::StaticArrayView<256, const Vector3ub> coolWarmSmooth() { + return Containers::StaticArrayView<256, const Vector3ub>{reinterpret_cast(&CoolWarmSmooth[0][0])}; +} + +Containers::StaticArrayView<256, const Vector3ub> coolWarmBent() { + return Containers::StaticArrayView<256, const Vector3ub>{reinterpret_cast(&CoolWarmBent[0][0])}; +} + }}} diff --git a/src/Magnum/DebugTools/ColorMap.h b/src/Magnum/DebugTools/ColorMap.h index e998a9543..7a4763a11 100644 --- a/src/Magnum/DebugTools/ColorMap.h +++ b/src/Magnum/DebugTools/ColorMap.h @@ -114,6 +114,30 @@ See @ref building, @ref cmake and @ref debug-tools for more information. @endparblock +@m_class{m-row} + +@parblock + +@m_div{m-col-l-8 m-push-l-3 m-col-m-8 m-push-m-4 m-nopadt} +@image html colormap-cool-warm-smooth.png width=100% +@m_enddiv + +@m_div{m-col-l-2 m-pull-l-7 m-col-m-4 m-pull-m-8 m-text-center m-nopadt} @ref coolWarmSmooth() @m_enddiv + +@endparblock + +@m_class{m-row} + +@parblock + +@m_div{m-col-l-8 m-push-l-3 m-col-m-8 m-push-m-4 m-nopadt} +@image html colormap-cool-warm-bent.png width=100% +@m_enddiv + +@m_div{m-col-l-2 m-pull-l-7 m-col-m-4 m-pull-m-8 m-text-center m-nopadt} @ref coolWarmBent() @m_enddiv + +@endparblock + For all color maps the returned data is the sRGB colorspace. Desired usage is by uploading to a texture with linear filtering, depending on the use case with either clamp or repeat wrapping. For a sRGB workflow don't forget to set the @@ -204,6 +228,44 @@ MAGNUM_DEBUGTOOLS_EXPORT Containers::StaticArrayView<256, const Vector3ub> infer */ MAGNUM_DEBUGTOOLS_EXPORT Containers::StaticArrayView<256, const Vector3ub> viridis(); +/** +@brief Smooth Cool-Warm colormap +@m_since_latest + +@image html colormap-cool-warm-smooth.png width=100% + +It is a diverging (double-ended) color map with a smooth transition in the +middle to prevent artifacts at the midpoint. Although not isoluminant, this +color map avoids dark colors to allow shading cues throughout. + +@m_class{m-block m-success} + +@thirdparty Created by [Kenneth Moreland](https://www.kennethmoreland.com/color-advice/), + released under a @m_class{m-label m-success} **BSD 3-clause** license as + part of Paraview ([license text](https://www.paraview.org/paraview-license/), + [choosealicense.com](https://choosealicense.com/licenses/bsd-3-clause/)). +*/ +MAGNUM_DEBUGTOOLS_EXPORT Containers::StaticArrayView<256, const Vector3ub> coolWarmSmooth(); + +/** +@brief Bent Cool-Warm colormap +@m_since_latest + +@image html colormap-cool-warm-bent.png width=100% + +This color map is similar @ref coolWarmSmooth() except that the luminance is +interpolated linearly with a sharp bend in the middle. This makes for less +washed out colors in the middle, but also creates an artifact at the midpoint. + +@m_class{m-block m-success} + +@thirdparty Created by [Kenneth Moreland](https://www.kennethmoreland.com/color-advice/), + released under a @m_class{m-label m-success} **BSD 3-clause** license as + part of Paraview ([license text](https://www.paraview.org/paraview-license/), + [choosealicense.com](https://choosealicense.com/licenses/bsd-3-clause/)). +*/ +MAGNUM_DEBUGTOOLS_EXPORT Containers::StaticArrayView<256, const Vector3ub> coolWarmBent(); + } }} diff --git a/src/Magnum/DebugTools/Implementation/cool-warm.py b/src/Magnum/DebugTools/Implementation/cool-warm.py new file mode 100755 index 000000000..7db999602 --- /dev/null +++ b/src/Magnum/DebugTools/Implementation/cool-warm.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, +# 2020 Vladimír Vondruš +# Copyright © 2020 janos +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +from numpy import genfromtxt + +def format(filename): + data = genfromtxt(filename, delimiter=',') + formatted = '' + data = data[1:,1:].astype(int) + formatted = '' + + for i in range(256//4): + line = ' ' + for j in range(4): + row = data[4*i+j] + line += '{{{:>3}, {:>3}, {:>3}}}, '.format(row[0], row[1], row[2]) + formatted = formatted + line + '\n' + + # Strip trailing comma and newline + return formatted[:-3] + +# The two CSV files taken from https://www.kennethmoreland.com/color-advice/ + +print("/* Generated with Implementation/cool-warm.py */") +print("constexpr UnsignedByte CoolWarmSmooth[][3] = {\n", end='') +print(format('smooth-cool-warm-table-byte-0256.csv')) +print("};\n") + +print("/* Generated with Implementation/cool-warm.py */") +print("constexpr UnsignedByte CoolWarmBent[][3] = {\n", end='') +print(format('bent-cool-warm-table-byte-0256.csv')) +print("};\n")