diff --git a/CMakeLists.txt b/CMakeLists.txt index cc59037..5b6534d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,13 +80,6 @@ if(COLOR_MANAGMENT) target_compile_definitions(tenmon PRIVATE "COLOR_MANAGMENT") endif(COLOR_MANAGMENT) -# not ready yet -#option(USE_OPENGLES ON) -if(USE_OPENGLES) - target_compile_definitions(tenmon PRIVATE "NOU_GLES_CONTEXT") -endif(USE_OPENGLES) - - if(UNIX AND NOT APPLE) target_include_directories(tenmon PRIVATE ${GIO_INCLUDE_DIRS}) endif() diff --git a/imagescrollareagl.cpp b/imagescrollareagl.cpp index c97b0bc..94d288b 100644 --- a/imagescrollareagl.cpp +++ b/imagescrollareagl.cpp @@ -16,6 +16,7 @@ #include int FILTERING = 1; +bool OpenGLES = false; struct RawImageType { @@ -50,6 +51,13 @@ RawImageType getRawImageType(const RawImage *img) type.textureFormat = QOpenGLTexture::R32F; type.dataType = QOpenGLTexture::Float32; break; + case RawImage::FLOAT16: + if(img->channels() >= 3) + type.textureFormat = QOpenGLTexture::RGBA16F; + else + type.textureFormat = QOpenGLTexture::R16F; + type.dataType = QOpenGLTexture::Float16; + break; default: qWarning() << "Invalid format" << img->type(); break; @@ -128,9 +136,11 @@ void ImageWidget::setImage(std::shared_ptr image, int index) m_image->allocateStorage(); m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear); m_image->setWrapMode(QOpenGLTexture::ClampToEdge); - m_image->setBorderColor(0, 0, 0, 0); - m_image->setData(0, rawImageType.pixelFormat, rawImageType.dataType, (const void*)image->data(), m_transferOptions.get()); - m_image->generateMipMaps(); + //m_image->setBorderColor(0, 0, 0, 0); + m_image->setData(0, rawImageType.pixelFormat, rawImageType.dataType, (const void*)image->data()); + //m_image->generateMipMaps(); + m_image->bind(); + f->glGenerateMipmap(GL_TEXTURE_2D); qDebug() << "setImage" << timer.elapsed(); m_unit_scale[0] = 1.0f; @@ -203,7 +213,7 @@ void ImageWidget::allocateThumbnails(const QStringList &paths) m_thumbnailTexture->destroy(); m_thumbnailTexture->create(); - m_thumbnailTexture->setFormat(QOpenGLTexture::RGBA16_UNorm); + m_thumbnailTexture->setFormat(QOpenGLTexture::RGBA16F); m_thumbnailTexture->setSize(THUMB_SIZE, THUMB_SIZE); m_thumbnailTexture->setLayers(std::min((int)paths.size(), m_maxArrayLayers)); m_thumbnailTexture->allocateStorage(); @@ -301,7 +311,7 @@ void ImageWidget::thumbnailLoaded(const Image *image) makeCurrent(); const RawImage *raw = image->thumbnail(); if(!raw || !raw->valid())return; - m_thumbnailTexture->setData(0, image->number(), QOpenGLTexture::RGBA, QOpenGLTexture::UInt16, raw->data(), m_transferOptions.get()); + m_thumbnailTexture->setData(0, image->number(), QOpenGLTexture::RGBA, QOpenGLTexture::Float16, raw->data()); float a = raw->thumbAspect(); int sizes[3] = { std::max(1, a > 1.0f ? THUMB_SIZE : (int)(THUMB_SIZE * a)), std::max(1, a < 1.0f ? THUMB_SIZE : (int)(THUMB_SIZE / a)), image->number() }; m_sizesDirty = true; @@ -355,6 +365,7 @@ void ImageWidget::paintGL() mvp.ortho(rect()); m_thumbnailProgram->setUniformValue("mvp", mvp); fx->glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_thumbnailCount); + m_vaoThumb->release(); QPainter painter(this); const int w = width()/THUMB_SIZE_BORDER; @@ -417,6 +428,7 @@ void ImageWidget::paintGL() m_program->setUniformValue("srgb", m_srgb); #endif f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + m_vao->release(); } } @@ -439,19 +451,24 @@ void ImageWidget::initializeGL() if(fx == nullptr) QMessageBox::critical(this, tr("OpenGL error"), tr("Could not initialize OpenGL 3.3 context. Ensure that proper GPU driver is installed.")); + OpenGLES = context()->isOpenGLES(); + auto loadShader = [](const QString &file) { QFile fr(file); fr.open(QIODevice::ReadOnly); QByteArray src; -#ifdef NOU_GLES_CONTEXT - src = "#version 300 es\n" - "precision highp float;\n" - "precision highp sampler2DArray;\n" - "#line 1\n"; -#else - src = "#version 330\n#line 1\n"; -#endif + if(OpenGLES) + { + src = "#version 300 es\n" + "precision highp float;\n" + "precision highp sampler2DArray;\n" + "#line 1\n"; + } + else + { + src = "#version 330\n#line 1\n"; + } src.append(fr.readAll()); return src; }; @@ -551,6 +568,7 @@ void ImageWidget::initializeGL() m_thumbnailProgram->enableAttributeArray("imageSize_num"); fx->glVertexAttribIPointer(m_thumbnailProgram->attributeLocation("imageSize_num"), 3, GL_INT, 0, nullptr); fx->glVertexAttribDivisor(m_thumbnailProgram->attributeLocation("imageSize_num"), 1); + m_vaoThumb->release(); m_image = std::unique_ptr(new QOpenGLTexture(QOpenGLTexture::Target2D)); m_image->setFormat(QOpenGLTexture::RGB8U); diff --git a/loadrunable.cpp b/loadrunable.cpp index 8b17119..8fd1683 100644 --- a/loadrunable.cpp +++ b/loadrunable.cpp @@ -13,7 +13,6 @@ #include #include "rawimage.h" #include "starfit.h" -#include "wcslib/wcshdr.h" #ifdef COLOR_MANAGMENT #include @@ -270,9 +269,6 @@ bool loadFITS(const QString path, ImageInfoData &info, std::shared_ptr else image = RawImage::fromPlanar(img); - if(image) - image->convertToGLFormat(); - break; } } @@ -343,16 +339,14 @@ bool loadXISF(const QString &path, ImageInfoData &info, std::shared_ptr(tmpImage.width(), tmpImage.height(), 1, type); std::memcpy(image->data(), tmpImage.imageData(), tmpImage.imageDataSize() / tmpImage.channelCount()); + return true; } else if(tmpImage.channelCount() == 3 || tmpImage.channelCount() == 4) { image = RawImage::fromPlanar(tmpImage.imageData(), tmpImage.width(), tmpImage.height(), tmpImage.channelCount(), type); - } - if(image) - { - image->convertToGLFormat(); return true; } + return false; } catch (LibXISF::Error &err) { @@ -381,8 +375,10 @@ void LoadRunable::run() if(!loadImage(m_file, info, rawImage)) info.info.append({QObject::tr("Error"), QObject::tr("Failed to load image")}); + if(rawImage && !m_thumbnail) { + rawImage->convertToGLFormat(); timer.start(); rawImage->calcStats(); const RawImage::Stats &stats = rawImage->imageStats(); @@ -418,6 +414,7 @@ void LoadRunable::run() if(QUALITY_RESIZE) rawImage->resize(THUMB_SIZE, THUMB_SIZE); + rawImage->convertToGLFormat(); rawImage->convertToThumbnail(); } QMetaObject::invokeMethod(m_receiver, "thumbnailLoadFinish", Qt::QueuedConnection, Q_ARG(std::shared_ptr, rawImage)); diff --git a/main.cpp b/main.cpp index c3ecc85..2a4fd8c 100644 --- a/main.cpp +++ b/main.cpp @@ -4,26 +4,39 @@ #include #include +/*float h2f(unsigned short h) +{ + unsigned int + return f; +}*/ + int main(int argc, char *argv[]) { #ifdef __linux__ setenv("LC_NUMERIC", "C", 1); #endif + bool useGLES = false; + for(int i = 0; i < argc; i++) + if(std::strcmp("-gles", argv[i]) == 0) + { + useGLES = true; + } + QSurfaceFormat format; -#ifdef NOU_GLES_CONTEXT - format.setMajorVersion(3); - format.setMinorVersion(0); - format.setRenderableType(QSurfaceFormat::OpenGLES); - printf("OpenGL ES\n"); - qDebug() << "Requesting OpenGL ES"; -#else - format.setMajorVersion(3); - format.setMinorVersion(3); - //format.setOption(QSurfaceFormat::DebugContext); - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); - printf("OpenGL\n"); -#endif + if(useGLES) + { + format.setMajorVersion(3); + format.setMinorVersion(0); + format.setRenderableType(QSurfaceFormat::OpenGLES); + } + else + { + format.setMajorVersion(3); + format.setMinorVersion(3); + //format.setOption(QSurfaceFormat::DebugContext); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + } QSurfaceFormat::setDefaultFormat(format); QApplication a(argc, argv); diff --git a/rawimage.cpp b/rawimage.cpp index 15d2dea..d4b196f 100644 --- a/rawimage.cpp +++ b/rawimage.cpp @@ -2,12 +2,16 @@ #include #include #include +#include + +using F16 = qfloat16; int THUMB_SIZE = 128; int THUMB_SIZE_BORDER = 138; int THUMB_SIZE_BORDER_Y = 158; double SATURATION = 0.95; bool QUALITY_RESIZE = true; +extern bool OpenGLES; #ifdef __SSE2__ template @@ -21,6 +25,7 @@ size_t RawImage::typeSize(RawImage::DataType type) case RawImage::UINT8: return 1; case RawImage::UINT16: + case RawImage::FLOAT16: return 2; case RawImage::UINT32: case RawImage::FLOAT32: @@ -338,7 +343,7 @@ RawImage::DataType RawImage::type() const uint32_t RawImage::norm() const { - switch(m_type) + switch(m_origType) { case UINT8: return UINT8_MAX; @@ -404,10 +409,10 @@ void RawImage::convertToThumbnail() if(m_thumbAspect == 0.0f) m_thumbAspect = (float)width() / height(); - std::unique_ptr outptr = std::make_unique(THUMB_SIZE * THUMB_SIZE * 4 * sizeof(uint16_t)); - uint16_t *out = reinterpret_cast(outptr.get()); + std::unique_ptr outptr = std::make_unique(THUMB_SIZE * THUMB_SIZE * 4 * sizeof(qfloat16)); + F16 *out = reinterpret_cast(outptr.get()); - auto loop = [&](uint16_t *out, auto *in, auto scale) + auto loop = [&](F16 *out, auto *in, float scale) { for(int i=0; i(m_pixels.get()), 256); + loop(out, reinterpret_cast(m_pixels.get()), 1.0f/UINT8_MAX); break; case UINT16: - loop(out, reinterpret_cast(m_pixels.get()), 1); + loop(out, reinterpret_cast(m_pixels.get()), 1.0f/UINT16_MAX); break; case UINT32: - loop(out, reinterpret_cast(m_pixels.get()), UINT16_MAX/(float)UINT32_MAX); + loop(out, reinterpret_cast(m_pixels.get()), (float)(1.0/UINT32_MAX)); + break; + case FLOAT16: + loop(out, reinterpret_cast(m_pixels.get()), 1.0f); break; case FLOAT32: - loop(out, reinterpret_cast(m_pixels.get()), 65535.0); + loop(out, reinterpret_cast(m_pixels.get()), 1.0f); break; default: qWarning() << "FLOAT64 should not happend"; @@ -455,7 +463,7 @@ void RawImage::convertToThumbnail() m_height = THUMB_SIZE; m_ch = 4; m_channels = 3; - m_type = UINT16; + m_type = FLOAT16; } void RawImage::convertToGLFormat() @@ -483,6 +491,17 @@ void RawImage::convertToGLFormat() for(size_t i = 0; i < s; i++) dst[i] = src[i]; } + else if(OpenGLES && m_type == UINT16) + { + m_original = std::move(m_pixels); + allocate(m_width, m_height, m_channels, FLOAT16); + m_origType = UINT16; + F16 *dst = reinterpret_cast(m_pixels.get()); + uint16_t *src = reinterpret_cast(m_original.get()); + + for(size_t i = 0; i < s; i++) + dst[i] = src[i] / (float)UINT16_MAX; + } } float RawImage::thumbAspect() const @@ -571,6 +590,21 @@ bool RawImage::pixel(int x, int y, double &r, double &g, double &b) const } break; } + case FLOAT16: + { + const F16 *v = static_cast(origData(y, x)); + if(m_channels == 1) + { + r = g = b = *v; + } + else + { + r = v[0]; + g = v[1]; + b = v[2]; + } + break; + } } return true; } diff --git a/rawimage.h b/rawimage.h index 89be875..81a54ad 100644 --- a/rawimage.h +++ b/rawimage.h @@ -45,6 +45,7 @@ public: UINT8, UINT16, UINT32, + FLOAT16, FLOAT32, FLOAT64, };