improvements to JKQTPImage, which may now also own an image and can receive a copy to this internally owned object from an external instance

added example that shows how to plot a QImage
This commit is contained in:
jkriege2 2018-12-06 18:19:02 +01:00
parent 9e172915a6
commit 6b2ea6dc97
12 changed files with 208 additions and 8 deletions

View File

@ -13,6 +13,7 @@ SUBDIRS += jkqtplotterlib \
jkqtplotter_simpletest_barchart \ jkqtplotter_simpletest_barchart \
jkqtplotter_simpletest \ jkqtplotter_simpletest \
jkqtplotter_simpletest_speed \ jkqtplotter_simpletest_speed \
jkqtplotter_simpletest_rgbimageplot_qt \
jkqtplot_test jkqtplot_test
#jkqtplotter_simpletest_imageplot_nodatastore \ #jkqtplotter_simpletest_imageplot_nodatastore \
#jkqtplotter_simpletest_rgbimageplot_opencv \ #jkqtplotter_simpletest_rgbimageplot_opencv \
@ -72,3 +73,6 @@ jkqtplotter_simpletest_symbols_and_styles.depends = jkqtplotterlib
jkqtplotter_simpletest_speed.subdir = test/jkqtplotter_simpletest_speed jkqtplotter_simpletest_speed.subdir = test/jkqtplotter_simpletest_speed
jkqtplotter_simpletest_speed.depends = jkqtplotterlib jkqtplotter_simpletest_speed.depends = jkqtplotterlib
jkqtplotter_simpletest_rgbimageplot_qt.subdir = test/jkqtplotter_simpletest_rgbimageplot_qt
jkqtplotter_simpletest_rgbimageplot_qt.depends = jkqtplotterlib

View File

@ -37,6 +37,7 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
| Screenshot | Description | Notes | | Screenshot | Description | Notes |
|:-------------:| ------------- | ------------- | |:-------------:| ------------- | ------------- |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_rgbimageplot_qt_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_rgbimageplot_qt) | [`QImage` as a Graph](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_rgbimageplot_qt) | `JKQTPImage`<br/>`QImage` drawn onto a plot with arbitrary scaling) |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_imageplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot) | [Basic 1-channel Raw C Image Plot](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot) | `JKQTPColumnMathImage`<br/>image data copied from C-style row-major array into a single column of the internal datastore<br>Describes several options of the image plotting classes (different ways of color coding, what to do with data above/below the limits etc.) | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_imageplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot) | [Basic 1-channel Raw C Image Plot](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot) | `JKQTPColumnMathImage`<br/>image data copied from C-style row-major array into a single column of the internal datastore<br>Describes several options of the image plotting classes (different ways of color coding, what to do with data above/below the limits etc.) |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_imageplot_modifier_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot_modifier) | [Modifier-Feature of Image Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot_modifier) | `JKQTPColumnMathImage`<br/>image data copied from C-style row-major array into a single column of the internal datastore<br>Image is modified by a second image to display two data dimensions at the same time | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_imageplot_modifier_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot_modifier) | [Modifier-Feature of Image Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot_modifier) | `JKQTPColumnMathImage`<br/>image data copied from C-style row-major array into a single column of the internal datastore<br>Image is modified by a second image to display two data dimensions at the same time |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_imageplot_nodatastore_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot_nodatastore) | [Basic 1-channel Raw C Image Plot<br>without the internal datastore](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot_nodatastore) | `JKQTPMathImage`<br/>image data in a C-style row-major array, not using internal datastore | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_imageplot_nodatastore_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot_nodatastore) | [Basic 1-channel Raw C Image Plot<br>without the internal datastore](https://github.com/jkriege2/JKQtPlotter/tree/master/test/jkqtplotter_simpletest_imageplot_nodatastore) | `JKQTPMathImage`<br/>image data in a C-style row-major array, not using internal datastore |

View File

@ -155,33 +155,52 @@ void JKQTPImageBase::plotImage(JKQTPEnhancedPainter& painter, QImage& image, dou
JKQTPImage::JKQTPImage(JKQtBasePlotter *parent): JKQTPImage::JKQTPImage(JKQtBasePlotter *parent):
JKQTPImageBase(parent) JKQTPImageBase(parent), image_owned(false)
{ {
this->image=nullptr; this->image=nullptr;
createImageActions(); createImageActions();
} }
JKQTPImage::JKQTPImage(double x, double y, double width, double height, QImage* image, JKQtBasePlotter* parent): JKQTPImage::JKQTPImage(double x, double y, double width, double height, QImage* image, JKQtBasePlotter* parent):
JKQTPImageBase(x, y, width, height, parent) JKQTPImageBase(x, y, width, height, parent), image_owned(false)
{ {
this->image=image; this->image=image;
createImageActions(); createImageActions();
} }
JKQTPImage::JKQTPImage(JKQtPlotter *parent): JKQTPImage::JKQTPImage(JKQtPlotter *parent):
JKQTPImageBase(parent) JKQTPImageBase(parent), image_owned(false)
{ {
this->image=nullptr; this->image=nullptr;
createImageActions(); createImageActions();
} }
JKQTPImage::JKQTPImage(double x, double y, double width, double height, QImage* image, JKQtPlotter* parent): JKQTPImage::JKQTPImage(double x, double y, double width, double height, QImage* image, JKQtPlotter* parent):
JKQTPImageBase(x, y, width, height, parent) JKQTPImageBase(x, y, width, height, parent), image_owned(false)
{ {
this->image=image; this->image=image;
createImageActions(); createImageActions();
} }
JKQTPImage::JKQTPImage(double x, double y, double width, double height, const QImage &image, JKQtBasePlotter *parent):
JKQTPImageBase(x, y, width, height, parent), image_owned(true)
{
this->image=new QImage(image);
createImageActions();
}
JKQTPImage::JKQTPImage(double x, double y, double width, double height, const QImage &image, JKQtPlotter *parent):
JKQTPImageBase(x, y, width, height, parent), image_owned(true)
{
this->image=new QImage(image);
createImageActions();
}
JKQTPImage::~JKQTPImage()
{
clear_image();
}
void JKQTPImage::draw(JKQTPEnhancedPainter& painter) { void JKQTPImage::draw(JKQTPEnhancedPainter& painter) {
if (image) plotImage(painter, *image, x, y, width, height); if (image) plotImage(painter, *image, x, y, width, height);
@ -192,6 +211,31 @@ void JKQTPImage::drawKeyMarker(JKQTPEnhancedPainter &painter, QRectF &rect)
painter.drawImage(rect, QPixmap(":/JKQTPlotter/jkqtp_plot_image.png").toImage()); painter.drawImage(rect, QPixmap(":/JKQTPlotter/jkqtp_plot_image.png").toImage());
} }
void JKQTPImage::set_image(const QImage &image)
{
clear_image();
this->image=new QImage(image);
image_owned=true;
createImageActions();
}
void JKQTPImage::set_image(QImage *image)
{
clear_image();
this->image=image;
image_owned=false;
createImageActions();
}
void JKQTPImage::clear_image()
{
if (image_owned && image!=nullptr) {
delete image;
}
image=nullptr;
image_owned=false;
}
void JKQTPImage::createImageActions() void JKQTPImage::createImageActions()
{ {
actSaveImage=new QAction(tr("Save JKQTPImage ..."), this); actSaveImage=new QAction(tr("Save JKQTPImage ..."), this);

View File

@ -240,10 +240,16 @@ class LIB_EXPORT JKQTPImage: public JKQTPImageBase {
JKQTPImage(JKQtBasePlotter* parent=nullptr); JKQTPImage(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */ /** \brief class constructor */
JKQTPImage(JKQtPlotter* parent); JKQTPImage(JKQtPlotter* parent);
/** \brief class constructor */ /** \brief class constructor, which points to an external image (not owned by this object!!!) */
JKQTPImage(double x, double y, double width, double height, QImage* image, JKQtBasePlotter* parent=nullptr); JKQTPImage(double x, double y, double width, double height, QImage* image, JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */ /** \brief class constructor, which points to an external image (not owned by this object!!!) */
JKQTPImage(double x, double y, double width, double height, QImage* image, JKQtPlotter* parent); JKQTPImage(double x, double y, double width, double height, QImage* image, JKQtPlotter* parent);
/** \brief class constructor, which generates an internal image object, by copying \a image */
JKQTPImage(double x, double y, double width, double height, const QImage& image, JKQtBasePlotter* parent=nullptr);
/** \brief class constructor, which generates an internal image object, by copying \a image */
JKQTPImage(double x, double y, double width, double height, const QImage& image, JKQtPlotter* parent);
virtual ~JKQTPImage();
/** \brief plots the graph to the plotter object specified as parent */ /** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter); virtual void draw(JKQTPEnhancedPainter& painter);
@ -251,12 +257,21 @@ class LIB_EXPORT JKQTPImage: public JKQTPImageBase {
/** \brief plots a key marker inside the specified rectangle \a rect */ /** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect); virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect);
/** \brief copy an external image into an internally owned copy */
virtual void set_image(const QImage& image);
/** \brief set an external image to be plotted, the image will NOT BE OWNED by the graph-object */
virtual void set_image(QImage* image);
JKQTPGET_SET_MACRO(QImage*, image) /** \brief deletes the internal image */
void clear_image();
JKQTPGET_MACRO(QImage*, image)
protected: protected:
/** \brief the image to be plotted */ /** \brief the image to be plotted. This is freed by the destructor, iff \a image_owned is set to \c true (.e.g by QImage-copy-constructors) */
QImage* image; QImage* image;
/** \brief indicates that the image \a image is owned by this object (i.e. freed, when the object is destroyed) */
bool image_owned;
void createImageActions(); void createImageActions();

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,35 @@
[Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/)
# JKQtPlotter
## Simple RGB image plot, showing a 3-channel OpenCV cv::Mat
This project (see `./test/jkqtplotter_simpletest_rgbimageplot_qt/`) simply creates a JKQtPlotter widget (as a new window) and adds an image plot with an image taken from a QImage object.
The source code of the main application is (see `./test/jkqtplotter_simpletest_rgbimageplot_qt/jkqtplotter_simpletest_rgbimageplot_qt.cpp`). the main parts are:
```c++
// 2. now we open a BMP-file and load it into an OpenCV cv::Mat
QImage image(":/example.bmp");
// 3. create a graph (JKQTPImage) with a pointer to the QImage-object, generated above
JKQTPImage* graph=new JKQTPImage(&plot);
graph->set_title("");
// copy the image into the graph (optionally you could also give a pointer to a QImage,
// but then you need to ensure that the QImage is available as long as the JKQTPImage
// instace lives)
graph->set_image(image);
// where does the image start in the plot, given in plot-axis-coordinates (bottom-left corner)
graph->set_x(0);
graph->set_y(0);
// width/height of the image in plot coordinates
graph->set_width(image.width());
graph->set_height(image.height());
// 4. add the graphs to the plot, so it is actually displayed
plot.addGraph(graph);
```
The result looks like this:
![jkqtplotter_simpletest_imageplot](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_rgbimageplot_qt.png)
[Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

View File

@ -0,0 +1,65 @@
#include <QApplication>
#include <cmath>
#include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/jkqtpimageelements.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
JKQtPlotter plot;
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
plot.get_plotter()->set_useAntiAliasingForGraphs(true); // nicer (but slower) plotting
plot.get_plotter()->set_useAntiAliasingForSystem(true); // nicer (but slower) plotting
plot.get_plotter()->set_useAntiAliasingForText(true); // nicer (but slower) text rendering
JKQTPdatastore* ds=plot.getDatastore();
// 2. now we open a BMP-file and load it into an OpenCV cv::Mat
QImage image(":/example.bmp");
// 3. create a graph (JKQTPImage) with a pointer to the QImage-object, generated above
JKQTPImage* graph=new JKQTPImage(&plot);
graph->set_title("");
// copy the image into the graph (optionally you could also give a pointer to a QImage,
// but then you need to ensure that the QImage is available as long as the JKQTPImage
// instace lives)
graph->set_image(image);
// where does the image start in the plot, given in plot-axis-coordinates (bottom-left corner)
graph->set_x(0);
graph->set_y(0);
// width/height of the image in plot coordinates
graph->set_width(image.width());
graph->set_height(image.height());
// 5. add the graphs to the plot, so it is actually displayed
plot.addGraph(graph);
// 6. set axis labels
plot.get_xAxis()->set_axisLabel("x [pixels]");
plot.get_yAxis()->set_axisLabel("y [pixels]");
// 7. fix axis aspect ratio to width/height, so pixels are square
plot.get_plotter()->set_maintainAspectRatio(true);
plot.get_plotter()->set_aspectRatio(double(image.width())/double(image.height()));
// 8. autoscale the plot so the graph is contained
plot.zoomToFit();
// show plotter and make it a decent size
plot.show();
plot.resize(800,600);
plot.setWindowTitle("JKQTPImage");
return app.exec();
}

View File

@ -0,0 +1,23 @@
# source code for this simple demo
SOURCES += jkqtplotter_simpletest_rgbimageplot_qt.cpp
RESOURCES += jkqtplotter_simpletest_rgbimageplot_qt.qrc
# configure Qt
CONFIG += qt
QT += core gui xml svg
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
# output executable name
TARGET = jkqtplotter_simpletest_rgbimageplot_qt
# include JKQtPlotter source code
DEPENDPATH += . ../../lib
INCLUDEPATH += ../../lib
CONFIG (debug, debug|release):LIBS += -L../../lib/debug -ljkqtplotterlib
CONFIG (release):LIBS += -L../../lib/release -ljkqtplotterlib
# here you can activate some debug options
#DEFINES += SHOW_JKQTPLOTTER_DEBUG
#DEFINES += JKQTBP_AUTOTIMER

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>example.bmp</file>
</qresource>
</RCC>

View File

@ -0,0 +1,8 @@
TEMPLATE = subdirs
SUBDIRS += jkqtplotterlib jkqtplotter_simpletest_rgbimageplot_qt
jkqtplotterlib.file = ../../lib/jkqtplotterlib.pro
jkqtplotter_simpletest_rgbimageplot_qt.file=$$PWD/jkqtplotter_simpletest_rgbimageplot_qt.pro
jkqtplotter_simpletest_rgbimageplot_qt.depends = jkqtplotterlib