Back to Richel Bilderbeek's homepage.
Back to Richel Bilderbeek's Code Snippets.
For a value from 0.0 to 1.0, return three unsigned chars that when aligned show more or less a rainbow-like gradient (but for the real rainbow gradient see the Rainbow function), like the second row of the picture here. The full CLX code to obtain that picture is shown below the function, for those interested.
Code in plain text can be found here.
#include <cassert>
#include <cmath>
#include <algorithm>
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRgbGradient.htm
void RgbGradient(
const double x,
unsigned char& r,
unsigned char& g,
unsigned char& b)
{
r = GetRed(x);
g = GetGreen(x);
b = GetBlue(x);
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRgbGradient.htm
unsigned char GetRed(const double x)
{
assert( x >= 0.0 && x < 1.0);
const double f = std::max(0.0,
(x < 0.5
? std::cos(x * 1.5 * M_PI)
: -std::sin(x * 1.5 * M_PI)
) );
assert( f >= 0.0);
assert( f <= 1.0);
const double y = 255.0 * f;
assert( static_cast<int>(y) < 256 );
return static_cast<unsigned char>(y);
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRgbGradient.htm
unsigned char GetGreen(const double x)
{
assert( x >= 0.0 && x < 1.0);
const double f = std::max(0.0, std::sin( x * 1.5 * M_PI ) );
assert( f >= 0.0);
assert( f <= 1.0);
const double y = 255.0 * f;
assert( static_cast<int>(y) < 256 );
return static_cast<unsigned char>(y);
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRgbGradient.htm
unsigned char GetBlue(const double x)
{
assert( x >= 0.0 && x < 1.0);
const double f = std::max(0.0, -std::cos( x * 1.5 * M_PI ) );
assert( f >= 0.0);
assert( f <= 1.0);
const double y = 255.0 * f;
assert( static_cast<int>(y) < 256 );
return static_cast<unsigned char>(y);
}
//---------------------------------------------------------------------------
All you need to do at design-time is add a TImage and load a 24-bit or 32-bit bitmap in it.
It uses the SetPixel function, which I also shown for a VCL application. Just changing SetPixel to its VCL brother will get this code working under VCL.
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRgbGradient.htm
//---------------------------------------------------------------------------
#ifndef UnitRainbowH
#define UnitRainbowH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <QControls.hpp>
#include <QStdCtrls.hpp>
#include <QForms.hpp>
#include <QExtCtrls.hpp>
#include <QGraphics.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TImage *Image1;
void __fastcall FormResize(TObject *Sender);
void __fastcall FormShow(TObject *Sender);
private : // User declarations
public : // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
unsigned char GetRed(const double x);
unsigned char GetGreen(const double x);
unsigned char GetBlue(const double x);
void Rainbow(
const double x,
unsigned char& r,
unsigned char& g,
unsigned char& b);
TColor Rainbow(const double x);
void RgbGradient(
const double x,
unsigned char& r,
unsigned char& g,
unsigned char& b);
TColor RgbGradient(const double x);
void SetPixel(TImage * const image, const int x, const int y, const TColor& color);
#endif
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRgbGradient.htm
//---------------------------------------------------------------------------
#include <clx.h>
#pragma hdrstop
#include "UnitRainbow.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.xfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
#include <algorithm>
#include <cassert>
#include <cmath>
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Image1->Picture->Bitmap->Height = 5;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
Resize();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
const int width = ClientWidth;
Image1->Picture->Bitmap->Width = width;
for (int i=0; i!=width; ++i)
{
const double f = static_cast<double>(i) / static_cast<double>(width);
SetPixel(Image1,i,0,Rainbow(f));
SetPixel(Image1,i,1,RgbGradient(f));
SetPixel(Image1,i,2,static_cast<TColor>(RGB( GetRed(f), 0 , 0 ) ) );
SetPixel(Image1,i,3,static_cast<TColor>(RGB( 0, GetGreen(f) , 0 ) ) );
SetPixel(Image1,i,4,static_cast<TColor>(RGB( 0, 0 , GetBlue(f) ) ) );
}
Canvas->StretchDraw(this->GetClientRect(), Image1->Picture->Graphic);
}
//---------------------------------------------------------------------------
void Rainbow(
const double x,
unsigned char& r,
unsigned char& g,
unsigned char& b)
{
const int r0 = GetRed(x);
const int g0 = GetGreen(x);
const int b0 = GetBlue(x);
const int max = std::max(r0, std::max(g0,b0));
assert(max!=0);
r = 255.0 * static_cast<double>(r0) / static_cast<double>(max);
g = 255.0 * static_cast<double>(g0) / static_cast<double>(max);
b = 255.0 * static_cast<double>(b0) / static_cast<double>(max);
}
//---------------------------------------------------------------------------
TColor Rainbow(const double x)
{
unsigned char r = 0;
unsigned char g = 0;
unsigned char b = 0;
Rainbow(x,r,g,b);
return static_cast<TColor>(RGB(r,g,b));
}
//---------------------------------------------------------------------------
void RgbGradient(
const double x,
unsigned char& r,
unsigned char& g,
unsigned char& b)
{
r = GetRed(x);
g = GetGreen(x);
b = GetBlue(x);
}
//---------------------------------------------------------------------------
TColor RgbGradient(const double x)
{
unsigned char r = 0;
unsigned char g = 0;
unsigned char b = 0;
RgbGradient(x,r,g,b);
return static_cast<TColor>(RGB(r,g,b));
}
//---------------------------------------------------------------------------
unsigned char GetRed(const double x)
{
assert( x >= 0.0 && x < 1.0);
const double f = std::max(0.0,
(x < 0.5
? std::cos(x * 1.5 * M_PI)
: -std::sin(x * 1.5 * M_PI)
) );
assert( f >= 0.0);
assert( f <= 1.0);
const double y = 255.0 * f;
assert( static_cast<int>(y) < 256 );
return static_cast<unsigned char>(y);
}
//---------------------------------------------------------------------------
unsigned char GetGreen(const double x)
{
assert( x >= 0.0 && x < 1.0);
const double f = std::max(0.0, std::sin( x * 1.5 * M_PI ) );
assert( f >= 0.0);
assert( f <= 1.0);
const double y = 255.0 * f;
assert( static_cast<int>(y) < 256 );
return static_cast<unsigned char>(y);
}
//---------------------------------------------------------------------------
unsigned char GetBlue(const double x)
{
assert( x >= 0.0 && x < 1.0);
const double f = std::max(0.0, -std::cos( x * 1.5 * M_PI ) );
assert( f >= 0.0);
assert( f <= 1.0);
const double y = 255.0 * f;
assert( static_cast<int>(y) < 256 );
return static_cast<unsigned char>(y);
}
//---------------------------------------------------------------------------
void SetPixel(
TImage * const image,
const int x,
const int y,
const TColor& color)
{
assert(image!=0 && "Image is NULL");
assert(image->Picture->Bitmap!=0 && "Bitmap is NULL");
assert(image->Picture->Bitmap->PixelFormat == pf32bit && "Bitmap must be 32 bit");
assert( x >= 0 && "x coordinat is below zero");
assert( y >= 0 && "y coordinat is below zero");
assert( x < image->Picture->Bitmap->Width && "x coordinat is beyond image width");
assert( y < image->Picture->Bitmap->Height && "y coordinat is beyond image height");
static_cast<unsigned char*>(image->Picture->Bitmap->ScanLine[y])[x*4+2] = GetRValue(color);
static_cast<unsigned char*>(image->Picture->Bitmap->ScanLine[y])[x*4+1] = GetGValue(color);
static_cast<unsigned char*>(image->Picture->Bitmap->ScanLine[y])[x*4+0] = GetBValue(color);
}
//---------------------------------------------------------------------------
Back to Richel Bilderbeek's Code Snippets.
Back to Richel Bilderbeek's homepage.