 MelMed -4 years ago 314
C++ Question

# How to render a rainbow spectrum?

I have the need to programmatically generate the approximation of a rainbow spectrum, in a rectangular image, as shown below: I know how to draw the pixmap, what I'm looking for is how to generate the values of the colors. Kuba Ober
Answer Source

You need to read this paper. Seriously.

Other than that, all it could take is to iterate through hues 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's not physically accurate at all, but maybe it would do.

Otherwise, you need a slightly more complex code that very simplistically approximates the paper cited above. ``````#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;
QColor toColor(qreal factor) const {
qreal const gamma = 0.8;
int ci;
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, ci, ci);
}
} 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); ++ 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();
}
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download
Latest added