我需要在矩形图像中以编程方式生成彩虹光谱的近似值,如下所示:
我知道如何绘制像素图,我正在寻找的是如何生成颜色的值。
答案 0 :(得分:15)
您需要read this paper。严重。
除此之外,所有可能的方法是使用QColor::fromHslF(x/*0.8, 0.95, 0.5)
在HSL颜色表示中迭代色调,其中x
在彩虹上从0.0到1.0变化。它根本不是物理上准确的,但也许它会这样做。
否则,您需要一个稍微复杂的代码,它非常简单地接近上面引用的论文。
#include <QApplication>
#include <QPainter>
#include <QPixmap>
#include <QLabel>
#include <algorithm>
#include <cmath>
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 c[3];
QColor toColor(qreal factor) const {
qreal const gamma = 0.8;
int ci[3];
for (int i = 0; i < 3; ++i) {
ci[i] = c[i] == 0.0 ? 0.0 : qRound(255 * pow(c[i] * factor, gamma));
}
return QColor(ci[0], ci[1], ci[2]);
}
} color;
qreal factor = 0.0;
static qreal thresholds[] = { 380, 440, 490, 510, 580, 645, 780 };
for (unsigned int i = 0; i < sizeof(thresholds)/sizeof(thresholds[0]); ++ i) {
using std::swap;
qreal t1 = thresholds[i], t2 = thresholds[i+1];
if (lambda < t1 || lambda >= t2) continue;
if (i%2) swap(t1, t2);
color.c[i % 3] = (i < 5) ? (lambda - t2) / (t1-t2) : 0.0;;
color.c[2-i/2] = 1.0;
factor = 1.0;
break;
}
// Let the intensity fall off near the vision limits
if (lambda >= 380 && lambda < 420) {
factor = 0.3 + 0.7*(lambda-380) / (420 - 380);
}
else if (lambda >= 700 && lambda < 780) {
factor = 0.3 + 0.7*(780 - lambda) / (780 - 700);
}
return color.toColor(factor);
}
QPixmap rainbow(int w, int h)
{
QPixmap pm(w, h);
QPainter p(&pm);
qreal f1 = 1.0/400;
qreal f2 = 1.0/780;
for (int x = 0; x < w; ++ x) {
// Iterate across frequencies, not wavelengths
qreal lambda = 1.0/(f1-(x/qreal(w)*(f1-f2)));
p.setPen(wavelengthToColor(lambda));
p.drawLine(x, 0, x, h);
}
return pm;
}
class RainbowLabel : public QLabel {
protected:
void resizeEvent(QResizeEvent *) {
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();
}