JKQTPlotter trunk/v5.0.0
an extensive Qt5+Qt6 Plotter framework (including a feature-richt plotter widget, a speed-optimized, but limited variant and a LaTeX equation renderer!), written fully in C/C++ and without external dependencies
Loading...
Searching...
No Matches
Example (JKQTPlotter): Image Plots with Custom Palettes

This project (see ./examples/imageplot_userpal/) demonstrates how to use user-defined color-palettes for image plots. The source code of the main application is (see imageplot_userpal.cpp).

Build Palettes Programmatically

JKQTPlotter comes with a large set of predefined color palettes, which are enumerated in JKQTPMathImageColorPalette. In addition you can build your own palettes as simple lookup-tables of type JKQTPImageTools::LUTType (which is a QVector<QRgb>) and register them in the system (using JKQTPImageTools::registerPalette()). There are several options available for building such a palette:

  1. you can simply define a palette from single colors:
QColor("blue").rgb(),
QColor("green").rgb(),
QColor("white").rgb(),
QColor("yellow").rgb(),
QColor("red").rgb(),
QColor("red").rgb()
};
QVector< QRgb > LUTType
Datatype to store lookup-tables used to map data values (scales to 0..size-1) onto RGB-colors.
Definition jkqtpbasicimagetools.h:378

Such a palette will have exactly as many entries, as you specified: palsimple

  1. Alternatively you can build a palette from a set of colors with assocziated positions on the values axis (typically 0..1 as these are in any way later mapped to the actual data range):
QList<QPair<double, QRgb> > palsteps2;
palsteps2<<qMakePair<double, QRgb>(0.00, QColor("blue").rgba());
palsteps2<<qMakePair<double, QRgb>(0.05, QColor("green").rgba());
palsteps2<<qMakePair<double, QRgb>(0.45, QColor("white").rgba());
palsteps2<<qMakePair<double, QRgb>(0.55, QColor("yellow").rgba());
palsteps2<<qMakePair<double, QRgb>(0.95, QColor("red").rgba());
palsteps2<<qMakePair<double, QRgb>(1.00, QColor("red").rgba());
JKQTPImageTools::LUTType JKQTCOMMON_LIB_EXPORT JKQTPBuildColorPaletteLUT(JKQTPPaletteList items, int lut_size=JKQTPImageTools::LUTSIZE)
like JKQTPBuildColorPaletteLUTSorted(), but sorts items before processing it!
static JKQTCOMMON_LIB_EXPORT const int LUTSIZE
size of the lookup tables used by JKQTFPimagePlot_array2image()
Definition jkqtpbasicimagetools.h:386

Such a palette will have JKQTPImageTools::LUTSIZE (=255) entries and the colors are not spaced equally: palsteps2

  1. The palettes so far had steps, but you can also give a series of nodes with positions (on the value axis) and RGB-colors there (e.g. palsteps2 above) but then linearly interpolate between these by calling:
JKQTPImageTools::LUTType JKQTCOMMON_LIB_EXPORT JKQTPBuildColorPaletteLUTLinInterpolate(JKQTPPaletteList items, int lut_size=JKQTPImageTools::LUTSIZE)
like JKQTPBuildColorPaletteLUTLinInterpolateSorted(), but sorts items before processing it!
The resulting LUT is then:   ![imageplot_userpal_2_linear](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/imageplot_userpal_2_linear.png)
  1. Finally there is a second way of linear interpolation, where linear segments are given for the three color channels separately. To use such a definition, call JKQTPBuildColorPaletteLUTLinSegments instead (see documenttaion there).

For each of these options, you finally call JKQTPImageTools::registerPalette() to make them known to the system:

int userpalette_id=JKQTPImageTools::registerPalette("userpal_computer_readable_name", pal, QObject::tr("User Palette Human-Readable Name"));
static JKQTCOMMON_LIB_EXPORT int registerPalette(const QString &name, const LUTType &paletteLut, const QString &nameT=QString())
registers a new LUT defined by paletteLut and with the given name (computer-readable) for later use,...

This function returns an integer, which you can cast to a JKQTPMathImageColorPalette to use your new palette:

// ...
graph->setColorPalette(static_cast<JKQTPMathImageColorPalette>(userpalette_id));
void setColorPalette(int pal)
palette for plotting an image
class to plot an image from an 2-dimensional array of values stored in a column of the datastore
Definition jkqtpimage.h:771
JKQTPMathImageColorPalette
available palettes for coloring an image
Definition jkqtpbasicimagetools.h:84

Load Palettes from Files

In addition to building palettes/LUTs programmatically, as shown above, you can simply load palettes from files using:

JKQTPImageTools::registerPalettesFromFile(":/usercolorpalettes/palettes/All_idl_cmaps.xml");
static JKQTCOMMON_LIB_EXPORT QVector< int > registerPalettesFromFile(const QString &filename, bool interpolatePalette=false)
loads all palettes defined in the given palette files filename into global_jkqtpimagetools_userluts a...

This function may load different file formats (discriminated by the extension):

  1. XML-files (extension .xml) may contain one or more color palettes and should be formatted as follows:
<ColorMap name="PALETTENAME" space="RGB">
<Point x="scalar" r="RED" g="GREEN" b="BLUE"/>
<Point x="scalar" r="RED" g="GREEN" b="BLUE"/>
...
</ColorMap>

or with several palettes in one file:

<ColorMaps>
<ColorMap name="PALETTENAME" space="RGB">
<Point x="scalar" r="RED" g="GREEN" b="BLUE"/>
<Point x="scalar" r="RED" g="GREEN" b="BLUE"/>
...
</ColorMap>
<ColorMap name="PALETTENAME" space="RGB">
<Point x="scalar" r="RED" g="GREEN" b="BLUE"/>
<Point x="scalar" r="RED" g="GREEN" b="BLUE"/>
...
</ColorMap>
...
</ColorMaps>
  1. CSV-files (extensions .csv, .rgb, .pal) are simply a list of 3 or 4 comma-separated values:
red, green, blue
red, green, blue
...

or:

scalar, red, green, blue
scalar, red, green, blue
...

By default the palettes are simply read from the files as raw data. Alternatively you can linearly interpolate between the nodes in the file by calling

JKQTPImageTools::registerPalettesFromFile(":/usercolorpalettes/palettes/All_idl_cmaps.xml", true);

Examples for such palette files can be found here: /examples/imageplot_userpal/palettes/

Main Program of the Example (GUI)

The rest of the example program imageplot_userpal.cpp just generates a 2D function plot as a color-map and displays it ...

// 1. create a window containing a plotter and a combobox to select the color palette
// ... and get a pointer to the internal datastore (for convenience)
QWidget win;
QVBoxLayout* lay=new QVBoxLayout();
win.setLayout(lay);
lay->addWidget(cmbPalette);
JKQTPlotter* plot=new JKQTPlotter(&win);
lay->addWidget(plot);
// 2. now we create data for the charts (taken from https://commons.wikimedia.org/wiki/File:Energiemix_Deutschland.svg)
const int NX=100; // image dimension in x-direction [pixels]
const int NY=NX; // image dimension in x-direction [pixels]
const double dx=0.6e-2; // size of a pixel in x-direction [micrometers]
const double dy=0.6e-2; // size of a pixel in x-direction [micrometers]
// 2.1 Parameters for airy disk plot (see https://en.wikipedia.org/wiki/Airy_disk)
double NA=1.1; // numerical aperture of lens
double wavelength=488e-3; // wavelength of the light [micrometers]
// 2.2 calculate image of airy disk in a row-major array and immediately store the values
// in a new image column cAiryDisk
size_t cAiryDisk=ds->addCalculatedImageColumn(NX, NY, [&](size_t ix, size_t iy)->double {
double x=static_cast<double>(static_cast<int>(ix)-NX/2)*dx;
double y=static_cast<double>(static_cast<int>(iy)-NY/2)*dy;
const double r=sqrt(x*x+y*y);
const double v=2.0*M_PI*NA*r/wavelength;
if (ix==NX/2 && iy==NY/2) return 1.0;
else return pow(2.0*j1(v)/v, 2);
}, "imagedata");
// 3. create a graph (JKQTPColumnMathImage) with the column created above as data
// The data is color-coded with the color-palette JKQTPMathImageMATLAB
// the converted range of data is determined automatically because setAutoImageRange(true)
graph->setTitle("default MATLAB palette");
// set the image column with the data
graph->setImageColumn(cAiryDisk);
// where does the image start in the plot, given in plot-axis-coordinates (bottom-left corner)
graph->setX(0);
graph->setY(0);
// width and height of the image in plot-axis-coordinates
graph->setWidth(1);
graph->setHeight(1);
// color-map is taken from cmbPalette
cmbPalette->setCurrentColorPalette(graph->getPalette());
// 4. add the graphs to the plot, so it is actually displayed
plot->addGraph(graph);
// 5. fix axis and plot aspect ratio to 1
// 6. autoscale the plot so the graph is contained
plot->zoomToFit();
// 8. show plotter and make it a decent size
win.show();
win.resize(500,550);
win.setWindowTitle("JKQTPColumnMathImage, User Palettes");
void setMaintainAspectRatio(bool value)
en-/disables the maintaining of the data aspect ratio
void setMaintainAxisAspectRatio(bool value)
en-/disables the maintaining of the axis aspect ratio
virtual void setImageColumn(int __value)
column containing the displayed image
This class manages data columns (with entries of type double ), used by JKQTPlotter/JKQTBasePlotter t...
Definition jkqtpdatastorage.h:282
size_t addCalculatedImageColumn(size_t cols, size_t rows, const std::function< double(size_t, size_t)> &f, const QString &name=QString(""))
add an image column with width cols and height rows (i.e. rows * cols entries), that is calculated by...
void setHeight(double __value)
height of image
void setX(double __value)
x coordinate of lower left corner
void setWidth(double __value)
width of image
void setY(double __value)
y coordinate of lower left corner
class to plot an image from an 2-dimensional array of values
Definition jkqtpcomboboxes.h:39
void setCurrentColorPalette(JKQTPMathImageColorPalette palette)
void currentPaletteChanged(JKQTPMathImageColorPalette palette)
virtual void setTitle(const QString &title) override
sets the title of the plot (for display in key!).
plotter widget for scientific plots (uses JKQTBasePlotter to do the actual drawing)
Definition jkqtplotter.h:364
void zoomToFit(bool zoomX=true, bool zoomY=true, bool includeX0=false, bool includeY0=false, double scaleX=1.05, double scaleY=1.05)
this method zooms the graph so that all plotted datapoints are visible.
Definition jkqtplotter.h:1039
JKQTBasePlotter * getPlotter()
returns the JKQTBasePlotter object internally used for plotting
Definition jkqtplotter.h:404
void addGraph(JKQTPPlotElement *gr)
Definition jkqtplotter.h:784
JKQTPDatastore * getDatastore()
returns a pointer to the datastore used by this object
Definition jkqtplotter.h:611
void redrawPlot()
update the plot and the overlays

...along with a JKQTPMathImageColorPaletteComboBox to select a colormap and redraw the plot:

It also adds two QPushButtons that allow to save the current or all registered color-palettes to small PNG-Files:

QPushButton* btnSavePal=new QPushButton(QObject::tr("save current palette"), &win);
btnSavePal->connect(btnSavePal, &QPushButton::clicked, [&]() {
});
lay->addWidget(btnSavePal);
QPushButton* btnSaveAllPal=new QPushButton(QObject::tr("save all palettes"), &win);
btnSavePal->connect(btnSaveAllPal, &QPushButton::clicked, [&]() {
for (auto pn: JKQTPImageTools::getPredefinedPalettes()) {
}
});
lay->addWidget(btnSaveAllPal);
JKQTPMathImageColorPalette currentColorPalette() const
tool structure that summarizes several static properties of JKQTPlotters palette system,...
Definition jkqtpbasicimagetools.h:375
static JKQTCOMMON_LIB_EXPORT QString JKQTPMathImageColorPalette2String(JKQTPMathImageColorPalette p)
convert the palette p to a machine-readable string
static JKQTCOMMON_LIB_EXPORT JKQTPMathImageColorPalette String2JKQTPMathImageColorPalette(const QString &p)
convert the palette name p to JKQTPMathImageColorPalette (compatible with JKQTPImageTools::String2JKQ...
static JKQTCOMMON_LIB_EXPORT QImage GetPaletteImage(int i, int width)
generates a QImage with width width and height 1 for the i-th color palette (i is based on the list r...

The whole program looks like this:

imageplot_userpal_program