added image saving

master
Benjamin Kraft 3 years ago
parent 7bb704d984
commit d054592840
  1. 11
      headers/Mandelbrot.h
  2. 5
      headers/OutputWidget.h
  3. 20
      src/MainWindow.cpp
  4. 22
      src/Mandelbrot.cpp
  5. 76
      src/OutputWidget.cpp

@ -7,18 +7,23 @@
class Mandelbrot : public QObject, protected QOpenGLExtraFunctions {
Q_OBJECT
public:
void init();
void draw(GLuint, QOpenGLShaderProgram&);
void init(GLuint);
void draw();
void setIterations(int);
void translateRelative(QVector2D);
void zoomRelative(int, QVector2D);
void resizeRelative(QVector2D);
bool initShader();
private:
int iterations = 0;
QVector2D origin {-2, -1};
QVector2D size {2, 2};
float zoomModifier = 1.05;
void setShaderValues(QOpenGLShaderProgram&) const;
GLuint vao;
QOpenGLShaderProgram shader;
void setShaderValues();
};

@ -13,6 +13,7 @@ class OutputWidget : public QOpenGLWidget, protected QOpenGLExtraFunctions {
public:
explicit OutputWidget(QWidget* parent): QOpenGLWidget(parent) {}
Mandelbrot& getMandelbrot() {return mandelbrot;}
void saveToImage(const std::function<void(void)>&, const std::function<void(bool)>&);
private:
void initializeGL() override;
void paintGL() override;
@ -27,11 +28,7 @@ private:
QPoint mousePos;
QSize oldSize {0, 0};
void initShader();
static std::vector<QVector2D> genVertices();
GLuint createVAO();
GLuint vao {};
QOpenGLShaderProgram shader;
Mandelbrot mandelbrot;
};

@ -2,6 +2,7 @@
#include <QSlider>
#include <QLabel>
#include <iostream>
#include <QPushButton>
#include "../headers/MainWindow.h"
MainWindow::MainWindow(): outputWidget(OutputWidget(this)) {
@ -28,10 +29,29 @@ void MainWindow::buildUI() {
});
iterationsSlider->setValue(100);
auto saveInfo = new QLabel;
auto saveButton = new QPushButton("Save high resolution image");
connect(
saveButton,
&QPushButton::clicked,
this,
[this, saveInfo](){
saveInfo->setText("Receiving image...");
update();
this->outputWidget.saveToImage([saveInfo](){
saveInfo->setText("Saving...");
}, [saveInfo](bool success){
QString result = success ? "Success" : "Failure";
saveInfo->setText(result);
});
});
auto controls = new QGridLayout;
controls->addWidget(iterationsCaption, 1, 1);
controls->addWidget(iterationsLabel, 1, 2);
controls->addWidget(iterationsSlider, 1, 3);
controls->addWidget(saveInfo, 2, 1, 1, 2);
controls->addWidget(saveButton, 2, 3, 1, 1);
auto lyt = new QVBoxLayout(this);
lyt->addWidget(&outputWidget);

@ -1,19 +1,31 @@
#include <QImage>
#include <iostream>
#include <QOpenGLWidget>
#include "../headers/Mandelbrot.h"
void Mandelbrot::init() {
void Mandelbrot::init(GLuint vaoId) {
initializeOpenGLFunctions();
vao = vaoId;
}
void Mandelbrot::draw(GLuint vao, QOpenGLShaderProgram& shader) {
void Mandelbrot::draw() {
glClear(GL_COLOR_BUFFER_BIT);
shader.bind();
setShaderValues(shader);
setShaderValues();
glBindVertexArray(vao);
glDrawArrays(GL_QUADS, 0, 4);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
void Mandelbrot::setShaderValues(QOpenGLShaderProgram &shader) const {
bool Mandelbrot::initShader() {
if (!shader.addShaderFromSourceFile(QOpenGLShader::Vertex, "Vertex.glsl")) return false;
if (!shader.addShaderFromSourceFile(QOpenGLShader::Fragment, "Fragment.glsl")) return false;
if (!shader.link()) return false;
if (!shader.bind()) return false;
return true;
}
void Mandelbrot::setShaderValues() {
shader.setUniformValue("origin", origin);
shader.setUniformValue("size", size);
shader.setUniformValue("iterationCount", iterations);

@ -1,5 +1,10 @@
#include <iostream>
#include <QResource>
#include <thread>
#include <future>
#include <QOpenGLFramebufferObject>
#include <QFileDialog>
#include <utility>
#include "../headers/OutputWidget.h"
using std::cout, std::endl;
@ -7,19 +12,28 @@ using std::cout, std::endl;
void OutputWidget::initializeGL() {
cout << "Initialize OpenGL" << endl;
initializeOpenGLFunctions();
getMandelbrot().init();
initShader();
getMandelbrot().init(createVAO());
if (!getMandelbrot().initShader()) close();
auto format = this->format();
cout << "OpenGL version: " << format.majorVersion() << "." << format.minorVersion() << endl;
vao = createVAO();
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
}
void OutputWidget::paintGL() {
getMandelbrot().draw(vao, shader);
getMandelbrot().draw();
}
std::vector<QVector2D> genVertices() {
return {
{-1, -1},
{1, -1},
{1, 1},
{1, 1},
{-1, 1},
{-1, -1}
};
}
GLuint OutputWidget::createVAO() {
@ -44,23 +58,6 @@ GLuint OutputWidget::createVAO() {
return vaoId;
}
std::vector<QVector2D> OutputWidget::genVertices() {
return {
{-1, -1},
{1, -1},
{1, 1},
{-1, 1}
};
}
void OutputWidget::initShader() {
if (!shader.addShaderFromSourceFile(QOpenGLShader::Vertex, "Vertex.glsl")) close();
if (!shader.addShaderFromSourceFile(QOpenGLShader::Fragment, "Fragment.glsl")) close();
if (!shader.link()) close();
if (!shader.bind()) close();
}
QVector2D divide(QPoint p, QSize s){
return {
float(p.x()) / float(s.width()),
@ -113,3 +110,38 @@ void OutputWidget::mouseReleaseEvent(QMouseEvent *e) {
void OutputWidget::keyPressEvent(QKeyEvent *e) {
}
void OutputWidget::saveToImage(const std::function<void(void)>& receiveCb, const std::function<void(bool)>& saveCb) {
double maxSize = pow(2, 14);
double div = double(width()) / height();
int w, h;
if (div > 1){
w = int(maxSize);
h = int(maxSize / div);
} else {
h = int(maxSize);
w = int(maxSize * div);
}
QOpenGLFramebufferObject fbo(w, h);
fbo.bind();
glViewport(0, 0, w, h);
getMandelbrot().draw();
QOpenGLFramebufferObject::bindDefault();
QImage img = fbo.toImage();
receiveCb();
QString fileName = QFileDialog::getSaveFileName(this, "", "", tr("Images (*.png *.xpm *.jpg)"));
if (fileName.isNull()){
saveCb(false);
return;
}
std::thread job([saveCb](const QImage& img, const QString& fileName) {
saveCb(img.save(fileName));
}, img, fileName);
job.detach();
}

Loading…
Cancel
Save