c++plotcimg

plotting a vector in C++ with Cimg


As a part of a project I am working right now I need to plot a vector in a style similar to MATLAB. After researching some of the possibilities I came across with CIMG which seemed easy enough to put into my program and just right for what I need. I am very new at C++ and never used Cimg before.

Following one of the examples provided in the guide I arrived at this program to plot the vector (in this case named ecg_r), my code looks like this:

// Read command line argument   cimg_usage("Simple plotter of ECG signal");
const char *const formula = cimg_option("-f", "x", "Formula to plot");
const float x0 = cimg_option("-x0", 0.0f, "Minimal X-value");
const float x1 = cimg_option("-x1", 20.0f, "Maximal X-value");
int sizeecg = ecg_r.size();
const int resolution = cimg_option("-r", sizeecg, "Plot resolution");
const unsigned int nresolution = resolution>1 ? resolution : sizeecg;
const unsigned int plot_type = cimg_option("-p", 1, "Plot type");
const unsigned int vertex_type = cimg_option("-v", 1, "Vertex type");

// Create plot data.
CImg<double> values(1, nresolution, 1, 1, 0);

const unsigned int r = nresolution - 1;

for (int i1 = 0; i1 < sizeecg; ++i1)
{
    double xtime = x0 + i1*(x1 - x0) / r;
    values(0, i1) = ecg_r.at(i1);
}  

// Display interactive plot window.
values.display_graph(formula, plot_type, vertex_type, "X-axis", x0, x1, "Y-axis");

the image I see in the display window created is exactly what I was expecting, but when I try to save the image in bmp using:

values.save_bmp("test.bmp");

the image is totally black, how can I save the image I am seeing in the display function? I spent yesterday afternoon going trough the documentation and couldn't find a clue.

Thank you in advance..

This is the MCVE of what I am trying to do, I want to be able to save in a bmp what I am seeing in the display window. Thank you

#include "CImg.h"
#include <vector>

using namespace cimg_library;

int main(int argc, char** const argv)
{
    cimg_usage("Simple plotter of mathematical formulas");
    const char *const formula = cimg_option("-f", "sin(x)", "Formula to    plot");
    const float x0 = cimg_option("-x0", -5.0f, "Minimal X-value");
    const float x1 = cimg_option("-x1", 5.0f, "Maximal X-value");
    const int resolution = cimg_option("-r", 5000, "Plot resolution");
    const unsigned int nresolution = resolution>1 ? resolution : 5000;
    const unsigned int plot_type = cimg_option("-p", 1, "Plot type");
    const unsigned int vertex_type = cimg_option("-v", 1, "Vertex type");

    // Create plot data.
    CImg<double> values(1, nresolution, 1, 1, 0);

    const unsigned int r = nresolution - 1;

    for (int i1 = 0; i1 < resolution; ++i1)
    {
        double xtime = x0 + i1*(x1 - x0) / r;
        values(0, i1) = sin(xtime);
    }

    CImg<double> values2;
    values2 = values.display_graph(formula, plot_type, vertex_type, "X Axis", x0, x1, "Y Axis");
    values.normalize(0, 255);
    values.save_bmp("test.bmp");

}

Solution

  • Update Answer

    You were completely wrong, Mark! You can take a snapshot of the plot like this.

    #include "CImg.h"
    #include <vector>
    
    using namespace cimg_library;
    
    int main(int argc, char** const argv)
    {
        cimg_usage("Simple plotter of mathematical formulas");
        const char *const formula = cimg_option("-f", "sin(x)", "Formula to    plot");
        const float x0 = cimg_option("-x0", -5.0f, "Minimal X-value");
        const float x1 = cimg_option("-x1", 5.0f, "Maximal X-value");
        const int resolution = cimg_option("-r", 5000, "Plot resolution");
        const unsigned int nresolution = resolution>1 ? resolution : 5000;
        const unsigned int plot_type = cimg_option("-p", 1, "Plot type");
        const unsigned int vertex_type = cimg_option("-v", 1, "Vertex type");
    
        // Create plot data.
        CImg<double> values(1, nresolution, 1, 1, 0);
    
        const unsigned int r = nresolution - 1;
    
        for (int i1 = 0; i1 < resolution; ++i1)
        {
            double xtime = x0 + i1*(x1 - x0) / r;
            values(0, i1) = sin(xtime);
        }
    
        CImgDisplay disp;
        CImg<double> values2;
        values.display_graph(disp, plot_type, vertex_type, "X Axis", x0, x1, "Y Axis");
        disp.snapshot(values2);
        values2.save_bmp("result.bmp");
    }
    

    Original Answer

    I am happy to be told I am completely wrong if anyone knows better, and shows us the way, but I don't believe that CImg will give you the plot as a bitmap file like you want.

    So, I had a play with doing it using gnuplot. Your image looks like this on the screen:

    enter image description here

    So, as a rough approximation, if you make a few edits to your code like this:

    #include "CImg.h"
    #include <iostream>
    #include <fstream>
    #include <vector>
    
    using namespace cimg_library;
    using namespace std;
    
    int main(int argc, char** const argv)
    {
        cimg_usage("Simple plotter of mathematical formulas");
        const char *const formula = cimg_option("-f", "sin(x)", "Formula to    plot");
        const float x0 = cimg_option("-x0", -5.0f, "Minimal X-value");
        const float x1 = cimg_option("-x1", 5.0f, "Maximal X-value");
        const int resolution = cimg_option("-r", 5000, "Plot resolution");
        const unsigned int nresolution = resolution>1 ? resolution : 5000;
        const unsigned int plot_type = cimg_option("-p", 1, "Plot type");
        const unsigned int vertex_type = cimg_option("-v", 1, "Vertex type");
    
        // Create plot data.
        CImg<double> values(1, nresolution, 1, 1, 0);
    
        const unsigned int r = nresolution - 1;
    
        ofstream data;
        data.open("plot.dat");
    
        for (int i1 = 0; i1 < resolution; ++i1)
        {
            double xtime = x0 + i1*(x1 - x0) / r;
            values(0, i1) = sin(xtime);
            double x=x0 + i1*(x1-x0)/nresolution;
            data << x << " " << values(0,i1) << endl;
        }
        data.close();
    
        CImg<double> values2;
        values2 = values.display_graph(formula, plot_type, vertex_type, "X Axis", x0, x1, "Y Axis");
        cout << "set terminal png size 900,600 enhanced font \"Helvetica,20\"" << endl;
        cout << "set output 'out.png'" << endl;
        cout << "set xrange [" << x0 << ":" << x1 << "]" << endl;
        cout << "set grid" << endl;
        cout << "set ylabel 'Y Axis'" << endl;
        cout << "set xlabel 'X Axis'" << endl;
        cout << "plot \"plot.dat\" with linespoint lc 4" << endl;
    }
    

    and then run it like this:

    ./yourProgram | gnuplot
    

    you will get this:

    enter image description here