How to visualize the spectrum of the rainbow?

I need to programmatically generate an approximation of the rainbow spectrum in a rectangular image, as shown below:

rainbow spectrum

I know how to draw pixmap, I am looking for how to create color values.

+8
source share
1 answer

You need to read this article . Jokes aside.

In addition, all that may be required is to QColor::fromHslF(x/*0.8, 0.95, 0.5) over the shades in the HSL color representation using QColor::fromHslF(x/*0.8, 0.95, 0.5) where x varies from 0.0 to 1.0 over the rainbow. It is physically not entirely accurate, but perhaps it will do.

Otherwise, you will need a bit more complex code that approximates the above article very simplified.

screenshot

 // https://github.com/KubaO/stackoverflown/tree/master/questions/rainbow-19452530 #include <QtGui> #if QT_VERSION_MAJOR > 4 #include <QtWidgets> #endif #include <array> #include <cmath> constexpr qreal linMap(qreal x1, qreal x, qreal x2, qreal y1 = 0., qreal y2 = 1.) { return y1 + (y1 - y2) * (x - x1) / (x1 - x2); } QColor wavelengthToColor(qreal lambda) { // Based on: http://www.efg2.com/Lab/ScienceAndEngineering/Spectra.htm // The foregoing is based on: http://www.midnightkite.com/color.html struct Color { qreal red = 0., green = 0., blue = 0.; QColor toColor(qreal factor) const { auto const map = [factor](qreal c) -> qreal { constexpr qreal gamma = 0.8; return pow(c * factor, gamma); }; return QColor::fromRgbF(map(red), map(green), map(blue)); } }; struct Threshold { qreal begin, end; Color (*color)(qreal); qreal (*factor)(qreal) = nullptr; }; static const std::array<Threshold, 8> thresholds{ // Let the intensity fall off near the vision limits Threshold{380, 420, nullptr, [](qreal x){ return 0.3 + 0.7*x; }}, Threshold{380, 440, [](qreal x){ return Color{1-x, 0, 1}; }}, Threshold{440, 490, [](qreal x){ return Color{0, x, 1}; }}, Threshold{490, 510, [](qreal x){ return Color{0, 1, 1-x}; }}, Threshold{510, 580, [](qreal x){ return Color{x, 1, 0}; }}, Threshold{580, 645, [](qreal x){ return Color{1, 1-x, 0}; }}, Threshold{645, 780, [](qreal ){ return Color{1, 0, 0}; }}, Threshold{700, 780, nullptr, [](qreal x){ return 1 - 0.7*x; }} }; Color color; qreal factor = 1.0; for (auto &thr : thresholds) { if (lambda < thr.begin || lambda >= thr.end) continue; auto x = linMap(thr.begin, lambda, thr.end); if (thr.factor) factor = thr.factor(x); if (thr.color) color = thr.color(x); } return color.toColor(factor); } QPixmap rainbow(int w, int h) { QPixmap pixmap(w, h); QPainter p(&pixmap); constexpr qreal f1 = 1.0 / 400, f2 = 1.0 / 780; for (int x = 0; x < w; ++x) { // Iterate across frequencies, not wavelengths auto freq = linMap(0, x, w, f1, f2); p.setPen(wavelengthToColor(1.0 / freq)); p.drawLine(x, 0, x, h); } return pixmap; } class RainbowLabel : public QLabel { protected: void resizeEvent(QResizeEvent *) override { setPixmap(rainbow(width(), height())); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); RainbowLabel l; l.resize(600, 100); l.show(); return a.exec(); } 
+16
source

Source: https://habr.com/ru/post/956254/


All Articles