First version OpenGL drawing

This commit is contained in:
2019-10-23 08:53:19 +02:00
parent 7e815634bb
commit 6aa52236a8
15 changed files with 318 additions and 17 deletions
+13
View File
@@ -0,0 +1,13 @@
#version 130
uniform sampler2D qt_Texture0;
varying vec2 qt_TexCoord0;
uniform vec2 scale;
void main(void)
{
float c = texture2D(qt_Texture0, qt_TexCoord0).r;
c = c*scale.x + scale.y;
float color = pow(c, 0.4545);
gl_FragColor = vec4(color, color, color, 1.0);
}
+11
View File
@@ -0,0 +1,11 @@
#version 130
attribute vec2 qt_Vertex;
attribute vec2 qt_MultiTexCoord0;
varying vec2 qt_TexCoord0;
void main(void)
{
gl_Position = vec4(qt_Vertex, 0.0, 1.0);
qt_TexCoord0 = qt_MultiTexCoord0;
}
+14 -2
View File
@@ -2,6 +2,7 @@
#include <QThreadPool> #include <QThreadPool>
#include <QDir> #include <QDir>
#include "loadrunable.h" #include "loadrunable.h"
#include "rawimage.h"
using namespace std; using namespace std;
@@ -31,6 +32,7 @@ void Image::load()
void Image::release() void Image::release()
{ {
m_pixmap = QPixmap(); m_pixmap = QPixmap();
m_rawImage.reset();
m_released = true; m_released = true;
m_loading = false; m_loading = false;
} }
@@ -45,6 +47,11 @@ QPixmap Image::pixmap() const
return m_pixmap; return m_pixmap;
} }
RawImageAbs *Image::rawImage()
{
return m_rawImage.get();
}
ImageInfoData Image::info() const ImageInfoData Image::info() const
{ {
return m_info; return m_info;
@@ -55,15 +62,20 @@ bool Image::isCurrent() const
return !m_released; return !m_released;
} }
void Image::imageLoaded(QImage img, ImageInfoData info) void Image::imageLoaded(QImage img, void *rawImage, ImageInfoData info)
{ {
m_loading = false; m_loading = false;
if(!m_released) if(!m_released)
{ {
m_pixmap = QPixmap::fromImage(img); m_pixmap = QPixmap::fromImage(img);
m_rawImage.reset(static_cast<RawImageAbs*>(rawImage));
m_info = info; m_info = info;
emit pixmapLoaded(this); emit pixmapLoaded(this);
} }
else
{
delete rawImage;
}
} }
ImageRingList::ImageRingList(QObject *parent) : QObject(parent) ImageRingList::ImageRingList(QObject *parent) : QObject(parent)
@@ -223,7 +235,7 @@ void ImageRingList::imageLoaded(Image *image)
{ {
if(image->name() == (*m_currImage)->name()) if(image->name() == (*m_currImage)->name())
{ {
emit pixmapLoaded(image->pixmap()); emit pixmapLoaded(image);
emit infoLoaded(image->info()); emit infoLoaded(image->info());
} }
} }
+5 -2
View File
@@ -7,6 +7,7 @@
#include <QPixmap> #include <QPixmap>
#include <memory> #include <memory>
#include "imageinfo.h" #include "imageinfo.h"
#include "rawimage.h"
class ImageRingList; class ImageRingList;
@@ -17,6 +18,7 @@ class Image : public QObject
bool m_released; bool m_released;
bool m_current; bool m_current;
QPixmap m_pixmap; QPixmap m_pixmap;
std::unique_ptr<RawImageAbs> m_rawImage;
QString m_name; QString m_name;
ImageInfoData m_info; ImageInfoData m_info;
ImageRingList *m_ringList; ImageRingList *m_ringList;
@@ -26,12 +28,13 @@ public:
void release(); void release();
QString name() const; QString name() const;
QPixmap pixmap() const; QPixmap pixmap() const;
RawImageAbs* rawImage();
ImageInfoData info() const; ImageInfoData info() const;
bool isCurrent() const; bool isCurrent() const;
signals: signals:
void pixmapLoaded(Image *ptr); void pixmapLoaded(Image *ptr);
protected slots: protected slots:
void imageLoaded(QImage img, ImageInfoData info); void imageLoaded(QImage img, void *rawImage, ImageInfoData info);
}; };
typedef std::shared_ptr<Image> ImagePtr; typedef std::shared_ptr<Image> ImagePtr;
@@ -65,7 +68,7 @@ protected:
QList<ImagePtr>::iterator increment(QList<ImagePtr>::iterator iter); QList<ImagePtr>::iterator increment(QList<ImagePtr>::iterator iter);
QList<ImagePtr>::iterator decrement(QList<ImagePtr>::iterator iter); QList<ImagePtr>::iterator decrement(QList<ImagePtr>::iterator iter);
signals: signals:
void pixmapLoaded(QPixmap pix); void pixmapLoaded(Image *image);
void infoLoaded(ImageInfoData info); void infoLoaded(ImageInfoData info);
void currentImageChanged(); void currentImageChanged();
protected slots: protected slots:
+130
View File
@@ -0,0 +1,130 @@
#include "imagescrollareagl.h"
#include <QOpenGLFunctions>
#include <QDebug>
#include <QKeyEvent>
#include <QOpenGLDebugLogger>
ImageScrollAreaGL::ImageScrollAreaGL(QWidget *parent) : QOpenGLWidget(parent)
{
setFocusPolicy(Qt::ClickFocus);
m_range = UINT16_MAX;
m_low = 0;
m_high = 1;
}
ImageScrollAreaGL::~ImageScrollAreaGL()
{
makeCurrent();
}
void ImageScrollAreaGL::setImage(RawImageAbs *image)
{
m_image->destroy();
m_image->setFormat(QOpenGLTexture::R16_UNorm);
m_image->setSize(image->width(), image->height());
m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
m_image->allocateStorage();
if(RawImage<uint8_t> *i8 = dynamic_cast<RawImage<uint8_t>*>(image))
{
m_image->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, i8->data());
m_range = UINT8_MAX;
}
else if(RawImage<uint16_t> *i16 = dynamic_cast<RawImage<uint16_t>*>(image))
{
m_image->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt16, i16->data());
m_range = UINT16_MAX;
}
else if(RawImage<uint32_t> *i32 = dynamic_cast<RawImage<uint32_t>*>(image))
{
m_image->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt32, i32->data());
m_range = UINT32_MAX;
}
m_image->generateMipMaps();
repaint();
}
void ImageScrollAreaGL::setLow(int low)
{
m_low = low/m_range;
repaint();
}
void ImageScrollAreaGL::setHigh(int high)
{
m_high = high/m_range;
repaint();
}
void ImageScrollAreaGL::paintGL()
{
float s = 1.0f/(m_high-m_low);
m_program->bind();
m_program->setUniformValue("scale", s, -m_low*s);
m_image->bind(0);
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void ImageScrollAreaGL::resizeGL(int w, int h)
{
m_width = w;
m_height = h;
f->glViewport(0, 0, w, h);
}
void ImageScrollAreaGL::initializeGL()
{
f = context()->functions();
f->glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
m_vao = std::unique_ptr<QOpenGLVertexArrayObject>(new QOpenGLVertexArrayObject);
m_vao->create();
m_vao->bind();
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
logger->initialize();
logger->startLogging();
connect(logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage &message)
{
qDebug() << message;
});
qDebug() << (char*)f->glGetString(GL_VENDOR);
qDebug() << (char*)f->glGetString(GL_RENDERER);
qDebug() << (char*)f->glGetString(GL_VERSION);
qDebug() << context()->format();
// each vertex is x,y 2D position and s,t texture coordinates
float vertexs[] = {-1.0f, -1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f,};
m_buffer = std::unique_ptr<QOpenGLBuffer>(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer));
m_buffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
m_buffer->create();
m_buffer->bind();
m_buffer->allocate(vertexs, sizeof(vertexs));
f->glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(float)*4, 0);
m_program = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram);
m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/image.vert");
m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/image.frag");
if(!m_program->link())
{
qDebug() << "Link failed" << m_program->log();
}
m_program->bind();
m_program->enableAttributeArray("qt_Vertex");
m_program->setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 2, sizeof(float)*4);
m_program->enableAttributeArray("qt_MultiTexCoord0");
m_program->setAttributeBuffer("qt_MultiTexCoord0", GL_FLOAT, sizeof(float)*2, 2, sizeof(float)*4);
m_program->setUniformValue("qt_Texture0", (GLuint)0);
m_program->setUniformValue("scale", 1.0f, 0.0f);
m_image = std::unique_ptr<QOpenGLTexture>(new QOpenGLTexture(QImage("/home/nou/Obrázky/1p6yap.jpg")));
m_image->bind(0);
m_image->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
m_image->setMagnificationFilter(QOpenGLTexture::Linear);
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef IMAGESCROLLAREAGL_H
#define IMAGESCROLLAREAGL_H
#include <memory>
#include <QObject>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QOpenGLVertexArrayObject>
#include "rawimage.h"
typedef enum
{
Linear,
Log,
Sqrt,
Power,
Asinh,
}StretchFunc;
class ImageScrollAreaGL : public QOpenGLWidget
{
Q_OBJECT
QOpenGLFunctions *f;
std::unique_ptr<QOpenGLShaderProgram> m_program;
std::unique_ptr<QOpenGLBuffer> m_buffer;
std::unique_ptr<QOpenGLTexture> m_image;
std::unique_ptr<QOpenGLVertexArrayObject> m_vao;
int m_width, m_height;
float m_low;
float m_high;
float m_range;
public:
explicit ImageScrollAreaGL(QWidget *parent = nullptr);
~ImageScrollAreaGL();
void setImage(RawImageAbs *image);
public slots:
void setLow(int low);
void setHigh(int high);
protected:
void paintGL();
void resizeGL(int w, int h);
void initializeGL();
};
#endif // IMAGESCROLLAREAGL_H
+3 -5
View File
@@ -264,13 +264,13 @@ void LoadRunable::run()
if(m_file.endsWith(".CR2", Qt::CaseInsensitive)) if(m_file.endsWith(".CR2", Qt::CaseInsensitive))
{ {
timer.start(); timer.start();
loadRAW(m_file, info, m_analyzeLevel != None ? &rawImage : nullptr, &img); loadRAW(m_file, info, &rawImage, &img);
raw = true; raw = true;
qDebug() << "LoadRaw" << timer.elapsed(); qDebug() << "LoadRaw" << timer.elapsed();
} }
else if(m_file.endsWith(".FIT", Qt::CaseInsensitive) || m_file.endsWith(".FITS", Qt::CaseInsensitive)) else if(m_file.endsWith(".FIT", Qt::CaseInsensitive) || m_file.endsWith(".FITS", Qt::CaseInsensitive))
{ {
loadFITS(m_file, info, m_analyzeLevel != None ? &rawImage : nullptr, &img); loadFITS(m_file, info, &rawImage, &img);
} }
else else
{ {
@@ -350,7 +350,5 @@ void LoadRunable::run()
} }
} }
if(rawImage)delete rawImage; QMetaObject::invokeMethod(m_receiver, "imageLoaded", Qt::QueuedConnection, Q_ARG(QImage, img), Q_ARG(void*, rawImage), Q_ARG(ImageInfoData, info));
QMetaObject::invokeMethod(m_receiver, "imageLoaded", Qt::QueuedConnection, Q_ARG(QImage, img), Q_ARG(ImageInfoData, info));
} }
+7
View File
@@ -1,8 +1,15 @@
#include "mainwindow.h" #include "mainwindow.h"
#include <QApplication> #include <QApplication>
#include <QSurfaceFormat>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QSurfaceFormat format;
format.setMajorVersion(3);
format.setMinorVersion(0);
format.setOption(QSurfaceFormat::DebugContext);
QSurfaceFormat::setDefaultFormat(format);
QApplication a(argc, argv); QApplication a(argc, argv);
a.setOrganizationName("nou"); a.setOrganizationName("nou");
a.setApplicationName("Tenmon"); a.setApplicationName("Tenmon");
+19 -4
View File
@@ -1,4 +1,5 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "stretchpanel.h"
#include <QScrollArea> #include <QScrollArea>
#include <QDir> #include <QDir>
#include <QKeyEvent> #include <QKeyEvent>
@@ -26,6 +27,7 @@ int MainWindow::socketPair[2] = {0, 0};
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{ {
qRegisterMetaType<ImageInfoData>("ImageInfoData"); qRegisterMetaType<ImageInfoData>("ImageInfoData");
qRegisterMetaType<RawImageAbs*>("RawImageAbs");
m_info = new ImageInfo(this); m_info = new ImageInfo(this);
QDockWidget *infoDock = new QDockWidget(tr("Image info"), this); QDockWidget *infoDock = new QDockWidget(tr("Image info"), this);
@@ -33,7 +35,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
infoDock->setObjectName("infoDock"); infoDock->setObjectName("infoDock");
addDockWidget(Qt::LeftDockWidgetArea, infoDock); addDockWidget(Qt::LeftDockWidgetArea, infoDock);
m_image = new ImageScrollArea(this); m_image = new ImageScrollArea(this);
setCentralWidget(m_image); m_image->resize(0,0);
//setCentralWidget(m_image);
resize(800, 600); resize(800, 600);
PhotoCapture *photoCapture = new PhotoCapture(this); PhotoCapture *photoCapture = new PhotoCapture(this);
@@ -42,10 +45,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
captureDock->setObjectName("captureDock"); captureDock->setObjectName("captureDock");
addDockWidget(Qt::BottomDockWidgetArea, captureDock); addDockWidget(Qt::BottomDockWidgetArea, captureDock);
m_imageGL = new ImageScrollAreaGL(this);
setCentralWidget(m_imageGL);
setWindowTitle(tr("Tenmon")); setWindowTitle(tr("Tenmon"));
m_ringList = new ImageRingList(this); m_ringList = new ImageRingList(this);
connect(m_ringList, SIGNAL(pixmapLoaded(QPixmap)), this, SLOT(pixmapLoaded(QPixmap))); connect(m_ringList, SIGNAL(pixmapLoaded(Image*)), this, SLOT(pixmapLoaded(Image*)));
connect(m_ringList, SIGNAL(currentImageChanged()), this, SLOT(updateWindowTitle())); connect(m_ringList, SIGNAL(currentImageChanged()), this, SLOT(updateWindowTitle()));
connect(m_ringList, SIGNAL(infoLoaded(ImageInfoData)), m_info, SLOT(setInfo(ImageInfoData))); connect(m_ringList, SIGNAL(infoLoaded(ImageInfoData)), m_info, SLOT(setInfo(ImageInfoData)));
@@ -106,6 +112,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
dockMenu->addAction(captureDock->toggleViewAction()); dockMenu->addAction(captureDock->toggleViewAction());
menuBar()->addMenu(dockMenu); menuBar()->addMenu(dockMenu);
StretchPanel *stretchPanel = new StretchPanel(this);
connect(stretchPanel, SIGNAL(lowChanged(int)), m_imageGL, SLOT(setLow(int)));
connect(stretchPanel, SIGNAL(highChanged(int)), m_imageGL, SLOT(setHigh(int)));
QDockWidget *stretchDock = new QDockWidget(tr("Stretch"), this);
stretchDock->setWidget(stretchPanel);
addDockWidget(Qt::LeftDockWidgetArea, stretchDock);
setupSigterm(); setupSigterm();
QSettings settings; QSettings settings;
restoreGeometry(settings.value("mainwindow/geometry").toByteArray()); restoreGeometry(settings.value("mainwindow/geometry").toByteArray());
@@ -187,9 +201,10 @@ void MainWindow::socketNotify()
socketNotifier->setEnabled(true); socketNotifier->setEnabled(true);
} }
void MainWindow::pixmapLoaded(QPixmap pix) void MainWindow::pixmapLoaded(Image *image)
{ {
m_image->setImage(pix); m_image->setImage(image->pixmap());
m_imageGL->setImage(image->rawImage());
} }
void MainWindow::openFile() void MainWindow::openFile()
+3 -1
View File
@@ -7,11 +7,13 @@
#include "imagescrollarea.h" #include "imagescrollarea.h"
#include "database.h" #include "database.h"
#include "imageinfo.h" #include "imageinfo.h"
#include "imagescrollareagl.h"
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
ImageScrollArea *m_image; ImageScrollArea *m_image;
ImageScrollAreaGL *m_imageGL;
ImageRingList *m_ringList; ImageRingList *m_ringList;
Database *m_database; Database *m_database;
ImageInfo *m_info; ImageInfo *m_info;
@@ -30,7 +32,7 @@ protected:
protected slots: protected slots:
void socketNotify(); void socketNotify();
void updateWindowTitle(); void updateWindowTitle();
void pixmapLoaded(QPixmap pix); void pixmapLoaded(Image *image);
void openFile(); void openFile();
void markImage(); void markImage();
void unmarkImage(); void unmarkImage();
+10 -1
View File
@@ -31,6 +31,8 @@ public:
class RawImageAbs class RawImageAbs
{ {
protected:
uint32_t m_width,m_height;
public: public:
virtual ~RawImageAbs(){} virtual ~RawImageAbs(){}
virtual bool imageStats(uint64_t *mean, double *stdDev, uint64_t *median, uint64_t *min, uint64_t *max) const = 0; virtual bool imageStats(uint64_t *mean, double *stdDev, uint64_t *median, uint64_t *min, uint64_t *max) const = 0;
@@ -38,12 +40,19 @@ public:
virtual int findPeaks(uint64_t background, double distance, std::vector<Peak> &peaks) const = 0; virtual int findPeaks(uint64_t background, double distance, std::vector<Peak> &peaks) const = 0;
virtual RawImageAbs* medianFilter() const = 0; virtual RawImageAbs* medianFilter() const = 0;
virtual void quarter() = 0; virtual void quarter() = 0;
uint32_t width() const
{
return m_width;
}
uint32_t height() const
{
return m_height;
}
}; };
template<typename T> template<typename T>
class RawImage : public RawImageAbs class RawImage : public RawImageAbs
{ {
uint32_t m_width,m_height;
std::vector<T> m_img; std::vector<T> m_img;
bool checkPixel(T c, uint32_t x, uint32_t y) const bool checkPixel(T c, uint32_t x, uint32_t y) const
{ {
+6
View File
@@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/shaders">
<file>image.frag</file>
<file>image.vert</file>
</qresource>
</RCC>
+21
View File
@@ -0,0 +1,21 @@
#include "stretchpanel.h"
#include <QVBoxLayout>
StretchPanel::StretchPanel(QWidget *parent) : QWidget(parent)
{
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
m_lowSlider = new QSlider(Qt::Horizontal, this);
m_highSlider = new QSlider(Qt::Horizontal, this);
m_lowSlider->setRange(0, UINT16_MAX);
m_highSlider->setRange(0, UINT16_MAX);
m_highSlider->setValue(UINT16_MAX);
layout->addWidget(m_lowSlider);
layout->addWidget(m_highSlider);
connect(m_lowSlider, SIGNAL(valueChanged(int)), this, SIGNAL(lowChanged(int)));
connect(m_highSlider, SIGNAL(valueChanged(int)), this, SIGNAL(highChanged(int)));
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef STRETCHPANEL_H
#define STRETCHPANEL_H
#include <QWidget>
#include <QSlider>
class StretchPanel : public QWidget
{
Q_OBJECT
QSlider *m_lowSlider;
QSlider *m_highSlider;
public:
explicit StretchPanel(QWidget *parent = nullptr);
signals:
void lowChanged(int low);
void highChanged(int high);
};
#endif // STRETCHPANEL_H
+9 -2
View File
@@ -29,7 +29,9 @@ SOURCES += main.cpp\
imageinfo.cpp \ imageinfo.cpp \
starfit.cpp \ starfit.cpp \
phd.cpp \ phd.cpp \
photocapture.cpp photocapture.cpp \
imagescrollareagl.cpp \
stretchpanel.cpp
HEADERS += mainwindow.h \ HEADERS += mainwindow.h \
imagescrollarea.h \ imagescrollarea.h \
@@ -40,4 +42,9 @@ HEADERS += mainwindow.h \
rawimage.h \ rawimage.h \
starfit.h \ starfit.h \
phd.h \ phd.h \
photocapture.h photocapture.h \
imagescrollareagl.h \
stretchpanel.h
RESOURCES += \
resources.qrc