mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-11-15 18:15:52 +08:00
2854 lines
123 KiB
C++
2854 lines
123 KiB
C++
/*
|
|
Copyright (c) 2008-2015 Jan W. Krieger & Sebastian Isbaner (contour plot), German Cancer Research Center
|
|
|
|
last modification: $LastChangedDate$ (revision $Rev$)
|
|
|
|
This software is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License (LGPL) as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License (LGPL) for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License (LGPL)
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#include "jkqtpimageelements.h"
|
|
#include "jkqtpbaseplotter.h"
|
|
#include "jkqtpimagetools.h"
|
|
#include "jkqtptools.h"
|
|
#include <QDebug>
|
|
#include <QImageWriter>
|
|
#include <QFileDialog>
|
|
#include <QFileInfo>
|
|
#include <QApplication>
|
|
#include <QClipboard>
|
|
|
|
#define PALETTE_ICON_WIDTH 64
|
|
#define PALETTE_IMAGEICON_HEIGHT 64
|
|
|
|
|
|
JKQTPImageBase::JKQTPImageBase(double x, double y, double width, double height, JKQtBasePlotter* parent):
|
|
JKQTPgraph(parent)
|
|
{
|
|
title="";
|
|
this->width=width;
|
|
this->height=height;
|
|
this->x=x;
|
|
this->y=y;
|
|
}
|
|
|
|
JKQTPImageBase::JKQTPImageBase(JKQtBasePlotter *parent):
|
|
JKQTPgraph(parent)
|
|
{
|
|
title="";
|
|
this->width=0;
|
|
this->height=0;
|
|
this->x=0;
|
|
this->y=0;
|
|
}
|
|
|
|
void JKQTPImageBase::drawKeyMarker(JKQTPEnhancedPainter& /*painter*/, QRectF& /*rect*/) {
|
|
|
|
}
|
|
|
|
bool JKQTPImageBase::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
|
|
minx=x;
|
|
maxx=x+width;
|
|
smallestGreaterZero=0;
|
|
if (x>10.0*DBL_MIN) smallestGreaterZero=x;
|
|
return true;
|
|
}
|
|
|
|
bool JKQTPImageBase::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
|
|
miny=y;
|
|
maxy=y+height;
|
|
smallestGreaterZero=0;
|
|
if (y>10.0*DBL_MIN) smallestGreaterZero=y;
|
|
return true;
|
|
}
|
|
|
|
QColor JKQTPImageBase::getKeyLabelColor() {
|
|
return QColor("black");
|
|
}
|
|
|
|
void JKQTPImageBase::plotImage(JKQTPEnhancedPainter& painter, QImage& image, double x, double y, double width, double height) {
|
|
if ((!JKQTPIsOKFloat(x))||(!JKQTPIsOKFloat(y))||(!JKQTPIsOKFloat(width))||(!JKQTPIsOKFloat(height))||(width<=0) || (height<=0) || image.isNull() || (image.width()<=0) || (image.height()<=0)) {
|
|
return;
|
|
}
|
|
painter.save();
|
|
|
|
double xmin=parent->getXMin();
|
|
double xmax=parent->getXMax();
|
|
double ymin=parent->getYMin();
|
|
double ymax=parent->getYMax();
|
|
QPointF pp1=transform(xmin,ymax);
|
|
QPointF pp2=transform(xmax,ymin);
|
|
QRectF pr(pp1, pp2);
|
|
|
|
QPointF p1=transform(x,y+height);
|
|
QPointF p2=transform(x+width,y);
|
|
QRectF r(p1, p2);
|
|
if (image.width()>0 && image.height()>0 && !image.isNull()) {
|
|
if (r.width()<2*pr.width() && r.height()<2*pr.height()) {
|
|
//painter.drawImage(QRectF(p1.x(), p2.y(), fabs(p2.x()-p1.x()), fabs(p2.y()-p1.y())), image);
|
|
painter.drawImage(QPoint(p1.x(), p1.y()), image.scaled(QSize(fabs(p2.x()-p1.x()), fabs(p2.y()-p1.y())), Qt::IgnoreAspectRatio, Qt::FastTransformation));
|
|
//qDebug()<<"\nimage.size = "<<image.size() <<" SIMPLE!";
|
|
} else {
|
|
double pixwidth=fabs(p2.x()-p1.x())/(double)image.width();
|
|
double pixheight=fabs(p2.y()-p1.y())/(double)image.height();
|
|
//qDebug()<<"\nimage.size = "<<image.size();
|
|
//qDebug()<<"size = "<<QSizeF(width, height);
|
|
//qDebug()<<"pixsize = "<<QSizeF(pixwidth, pixheight);
|
|
//qDebug()<<"p1 = "<<p1<< " p2 = "<<p2;
|
|
//qDebug()<<"pp1 = "<<pp1<<" pp2 = "<<pp2;
|
|
QPoint ps1(floor((pp1.x()-p1.x())/pixwidth), floor((pp1.y()-p1.y())/pixheight));
|
|
QPoint ps2=ps1+QPoint(ceil(fabs(pp2.x()-pp1.x())/pixwidth), ceil(fabs(pp2.y()-pp1.y())/pixheight));
|
|
if (ps1.x()<0) ps1.setX(0);
|
|
if (ps1.y()<0) ps1.setY(0);
|
|
if (ps2.x()>image.width()) ps2.setX(image.width());
|
|
if (ps2.y()>image.height()) ps2.setY(image.height());
|
|
QRect source(ps1, ps2);
|
|
QRectF target(p1.x()+ps1.x()*pixwidth, p1.y()+ps1.y()*pixheight, source.width()*pixwidth, source.height()*pixheight);
|
|
//qDebug()<<"source = "<<source;
|
|
//qDebug()<<"target = "<<target;
|
|
painter.drawImage(target, image, source);
|
|
}
|
|
}
|
|
painter.restore();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JKQTPImage::JKQTPImage(double x, double y, double width, double height, QImage* image, JKQtBasePlotter* parent):
|
|
JKQTPImageBase(x, y, width, height, parent)
|
|
{
|
|
actSaveImage=new QAction(tr("Save JKQTPImage ..."), this);
|
|
connect(actSaveImage, SIGNAL(triggered()), this, SLOT(saveImagePlotAsImage()));
|
|
actCopyImage=new QAction(tr("Copy JKQTPOverlayImage ..."), this);
|
|
connect(actCopyImage, SIGNAL(triggered()), this, SLOT(copyImagePlotAsImage()));
|
|
|
|
this->image=image;
|
|
}
|
|
|
|
|
|
void JKQTPImage::draw(JKQTPEnhancedPainter& painter) {
|
|
if (image) plotImage(painter, *image, x, y, width, height);
|
|
}
|
|
|
|
void JKQTPImage::drawKeyMarker(JKQTPEnhancedPainter &painter, QRectF &rect)
|
|
{
|
|
painter.drawImage(rect, QPixmap(":/jkqtp_plot_image.png").toImage());
|
|
}
|
|
|
|
void JKQTPImage::setParent(JKQtBasePlotter *parent)
|
|
{
|
|
if (this->parent) {
|
|
this->parent->deregisterAdditionalAction(actSaveImage);
|
|
this->parent->deregisterAdditionalAction(actCopyImage);
|
|
}
|
|
JKQTPImageBase::setParent(parent);
|
|
if (parent) {
|
|
parent->registerAdditionalAction(tr("Save Image Plot Images ..."), actSaveImage);
|
|
parent->registerAdditionalAction(tr("Copy Image Plot Images ..."), actCopyImage);
|
|
}
|
|
actSaveImage->setEnabled(parent);
|
|
actCopyImage->setEnabled(parent);
|
|
}
|
|
|
|
void JKQTPImage::set_title(const typedef_set_title &title)
|
|
{
|
|
JKQTPImageBase::set_title(title);
|
|
QString t=title;
|
|
if (t.isEmpty()) t="JKQTPImage";
|
|
actSaveImage->setText(tr("Save %1 ...").arg(t));
|
|
actCopyImage->setText(tr("Copy %1 ...").arg(t));
|
|
}
|
|
|
|
void JKQTPImage::saveImagePlotAsImage(const QString &filename, const QByteArray &outputFormat)
|
|
{
|
|
if (parent && image) {
|
|
parent->loadUserSettings();
|
|
QString currentSaveDirectory=parent->get_currentSaveDirectory();
|
|
QString currentFileFormat=parent->get_currentFileFormat();
|
|
QString fn=filename;
|
|
QStringList filt;
|
|
QList<QByteArray> writerformats=QImageWriter::supportedImageFormats();
|
|
for (int i=0; i<writerformats.size(); i++) {
|
|
filt<<QString("%1 Image (*.%2)").arg(QString(writerformats[i]).toUpper()).arg(QString(writerformats[i].toLower()));
|
|
}
|
|
QString selFormat;
|
|
if (fn.isEmpty()) {
|
|
selFormat=currentFileFormat;
|
|
fn = QFileDialog::getSaveFileName(NULL, tr("Save Image Plot As Image ..."),
|
|
currentSaveDirectory,
|
|
filt.join(";;"), &selFormat);
|
|
if (!fn.isEmpty()) currentSaveDirectory=QFileInfo(fn).absolutePath();
|
|
}
|
|
|
|
parent->set_currentFileFormat(currentFileFormat);
|
|
parent->set_currentSaveDirectory(currentSaveDirectory);
|
|
parent->saveUserSettings();
|
|
if (!fn.isEmpty()) {
|
|
int filtID=filt.indexOf(selFormat);
|
|
QString form="NONE";
|
|
if (filtID>=0 && filtID<writerformats.size()) {
|
|
form=writerformats[filtID];
|
|
}
|
|
if (outputFormat.size()>0) {
|
|
form =outputFormat;
|
|
}
|
|
|
|
if (form=="NONE") image->save(fn);
|
|
else image->save(fn, form.toLatin1().data());
|
|
}
|
|
}
|
|
}
|
|
|
|
void JKQTPImage::copyImagePlotAsImage()
|
|
{
|
|
QClipboard* clip=QApplication::clipboard();
|
|
if (clip && image) {
|
|
clip->setImage(*image);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JKQTPMathImageBase::JKQTPMathImageBase(double x, double y, double width, double height, DataType datatype, void* data, uint32_t Nx, uint32_t Ny, JKQtBasePlotter* parent):
|
|
JKQTPImageBase(x, y, width, height, parent)
|
|
{
|
|
this->data=data;
|
|
this->datatype=datatype;
|
|
this->Nx=Nx;
|
|
this->Ny=Ny;
|
|
dataModifier=NULL;
|
|
datatypeModifier=DoubleArray;
|
|
modifierMode=ModifyNone;
|
|
}
|
|
|
|
void JKQTPMathImageBase::drawKeyMarker(JKQTPEnhancedPainter &/*painter*/, QRectF &/*rect*/)
|
|
{
|
|
|
|
}
|
|
|
|
JKQTPMathImageBase::JKQTPMathImageBase(JKQtBasePlotter *parent):
|
|
JKQTPImageBase(parent)
|
|
{
|
|
this->data=NULL;
|
|
this->Nx=0;
|
|
this->Ny=0;
|
|
this->datatype=DoubleArray;
|
|
dataModifier=NULL;
|
|
datatypeModifier=DoubleArray;
|
|
modifierMode=ModifyNone;
|
|
}
|
|
|
|
JKQTPMathImageBase::JKQTPMathImageBase(double x, double y, double width, double height, JKQtBasePlotter *parent):
|
|
JKQTPImageBase(x,y,width,height,parent)
|
|
{
|
|
this->data=NULL;
|
|
this->Nx=0;
|
|
this->Ny=0;
|
|
this->datatype=DoubleArray;
|
|
dataModifier=NULL;
|
|
datatypeModifier=DoubleArray;
|
|
modifierMode=ModifyNone;
|
|
}
|
|
|
|
|
|
void JKQTPMathImageBase::set_data(void* data, uint32_t Nx, uint32_t Ny, DataType datatype) {
|
|
this->data=data;
|
|
this->datatype=datatype;
|
|
this->Nx=Nx;
|
|
this->Ny=Ny;
|
|
}
|
|
|
|
void JKQTPMathImageBase::set_data(void* data, uint32_t Nx, uint32_t Ny) {
|
|
this->data=data;
|
|
this->Nx=Nx;
|
|
this->Ny=Ny;
|
|
}
|
|
|
|
void JKQTPMathImageBase::set_dataModifier(void *data, JKQTPMathImageBase::DataType datatype)
|
|
{
|
|
this->dataModifier=data;
|
|
this->datatypeModifier=datatype;
|
|
}
|
|
|
|
|
|
void JKQTPMathImageBase::getDataMinMax(double& imin, double& imax) {
|
|
ensureImageData();
|
|
imin=imax=0;
|
|
if (!data) return;
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray:
|
|
imin= JKQTPimagePlot_getImageMin<double>((double*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<double>((double*)data, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::FloatArray:
|
|
imin= JKQTPimagePlot_getImageMin<float>((float*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<float>((float*)data, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt8Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint8_t>((uint8_t*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint8_t>((uint8_t*)data, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt16Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint16_t>((uint16_t*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint16_t>((uint16_t*)data, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt32Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint32_t>((uint32_t*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint32_t>((uint32_t*)data, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt64Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint64_t>((uint64_t*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint64_t>((uint64_t*)data, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int8Array:
|
|
imin= JKQTPimagePlot_getImageMin<int8_t>((int8_t*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int8_t>((int8_t*)data, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int16Array:
|
|
imin= JKQTPimagePlot_getImageMin<int16_t>((int16_t*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int16_t>((int16_t*)data, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int32Array:
|
|
imin= JKQTPimagePlot_getImageMin<int32_t>((int32_t*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int32_t>((int32_t*)data, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int64Array:
|
|
imin= JKQTPimagePlot_getImageMin<int64_t>((int64_t*)data, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int64_t>((int64_t*)data, Nx, Ny);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void JKQTPMathImageBase::getModifierMinMax(double &imin, double &imax)
|
|
{
|
|
ensureImageData();
|
|
imin=imax=0;
|
|
if (!dataModifier) return;
|
|
switch(datatypeModifier) {
|
|
case JKQTPMathImageBase::DoubleArray:
|
|
imin= JKQTPimagePlot_getImageMin<double>((double*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<double>((double*)dataModifier, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::FloatArray:
|
|
imin= JKQTPimagePlot_getImageMin<float>((float*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<float>((float*)dataModifier, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt8Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint8_t>((uint8_t*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint8_t>((uint8_t*)dataModifier, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt16Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint16_t>((uint16_t*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint16_t>((uint16_t*)dataModifier, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt32Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint32_t>((uint32_t*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint32_t>((uint32_t*)dataModifier, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt64Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint64_t>((uint64_t*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint64_t>((uint64_t*)dataModifier, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int8Array:
|
|
imin= JKQTPimagePlot_getImageMin<int8_t>((int8_t*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int8_t>((int8_t*)dataModifier, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int16Array:
|
|
imin= JKQTPimagePlot_getImageMin<int16_t>((int16_t*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int16_t>((int16_t*)dataModifier, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int32Array:
|
|
imin= JKQTPimagePlot_getImageMin<int32_t>((int32_t*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int32_t>((int32_t*)dataModifier, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int64Array:
|
|
imin= JKQTPimagePlot_getImageMin<int64_t>((int64_t*)dataModifier, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int64_t>((int64_t*)dataModifier, Nx, Ny);
|
|
break;
|
|
}
|
|
}
|
|
|
|
QVector<double> JKQTPMathImageBase::getDataAsDoubleVector() const
|
|
{
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray:
|
|
return JKQTPimagePlot_arrayToDVector((double*)data, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::FloatArray:
|
|
return JKQTPimagePlot_arrayToDVector((float*)data, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt8Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint8_t*)data, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt16Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint16_t*)data, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt32Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint32_t*)data, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt64Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint64_t*)data, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int8Array:
|
|
return JKQTPimagePlot_arrayToDVector((int8_t*)data, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int16Array:
|
|
return JKQTPimagePlot_arrayToDVector((int16_t*)data, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int32Array:
|
|
return JKQTPimagePlot_arrayToDVector((int32_t*)data, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int64Array:
|
|
return JKQTPimagePlot_arrayToDVector((int64_t*)data, Nx*Ny);
|
|
break;
|
|
}
|
|
QVector<double> res;
|
|
return res;
|
|
}
|
|
|
|
QVector<double> JKQTPMathImageBase::getDataModifierAsDoubleVector() const
|
|
{
|
|
switch(datatypeModifier) {
|
|
case JKQTPMathImageBase::DoubleArray:
|
|
return JKQTPimagePlot_arrayToDVector((double*)dataModifier, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::FloatArray:
|
|
return JKQTPimagePlot_arrayToDVector((float*)dataModifier, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt8Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint8_t*)dataModifier, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt16Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint16_t*)dataModifier, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt32Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint32_t*)dataModifier, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt64Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint64_t*)dataModifier, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int8Array:
|
|
return JKQTPimagePlot_arrayToDVector((int8_t*)dataModifier, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int16Array:
|
|
return JKQTPimagePlot_arrayToDVector((int16_t*)dataModifier, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int32Array:
|
|
return JKQTPimagePlot_arrayToDVector((int32_t*)dataModifier, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int64Array:
|
|
return JKQTPimagePlot_arrayToDVector((int64_t*)dataModifier, Nx*Ny);
|
|
break;
|
|
}
|
|
QVector<double> res;
|
|
return res;
|
|
}
|
|
|
|
void JKQTPMathImageBase::ensureImageData()
|
|
{
|
|
}
|
|
|
|
|
|
void JKQTPMathImageBase::modifyImage(QImage &img)
|
|
{
|
|
modifyImage(img, dataModifier, datatypeModifier, Nx, Ny, internalModifierMin, internalModifierMax);
|
|
}
|
|
|
|
void JKQTPMathImageBase::modifyImage(QImage &img, void *dataModifier, JKQTPMathImageBase::DataType datatypeModifier, uint32_t Nx, uint32_t Ny, double internalModifierMin, double internalModifierMax)
|
|
{
|
|
if (!dataModifier) return;
|
|
getModifierMinMax(internalModifierMin, internalModifierMax);
|
|
if (modifierMode!=ModifyNone) {
|
|
JKQTPRGBMathImageRGBMode rgbModMode=JKQTPRGBMathImageModeRGBMode;
|
|
int modChannel=3;
|
|
if (modifierMode==ModifyValue) {
|
|
modChannel=5;
|
|
rgbModMode=JKQTPRGBMathImageModeRGBMode;
|
|
} else if (modifierMode==ModifySaturation) {
|
|
modChannel=4;
|
|
rgbModMode=JKQTPRGBMathImageModeRGBMode;
|
|
} else if (modifierMode==ModifyAlpha) {
|
|
modChannel=3;
|
|
rgbModMode=JKQTPRGBMathImageModeRGBMode;
|
|
}
|
|
//qDebug()<<"mod: "<<modifierMode<<" ch:"<<modChannel<<" rgb:"<<rgbModMode;
|
|
switch(datatypeModifier) {
|
|
case JKQTPMathImageBase::DoubleArray: JKQTPimagePlot_array2RGBimage<double>((double*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
case JKQTPMathImageBase::FloatArray: JKQTPimagePlot_array2RGBimage<float>((float*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
case JKQTPMathImageBase::UInt8Array: JKQTPimagePlot_array2RGBimage<uint8_t>((uint8_t*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
case JKQTPMathImageBase::UInt16Array: JKQTPimagePlot_array2RGBimage<uint16_t>((uint16_t*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
case JKQTPMathImageBase::UInt32Array: JKQTPimagePlot_array2RGBimage<uint32_t>((uint32_t*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
case JKQTPMathImageBase::UInt64Array: JKQTPimagePlot_array2RGBimage<uint64_t>((uint64_t*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
case JKQTPMathImageBase::Int8Array: JKQTPimagePlot_array2RGBimage<int8_t>((int8_t*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
case JKQTPMathImageBase::Int16Array: JKQTPimagePlot_array2RGBimage<int16_t>((int16_t*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
case JKQTPMathImageBase::Int32Array: JKQTPimagePlot_array2RGBimage<int32_t>((int32_t*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
case JKQTPMathImageBase::Int64Array: JKQTPimagePlot_array2RGBimage<int64_t>((int64_t*)dataModifier, Nx, Ny, img, modChannel, internalModifierMin, internalModifierMax, rgbModMode); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JKQTPMathImage::JKQTPMathImage(double x, double y, double width, double height, DataType datatype, void* data, uint32_t Nx, uint32_t Ny, JKQTPMathImageColorPalette palette, JKQtBasePlotter* parent):
|
|
JKQTPMathImageBase(x, y, width, height, datatype, data, Nx, Ny, parent)
|
|
{
|
|
actSaveImage=new QAction(tr("Save JKQTPMathImage ..."), this);
|
|
connect(actSaveImage, SIGNAL(triggered()), this, SLOT(saveImagePlotAsImage()));
|
|
actCopyImage=new QAction(tr("Copy JKQTPOverlayImage ..."), this);
|
|
connect(actCopyImage, SIGNAL(triggered()), this, SLOT(copyImagePlotAsImage()));
|
|
|
|
colorBarRightAxis=new JKQTPverticalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarRightAxis->loadSettings(parent->getYAxis());
|
|
colorBarRightAxis->set_drawMode1(JKQTPCADMline);
|
|
colorBarRightAxis->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarRightAxis->set_axisLabel("");
|
|
colorBarRightAxis->set_minTicks(5);
|
|
colorBarRightAxis->set_minorTicks(0);
|
|
colorBarRightAxis->set_tickOutsideLength(0);
|
|
colorBarRightAxis->set_minorTickOutsideLength(0);
|
|
colorBarRightAxis->set_showZeroAxis(false);
|
|
colorBarTopAxis=new JKQTPhorizontalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarTopAxis->loadSettings(parent->getXAxis());
|
|
colorBarTopAxis->set_drawMode1(JKQTPCADMline);
|
|
colorBarTopAxis->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarTopAxis->set_axisLabel("");
|
|
colorBarTopAxis->set_minTicks(3);
|
|
colorBarTopAxis->set_minorTicks(0);
|
|
colorBarTopAxis->set_tickOutsideLength(0);
|
|
colorBarTopAxis->set_minorTickOutsideLength(0);
|
|
colorBarTopAxis->set_showZeroAxis(false);
|
|
|
|
modifierColorBarTopAxis=new JKQTPverticalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) modifierColorBarTopAxis->loadSettings(parent->getXAxis());
|
|
modifierColorBarTopAxis->set_drawMode1(JKQTPCADMline);
|
|
modifierColorBarTopAxis->set_drawMode2(JKQTPCADMcomplete);
|
|
modifierColorBarTopAxis->set_axisLabel("");
|
|
modifierColorBarTopAxis->set_minTicks(3);
|
|
modifierColorBarTopAxis->set_showZeroAxis(false);
|
|
modifierColorBarTopAxis->set_minorTicks(0);
|
|
modifierColorBarTopAxis->set_tickOutsideLength(0);
|
|
modifierColorBarTopAxis->set_minorTickOutsideLength(0);
|
|
modifierColorBarRightAxis=new JKQTPhorizontalIndependentAxis (0, 100, 0, 100, parent);
|
|
if (parent) modifierColorBarRightAxis->loadSettings(parent->getYAxis());
|
|
modifierColorBarRightAxis->set_drawMode1(JKQTPCADMline);
|
|
modifierColorBarRightAxis->set_drawMode2(JKQTPCADMcomplete);
|
|
modifierColorBarRightAxis->set_axisLabel("");
|
|
modifierColorBarRightAxis->set_minTicks(5);
|
|
modifierColorBarRightAxis->set_showZeroAxis(false);
|
|
modifierColorBarRightAxis->set_minorTicks(0);
|
|
modifierColorBarRightAxis->set_tickOutsideLength(0);
|
|
modifierColorBarRightAxis->set_minorTickOutsideLength(0);
|
|
this->colorBarModifiedWidth=80;
|
|
|
|
this->colorBarTopVisible=true;
|
|
this->colorBarRightVisible=true;
|
|
this->palette=palette;
|
|
this->imageNameFontName=parent->get_keyFont();
|
|
this->imageNameFontSize=parent->get_keyFontSize();
|
|
this->imageName="";
|
|
this->showColorBar=true;
|
|
this->colorBarWidth=14;
|
|
this->colorBarRelativeHeight=0.75;
|
|
this->autoImageRange=true;
|
|
this->imageMin=0;
|
|
this->imageMax=1;
|
|
this->colorBarOffset=4;
|
|
this->rangeMinFailAction=JKQTPMathImageLastPaletteColor;
|
|
this->rangeMaxFailAction=JKQTPMathImageLastPaletteColor;
|
|
this->rangeMinFailColor=QColor("black");
|
|
this->rangeMaxFailColor=QColor("black");
|
|
this->nanColor=QColor("black");
|
|
this->infColor=QColor("black");
|
|
this->colorBarTopVisible=false;
|
|
this->colorBarRightVisible=true;
|
|
this->autoModifierRange=true;
|
|
}
|
|
|
|
JKQTPMathImage::JKQTPMathImage(JKQtBasePlotter *parent):
|
|
JKQTPMathImageBase(0, 0, 1, 1, JKQTPMathImageBase::UInt8Array, NULL, 0, 0, parent)
|
|
{
|
|
actSaveImage=new QAction(tr("Save JKQTPMathImage ..."), this);
|
|
connect(actSaveImage, SIGNAL(triggered()), this, SLOT(saveImagePlotAsImage()));
|
|
actCopyImage=new QAction(tr("Copy JKQTPOverlayImage ..."), this);
|
|
connect(actCopyImage, SIGNAL(triggered()), this, SLOT(copyImagePlotAsImage()));
|
|
|
|
colorBarRightAxis=new JKQTPverticalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarRightAxis->loadSettings(parent->getYAxis());
|
|
colorBarRightAxis->set_drawMode1(JKQTPCADMline);
|
|
colorBarRightAxis->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarRightAxis->set_axisLabel("");
|
|
colorBarRightAxis->set_minTicks(3);
|
|
colorBarRightAxis->set_showZeroAxis(false);
|
|
colorBarRightAxis->set_minorTicks(0);
|
|
colorBarRightAxis->set_tickOutsideLength(0);
|
|
colorBarRightAxis->set_minorTickOutsideLength(0);
|
|
colorBarTopAxis=new JKQTPhorizontalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarTopAxis->loadSettings(parent->getXAxis());
|
|
colorBarTopAxis->set_drawMode1(JKQTPCADMline);
|
|
colorBarTopAxis->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarTopAxis->set_axisLabel("");
|
|
colorBarTopAxis->set_minTicks(3);
|
|
colorBarTopAxis->set_showZeroAxis(false);
|
|
colorBarTopAxis->set_minorTicks(0);
|
|
colorBarTopAxis->set_tickOutsideLength(0);
|
|
colorBarTopAxis->set_minorTickOutsideLength(0);
|
|
|
|
modifierColorBarTopAxis=new JKQTPverticalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) modifierColorBarTopAxis->loadSettings(parent->getXAxis());
|
|
modifierColorBarTopAxis->set_drawMode1(JKQTPCADMcomplete);
|
|
modifierColorBarTopAxis->set_drawMode2(JKQTPCADMline);
|
|
modifierColorBarTopAxis->set_axisLabel("");
|
|
modifierColorBarTopAxis->set_minTicks(3);
|
|
modifierColorBarTopAxis->set_showZeroAxis(false);
|
|
modifierColorBarTopAxis->set_minorTicks(0);
|
|
modifierColorBarTopAxis->set_tickOutsideLength(0);
|
|
modifierColorBarTopAxis->set_minorTickOutsideLength(0);
|
|
modifierColorBarRightAxis=new JKQTPhorizontalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) modifierColorBarRightAxis->loadSettings(parent->getYAxis());
|
|
modifierColorBarRightAxis->set_drawMode1(JKQTPCADMcomplete);
|
|
modifierColorBarRightAxis->set_drawMode2(JKQTPCADMline);
|
|
modifierColorBarRightAxis->set_axisLabel("");
|
|
modifierColorBarRightAxis->set_minTicks(5);
|
|
modifierColorBarRightAxis->set_showZeroAxis(false);
|
|
modifierColorBarRightAxis->set_minorTicks(0);
|
|
modifierColorBarRightAxis->set_tickOutsideLength(0);
|
|
modifierColorBarRightAxis->set_minorTickOutsideLength(0);
|
|
this->colorBarModifiedWidth=80;
|
|
|
|
this->palette=palette;
|
|
this->imageNameFontName=parent->get_keyFont();
|
|
this->imageNameFontSize=parent->get_keyFontSize();
|
|
this->imageName="";
|
|
this->showColorBar=true;
|
|
this->colorBarWidth=14;
|
|
this->colorBarRelativeHeight=0.75;
|
|
this->autoImageRange=true;
|
|
this->imageMin=0;
|
|
this->imageMax=1;
|
|
this->autoModifierRange=true;
|
|
this->modifierMin=0;
|
|
this->modifierMax=1;
|
|
this->colorBarOffset=4;
|
|
this->rangeMinFailAction=JKQTPMathImageLastPaletteColor;
|
|
this->rangeMaxFailAction=JKQTPMathImageLastPaletteColor;
|
|
this->rangeMinFailColor=QColor("black");
|
|
this->rangeMaxFailColor=QColor("black");
|
|
this->nanColor=QColor("black");
|
|
this->infColor=QColor("black");
|
|
this->colorBarTopVisible=false;
|
|
this->colorBarRightVisible=true;
|
|
this->autoModifierRange=true;
|
|
}
|
|
|
|
void JKQTPMathImage::setParent(JKQtBasePlotter* parent) {
|
|
if (this->parent) {
|
|
this->parent->deregisterAdditionalAction(actSaveImage);
|
|
this->parent->deregisterAdditionalAction(actCopyImage);
|
|
}
|
|
JKQTPMathImageBase::setParent(parent);
|
|
colorBarRightAxis->set_parent(parent);
|
|
colorBarTopAxis->set_parent(parent);
|
|
modifierColorBarRightAxis->set_parent(parent);
|
|
modifierColorBarTopAxis->set_parent(parent);
|
|
if (parent) {
|
|
parent->registerAdditionalAction(tr("Save Image Plot Images ..."), actSaveImage);
|
|
parent->registerAdditionalAction(tr("Copy Image Plot Images ..."), actCopyImage);
|
|
}
|
|
actSaveImage->setEnabled(parent);
|
|
actCopyImage->setEnabled(parent);
|
|
}
|
|
|
|
void JKQTPMathImage::set_title(const JKQTPgraph::typedef_set_title &title)
|
|
{
|
|
JKQTPMathImageBase::set_title(title);
|
|
QString t=title;
|
|
if (t.isEmpty()) t="JKQTPMathImage";
|
|
actSaveImage->setText(tr("Save %1 ...").arg(t));
|
|
actCopyImage->setText(tr("Copy %1 ...").arg(t));
|
|
}
|
|
|
|
void JKQTPMathImage::saveImagePlotAsImage(const QString &filename, const QByteArray &outputFormat)
|
|
{
|
|
if (parent) {
|
|
parent->loadUserSettings();
|
|
QString currentSaveDirectory=parent->get_currentSaveDirectory();
|
|
QString currentFileFormat=parent->get_currentFileFormat();
|
|
QString fn=filename;
|
|
QStringList filt;
|
|
QList<QByteArray> writerformats=QImageWriter::supportedImageFormats();
|
|
for (int i=0; i<writerformats.size(); i++) {
|
|
filt<<QString("%1 Image (*.%2)").arg(QString(writerformats[i]).toUpper()).arg(QString(writerformats[i].toLower()));
|
|
}
|
|
QString selFormat;
|
|
if (fn.isEmpty()) {
|
|
selFormat=currentFileFormat;
|
|
fn = QFileDialog::getSaveFileName(NULL, tr("Save Image Plot As Image ..."),
|
|
currentSaveDirectory,
|
|
filt.join(";;"), &selFormat);
|
|
if (!fn.isEmpty()) currentSaveDirectory=QFileInfo(fn).absolutePath();
|
|
}
|
|
|
|
parent->set_currentFileFormat(currentFileFormat);
|
|
parent->set_currentSaveDirectory(currentSaveDirectory);
|
|
parent->saveUserSettings();
|
|
if (!fn.isEmpty()) {
|
|
int filtID=filt.indexOf(selFormat);
|
|
QString form="NONE";
|
|
if (filtID>=0 && filtID<writerformats.size()) {
|
|
form=writerformats[filtID];
|
|
}
|
|
if (outputFormat.size()>0) {
|
|
form =outputFormat;
|
|
}
|
|
|
|
QImage image=drawImage();
|
|
|
|
if (form=="NONE") image.save(fn);
|
|
else image.save(fn, form.toLatin1().data());
|
|
}
|
|
}
|
|
}
|
|
|
|
void JKQTPMathImage::copyImagePlotAsImage()
|
|
{
|
|
QClipboard* clip=QApplication::clipboard();
|
|
if (clip) {
|
|
clip->setImage(drawImage());
|
|
}
|
|
}
|
|
|
|
void JKQTPMathImage::draw(JKQTPEnhancedPainter& painter) {
|
|
ensureImageData();
|
|
if (!data) return;
|
|
QImage img=drawImage();
|
|
plotImage(painter, img, x, y, width, height);
|
|
}
|
|
|
|
|
|
|
|
void JKQTPMathImage::getOutsideSize(JKQTPEnhancedPainter& painter, int& leftSpace, int& rightSpace, int& topSpace, int& bottomSpace) {
|
|
JKQTPgraph::getOutsideSize(painter, leftSpace, rightSpace, topSpace, bottomSpace);
|
|
if (showColorBar) {
|
|
getDataMinMax(internalDataMin, internalDataMax);
|
|
getModifierMinMax(internalModifierMin, internalModifierMax);
|
|
if (colorBarRightVisible) {
|
|
rightSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset);
|
|
colorBarRightAxis->setRange(internalDataMin, internalDataMax);
|
|
colorBarRightAxis->set_axisWidth(colorBarRelativeHeight*parent->get_plotHeight());
|
|
modifierColorBarRightAxis->setRange(internalModifierMin, internalModifierMax);
|
|
modifierColorBarRightAxis->set_axisWidth(parent->pt2px(painter, colorBarModifiedWidth));
|
|
QSize s=colorBarRightAxis->getSize2(painter);
|
|
/*parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageName);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);*/
|
|
QSizeF names=parent->getTextSizeSize(imageNameFontName, imageNameFontSize*parent->get_fontSizeMultiplier(), imageName, painter);
|
|
rightSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset)+qMax((double)s.width(), (double)names.width());
|
|
//qDebug()<<"osr: "<<imageName<<rightSpace<<colorBarModifiedWidth<<colorBarWidth;
|
|
if (modifierMode!=ModifyNone) {
|
|
rightSpace=rightSpace+(2*parent->pt2px(painter, colorBarModifiedWidth-colorBarWidth));
|
|
}
|
|
//qDebug()<<" "<<imageName<<rightSpace;
|
|
}
|
|
if (colorBarTopVisible) {
|
|
//topSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset);
|
|
colorBarTopAxis->setRange(internalDataMin, internalDataMax);
|
|
colorBarTopAxis->set_axisWidth(colorBarRelativeHeight*parent->get_plotWidth());
|
|
modifierColorBarTopAxis->setRange(internalModifierMin, internalModifierMax);
|
|
modifierColorBarTopAxis->set_axisWidth(parent->pt2px(painter, colorBarModifiedWidth));
|
|
QSize s=colorBarTopAxis->getSize2(painter);
|
|
/*parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageName);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);*/
|
|
QSizeF names=parent->getTextSizeSize(imageNameFontName, imageNameFontSize*parent->get_fontSizeMultiplier(), imageName, painter);
|
|
//qDebug()<<topSpace<<s<<imageName<<names;
|
|
//qDebug()<<colorBarWidth<<colorBarOffset<<parent->pt2px(painter, colorBarWidth+colorBarOffset);
|
|
topSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset)+qMax((double)s.height(), (double)names.height());
|
|
if (modifierMode!=ModifyNone) {
|
|
topSpace=topSpace+(2*parent->pt2px(painter, colorBarModifiedWidth-colorBarWidth));
|
|
}
|
|
//qDebug()<<topSpace;
|
|
//qDebug()<<"ost: "<<imageName<<topSpace<<colorBarModifiedWidth<<colorBarWidth;
|
|
}
|
|
}
|
|
}
|
|
|
|
void JKQTPMathImage::drawOutside(JKQTPEnhancedPainter& painter, QRect /*leftSpace*/, QRect rightSpace, QRect topSpace, QRect /*bottomSpace*/) {
|
|
if (showColorBar) {
|
|
getDataMinMax(internalDataMin, internalDataMax);
|
|
getModifierMinMax(internalModifierMin, internalModifierMax);
|
|
if (colorBarRightVisible) {
|
|
painter.save();
|
|
|
|
uint8_t h=1;
|
|
if (modifierMode!=ModifyNone) {
|
|
h=50;
|
|
}
|
|
uint8_t d[200*h], dd[200*h];
|
|
for (int i=0; i<200; i++) {
|
|
for (int j=0; j<h; j++) {
|
|
d[i*h+j]=i;
|
|
dd[i*h+j]=j;
|
|
}
|
|
}
|
|
QImage b(h, 200, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(d, h, 200, b, palette, 0, 199);
|
|
if (modifierMode!=ModifyNone) {
|
|
modifyImage(b, dd, UInt8Array, h, 200, 0, h-1);
|
|
}
|
|
|
|
/*parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageName);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);*/
|
|
QSizeF names=parent->getTextSizeSize(imageNameFontName, imageNameFontSize*parent->get_fontSizeMultiplier(), imageName, painter);
|
|
|
|
double icolorBarRelativeHeight=colorBarRelativeHeight;
|
|
int barHeight=rightSpace.height()*icolorBarRelativeHeight;
|
|
if (barHeight<1) barHeight=1;
|
|
// find a height for the bar that allows to show the image name
|
|
while ((barHeight>1) && ((rightSpace.height()-barHeight)/2<names.height())) {
|
|
barHeight--;
|
|
}
|
|
|
|
//qDebug()<<"r: "<<imageName<<rightSpace;
|
|
|
|
QRect cb(rightSpace.x()+parent->pt2px(painter, colorBarOffset), rightSpace.top()+(rightSpace.height()-barHeight)/2, parent->pt2px(painter, (modifierMode==ModifyNone)?colorBarWidth:colorBarModifiedWidth), barHeight);
|
|
painter.drawImage(cb, b.mirrored(true, false));
|
|
QPen p=painter.pen();
|
|
p.setColor(colorBarRightAxis->get_axisColor());
|
|
p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, colorBarRightAxis->get_lineWidth()*parent->get_lineWidthMultiplier())));
|
|
painter.setPen(p);
|
|
painter.drawRect(cb);
|
|
|
|
colorBarRightAxis->setRange(internalDataMin, internalDataMax);
|
|
colorBarRightAxis->set_axisWidth(cb.height());
|
|
colorBarRightAxis->set_axisOffset(cb.top());
|
|
colorBarRightAxis->set_otherAxisOffset(cb.left());
|
|
colorBarRightAxis->set_otherAxisWidth(cb.width());
|
|
colorBarRightAxis->drawAxes(painter);
|
|
|
|
if (modifierMode!=ModifyNone) {
|
|
modifierColorBarRightAxis->setRange(internalModifierMin, internalModifierMax);
|
|
modifierColorBarRightAxis->set_axisWidth(parent->pt2px(painter, colorBarModifiedWidth));
|
|
modifierColorBarRightAxis->set_axisOffset(cb.left());
|
|
modifierColorBarRightAxis->set_otherAxisOffset(cb.top());
|
|
modifierColorBarRightAxis->set_otherAxisWidth(cb.height());
|
|
modifierColorBarRightAxis->drawAxes(painter);
|
|
}
|
|
|
|
parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageName);
|
|
parent->get_mathText()->draw(painter, Qt::AlignHCenter|Qt::AlignVCenter, QRect(rightSpace.x(), rightSpace.y(), rightSpace.width(), (rightSpace.height()-barHeight)/2));
|
|
|
|
painter.restore();
|
|
}
|
|
if (colorBarTopVisible) {
|
|
painter.save();
|
|
|
|
/*uint8_t d[200];
|
|
for (int i=0; i<200; i++) d[i]=i;
|
|
QImage b(200,1, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(d, 200, 1, b, palette, 0, 199);*/
|
|
|
|
|
|
uint8_t h=1;
|
|
if (modifierMode!=ModifyNone) {
|
|
h=50;
|
|
}
|
|
uint8_t d[200*h], dd[200*h];
|
|
for (int i=0; i<200; i++) {
|
|
for (int j=0; j<h; j++) {
|
|
d[i*h+j]=i;
|
|
dd[i*h+j]=j;
|
|
}
|
|
}
|
|
QImage b(h,200, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(d,h,200, b, palette, 0, 199);
|
|
if (modifierMode!=ModifyNone) {
|
|
modifyImage(b, dd, UInt8Array, h,200, 0, h-1);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageName);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);*/
|
|
QSizeF names=parent->getTextSizeSize(imageNameFontName, imageNameFontSize*parent->get_fontSizeMultiplier(), imageName, painter);
|
|
|
|
double icolorBarRelativeHeight=colorBarRelativeHeight;
|
|
int barWidth=topSpace.width()*icolorBarRelativeHeight;
|
|
if (barWidth<1) barWidth=1;
|
|
// find a height for the bar that allows to show the image name
|
|
while ((barWidth>1) && ((topSpace.width()-barWidth)/2<names.width())) {
|
|
barWidth--;
|
|
}
|
|
|
|
|
|
QRect cb(topSpace.x()+(topSpace.width()-barWidth)/2, topSpace.bottom()-parent->pt2px(painter, colorBarOffset+((modifierMode==ModifyNone)?colorBarWidth:colorBarModifiedWidth)), barWidth, parent->pt2px(painter, (modifierMode==ModifyNone)?colorBarWidth:colorBarModifiedWidth));
|
|
//qDebug()<<"t: "<<imageName<<topSpace<<topSpace.bottom()<<colorBarOffset<<"\n "<<cb;
|
|
QMatrix rm;
|
|
rm.rotate(90);
|
|
painter.drawImage(cb, b.transformed(rm));
|
|
QPen p=painter.pen();
|
|
p.setColor(colorBarTopAxis->get_axisColor());
|
|
p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, colorBarTopAxis->get_lineWidth()*parent->get_lineWidthMultiplier())));
|
|
painter.setPen(p);
|
|
painter.drawRect(cb);
|
|
|
|
|
|
colorBarTopAxis->setRange(internalDataMin, internalDataMax);
|
|
colorBarTopAxis->set_axisWidth(cb.width());
|
|
colorBarTopAxis->set_axisOffset(cb.left());
|
|
colorBarTopAxis->set_otherAxisOffset(cb.top());
|
|
colorBarTopAxis->set_otherAxisWidth(cb.height());
|
|
colorBarTopAxis->drawAxes(painter);
|
|
|
|
if (modifierMode!=ModifyNone) {
|
|
modifierColorBarTopAxis->setRange(internalModifierMin, internalModifierMax);
|
|
modifierColorBarTopAxis->set_axisWidth(parent->pt2px(painter, colorBarModifiedWidth));
|
|
modifierColorBarTopAxis->set_axisOffset(cb.top());
|
|
modifierColorBarTopAxis->set_otherAxisOffset(cb.left());
|
|
modifierColorBarTopAxis->set_otherAxisWidth(cb.width());
|
|
modifierColorBarTopAxis->drawAxes(painter);
|
|
}
|
|
|
|
parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageName);
|
|
parent->get_mathText()->draw(painter, Qt::AlignHCenter|Qt::AlignVCenter, QRect(topSpace.right()-(topSpace.width()-barWidth)/2, topSpace.y(), (topSpace.width()-barWidth)/2, topSpace.height()));
|
|
|
|
painter.restore();
|
|
}
|
|
}
|
|
}
|
|
|
|
void JKQTPMathImage::getDataMinMax(double& imin, double& imax) {
|
|
ensureImageData();
|
|
if (autoImageRange) {
|
|
JKQTPMathImageBase::getDataMinMax(imin, imax);
|
|
} else {
|
|
imin=imageMin;
|
|
imax=imageMax;
|
|
}
|
|
}
|
|
|
|
void JKQTPMathImage::getModifierMinMax(double &imin, double &imax)
|
|
{
|
|
ensureImageData();
|
|
if (autoModifierRange) {
|
|
JKQTPMathImageBase::getModifierMinMax(imin, imax);
|
|
} else {
|
|
imin=modifierMin;
|
|
imax=modifierMax;
|
|
}
|
|
}
|
|
|
|
double JKQTPMathImage::getValueAt(double x, double y)
|
|
{
|
|
ensureImageData();
|
|
int xx=trunc((x-this->x)/width*double(Nx));
|
|
int yy=trunc((y-this->y)/height*double(Ny));
|
|
if (xx>=0 && xx<(int64_t)Nx && yy>=0 && yy<(int64_t)Ny) {
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray: return ((double*)data)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::FloatArray: return ((float*)data)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::UInt8Array: return ((uint8_t*)data)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::UInt16Array: return ((uint16_t*)data)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::UInt32Array: return ((uint32_t*)data)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::UInt64Array: return ((uint64_t*)data)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::Int8Array: return ((int8_t*)data)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::Int16Array: return ((int16_t*)data)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::Int32Array: return ((int32_t*)data)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::Int64Array: return ((int64_t*)data)[yy*Nx+xx]; break;
|
|
} }
|
|
return 0.0;
|
|
}
|
|
|
|
void JKQTPMathImage::drawKeyMarker(JKQTPEnhancedPainter &painter, QRectF &rect)
|
|
{
|
|
painter.drawImage(rect, getPaletteKeyImage(palette, 32,32));
|
|
}
|
|
|
|
QStringList JKQTPMathImage::getPalettes() {
|
|
return JKQTPimagePlot_getPredefinedPalettes();
|
|
}
|
|
|
|
int JKQTPMathImage::getPalettesCount()
|
|
{
|
|
return getPalettes().size();
|
|
}
|
|
|
|
QIcon JKQTPMathImage::getPaletteIcon(int i) {
|
|
QImage img=getPaletteImage(i, PALETTE_ICON_WIDTH);
|
|
QPixmap pix(PALETTE_ICON_WIDTH,8);
|
|
QRect r(0,0,PALETTE_ICON_WIDTH-1,7);
|
|
JKQTPEnhancedPainter p(&pix);
|
|
p.drawImage(r, img);
|
|
p.setPen(QPen(QColor("black")));
|
|
p.drawRect(r);
|
|
p.end();
|
|
return QIcon(pix);
|
|
|
|
}
|
|
|
|
QIcon JKQTPMathImage::getPaletteIcon(JKQTPMathImageColorPalette palette) {
|
|
return getPaletteIcon((int)palette);
|
|
}
|
|
|
|
QImage JKQTPMathImage::getPaletteImage(int i, int width)
|
|
{
|
|
QImage img;
|
|
double* pic=(double*)malloc(width*sizeof(double));
|
|
for (int j=0; j<width; j++) {
|
|
pic[j]=j;
|
|
}
|
|
JKQTPimagePlot_array2image<double>(pic, width, 1, img, (JKQTPMathImageColorPalette)i, 0, width-1);
|
|
free(pic);
|
|
return img;
|
|
}
|
|
|
|
QImage JKQTPMathImage::getPaletteImage(JKQTPMathImageColorPalette palette, int width)
|
|
{
|
|
return getPaletteImage((int)palette, width);
|
|
}
|
|
|
|
QIcon JKQTPMathImage::getPaletteKeyIcon(int i)
|
|
{
|
|
QImage img=getPaletteKeyImage(i, PALETTE_ICON_WIDTH, PALETTE_IMAGEICON_HEIGHT);
|
|
QPixmap pix(PALETTE_ICON_WIDTH,PALETTE_IMAGEICON_HEIGHT);
|
|
QRect r(0,0,PALETTE_ICON_WIDTH-1,PALETTE_IMAGEICON_HEIGHT-1);
|
|
JKQTPEnhancedPainter p(&pix);
|
|
p.drawImage(r, img);
|
|
p.setPen(QPen(QColor("black")));
|
|
p.drawRect(r);
|
|
p.end();
|
|
return QIcon(pix);
|
|
}
|
|
|
|
QIcon JKQTPMathImage::getPaletteKeyIcon(JKQTPMathImageColorPalette palette)
|
|
{
|
|
return getPaletteIcon((int)palette);
|
|
}
|
|
|
|
QImage JKQTPMathImage::getPaletteKeyImage(int i, int width, int height)
|
|
{
|
|
QImage img;
|
|
|
|
const double x01=double(width)/3.0;
|
|
const double y01=double(height)/3.0*2.0;
|
|
const double w1x=double(width*width)/(5.0*5.0);
|
|
const double w1y=double(height*height)/(2.0*2.0);
|
|
const double x02=double(width)/3.0*2.0;
|
|
const double y02=double(height)/4.0;
|
|
const double w2x=double(width*width)/(8.0*8.0);
|
|
const double w2y=double(height*height)/(8.0*8.0);
|
|
|
|
double* pic=(double*)malloc(width*height*sizeof(double));
|
|
double mmax=0;
|
|
for (int j=0; j<width*height; j++) {
|
|
const int x=j%width;
|
|
const int y=j/width;
|
|
pic[j]=exp(-0.5*(double((x-x01)*double(x-x01))/w1x+double((y-y01)*double(y-y01))/w1y))+0.7*exp(-0.5*(double((x-x02)*double(x-x02))/w2x+double((y-y02)*double(y-y02))/w2y));
|
|
if (pic[j]>mmax) mmax=pic[j];
|
|
}
|
|
JKQTPimagePlot_array2image<double>(pic, width, height, img, (JKQTPMathImageColorPalette)i, 0, mmax);
|
|
free(pic);
|
|
return img;
|
|
}
|
|
|
|
QImage JKQTPMathImage::getPaletteKeyImage(JKQTPMathImageColorPalette palette, int width, int height)
|
|
{
|
|
return getPaletteKeyImage((int)palette, width, height);
|
|
}
|
|
|
|
|
|
|
|
QImage JKQTPMathImage::drawImage() {
|
|
if (!data) return QImage();
|
|
QImage img(Nx, Ny, QImage::Format_ARGB32);
|
|
getDataMinMax(internalDataMin, internalDataMax);
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray: JKQTPimagePlot_array2image<double>((double*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
case JKQTPMathImageBase::FloatArray: JKQTPimagePlot_array2image<float>((float*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
case JKQTPMathImageBase::UInt8Array: JKQTPimagePlot_array2image<uint8_t>((uint8_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
case JKQTPMathImageBase::UInt16Array: JKQTPimagePlot_array2image<uint16_t>((uint16_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
case JKQTPMathImageBase::UInt32Array: JKQTPimagePlot_array2image<uint32_t>((uint32_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
case JKQTPMathImageBase::UInt64Array: JKQTPimagePlot_array2image<uint64_t>((uint64_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
case JKQTPMathImageBase::Int8Array: JKQTPimagePlot_array2image<int8_t>((int8_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
case JKQTPMathImageBase::Int16Array: JKQTPimagePlot_array2image<int16_t>((int16_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
case JKQTPMathImageBase::Int32Array: JKQTPimagePlot_array2image<int32_t>((int32_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
case JKQTPMathImageBase::Int64Array: JKQTPimagePlot_array2image<int64_t>((int64_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rangeMinFailAction, rangeMaxFailAction, rangeMinFailColor, rangeMaxFailColor, nanColor, infColor); break;
|
|
}
|
|
modifyImage(img);
|
|
return img;
|
|
}
|
|
|
|
|
|
void JKQTPMathImage::set_palette(int pal) {
|
|
palette=(JKQTPMathImageColorPalette)pal;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JKQTPOverlayImage::JKQTPOverlayImage(double x, double y, double width, double height, bool* data, uint32_t Nx, uint32_t Ny, QColor colTrue, JKQtBasePlotter* parent):
|
|
JKQTPImageBase(x, y, width, height, parent)
|
|
{
|
|
actSaveImage=new QAction(tr("Save JKQTPOverlayImage ..."), this);
|
|
connect(actSaveImage, SIGNAL(triggered()), this, SLOT(saveImagePlotAsImage()));
|
|
actCopyImage=new QAction(tr("Copy JKQTPOverlayImage ..."), this);
|
|
connect(actCopyImage, SIGNAL(triggered()), this, SLOT(copyImagePlotAsImage()));
|
|
this->Nx=Nx;
|
|
this->Ny=Ny;
|
|
this->data=data;
|
|
this->trueColor=colTrue;
|
|
this->falseColor=QColor(Qt::transparent);
|
|
}
|
|
|
|
JKQTPOverlayImage::JKQTPOverlayImage(JKQtBasePlotter *parent):
|
|
JKQTPImageBase(0,0,1,1, parent)
|
|
{
|
|
actSaveImage=new QAction(tr("Save JKQTPOverlayImage ..."), this);
|
|
connect(actSaveImage, SIGNAL(triggered()), this, SLOT(saveImagePlotAsImage()));
|
|
actCopyImage=new QAction(tr("Copy JKQTPOverlayImage ..."), this);
|
|
connect(actCopyImage, SIGNAL(triggered()), this, SLOT(copyImagePlotAsImage()));
|
|
this->Nx=0;
|
|
this->Ny=0;
|
|
this->data=NULL;
|
|
this->trueColor=QColor("red");
|
|
}
|
|
|
|
|
|
void JKQTPOverlayImage::draw(JKQTPEnhancedPainter& painter) {
|
|
if (!data) return;
|
|
QImage img=drawImage();
|
|
plotImage(painter, img, x, y, width, height);
|
|
}
|
|
|
|
QImage JKQTPOverlayImage::drawImage() {
|
|
if (!data) return QImage();
|
|
QImage img(Nx, Ny, QImage::Format_ARGB32);
|
|
|
|
//QRgb tc=trueColor.rgba();
|
|
//QRgb fc=falseColor.rgba();
|
|
QRgb tc=qRgba(round(trueColor.red()*trueColor.alphaF()), round(trueColor.green()*trueColor.alphaF()), round(trueColor.blue()*trueColor.alphaF()), trueColor.alpha());
|
|
QRgb fc=qRgba(round(falseColor.red()*falseColor.alphaF()), round(falseColor.green()*falseColor.alphaF()), round(falseColor.blue()*falseColor.alphaF()), falseColor.alpha());
|
|
|
|
for (uint32_t y=0; y<Ny; y++) {
|
|
QRgb* line=(QRgb*)img.scanLine(Ny-1-y);
|
|
for (uint32_t x=0; x<Nx; x++) {
|
|
if (data[x+y*Nx]) {
|
|
line[x]=tc;
|
|
} else {
|
|
line[x]=fc;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return img;
|
|
}
|
|
|
|
void JKQTPOverlayImage::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
|
int w=rect.width()/2;
|
|
QRectF r1=QRectF(rect.topLeft(), QSizeF(w, rect.height()));
|
|
QRectF r2=QRectF(QPoint(rect.left()+w, rect.top()), QSizeF(w, rect.height()));
|
|
painter.save();
|
|
painter.setPen(Qt::transparent);
|
|
painter.setBrush(QBrush(trueColor));
|
|
painter.fillRect(r1, QBrush(trueColor));
|
|
painter.setBrush(QBrush(falseColor));
|
|
painter.fillRect(r2, QBrush(falseColor));
|
|
painter.restore();
|
|
|
|
}
|
|
|
|
QColor JKQTPOverlayImage::getKeyLabelColor() {
|
|
QColor c=trueColor;
|
|
c.setAlpha(255);
|
|
return c;
|
|
}
|
|
|
|
void JKQTPOverlayImage::set_data(bool* data, uint32_t Nx, uint32_t Ny) {
|
|
this->data=data;
|
|
this->Nx=Nx;
|
|
this->Ny=Ny;
|
|
}
|
|
|
|
|
|
JKQTPOverlayImageEnhanced::JKQTPOverlayImageEnhanced(double x, double y, double width, double height, bool* data, uint32_t Nx, uint32_t Ny, QColor colTrue, JKQtBasePlotter* parent):
|
|
JKQTPOverlayImage(x, y, width, height, data, Nx, Ny, colTrue, parent)
|
|
{
|
|
symbol=JKQTPtarget;
|
|
symbolWidth=1;
|
|
drawAsRectangles=true;
|
|
symbolSizeFactor=0.9;
|
|
rectanglesAsImageOverlay=false;
|
|
}
|
|
|
|
JKQTPOverlayImageEnhanced::JKQTPOverlayImageEnhanced(JKQtBasePlotter *parent):
|
|
JKQTPOverlayImage(0,0,1,1,NULL,0,0, QColor("red"), parent)
|
|
{
|
|
symbol=JKQTPtarget;
|
|
symbolWidth=1;
|
|
drawAsRectangles=true;
|
|
symbolSizeFactor=0.9;
|
|
rectanglesAsImageOverlay=false;
|
|
}
|
|
|
|
void JKQTPOverlayImageEnhanced::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
|
if (drawAsRectangles) JKQTPOverlayImage::drawKeyMarker(painter, rect);
|
|
else plotSymbol(painter, rect.center().x(), rect.center().y(), symbol, qMin(rect.width(), rect.height()), parent->pt2px(painter, symbolWidth*parent->get_lineWidthMultiplier()), trueColor, trueColor.lighter());
|
|
}
|
|
|
|
void JKQTPOverlayImageEnhanced::draw(JKQTPEnhancedPainter& painter) {
|
|
if (!data) return;
|
|
|
|
if (drawAsRectangles && rectanglesAsImageOverlay) {
|
|
JKQTPOverlayImage::draw(painter);
|
|
} else {
|
|
|
|
painter.save();
|
|
|
|
double dx=width/(double)Nx;
|
|
double dy=height/(double)Ny;
|
|
for (int ix=0; ix<(int64_t)Nx; ix++) {
|
|
for (int iy=0; iy<(int64_t)Ny; iy++) {
|
|
QPointF p1=transform(x+(double)ix*dx, y+(double)iy*dy);
|
|
QPointF p2=transform(x+(double)(ix+1)*dx, y+(double)(iy+1)*dx);
|
|
if (drawAsRectangles) {
|
|
if (data[ix+iy*Nx]) {
|
|
if (trueColor.alpha()>0) {
|
|
painter.fillRect(QRectF(qMin(p1.x(), p2.x())-1.0, qMin(p2.y(), p1.y())-1.0, fabs(p2.x()-p1.x())+1.0, fabs(p2.y()-p1.y())+1.0), QBrush(trueColor));
|
|
//painter.setPen(QPen(trueColor));
|
|
//painter.drawRect(QRectF(qMin(p1.x(), p2.x()), qMin(p2.y(), p1.y()), fabs(p2.x()-p1.x()), fabs(p2.y()-p1.y())));
|
|
}
|
|
} else {
|
|
if (falseColor.alpha()>0) {
|
|
//painter.setPen(QPen(falseColor));
|
|
painter.fillRect(QRectF(qMin(p1.x(), p2.x())-1.0, qMin(p2.y(), p1.y())-1.0, fabs(p2.x()-p1.x())+1.0, fabs(p2.y()-p1.y())+1.0), QBrush(falseColor));
|
|
//painter.drawRect(QRectF(qMin(p1.x(), p2.x()), qMin(p2.y(), p1.y()), fabs(p2.x()-p1.x()), fabs(p2.y()-p1.y())));
|
|
}
|
|
}
|
|
} else {
|
|
QPointF p=(p1+p2)/2.0;
|
|
if (data[ix+iy*Nx]) {
|
|
plotSymbol(painter, p.x(), p.y(), symbol, fabs(p2.x()-p1.x())*symbolSizeFactor, parent->pt2px(painter, symbolWidth*parent->get_lineWidthMultiplier()), trueColor, trueColor.lighter());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
painter.restore();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JKQTPRGBMathImage::JKQTPRGBMathImage(double x, double y, double width, double height, DataType datatype, void* data, uint32_t Nx, uint32_t Ny, JKQtBasePlotter *parent):
|
|
JKQTPMathImageBase(x, y, width, height, datatype, data, Nx, Ny, parent)
|
|
{
|
|
actSaveImage=new QAction(tr("Save JKQTPRGBMathImage ..."), this);
|
|
connect(actSaveImage, SIGNAL(triggered()), this, SLOT(saveImagePlotAsImage()));
|
|
actCopyImage=new QAction(tr("Copy JKQTPOverlayImage ..."), this);
|
|
connect(actCopyImage, SIGNAL(triggered()), this, SLOT(copyImagePlotAsImage()));
|
|
|
|
rgbMode=JKQTPRGBMathImageModeRGBMode;
|
|
colorBarRightAxis=new JKQTPverticalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarRightAxis->loadSettings(parent->getYAxis());
|
|
colorBarRightAxis->set_drawMode1(JKQTPCADMline);
|
|
colorBarRightAxis->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarRightAxis->set_axisLabel("");
|
|
colorBarRightAxis->set_minTicks(5);
|
|
colorBarRightAxis->set_minorTicks(0);
|
|
colorBarRightAxis->set_tickOutsideLength(0);
|
|
colorBarRightAxis->set_minorTickOutsideLength(0);
|
|
colorBarRightAxis->set_showZeroAxis(false);
|
|
colorBarTopAxis=new JKQTPhorizontalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarTopAxis->loadSettings(parent->getXAxis());
|
|
colorBarTopAxis->set_drawMode1(JKQTPCADMline);
|
|
colorBarTopAxis->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarTopAxis->set_axisLabel("");
|
|
colorBarTopAxis->set_minTicks(3);
|
|
colorBarTopAxis->set_minorTicks(0);
|
|
colorBarTopAxis->set_tickOutsideLength(0);
|
|
colorBarTopAxis->set_minorTickOutsideLength(0);
|
|
colorBarTopAxis->set_showZeroAxis(false);
|
|
|
|
colorBarRightAxisG=new JKQTPverticalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarRightAxisG->loadSettings(parent->getYAxis());
|
|
colorBarRightAxisG->set_drawMode1(JKQTPCADMline);
|
|
colorBarRightAxisG->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarRightAxisG->set_axisLabel("");
|
|
colorBarRightAxisG->set_minTicks(5);
|
|
colorBarRightAxisG->set_showZeroAxis(false);
|
|
colorBarRightAxisG->set_minorTicks(0);
|
|
colorBarRightAxisG->set_tickOutsideLength(0);
|
|
colorBarRightAxisG->set_minorTickOutsideLength(0);
|
|
colorBarTopAxisG=new JKQTPhorizontalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarTopAxisG->loadSettings(parent->getXAxis());
|
|
colorBarTopAxisG->set_drawMode1(JKQTPCADMline);
|
|
colorBarTopAxisG->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarTopAxisG->set_axisLabel("");
|
|
colorBarTopAxisG->set_minTicks(3);
|
|
colorBarTopAxisG->set_showZeroAxis(false);
|
|
colorBarTopAxisG->set_minorTicks(0);
|
|
colorBarTopAxisG->set_tickOutsideLength(0);
|
|
colorBarTopAxisG->set_minorTickOutsideLength(0);
|
|
|
|
colorBarRightAxisB=new JKQTPverticalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarRightAxisB->loadSettings(parent->getYAxis());
|
|
colorBarRightAxisB->set_drawMode1(JKQTPCADMline);
|
|
colorBarRightAxisB->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarRightAxisB->set_axisLabel("");
|
|
colorBarRightAxisB->set_minTicks(5);
|
|
colorBarRightAxisB->set_showZeroAxis(false);
|
|
colorBarRightAxisB->set_minorTicks(0);
|
|
colorBarRightAxisB->set_tickOutsideLength(0);
|
|
colorBarRightAxisB->set_minorTickOutsideLength(0);
|
|
colorBarTopAxisB=new JKQTPhorizontalIndependentAxis(0, 100, 0, 100, parent);
|
|
if (parent) colorBarTopAxisB->loadSettings(parent->getXAxis());
|
|
colorBarTopAxisB->set_drawMode1(JKQTPCADMline);
|
|
colorBarTopAxisB->set_drawMode2(JKQTPCADMcomplete);
|
|
colorBarTopAxisB->set_axisLabel("");
|
|
colorBarTopAxisB->set_minTicks(3);
|
|
colorBarTopAxisB->set_showZeroAxis(false);
|
|
colorBarTopAxisB->set_minorTicks(0);
|
|
colorBarTopAxisB->set_tickOutsideLength(0);
|
|
colorBarTopAxisB->set_minorTickOutsideLength(0);
|
|
|
|
|
|
this->colorBarTopVisible=true;
|
|
this->colorBarRightVisible=true;
|
|
this->imageNameFontName=parent->get_keyFont();
|
|
this->imageNameFontSize=parent->get_keyFontSize();
|
|
this->imageName="";
|
|
this->showColorBar=true;
|
|
this->colorBarWidth=14;
|
|
this->colorBarRelativeHeight=0.75;
|
|
this->autoImageRange=true;
|
|
this->imageMin=0;
|
|
this->imageMax=1;
|
|
this->imageMinG=0;
|
|
this->imageMaxG=1;
|
|
this->imageMinB=0;
|
|
this->imageMaxB=1;
|
|
this->colorBarOffset=4;
|
|
this->colorBarTopVisible=false;
|
|
this->colorBarRightVisible=true;
|
|
this->colorbarsSideBySide=true;
|
|
}
|
|
|
|
void JKQTPRGBMathImage::setParent(JKQtBasePlotter* parent) {
|
|
if (this->parent) {
|
|
this->parent->deregisterAdditionalAction(actSaveImage);
|
|
this->parent->deregisterAdditionalAction(actCopyImage);
|
|
}
|
|
JKQTPMathImageBase::setParent(parent);
|
|
colorBarRightAxis->set_parent(parent);
|
|
colorBarTopAxis->set_parent(parent);
|
|
|
|
if (parent) {
|
|
parent->registerAdditionalAction(tr("Save Image Plot Images ..."), actSaveImage);
|
|
parent->registerAdditionalAction(tr("Copy Image Plot Images ..."), actCopyImage);
|
|
}
|
|
actSaveImage->setEnabled(parent);
|
|
actCopyImage->setEnabled(parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPRGBMathImage::draw(JKQTPEnhancedPainter& painter) {
|
|
ensureImageData();
|
|
if (!data && !dataG && !dataB) return;
|
|
QImage img=drawImage();
|
|
plotImage(painter, img, x, y, width, height);
|
|
}
|
|
|
|
|
|
|
|
void JKQTPRGBMathImage::getOutsideSize(JKQTPEnhancedPainter& painter, int& leftSpace, int& rightSpace, int& topSpace, int& bottomSpace) {
|
|
ensureImageData();
|
|
JKQTPgraph::getOutsideSize(painter, leftSpace, rightSpace, topSpace, bottomSpace);
|
|
if (showColorBar) {
|
|
int visibleColorBars=0;
|
|
if (data) visibleColorBars++;
|
|
if (dataG) visibleColorBars++;
|
|
if (dataB) visibleColorBars++;
|
|
double sizeFactor=0.8/double(visibleColorBars);
|
|
if (!colorbarsSideBySide) sizeFactor=1;
|
|
|
|
bool firstC=false;
|
|
|
|
getDataMinMax(internalDataMin, internalDataMax);
|
|
if (data) {
|
|
if (colorBarRightVisible) {
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) rightSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset);
|
|
colorBarRightAxis->setRange(internalDataMin, internalDataMax);
|
|
colorBarRightAxis->set_axisWidth(sizeFactor*colorBarRelativeHeight*parent->get_plotHeight());
|
|
colorBarRightAxisB->set_axisLabel(imageName);
|
|
QSize s=colorBarRightAxis->getSize2(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) rightSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset)+(double)s.width();
|
|
/*QSize s=colorBarRightAxis->getSize2(painter);
|
|
parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageName);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) rightSpace+=colorBarWidth+colorBarOffset+qMax((double)s.width(), (double)names.width());*/
|
|
}
|
|
if (colorBarTopVisible) {
|
|
//if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) topSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset);
|
|
colorBarTopAxis->setRange(internalDataMin, internalDataMax);
|
|
colorBarTopAxis->set_axisWidth(sizeFactor*colorBarRelativeHeight*parent->get_plotWidth());
|
|
colorBarTopAxisB->set_axisLabel(imageName);
|
|
QSize s=colorBarTopAxisB->getSize2(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) topSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset)+(double)s.height();
|
|
/*QSize s=colorBarTopAxis->getSize2(painter);
|
|
parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageName);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) topSpace+=colorBarWidth+colorBarOffset+qMax((double)s.height(), (double)names.height());*/
|
|
}
|
|
firstC=true;
|
|
}
|
|
|
|
getDataMinMaxG(internalDataMinG, internalDataMaxG);
|
|
if (dataG) {
|
|
if (colorBarRightVisible) {
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) rightSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset);
|
|
colorBarRightAxisG->setRange(internalDataMinG, internalDataMaxG);
|
|
colorBarRightAxisG->set_axisWidth(sizeFactor*colorBarRelativeHeight*parent->get_plotHeight());
|
|
colorBarRightAxisB->set_axisLabel(imageNameG);
|
|
QSize s=colorBarRightAxis->getSize2(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) rightSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset)+(double)s.width();
|
|
/*QSize s=colorBarRightAxis->getSize2(painter);
|
|
parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageNameG);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) rightSpace+=colorBarWidth+colorBarOffset+qMax((double)s.width(), (double)names.width());*/
|
|
}
|
|
if (colorBarTopVisible) {
|
|
//if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) topSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset);
|
|
colorBarTopAxisG->setRange(internalDataMinG, internalDataMaxG);
|
|
colorBarTopAxisG->set_axisWidth(sizeFactor*colorBarRelativeHeight*parent->get_plotWidth());
|
|
colorBarTopAxisB->set_axisLabel(imageNameG);
|
|
QSize s=colorBarTopAxisB->getSize2(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) topSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset)+(double)s.height();
|
|
/*QSize s=colorBarTopAxisG->getSize2(painter);
|
|
parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageNameG);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) topSpace+=colorBarWidth+colorBarOffset+qMax((double)s.height(), (double)names.height());*/
|
|
}
|
|
firstC=true;
|
|
}
|
|
|
|
getDataMinMaxB(internalDataMinB, internalDataMaxB);
|
|
if (dataB) {
|
|
if (colorBarRightVisible) {
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) rightSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset);
|
|
colorBarRightAxisB->setRange(internalDataMinB, internalDataMaxB);
|
|
colorBarRightAxisB->set_axisWidth(sizeFactor*colorBarRelativeHeight*parent->get_plotHeight());
|
|
colorBarRightAxisB->set_axisLabel(imageNameB);
|
|
QSize s=colorBarRightAxis->getSize2(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) rightSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset)+(double)s.width();
|
|
/*
|
|
parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageNameB);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) rightSpace+=colorBarWidth+colorBarOffset+qMax((double)s.width(), (double)names.width());*/
|
|
}
|
|
if (colorBarTopVisible) {
|
|
//if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) topSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset);
|
|
colorBarTopAxisB->setRange(internalDataMinB, internalDataMaxB);
|
|
colorBarTopAxisB->set_axisWidth(sizeFactor*colorBarRelativeHeight*parent->get_plotWidth());
|
|
colorBarTopAxisB->set_axisLabel(imageNameB);
|
|
QSize s=colorBarTopAxisB->getSize2(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) topSpace+=parent->pt2px(painter, colorBarWidth+colorBarOffset)+(double)s.height();
|
|
/*parent->get_mathText()->set_fontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
parent->get_mathText()->set_fontRoman(imageNameFontName);
|
|
parent->get_mathText()->parse(imageNameB);
|
|
QSizeF names=parent->get_mathText()->getSize(painter);
|
|
if (!colorbarsSideBySide || (colorbarsSideBySide && !firstC)) topSpace+=colorBarWidth+colorBarOffset+qMax((double)s.height(), (double)names.height());*/
|
|
}
|
|
firstC=true;
|
|
}
|
|
}
|
|
}
|
|
|
|
struct RGBOutsizeData {
|
|
double internalDataMin;
|
|
double internalDataMax;
|
|
void* data;
|
|
JKQTPverticalIndependentAxis* colorBarRightAxis;
|
|
JKQTPhorizontalIndependentAxis* colorBarTopAxis;
|
|
QString name;
|
|
JKQTPMathImageColorPalette palette;
|
|
QImage paletteImage;
|
|
};
|
|
|
|
void JKQTPRGBMathImage::drawOutside(JKQTPEnhancedPainter& painter, QRect /*leftSpace*/, QRect rightSpace, QRect topSpace, QRect /*bottomSpace*/) {
|
|
ensureImageData();
|
|
if (showColorBar) {
|
|
QList<RGBOutsizeData> l;
|
|
int visibleColorBars=0;
|
|
const int pd_size=200;
|
|
uint8_t pd[pd_size];
|
|
for (int i=0; i<pd_size; i++) pd[i]=i;
|
|
|
|
if (data) {
|
|
RGBOutsizeData d;
|
|
d.data=data;
|
|
getDataMinMax(internalDataMin, internalDataMax);
|
|
d.internalDataMin=internalDataMin;
|
|
d.internalDataMax=internalDataMax;
|
|
d.colorBarRightAxis=colorBarRightAxis;
|
|
d.colorBarTopAxis=colorBarTopAxis;
|
|
d.name=imageName;
|
|
if (rgbMode==JKQTPRGBMathImageModeRGBMode) {
|
|
d.palette=JKQTPMathImageRED;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, d.palette, 0, pd_size-1);
|
|
} else if (rgbMode==JKQTPRGBMathImageModeCMYMode) {
|
|
d.palette=JKQTPMathImageINVERTED_CYANWHITE;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, d.palette, 0, pd_size-1);
|
|
} else if (rgbMode==JKQTPRGBMathImageModeHSVMode || rgbMode==JKQTPRGBMathImageModeHSLMode) {
|
|
d.palette=JKQTPMathImageHSV;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, d.palette, 0, pd_size-1);
|
|
}
|
|
|
|
l<<d;
|
|
visibleColorBars++;
|
|
}
|
|
if (dataG) {
|
|
RGBOutsizeData d;
|
|
d.data=dataG;
|
|
getDataMinMaxG(internalDataMinG, internalDataMaxG);
|
|
d.internalDataMin=internalDataMinG;
|
|
d.internalDataMax=internalDataMaxG;
|
|
d.colorBarRightAxis=colorBarRightAxisG;
|
|
d.colorBarTopAxis=colorBarTopAxisG;
|
|
d.name=imageNameG;
|
|
JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, d.palette, 0, 199);
|
|
if (rgbMode==JKQTPRGBMathImageModeRGBMode) {
|
|
d.palette=JKQTPMathImageGREEN;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, d.palette, 0, pd_size-1);
|
|
} else if (rgbMode==JKQTPRGBMathImageModeCMYMode) {
|
|
d.palette=JKQTPMathImageINVERTED_MAGENTAWHITE;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, d.palette, 0, pd_size-1);
|
|
} else if (rgbMode==JKQTPRGBMathImageModeHSVMode) {
|
|
d.palette=JKQTPMathImageGRAY;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
//JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, l[li].palette, 0, pd_size-1);
|
|
QRgb* line=(QRgb*)(d.paletteImage.scanLine(0));
|
|
for (int i=0; i<pd_size; i++) {
|
|
QColor c=QColor("red");
|
|
c.setHsv(c.hue(), double(i)/double(pd_size-1)*255.0, c.value(), c.alpha());
|
|
line[i]=c.rgba();
|
|
}
|
|
} else if (rgbMode==JKQTPRGBMathImageModeHSLMode) {
|
|
d.palette=JKQTPMathImageGRAY;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
//JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, l[li].palette, 0, pd_size-1);
|
|
QRgb* line=(QRgb*)(d.paletteImage.scanLine(0));
|
|
for (int i=0; i<pd_size; i++) {
|
|
QColor c=QColor("red");
|
|
c.setHsl(c.hue(), double(i)/double(pd_size-1)*255.0, c.lightness(), c.alpha());
|
|
line[i]=c.rgba();
|
|
}
|
|
}
|
|
|
|
l<<d;
|
|
visibleColorBars++;
|
|
}
|
|
if (dataB) {
|
|
RGBOutsizeData d;
|
|
d.data=dataB;
|
|
getDataMinMax(internalDataMinB, internalDataMaxB);
|
|
d.internalDataMin=internalDataMinB;
|
|
d.internalDataMax=internalDataMaxB;
|
|
d.colorBarRightAxis=colorBarRightAxisB;
|
|
d.colorBarTopAxis=colorBarTopAxisB;
|
|
d.name=imageNameB;
|
|
JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, d.palette, 0, 199);
|
|
if (rgbMode==JKQTPRGBMathImageModeRGBMode) {
|
|
d.palette=JKQTPMathImageBLUE;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, d.palette, 0, pd_size-1);
|
|
} else if (rgbMode==JKQTPRGBMathImageModeCMYMode) {
|
|
d.palette=JKQTPMathImageINVERTED_YELLOWWHITE;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, d.palette, 0, pd_size-1);
|
|
} else if (rgbMode==JKQTPRGBMathImageModeHSVMode) {
|
|
d.palette=JKQTPMathImageGRAY;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
//JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, l[li].palette, 0, pd_size-1);
|
|
QRgb* line=(QRgb*)(d.paletteImage.scanLine(0));
|
|
for (int i=0; i<pd_size; i++) {
|
|
QColor c=QColor("red");
|
|
c.setHsv(c.hue(), c.saturation(), double(i)/double(pd_size-1)*255.0, c.alpha());
|
|
line[i]=c.rgba();
|
|
}
|
|
} else if (rgbMode==JKQTPRGBMathImageModeHSLMode) {
|
|
d.palette=JKQTPMathImageGRAY;
|
|
d.paletteImage=QImage(1, pd_size, QImage::Format_ARGB32);
|
|
//JKQTPimagePlot_array2image<uint8_t>(pd, 1, pd_size, d.paletteImage, l[li].palette, 0, pd_size-1);
|
|
QRgb* line=(QRgb*)(d.paletteImage.scanLine(0));
|
|
for (int i=0; i<pd_size; i++) {
|
|
QColor c=QColor("red");
|
|
c.setHsl(c.hue(), c.saturation(), double(i)/double(pd_size-1)*255.0, c.alpha());
|
|
line[i]=c.rgba();
|
|
}
|
|
}
|
|
l<<d;
|
|
visibleColorBars++;
|
|
}
|
|
|
|
|
|
double sizeFactor=0.9/double(visibleColorBars);
|
|
double shiftSizeFactor=1.0/double(visibleColorBars);
|
|
if (!colorbarsSideBySide) {
|
|
sizeFactor=1;
|
|
shiftSizeFactor=1;
|
|
}
|
|
double icolorBarRelativeHeight=colorBarRelativeHeight*sizeFactor;
|
|
|
|
int gbarHeight=qMax(1, (int)round((double)rightSpace.height()*icolorBarRelativeHeight));
|
|
int gbarWidth=qMax(1, (int)round((double)topSpace.width()*icolorBarRelativeHeight));
|
|
|
|
|
|
|
|
double rX=rightSpace.x()+parent->pt2px(painter, colorBarOffset);
|
|
double rY=rightSpace.top()+(rightSpace.height()-gbarHeight)/2;
|
|
double tX=topSpace.x()+(topSpace.width()-gbarWidth)/2;
|
|
double tY=topSpace.bottom()-parent->pt2px(painter, colorBarOffset+colorBarWidth);
|
|
if(colorbarsSideBySide) {
|
|
rY=rightSpace.top()+(rightSpace.height()-gbarHeight*visibleColorBars)/2;
|
|
tX=topSpace.x()+(topSpace.width()-gbarWidth*visibleColorBars)/2;
|
|
}
|
|
|
|
|
|
for (int li=0; li<l.size(); li++) {
|
|
if (colorBarRightVisible) {
|
|
painter.save();
|
|
|
|
|
|
QRect cb(rX, rY, parent->pt2px(painter, colorBarWidth), gbarHeight);
|
|
painter.drawImage(cb, l[li].paletteImage.mirrored(true, false));
|
|
QPen p=painter.pen();
|
|
p.setColor(l[li].colorBarRightAxis->get_axisColor());
|
|
p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, l[li].colorBarRightAxis->get_lineWidth()*parent->get_lineWidthMultiplier())));
|
|
painter.setPen(p);
|
|
painter.drawRect(cb);
|
|
|
|
l[li].colorBarRightAxis->setRange(l[li].internalDataMin, l[li].internalDataMax);
|
|
l[li].colorBarRightAxis->set_axisWidth(cb.height());
|
|
l[li].colorBarRightAxis->set_axisOffset(cb.top());
|
|
l[li].colorBarRightAxis->set_otherAxisOffset(cb.left());
|
|
l[li].colorBarRightAxis->set_otherAxisWidth(cb.width());
|
|
l[li].colorBarRightAxis->set_labelFontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
l[li].colorBarRightAxis->set_labelFont(imageNameFontName);
|
|
l[li].colorBarRightAxis->set_axisLabel(l[li].name);
|
|
l[li].colorBarRightAxis->drawAxes(painter);
|
|
|
|
painter.restore();
|
|
|
|
if (!colorbarsSideBySide) {
|
|
rX=rX+(double)rightSpace.width()/double(visibleColorBars);
|
|
} else {
|
|
rY=rY+(double)rightSpace.height()*shiftSizeFactor*colorBarRelativeHeight;
|
|
}
|
|
}
|
|
if (colorBarTopVisible) {
|
|
painter.save();
|
|
|
|
|
|
QRect cb(tX, tY, gbarWidth, parent->pt2px(painter, colorBarWidth));
|
|
QMatrix mt;
|
|
mt.rotate(90);
|
|
painter.drawImage(cb, l[li].paletteImage.transformed(mt));
|
|
QPen p=painter.pen();
|
|
p.setColor(l[li].colorBarTopAxis->get_axisColor());
|
|
p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, l[li].colorBarTopAxis->get_lineWidth()*parent->get_lineWidthMultiplier())));
|
|
painter.setPen(p);
|
|
painter.drawRect(cb);
|
|
|
|
|
|
l[li].colorBarTopAxis->setRange(l[li].internalDataMin, l[li].internalDataMax);
|
|
l[li].colorBarTopAxis->set_axisWidth(cb.width());
|
|
l[li].colorBarTopAxis->set_axisOffset(cb.left());
|
|
l[li].colorBarTopAxis->set_otherAxisOffset(cb.top());
|
|
l[li].colorBarTopAxis->set_otherAxisWidth(cb.height());
|
|
l[li].colorBarTopAxis->set_labelFontSize(imageNameFontSize*parent->get_fontSizeMultiplier());
|
|
l[li].colorBarTopAxis->set_labelFont(imageNameFontName);
|
|
l[li].colorBarTopAxis->set_axisLabel(l[li].name);
|
|
l[li].colorBarTopAxis->drawAxes(painter);
|
|
|
|
painter.restore();
|
|
if (!colorbarsSideBySide) {
|
|
tY=tY-topSpace.height()/double(visibleColorBars);
|
|
} else {
|
|
tX=tX+topSpace.width()*shiftSizeFactor*colorBarRelativeHeight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void JKQTPRGBMathImage::getDataMinMax(double& imin, double& imax) {
|
|
ensureImageData();
|
|
if (autoImageRange) {
|
|
JKQTPMathImageBase::getDataMinMax(imin, imax);
|
|
} else {
|
|
imin=imageMin;
|
|
imax=imageMax;
|
|
}
|
|
}
|
|
|
|
void JKQTPRGBMathImage::getDataMinMaxG(double& imin, double& imax) {
|
|
ensureImageData();
|
|
if (autoImageRange) {
|
|
imin=imax=0;
|
|
if (!dataG) return;
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray:
|
|
imin= JKQTPimagePlot_getImageMin<double>((double*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<double>((double*)dataG, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::FloatArray:
|
|
imin= JKQTPimagePlot_getImageMin<float>((float*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<float>((float*)dataG, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt8Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint8_t>((uint8_t*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint8_t>((uint8_t*)dataG, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt16Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint16_t>((uint16_t*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint16_t>((uint16_t*)dataG, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt32Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint32_t>((uint32_t*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint32_t>((uint32_t*)dataG, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt64Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint64_t>((uint64_t*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint64_t>((uint64_t*)dataG, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int8Array:
|
|
imin= JKQTPimagePlot_getImageMin<int8_t>((int8_t*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int8_t>((int8_t*)dataG, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int16Array:
|
|
imin= JKQTPimagePlot_getImageMin<int16_t>((int16_t*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int16_t>((int16_t*)dataG, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int32Array:
|
|
imin= JKQTPimagePlot_getImageMin<int32_t>((int32_t*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int32_t>((int32_t*)dataG, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int64Array:
|
|
imin= JKQTPimagePlot_getImageMin<int64_t>((int64_t*)dataG, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int64_t>((int64_t*)dataG, Nx, Ny);
|
|
break;
|
|
}
|
|
} else {
|
|
imin=imageMinG;
|
|
imax=imageMaxG;
|
|
}
|
|
}
|
|
|
|
void JKQTPRGBMathImage::getDataMinMaxB(double& imin, double& imax) {
|
|
ensureImageData();
|
|
if (autoImageRange) {
|
|
imin=imax=0;
|
|
if (!dataG) return;
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray:
|
|
imin= JKQTPimagePlot_getImageMin<double>((double*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<double>((double*)dataB, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::FloatArray:
|
|
imin= JKQTPimagePlot_getImageMin<float>((float*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<float>((float*)dataB, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt8Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint8_t>((uint8_t*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint8_t>((uint8_t*)dataB, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt16Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint16_t>((uint16_t*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint16_t>((uint16_t*)dataB, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt32Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint32_t>((uint32_t*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint32_t>((uint32_t*)dataB, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt64Array:
|
|
imin= JKQTPimagePlot_getImageMin<uint64_t>((uint64_t*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<uint64_t>((uint64_t*)dataB, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int8Array:
|
|
imin= JKQTPimagePlot_getImageMin<int8_t>((int8_t*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int8_t>((int8_t*)dataB, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int16Array:
|
|
imin= JKQTPimagePlot_getImageMin<int16_t>((int16_t*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int16_t>((int16_t*)dataB, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int32Array:
|
|
imin= JKQTPimagePlot_getImageMin<int32_t>((int32_t*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int32_t>((int32_t*)dataB, Nx, Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int64Array:
|
|
imin= JKQTPimagePlot_getImageMin<int64_t>((int64_t*)dataB, Nx, Ny);
|
|
imax= JKQTPimagePlot_getImageMax<int64_t>((int64_t*)dataB, Nx, Ny);
|
|
break;
|
|
}
|
|
} else {
|
|
imin=imageMinB;
|
|
imax=imageMaxB;
|
|
}
|
|
}
|
|
|
|
double JKQTPRGBMathImage::getValueAt(double x, double y, int channel)
|
|
{
|
|
ensureImageData();
|
|
void* dd=data;
|
|
if (channel==0) dd=data;
|
|
if (channel==1) dd=dataG;
|
|
if (channel==2) dd=dataB;
|
|
int xx=trunc((x-this->x)/width*double(Nx));
|
|
int yy=trunc((y-this->y)/height*double(Ny));
|
|
if (xx>=0 && xx<(int64_t)Nx && yy>=0 && yy<(int64_t)Ny) {
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray: return ((double*)dd)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::FloatArray: return ((float*)dd)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::UInt8Array: return ((uint8_t*)dd)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::UInt16Array: return ((uint16_t*)dd)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::UInt32Array: return ((uint32_t*)dd)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::UInt64Array: return ((uint64_t*)dd)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::Int8Array: return ((int8_t*)dd)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::Int16Array: return ((int16_t*)dd)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::Int32Array: return ((int32_t*)dd)[yy*Nx+xx]; break;
|
|
case JKQTPMathImageBase::Int64Array: return ((int64_t*)dd)[yy*Nx+xx]; break;
|
|
} }
|
|
return 0.0;
|
|
}
|
|
|
|
void JKQTPRGBMathImage::drawKeyMarker(JKQTPEnhancedPainter &painter, QRectF &rect)
|
|
{
|
|
painter.drawImage(rect, QPixmap(":/jkqtp_plot_rgbimage.png").toImage());
|
|
}
|
|
|
|
void JKQTPRGBMathImage::set_title(const JKQTPgraph::typedef_set_title &title)
|
|
{
|
|
JKQTPImageBase::set_title(title);
|
|
QString t=title;
|
|
if (t.isEmpty()) t="JKQTPRGBMathImage";
|
|
actSaveImage->setText(tr("Save %1 ...").arg(t));
|
|
actCopyImage->setText(tr("Copy %1 ...").arg(t));
|
|
}
|
|
|
|
void JKQTPRGBMathImage::saveImagePlotAsImage(const QString &filename, const QByteArray &outputFormat)
|
|
{
|
|
if (parent) {
|
|
parent->loadUserSettings();
|
|
QString currentSaveDirectory=parent->get_currentSaveDirectory();
|
|
QString currentFileFormat=parent->get_currentFileFormat();
|
|
QString fn=filename;
|
|
QStringList filt;
|
|
QList<QByteArray> writerformats=QImageWriter::supportedImageFormats();
|
|
for (int i=0; i<writerformats.size(); i++) {
|
|
filt<<QString("%1 Image (*.%2)").arg(QString(writerformats[i]).toUpper()).arg(QString(writerformats[i].toLower()));
|
|
}
|
|
QString selFormat;
|
|
if (fn.isEmpty()) {
|
|
selFormat=currentFileFormat;
|
|
fn = QFileDialog::getSaveFileName(NULL, tr("Save Image Plot As Image ..."),
|
|
currentSaveDirectory,
|
|
filt.join(";;"), &selFormat);
|
|
if (!fn.isEmpty()) currentSaveDirectory=QFileInfo(fn).absolutePath();
|
|
}
|
|
|
|
parent->set_currentFileFormat(currentFileFormat);
|
|
parent->set_currentSaveDirectory(currentSaveDirectory);
|
|
parent->saveUserSettings();
|
|
if (!fn.isEmpty()) {
|
|
int filtID=filt.indexOf(selFormat);
|
|
QString form="NONE";
|
|
if (filtID>=0 && filtID<writerformats.size()) {
|
|
form=writerformats[filtID];
|
|
}
|
|
if (outputFormat.size()>0) {
|
|
form =outputFormat;
|
|
}
|
|
|
|
QImage image=drawImage();
|
|
|
|
if (form=="NONE") image.save(fn);
|
|
else image.save(fn, form.toLatin1().data());
|
|
}
|
|
}
|
|
}
|
|
|
|
void JKQTPRGBMathImage::copyImagePlotAsImage()
|
|
{
|
|
QClipboard* clip=QApplication::clipboard();
|
|
if (clip) {
|
|
clip->setImage(drawImage());
|
|
}
|
|
}
|
|
|
|
QImage JKQTPRGBMathImage::drawImage() {
|
|
ensureImageData();
|
|
if (!data && !dataG && !dataB) return QImage();
|
|
QImage img(Nx, Ny, QImage::Format_ARGB32);
|
|
|
|
if (rgbMode==JKQTPRGBMathImageModeRGBMode) {
|
|
img.fill(Qt::transparent);
|
|
} else if (rgbMode==JKQTPRGBMathImageModeCMYMode) {
|
|
img.fill(Qt::white);
|
|
} else if (rgbMode==JKQTPRGBMathImageModeHSVMode) {
|
|
QColor c("white");
|
|
c.setHsv(0,255,255);
|
|
img.fill(c.rgba());
|
|
} else if (rgbMode==JKQTPRGBMathImageModeHSLMode) {
|
|
QColor c("white");
|
|
c.setHsv(0,255,127);
|
|
img.fill(c.rgba());
|
|
}
|
|
getDataMinMax(internalDataMin, internalDataMax);
|
|
getDataMinMaxG(internalDataMinG, internalDataMaxG);
|
|
getDataMinMaxB(internalDataMinB, internalDataMaxB);
|
|
int palette = 0;
|
|
if (data) {
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray: JKQTPimagePlot_array2RGBimage<double>((double*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
case JKQTPMathImageBase::FloatArray: JKQTPimagePlot_array2RGBimage<float>((float*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt8Array: JKQTPimagePlot_array2RGBimage<uint8_t>((uint8_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt16Array: JKQTPimagePlot_array2RGBimage<uint16_t>((uint16_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt32Array: JKQTPimagePlot_array2RGBimage<uint32_t>((uint32_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt64Array: JKQTPimagePlot_array2RGBimage<uint64_t>((uint64_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
case JKQTPMathImageBase::Int8Array: JKQTPimagePlot_array2RGBimage<int8_t>((int8_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
case JKQTPMathImageBase::Int16Array: JKQTPimagePlot_array2RGBimage<int16_t>((int16_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
case JKQTPMathImageBase::Int32Array: JKQTPimagePlot_array2RGBimage<int32_t>((int32_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
case JKQTPMathImageBase::Int64Array: JKQTPimagePlot_array2RGBimage<int64_t>((int64_t*)data, Nx, Ny, img, palette, internalDataMin, internalDataMax, rgbMode); break;
|
|
}
|
|
}
|
|
palette = 1;
|
|
if (dataG) {
|
|
switch(datatypeG) {
|
|
case JKQTPMathImageBase::DoubleArray: JKQTPimagePlot_array2RGBimage<double>((double*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
case JKQTPMathImageBase::FloatArray: JKQTPimagePlot_array2RGBimage<float>((float*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt8Array: JKQTPimagePlot_array2RGBimage<uint8_t>((uint8_t*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt16Array: JKQTPimagePlot_array2RGBimage<uint16_t>((uint16_t*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt32Array: JKQTPimagePlot_array2RGBimage<uint32_t>((uint32_t*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt64Array: JKQTPimagePlot_array2RGBimage<uint64_t>((uint64_t*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
case JKQTPMathImageBase::Int8Array: JKQTPimagePlot_array2RGBimage<int8_t>((int8_t*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
case JKQTPMathImageBase::Int16Array: JKQTPimagePlot_array2RGBimage<int16_t>((int16_t*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
case JKQTPMathImageBase::Int32Array: JKQTPimagePlot_array2RGBimage<int32_t>((int32_t*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
case JKQTPMathImageBase::Int64Array: JKQTPimagePlot_array2RGBimage<int64_t>((int64_t*)dataG, Nx, Ny, img, palette, internalDataMinG, internalDataMaxG, rgbMode); break;
|
|
}
|
|
}
|
|
palette = 2;
|
|
if (dataB) {
|
|
switch(datatypeB) {
|
|
case JKQTPMathImageBase::DoubleArray: JKQTPimagePlot_array2RGBimage<double>((double*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
case JKQTPMathImageBase::FloatArray: JKQTPimagePlot_array2RGBimage<float>((float*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt8Array: JKQTPimagePlot_array2RGBimage<uint8_t>((uint8_t*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt16Array: JKQTPimagePlot_array2RGBimage<uint16_t>((uint16_t*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt32Array: JKQTPimagePlot_array2RGBimage<uint32_t>((uint32_t*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
case JKQTPMathImageBase::UInt64Array: JKQTPimagePlot_array2RGBimage<uint64_t>((uint64_t*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
case JKQTPMathImageBase::Int8Array: JKQTPimagePlot_array2RGBimage<int8_t>((int8_t*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
case JKQTPMathImageBase::Int16Array: JKQTPimagePlot_array2RGBimage<int16_t>((int16_t*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
case JKQTPMathImageBase::Int32Array: JKQTPimagePlot_array2RGBimage<int32_t>((int32_t*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
case JKQTPMathImageBase::Int64Array: JKQTPimagePlot_array2RGBimage<int64_t>((int64_t*)dataB, Nx, Ny, img, palette, internalDataMinB, internalDataMaxB, rgbMode); break;
|
|
}
|
|
}
|
|
|
|
modifyImage(img);
|
|
|
|
return img;
|
|
}
|
|
|
|
void JKQTPRGBMathImage::set_data(void* data, uint32_t Nx, uint32_t Ny, DataType datatype) {
|
|
this->data=data;
|
|
this->datatype=datatype;
|
|
this->dataG=NULL;
|
|
this->dataB=NULL;
|
|
this->Nx=Nx;
|
|
this->Ny=Ny;
|
|
}
|
|
|
|
void JKQTPRGBMathImage::set_data(void* data, uint32_t Nx, uint32_t Ny) {
|
|
this->data=data;
|
|
this->Nx=Nx;
|
|
this->Ny=Ny;
|
|
this->dataG=NULL;
|
|
this->dataB=NULL;
|
|
}
|
|
|
|
|
|
void JKQTPRGBMathImage::set_data(void *data, void *dataG, void *dataB, uint32_t Nx, uint32_t Ny, JKQTPMathImageBase::DataType datatype) {
|
|
this->data=data;
|
|
this->datatype=datatype;
|
|
this->datatypeG=datatype;
|
|
this->datatypeB=datatype;
|
|
this->dataG=dataG;
|
|
this->dataB=dataB;
|
|
this->Nx=Nx;
|
|
this->Ny=Ny;
|
|
}
|
|
|
|
void JKQTPRGBMathImage::set_data(void *data, void *dataG, void *dataB, uint32_t Nx, uint32_t Ny) {
|
|
this->data=data;
|
|
this->dataG=dataG;
|
|
this->dataB=dataB;
|
|
this->Nx=Nx;
|
|
this->Ny=Ny;
|
|
}
|
|
|
|
|
|
|
|
JKQTPColumnMathImage::JKQTPColumnMathImage(JKQtBasePlotter *parent):
|
|
JKQTPMathImage(parent)
|
|
{
|
|
this->modifierColumn=-1;
|
|
this->imageColumn=-1;
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
}
|
|
|
|
JKQTPColumnMathImage::JKQTPColumnMathImage(double x, double y, double width, double height, uint32_t Nx, uint32_t Ny, JKQtBasePlotter *parent):
|
|
JKQTPMathImage(x,y,width,height,JKQTPMathImageBase::DoubleArray,NULL,Nx,Ny,JKQTPMathImageGRAY,parent)
|
|
{
|
|
this->modifierColumn=-1;
|
|
this->imageColumn=-1;
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
}
|
|
|
|
JKQTPColumnMathImage::JKQTPColumnMathImage(double x, double y, double width, double height, int imageColumn, uint32_t Nx, uint32_t Ny, JKQTPMathImageColorPalette palette, JKQtBasePlotter *parent):
|
|
JKQTPMathImage(x,y,width,height,JKQTPMathImageBase::DoubleArray,NULL,Nx,Ny,palette,parent)
|
|
{
|
|
this->modifierColumn=-1;
|
|
this->imageColumn=imageColumn;
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
}
|
|
|
|
bool JKQTPColumnMathImage::usesColumn(int c)
|
|
{
|
|
return (c==imageColumn)||(c==modifierColumn);
|
|
}
|
|
|
|
|
|
void JKQTPColumnMathImage::ensureImageData()
|
|
{
|
|
|
|
if (this->Nx==0 || imageColumn<0 || !parent->getDatastore()->getColumn(imageColumn).getPointer(0)) {
|
|
this->Ny=0;
|
|
this->data=NULL;
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
} else {
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
this->data=parent->getDatastore()->getColumn(imageColumn).getPointer(0);
|
|
this->Ny=parent->getDatastore()->getColumn(imageColumn).getRows()/this->Nx;
|
|
}
|
|
if (this->Nx==0 || modifierColumn<0 || !parent->getDatastore()->getColumn(modifierColumn).getPointer(0)) {
|
|
this->dataModifier=NULL;
|
|
} else {
|
|
this->datatypeModifier=JKQTPMathImageBase::DoubleArray;
|
|
this->dataModifier=parent->getDatastore()->getColumn(modifierColumn).getPointer(0);
|
|
}
|
|
}
|
|
|
|
JKQTPColumnOverlayImageEnhanced::JKQTPColumnOverlayImageEnhanced(JKQtBasePlotter *parent):
|
|
JKQTPOverlayImageEnhanced(parent)
|
|
{
|
|
imageColumn=-1;
|
|
}
|
|
|
|
void JKQTPColumnOverlayImageEnhanced::draw(JKQTPEnhancedPainter &painter) {
|
|
double* d=parent->getDatastore()->getColumn(imageColumn).getPointer(0);
|
|
int imgSize=parent->getDatastore()->getColumn(imageColumn).getRows();
|
|
this->data=(bool*)malloc(imgSize*sizeof(bool));
|
|
this->Ny=imgSize/this->Nx;
|
|
for (int i=0; i<imgSize; i++) {
|
|
data[i]=d[i];
|
|
}
|
|
JKQTPOverlayImageEnhanced::draw(painter);
|
|
free(data);
|
|
data=NULL;
|
|
}
|
|
|
|
bool JKQTPColumnOverlayImageEnhanced::usesColumn(int c)
|
|
{
|
|
return (c==imageColumn);
|
|
}
|
|
|
|
JKQTPColumnRGBMathImage::JKQTPColumnRGBMathImage(JKQtBasePlotter *parent):
|
|
JKQTPRGBMathImage(0,0,0,0,DoubleArray,NULL,0,0,parent)
|
|
{
|
|
this->modifierColumn=-1;
|
|
this->imageRColumn=-1;
|
|
this->imageGColumn=-1;
|
|
this->imageBColumn=-1;
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
}
|
|
|
|
JKQTPColumnRGBMathImage::JKQTPColumnRGBMathImage(double x, double y, double width, double height, uint32_t Nx, uint32_t Ny, JKQtBasePlotter *parent):
|
|
JKQTPRGBMathImage(x,y,width,height,DoubleArray,NULL,Nx,Ny,parent)
|
|
{
|
|
this->modifierColumn=-1;
|
|
this->imageRColumn=-1;
|
|
this->imageGColumn=-1;
|
|
this->imageBColumn=-1;
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
}
|
|
|
|
JKQTPColumnRGBMathImage::JKQTPColumnRGBMathImage(double x, double y, double width, double height, int imageRColumn, uint32_t Nx, uint32_t Ny, JKQtBasePlotter *parent):
|
|
JKQTPRGBMathImage(x,y,width,height,DoubleArray,NULL,Nx,Ny,parent)
|
|
{
|
|
this->modifierColumn=-1;
|
|
this->imageRColumn=imageRColumn;
|
|
this->imageGColumn=-1;
|
|
this->imageBColumn=-1;
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
}
|
|
|
|
JKQTPColumnRGBMathImage::JKQTPColumnRGBMathImage(double x, double y, double width, double height, int imageRColumn, int imageGColumn, uint32_t Nx, uint32_t Ny, JKQtBasePlotter *parent):
|
|
JKQTPRGBMathImage(x,y,width,height,DoubleArray,NULL,Nx,Ny,parent)
|
|
{
|
|
this->modifierColumn=-1;
|
|
this->imageRColumn=imageRColumn;
|
|
this->imageGColumn=imageGColumn;
|
|
this->imageBColumn=-1;
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
}
|
|
|
|
JKQTPColumnRGBMathImage::JKQTPColumnRGBMathImage(double x, double y, double width, double height, int imageRColumn, int imageGColumn, int imageBColumn, uint32_t Nx, uint32_t Ny, JKQtBasePlotter *parent):
|
|
JKQTPRGBMathImage(x,y,width,height,DoubleArray,NULL,Nx,Ny,parent)
|
|
{
|
|
this->modifierColumn=-1;
|
|
this->imageRColumn=imageRColumn;
|
|
this->imageGColumn=imageGColumn;
|
|
this->imageBColumn=imageBColumn;
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
}
|
|
|
|
bool JKQTPColumnRGBMathImage::usesColumn(int c)
|
|
{
|
|
return (c==imageRColumn)||(c==imageBColumn)||(c==imageGColumn)||(c==modifierColumn);
|
|
}
|
|
|
|
|
|
void JKQTPColumnRGBMathImage::ensureImageData()
|
|
{
|
|
this->datatype=JKQTPMathImageBase::DoubleArray;
|
|
this->datatypeG=JKQTPMathImageBase::DoubleArray;
|
|
this->datatypeB=JKQTPMathImageBase::DoubleArray;
|
|
this->data=parent->getDatastore()->getColumn(imageRColumn).getPointer(0);
|
|
this->dataG=parent->getDatastore()->getColumn(imageGColumn).getPointer(0);
|
|
this->dataB=parent->getDatastore()->getColumn(imageBColumn).getPointer(0);
|
|
this->Ny=parent->getDatastore()->getColumn(imageRColumn).getRows()/this->Nx;
|
|
this->datatypeModifier=JKQTPMathImageBase::DoubleArray;
|
|
this->dataModifier=parent->getDatastore()->getColumn(modifierColumn).getPointer(0);
|
|
}
|
|
|
|
JKQTPImageModifierModeComboBox::JKQTPImageModifierModeComboBox(QWidget */*parent*/)
|
|
{
|
|
addMode(JKQTPMathImageBase::ModifyNone, tr("none"));
|
|
addMode(JKQTPMathImageBase::ModifyValue, tr("value"));
|
|
addMode(JKQTPMathImageBase::ModifySaturation, tr("saturation"));
|
|
addMode(JKQTPMathImageBase::ModifyAlpha, tr("alpha"));
|
|
}
|
|
|
|
JKQTPMathImageBase::ModifierMode JKQTPImageModifierModeComboBox::getModifierMode() const
|
|
{
|
|
bool ok=false;
|
|
JKQTPMathImageBase::ModifierMode m=JKQTPMathImageBase::ModifyNone;
|
|
if (currentIndex()>=0) m=JKQTPMathImageBase::ModifierMode(itemData(currentIndex()).toInt(&ok));
|
|
if (!ok) m=JKQTPMathImageBase::ModifyNone;
|
|
return m;
|
|
}
|
|
|
|
void JKQTPImageModifierModeComboBox::setModifierMode(JKQTPMathImageBase::ModifierMode mode)
|
|
{
|
|
setCurrentIndex(findData((int)mode));
|
|
}
|
|
|
|
void JKQTPImageModifierModeComboBox::addMode(JKQTPMathImageBase::ModifierMode mode, const QString &name, const QIcon &icon)
|
|
{
|
|
addItem(icon, name, (int)mode);
|
|
}
|
|
|
|
|
|
QVector<double> JKQTPRGBMathImage::getDataGAsDoubleVector() const
|
|
{
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray:
|
|
return JKQTPimagePlot_arrayToDVector((double*)dataG, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::FloatArray:
|
|
return JKQTPimagePlot_arrayToDVector((float*)dataG, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt8Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint8_t*)dataG, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt16Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint16_t*)dataG, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt32Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint32_t*)dataG, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt64Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint64_t*)dataG, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int8Array:
|
|
return JKQTPimagePlot_arrayToDVector((int8_t*)dataG, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int16Array:
|
|
return JKQTPimagePlot_arrayToDVector((int16_t*)dataG, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int32Array:
|
|
return JKQTPimagePlot_arrayToDVector((int32_t*)dataG, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int64Array:
|
|
return JKQTPimagePlot_arrayToDVector((int64_t*)dataG, Nx*Ny);
|
|
break;
|
|
}
|
|
QVector<double> res;
|
|
return res;
|
|
}
|
|
|
|
QVector<double> JKQTPRGBMathImage::getDataBAsDoubleVector() const
|
|
{
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray:
|
|
return JKQTPimagePlot_arrayToDVector((double*)dataB, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::FloatArray:
|
|
return JKQTPimagePlot_arrayToDVector((float*)dataB, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt8Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint8_t*)dataB, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt16Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint16_t*)dataB, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt32Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint32_t*)dataB, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::UInt64Array:
|
|
return JKQTPimagePlot_arrayToDVector((uint64_t*)dataB, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int8Array:
|
|
return JKQTPimagePlot_arrayToDVector((int8_t*)dataB, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int16Array:
|
|
return JKQTPimagePlot_arrayToDVector((int16_t*)dataB, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int32Array:
|
|
return JKQTPimagePlot_arrayToDVector((int32_t*)dataB, Nx*Ny);
|
|
break;
|
|
case JKQTPMathImageBase::Int64Array:
|
|
return JKQTPimagePlot_arrayToDVector((int64_t*)dataB, Nx*Ny);
|
|
break;
|
|
}
|
|
QVector<double> res;
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
|
|
QVector<double> JKQTPOverlayImage::getDataAsDoubleVector() const
|
|
{
|
|
return JKQTPimagePlot_BarrayToDVector(data, Nx*Ny);
|
|
|
|
}
|
|
|
|
void JKQTPOverlayImage::set_title(const JKQTPgraph::typedef_set_title &title)
|
|
{
|
|
JKQTPImageBase::set_title(title);
|
|
QString t=title;
|
|
if (t.isEmpty()) t="JKQTPOverlayImage";
|
|
actSaveImage->setText(tr("Save %1 ...").arg(t));
|
|
actCopyImage->setText(tr("Copy %1 ...").arg(t));
|
|
|
|
}
|
|
|
|
void JKQTPOverlayImage::setParent(JKQtBasePlotter *parent)
|
|
{
|
|
if (this->parent) {
|
|
this->parent->deregisterAdditionalAction(actSaveImage);
|
|
this->parent->deregisterAdditionalAction(actCopyImage);
|
|
|
|
}
|
|
JKQTPImageBase::setParent(parent);
|
|
|
|
if (parent) {
|
|
parent->registerAdditionalAction(tr("Save Image Plot Images ..."), actSaveImage);
|
|
parent->registerAdditionalAction(tr("Copy Image Plot Images ..."), actCopyImage);
|
|
|
|
}
|
|
actSaveImage->setEnabled(parent);
|
|
actCopyImage->setEnabled(parent);
|
|
|
|
}
|
|
|
|
void JKQTPOverlayImage::saveImagePlotAsImage(const QString &filename, const QByteArray &outputFormat)
|
|
{
|
|
if (parent) {
|
|
parent->loadUserSettings();
|
|
QString currentSaveDirectory=parent->get_currentSaveDirectory();
|
|
QString currentFileFormat=parent->get_currentFileFormat();
|
|
QString fn=filename;
|
|
QStringList filt;
|
|
QList<QByteArray> writerformats=QImageWriter::supportedImageFormats();
|
|
for (int i=0; i<writerformats.size(); i++) {
|
|
filt<<QString("%1 Image (*.%2)").arg(QString(writerformats[i]).toUpper()).arg(QString(writerformats[i].toLower()));
|
|
}
|
|
QString selFormat;
|
|
if (fn.isEmpty()) {
|
|
selFormat=currentFileFormat;
|
|
fn = QFileDialog::getSaveFileName(NULL, tr("Save Image Plot As Image ..."),
|
|
currentSaveDirectory,
|
|
filt.join(";;"), &selFormat);
|
|
if (!fn.isEmpty()) currentSaveDirectory=QFileInfo(fn).absolutePath();
|
|
}
|
|
|
|
parent->set_currentFileFormat(currentFileFormat);
|
|
parent->set_currentSaveDirectory(currentSaveDirectory);
|
|
parent->saveUserSettings();
|
|
if (!fn.isEmpty()) {
|
|
int filtID=filt.indexOf(selFormat);
|
|
QString form="NONE";
|
|
if (filtID>=0 && filtID<writerformats.size()) {
|
|
form=writerformats[filtID];
|
|
}
|
|
if (outputFormat.size()>0) {
|
|
form =outputFormat;
|
|
}
|
|
|
|
QImage image=drawImage();
|
|
|
|
if (form=="NONE") image.save(fn);
|
|
else image.save(fn, form.toLatin1().data());
|
|
}
|
|
}
|
|
}
|
|
|
|
void JKQTPOverlayImage::copyImagePlotAsImage()
|
|
{
|
|
QClipboard* clip=QApplication::clipboard();
|
|
if (clip) {
|
|
clip->setImage(drawImage());
|
|
}
|
|
}
|
|
|
|
# include <QVector3D>
|
|
void JKQTPContour::draw(JKQTPEnhancedPainter &painter)
|
|
{
|
|
//qDebug()<<"JKQTPContourPlot::draw";
|
|
|
|
if(contourLevels.isEmpty()) createContourLevels(numberOfLevels);
|
|
else {
|
|
numberOfLevels=contourLevels.size();
|
|
// qSort(contourLevels);
|
|
}
|
|
|
|
if(contourLines.isEmpty()) { // contour lines are only calculated once
|
|
for(int i =0; i<contourLevels.size();++i) {
|
|
contourLines.append(QVector<QLineF> (0));
|
|
}
|
|
this->calcContourLines(contourLines);
|
|
}
|
|
|
|
|
|
|
|
// draw lines
|
|
painter.save();
|
|
QPen p;
|
|
p.setStyle(style);
|
|
p.setColor(lineColor);
|
|
p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier())));
|
|
|
|
painter.setPen(p);
|
|
QImage colorLevels = getPaletteImage(palette,numberOfLevels);
|
|
QVector<QLineF> contourLinesTransformedSingleLevel;
|
|
QLineF lineTranformed;
|
|
for(int i =0; i<numberOfLevels;++i) {
|
|
if(colorFromPalette) {
|
|
p.setColor(QColor(colorLevels.pixel(i,0)));
|
|
painter.setPen(p);
|
|
}
|
|
// transform into plot coordinates
|
|
for(QVector<QLineF >::const_iterator line =contourLines.at(i).begin(); line!=contourLines.at(i).end();++line ) {
|
|
lineTranformed.setP1(transform(x+line->p1().x()/double(Nx-1)*width, y+line->p1().y()/double(Ny-1)*height));
|
|
lineTranformed.setP2(transform(x+line->p2().x()/double(Nx-1)*width, y+line->p2().y()/double(Ny-1)*height));
|
|
contourLinesTransformedSingleLevel.append(lineTranformed);
|
|
}
|
|
painter.drawLines(contourLinesTransformedSingleLevel);
|
|
contourLinesTransformedSingleLevel.clear();
|
|
}
|
|
|
|
painter.restore();
|
|
}
|
|
|
|
void JKQTPContour::createContourLevels(int nLevels)
|
|
{
|
|
if (!data) return;
|
|
if (nLevels<1) return;
|
|
double min,max;
|
|
getDataMinMax(min,max);
|
|
double delta=(max-min)/((double)nLevels+1);
|
|
|
|
for(int i=1; i<=nLevels; ++i) {
|
|
contourLevels.append(min + i*delta);
|
|
}
|
|
relativeLevels=false;
|
|
|
|
}
|
|
|
|
void JKQTPContour::createContourLevelsLog(int nLevels, int m)
|
|
{
|
|
if (!data) return;
|
|
if (nLevels<1) return;
|
|
double min,max;
|
|
getDataMinMax(min,max);
|
|
if(min<=0) min=1; // FIXME get smallest number greater zero
|
|
|
|
int S=floor((log10(max)-log10(min))/log10(m));
|
|
if(S<2) S=1;
|
|
int P = floor((double)nLevels/(double)S);
|
|
if(P<1) P=1;
|
|
|
|
double delta=min;
|
|
contourLevels.append(2*delta);
|
|
for (long s=0; s<S; s++) {
|
|
for (long p=0; p<P; p++) {
|
|
{
|
|
contourLevels.append(contourLevels.last()+delta);
|
|
}
|
|
}
|
|
delta=delta*m;
|
|
}
|
|
|
|
if(nLevels!=contourLevels.size()) {
|
|
//qDebug()<<"nLevels="<<nLevels<<"contourLevels.size()="<<contourLevels.size();
|
|
//qDebug()<<"adapt m";
|
|
}
|
|
|
|
relativeLevels=false;
|
|
}
|
|
|
|
void JKQTPContour::set_imageColumn(size_t columnID)
|
|
{
|
|
datatype=JKQTPMathImageBase::DoubleArray;
|
|
data=parent->getDatastore()->getColumn(columnID).getPointer(0);
|
|
}
|
|
|
|
|
|
void JKQTPContour::ensureImageData()
|
|
{
|
|
}
|
|
|
|
double JKQTPContour::value(int xIdx, int yIdx)
|
|
{
|
|
// row-major in datastore
|
|
ensureImageData();
|
|
if (!data) return 0;
|
|
switch(datatype) {
|
|
case JKQTPMathImageBase::DoubleArray:
|
|
return ((double*)data)[yIdx*get_Nx()+xIdx];
|
|
case JKQTPMathImageBase::FloatArray:
|
|
return ((float*)data)[yIdx*get_Nx()+xIdx];
|
|
case JKQTPMathImageBase::UInt8Array:
|
|
return ((uint8_t*)data)[yIdx*get_Nx()+xIdx];
|
|
case JKQTPMathImageBase::UInt16Array:
|
|
return ((uint16_t*)data)[yIdx*get_Nx()+xIdx];
|
|
case JKQTPMathImageBase::UInt32Array:
|
|
return ((uint32_t*)data)[yIdx*get_Nx()+xIdx];
|
|
case JKQTPMathImageBase::UInt64Array:
|
|
return ((uint64_t*)data)[yIdx*get_Nx()+xIdx];
|
|
case JKQTPMathImageBase::Int8Array:
|
|
return ((int8_t*)data)[yIdx*get_Nx()+xIdx];
|
|
case JKQTPMathImageBase::Int16Array:
|
|
return ((int16_t*)data)[yIdx*get_Nx()+xIdx];
|
|
case JKQTPMathImageBase::Int32Array:
|
|
return ((int32_t*)data)[yIdx*get_Nx()+xIdx];
|
|
case JKQTPMathImageBase::Int64Array:
|
|
return ((int64_t*)data)[yIdx*get_Nx()+xIdx];
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool JKQTPContour::intersect(QLineF &line, const QVector3D &vertex1,const QVector3D &vertex2,const QVector3D &vertex3,const double &level)
|
|
{
|
|
bool found = true;
|
|
|
|
// Are the vertices below (-1), on (0) or above (1) the plane ?
|
|
const int eq1 = compare2level(vertex1,level);
|
|
const int eq2 = compare2level(vertex2,level);
|
|
const int eq3 = compare2level(vertex3,level);
|
|
|
|
/*
|
|
(a) All the vertices lie below the contour level.
|
|
(b) Two vertices lie below and one on the contour level.
|
|
(c) Two vertices lie below and one above the contour level.
|
|
(d) One vertex lies below and two on the contour level.
|
|
(e) One vertex lies below, one on and one above the contour level.
|
|
(f) One vertex lies below and two above the contour level.
|
|
(g) Three vertices lie on the contour level.
|
|
(h) Two vertices lie on and one above the contour level.
|
|
(i) One vertex lies on and two above the contour level.
|
|
(j) All the vertices lie above the contour level.
|
|
*/
|
|
|
|
static const int caseLUT[3][3][3] =
|
|
{
|
|
// jump table to avoid nested case statements
|
|
{ { 0, 0, 8 }, { 0, 2, 5 }, { 7, 6, 9 } },
|
|
{ { 0, 3, 4 }, { 1, 10, 1 }, { 4, 3, 0 } },
|
|
{ { 9, 6, 7 }, { 5, 2, 0 }, { 8, 0, 0 } }
|
|
};
|
|
|
|
const int caseType = caseLUT[eq1+1][eq2+1][eq3+1];
|
|
switch (caseType)
|
|
{
|
|
case 1:
|
|
// d(0,0,-1), h(0,0,1)
|
|
line.setP1(vertex1.toPointF());
|
|
line.setP2(vertex2.toPointF());
|
|
break;
|
|
case 2:
|
|
// d(-1,0,0), h(1,0,0)
|
|
line.setP1(vertex2.toPointF());
|
|
line.setP2(vertex3.toPointF());
|
|
break;
|
|
case 3:
|
|
// d(0,-1,0), h(0,1,0)
|
|
line.setP1(vertex3.toPointF());
|
|
line.setP2(vertex1.toPointF());
|
|
break;
|
|
case 4:
|
|
// e(0,-1,1), e(0,1,-1)
|
|
line.setP1(vertex1.toPointF());
|
|
line.setP2(interpolatePoint(vertex2, vertex3, level));
|
|
break;
|
|
case 5:
|
|
// e(-1,0,1), e(1,0,-1)
|
|
line.setP1(vertex2.toPointF());
|
|
line.setP2(interpolatePoint(vertex3, vertex1, level));
|
|
break;
|
|
case 6:
|
|
// e(-1,1,0), e(1,0,-1)
|
|
line.setP1(vertex3.toPointF());
|
|
line.setP2(interpolatePoint(vertex1, vertex2, level));
|
|
break;
|
|
case 7:
|
|
// c(-1,1,-1), f(1,1,-1)
|
|
line.setP1(interpolatePoint(vertex1, vertex2, level));
|
|
line.setP2(interpolatePoint(vertex2, vertex3, level));
|
|
break;
|
|
case 8:
|
|
// c(-1,-1,1), f(1,1,-1)
|
|
line.setP1(interpolatePoint(vertex2, vertex3, level));
|
|
line.setP2(interpolatePoint(vertex3, vertex1, level));
|
|
break;
|
|
case 9:
|
|
// f(-1,1,1), c(1,-1,-1)
|
|
line.setP1(interpolatePoint(vertex3, vertex1, level));
|
|
line.setP2(interpolatePoint(vertex1, vertex2, level));
|
|
break;
|
|
case 10:
|
|
// g(0,0,0)
|
|
// The CONREC algorithm has no satisfying solution for
|
|
// what to do, when all vertices are on the plane.
|
|
|
|
if ( ignoreOnPlane )
|
|
found = false;
|
|
else
|
|
{
|
|
line.setP1(vertex3.toPointF());
|
|
line.setP2(vertex1.toPointF());
|
|
}
|
|
break;
|
|
default:
|
|
found = false;
|
|
}
|
|
// qDebug()<<caseType;
|
|
// qDebug()<<line;
|
|
return found;
|
|
}
|
|
|
|
|
|
JKQTPContour::JKQTPContour(JKQtBasePlotter *parent) :
|
|
JKQTPMathImage(parent)
|
|
{
|
|
lineColor=QColor("red");
|
|
colorBarRightVisible=false;
|
|
lineWidth=1;
|
|
style=Qt::SolidLine;
|
|
ignoreOnPlane=false;
|
|
numberOfLevels=1;
|
|
colorFromPalette=true;
|
|
datatype=JKQTPMathImageBase::DoubleArray;
|
|
relativeLevels=false;
|
|
|
|
if (parent) { // get style settings from parent object
|
|
lineColor=parent->getPlotStyle(parent->getNextStyle()).color();
|
|
}
|
|
}
|
|
|
|
JKQTPContour::JKQTPContour(double x, double y, double width, double height, void* data, uint32_t Nx, uint32_t Ny, JKQTPMathImageColorPalette palette, DataType datatype, JKQtBasePlotter* parent) :
|
|
JKQTPMathImage( x, y, width, height, datatype, data, Nx, Ny, palette, parent)
|
|
{
|
|
lineColor=QColor("red");
|
|
colorBarRightVisible=false;
|
|
lineWidth=1;
|
|
style=Qt::SolidLine;
|
|
ignoreOnPlane=false;
|
|
numberOfLevels=1;
|
|
colorFromPalette=true;
|
|
relativeLevels=false;
|
|
}
|
|
|
|
|
|
int JKQTPContour::compare2level(const QVector3D &vertex, const double &level)
|
|
{
|
|
if (vertex.z() > level)
|
|
return 1;
|
|
|
|
if (vertex.z() < level)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void JKQTPContour::calcContourLines(QList<QVector<QLineF> > &ContourLines)
|
|
{
|
|
|
|
double scale=1; ///< scale of the contour levels;
|
|
|
|
if(relativeLevels) {
|
|
double min;
|
|
double max;
|
|
getDataMinMax(min,max);
|
|
scale=1/(max-min);
|
|
}
|
|
|
|
enum Position
|
|
{
|
|
// the positions of points of one box
|
|
// vertex 1 +-------------------+ vertex 2
|
|
// | \ / |
|
|
// | \ m=3 / |
|
|
// | \ / |
|
|
// | \ / |
|
|
// | m=2 X m=2 | the center is vertex 0
|
|
// | / \ |
|
|
// | / \ |
|
|
// | / m=1 \ |
|
|
// | / \ |
|
|
// vertex 4 +-------------------+ vertex 3
|
|
Center=0,
|
|
|
|
TopLeft=1,
|
|
TopRight=2,
|
|
BottomRight=3,
|
|
BottomLeft=4,
|
|
|
|
NumPositions=5
|
|
};
|
|
|
|
|
|
for ( int yp = 0; yp < (int64_t)get_Ny() - 1; ++yp ) { // go through image (pixel coordinates) in row major order
|
|
QVector<QVector3D> vertices(NumPositions);
|
|
|
|
for ( int xp = 0; xp < (int64_t)get_Ny() - 1; ++xp ) {
|
|
|
|
if ( xp == 0 )
|
|
{
|
|
vertices[TopRight].setX(xp); // will be used for TopLeft later
|
|
vertices[TopRight].setY(yp);
|
|
vertices[TopRight].setZ(
|
|
value( vertices[TopRight].x(), vertices[TopRight].y())*scale
|
|
);
|
|
|
|
vertices[BottomRight].setX(xp);
|
|
vertices[BottomRight].setY(yp+1);
|
|
vertices[BottomRight].setZ(
|
|
value(vertices[BottomRight].x(), vertices[BottomRight].y())*scale
|
|
);
|
|
}
|
|
|
|
vertices[TopLeft] = vertices[TopRight]; // use right vertices of the last box as new left vertices
|
|
vertices[BottomLeft] = vertices[BottomRight];
|
|
|
|
vertices[TopRight].setX(xp + 1);
|
|
vertices[TopRight].setY(yp); // <----
|
|
vertices[TopRight].setZ(
|
|
value(vertices[TopRight].x(), vertices[TopRight].y())*scale
|
|
);
|
|
|
|
vertices[BottomRight].setX(xp + 1);
|
|
vertices[BottomRight].setY(yp + 1);
|
|
vertices[BottomRight].setZ(
|
|
value(vertices[BottomRight].x(), vertices[BottomRight].y())*scale
|
|
);
|
|
|
|
double zMin = vertices[TopLeft].z();
|
|
double zMax = zMin;
|
|
double zSum = zMin;
|
|
|
|
for ( int i = TopRight; i <= BottomLeft; ++i ) {
|
|
const double z = vertices[i].z();
|
|
|
|
zSum += z;
|
|
if ( z < zMin )
|
|
zMin = z;
|
|
if ( z > zMax )
|
|
zMax = z;
|
|
}
|
|
|
|
|
|
if ( zMax >= contourLevels.first() && zMin <= contourLevels.last() ) {
|
|
|
|
vertices[Center].setX(xp + 0.5); // pseudo pixel coordinates
|
|
vertices[Center].setY(yp + 0.5);
|
|
vertices[Center].setZ(0.25 * zSum);
|
|
for (int levelIdx=0; levelIdx<contourLevels.size(); ++levelIdx) {
|
|
if ( contourLevels.at(levelIdx) >= zMin && contourLevels.at(levelIdx) <= zMax ) {
|
|
|
|
QLineF line;
|
|
QVector<QVector3D> triangle(3);
|
|
|
|
/* triangle[1]
|
|
X
|
|
/ \
|
|
/ \
|
|
/ m \
|
|
/ \
|
|
triangle[2] +-------------------+ triangle[0]
|
|
*/
|
|
|
|
for (int m = TopLeft; m < NumPositions; m++) { // construct triangles
|
|
triangle[0] = vertices[m];
|
|
triangle[1] = vertices[Center];
|
|
triangle[2] = vertices[(m!=BottomLeft)?(m + 1):TopLeft];
|
|
|
|
const bool intersects =intersect(line, triangle.at(0),triangle.at(1),triangle.at(2),
|
|
contourLevels.at(levelIdx));
|
|
if ( intersects ) {
|
|
ContourLines[levelIdx]<<line;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
QPointF JKQTPContour::interpolatePoint(const QVector3D &point1, const QVector3D &point2,const double &level)
|
|
{
|
|
const double h1 = point1.z() - level; // height above contour level
|
|
const double h2 = point2.z() - level;
|
|
|
|
// // check if h1 or h2 is zero
|
|
// Division by zero is not possible (the intersect function is not called if h2-h1 is zero, !)
|
|
// if(h2-h1==0||h1==0||h2==0) {
|
|
// qDebug()<<h1<<h2;
|
|
// qDebug()<<"interpolate p1="<<point1<<", p2="<<point2<<" level="<<level;
|
|
// }
|
|
|
|
const double x = (h2 * point1.x() - h1 * point2.x()) / (h2 - h1); // linear interpolation in x.direction (independent of y)
|
|
const double y = (h2 * point1.y() - h1 * point2.y()) / (h2 - h1);
|
|
|
|
// const double alpha=(level-point1.z())/(point2.z()-point1.z());
|
|
// const double x=point1.x()+alpha*(point2.x()-point1.x());
|
|
// const double y=point1.y()+alpha*(point2.y()-point1.y());
|
|
|
|
return QPointF(x, y);
|
|
}
|
|
|