我需要以编程方式在矩形图像中生成彩虹光谱的近似值,如下所示:
我知道如何绘制像素图,我正在寻找的是如何生成颜色的值。
你需要阅读这篇论文。严重地。
除此之外,它所要做的就是迭代 HSL 颜色表示中的色调,在彩虹上使用从 0.0 到 1.0 的变化QColor::fromHslF(x/*0.8, 0.95, 0.5)
。x
它在物理上根本不准确,但也许可以。
否则,您需要一个稍微复杂一点的代码,该代码非常简单地近似于上面引用的论文。
// 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();
}