3#include "../../global.hpp"
5#include "../_decl/decl_image_scene.hpp"
6#include "../_decl/decl_image_view.hpp"
7#include "../_decl/decl_opengl_image_renderer_factory.hpp"
9#include "../../_decl/decl_image.hpp"
10#include "../../_decl/decl_image_plane.hpp"
11#include "../../_decl/decl_vpat.hpp"
13#include "../../driver/_decl/decl_device_image.hpp"
25 std::unique_lock<std::mutex> guard(renderMutex_);
27 if (renderEngine == RenderEngine())
30 std::unique_ptr<Engine> engine;
34 throw std::runtime_error(
"failed to set unknown render engine.");
38 engine = std::make_unique<RasterEngine>(*
this);
43 engine = std::make_unique<GLEngine>(*
this, renderEngine);
49 throw std::runtime_error(
"cannot change the render engine for a scene without a view.");
51 imageView->setViewport(engine->CreateViewport());
52 std::swap(engine_, engine);
55 inline void ImageScene::UpdateSceneRect(
const Image &image)
noexcept
57 auto currentSceneRect = sceneRect().toRect();
58 QRect requredSceneRect(0, 0, image.Width(), image.Height());
59 if (currentSceneRect == requredSceneRect)
62 setSceneRect(requredSceneRect);
68 UpdateSceneRect(image);
69 auto mappedImage = UpdateRenderTarget(image);
75 CopyImageData(*mappedImage);
80 auto viewList = views();
84 return dynamic_cast<class
ImageView *
>(viewList.first());
87 inline void ImageScene::RasterEngine::Render(QPainter *painter,
const QRectF &rect)
noexcept
94 if (screenImage_.isNull())
97 painter->drawImage(rect, screenImage_, rect);
101 auto image = imageView->Image();
106 auto imageRect = ImageScene().sceneRect();
107 auto targetRect = rect;
108 targetRect.setLeft(qMax(0.0, targetRect.left()));
109 targetRect.setWidth(qMin(imageRect.width(), targetRect.width()));
110 targetRect.setTop(qMax(0.0, targetRect.top()));
111 targetRect.setHeight(qMin(imageRect.height(), targetRect.height()));
113 painter->drawImage(targetRect, screenImage_, screenImageRect_);
117 inline std::unique_ptr<Image> ImageScene::RasterEngine::UpdateRenderTarget(
const Image &image)
noexcept
124 auto currentWidth = image.Width();
125 auto currentHeight = image.Height();
126 if (screenImage_.size() == QSize(currentWidth, currentHeight))
127 return std::unique_ptr<class Image>();
129 screenImage_ = QImage(currentWidth, currentHeight, QImage::Format_ARGB32_Premultiplied);
130 return std::unique_ptr<class Image>();
134 auto viewportRect = imageView->viewport()->rect();
135 auto mappedViewportRect = imageView->mapToScene(viewportRect).boundingRect();
139 QRectF(qMax(imageRectF.left(), mappedViewportRect.left()), qMax(imageRectF.top(), mappedViewportRect.top()),
140 qMin(imageRectF.width(), mappedViewportRect.width()),
141 qMin(imageRectF.height(), mappedViewportRect.height()));
145 auto sourceLeft = qMax(qFloor(mappedViewportRect.left()), 0);
146 auto sourceTop = qMax(qFloor(mappedViewportRect.top()), 0);
147 auto sourceRight = qMin(qCeil(mappedViewportRect.right()), image.Width() - 1);
148 auto sourceBottom = qMin(qCeil(mappedViewportRect.bottom()), image.Height() - 1);
149 Size2D<int> sourceSize(sourceRight - sourceLeft, sourceBottom - sourceTop);
150 Rect<int> sourceRect(Point2D<int>(sourceLeft, sourceTop), sourceSize);
153 if (sourceRect.Width() <= 0 || sourceRect.Height() <= 0)
154 return std::unique_ptr<class Image>();
156 auto targetRectF = QRectF(imageView->mapFromScene(sourceRectF).boundingRect());
157 Size2D<int> targetSize;
158 if (mappedViewportRect.width() <= targetRectF.width())
160 targetSize = sourceRect.Size();
161 screenImageRect_ = QRectF(mappedViewportRect.left() - qFloor(mappedViewportRect.left()),
162 mappedViewportRect.top() - qFloor(mappedViewportRect.top()),
163 qMin(mappedViewportRect.width(),
static_cast<qreal
>(sourceRect.Width())),
164 qMin(mappedViewportRect.height(),
static_cast<qreal
>(sourceRect.Height())));
168 targetSize = Size2D<int>(
static_cast<int>(targetRectF.width()),
static_cast<int>(targetRectF.height()));
169 screenImageRect_ = QRectF(0.0, 0.0, targetSize.Width(), targetSize.Height());
172 auto mappedImage = image.Map(sourceRect, targetSize);
173 if (screenImage_.size() == QSize(targetSize.Width(), targetSize.Height()))
176 screenImage_ = QImage(targetSize.Width(), targetSize.Height(), QImage::Format_ARGB32_Premultiplied);
181 inline void ImageScene::RasterEngine::CopyImageData(
const Image &image)
noexcept
183 switch (image.PlanesCount())
189 Private::CopyImageDataMonoToBGRA(image, screenImage_.bits());
194 Private::CopyImageDataRGBToBGRA(image, screenImage_.bits());
199 inline void ImageScene::GLEngine::Render(QPainter *painter,
const QRectF &rect)
noexcept
205 painter->beginNativePainting();
207 glClearColor(
static_cast<GLclampf
>(clearColor_.redF()),
static_cast<GLclampf
>(clearColor_.greenF()),
208 static_cast<GLclampf
>(clearColor_.blueF()), 1.0);
209 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
211 renderer_->Render(rect);
213 painter->endNativePainting();
216 inline std::unique_ptr<Image> ImageScene::GLEngine::UpdateRenderTarget(
const Image &image)
noexcept
219 return std::unique_ptr<class Image>();
221 if (QThread::currentThread() != QApplication::instance()->thread())
224 return std::unique_ptr<class Image>();
231 auto uploadMode = imageView->UploadMode();
236 bufferFormat.Width = image.Width();
237 bufferFormat.Height = image.Height();
239 if (bufferFormat != renderer_->BufferFormat())
241 renderer_->UpdateBufferFormat(bufferFormat);
242 renderer_->UpdateMaping(
ImageScene().sceneRect(), Size2D<int>());
245 return std::unique_ptr<class Image>();
250 auto viewportRect = imageView->viewport()->rect();
251 auto mappedViewportRect = imageView->mapToScene(viewportRect).boundingRect();
256 QRectF(qMax(imageRectF.left(), mappedViewportRect.left()), qMax(imageRectF.top(), mappedViewportRect.top()),
257 qMin(imageRectF.width(), mappedViewportRect.width()),
258 qMin(imageRectF.height(), mappedViewportRect.height()));
262 auto sourceLeft = qMax(qFloor(mappedViewportRect.left()), 0);
263 auto sourceTop = qMax(qFloor(mappedViewportRect.top()), 0);
264 auto sourceRight = qMin(qCeil(mappedViewportRect.right()), image.Width() - 1);
265 auto sourceBottom = qMin(qCeil(mappedViewportRect.bottom()), image.Height() - 1);
266 Size2D<int> sourceSize(sourceRight - sourceLeft, sourceBottom - sourceTop);
267 Rect<int> sourceRect(Point2D<int>(sourceLeft, sourceTop), sourceSize);
270 if (sourceRect.Width() <= 0 || sourceRect.Height() <= 0)
271 return std::unique_ptr<class Image>();
273 auto targetRectF = QRectF(imageView->mapFromScene(sourceRectF).boundingRect());
274 Size2D<int> targetSize;
276 if (mappedViewportRect.width() <= targetRectF.width())
279 targetSize = sourceRect.Size();
286 targetSize = Size2D<int>(
static_cast<int>(qMin(targetRectF.width(), imageRectF.width())),
287 static_cast<int>(qMin(targetRectF.height(), imageRectF.height())));
290 auto mappedImage = image.Map(sourceRect, targetSize);
295 ? targetSize.Width() % 4
297 bufferFormat.LinePad = (modWidth) ? 4 - modWidth : 0;
298 bufferFormat.Width = targetSize.Width();
299 bufferFormat.Height = targetSize.Height();
301 if (bufferFormat != renderer_->BufferFormat())
302 renderer_->UpdateBufferFormat(bufferFormat);
304 renderer_->UpdateMaping(sourceRectF, targetSize);
310 inline void ImageScene::GLEngine::CopyImageData(
const Image &image)
noexcept
315 if (QThread::currentThread() != QApplication::instance()->thread())
323 auto dst = renderer_->BeginBufferAccess(linePad);
327 switch (image.PlanesCount())
333 if (renderer_->MonoUploadSupported())
334 Private::CopyImageDataMonoToMono(image, dst, linePad);
336 Private::CopyImageDataMonoToRGBA(image, dst);
341 Private::CopyImageDataRGBToRGBA(image, dst);
345 renderer_->EndBufferAccess();
348 inline QWidget *ImageScene::GLEngine::CreateViewport()
350 auto glViewport =
new ImageScene::GLViewport(*
this);
353 glViewport->setFormat(format);
357 inline void ImageScene::GLEngine::ViewPortSetup()
360 initializeOpenGLFunctions();
373 inline void ImageScene::GLEngine::MakeCurrent() noexcept
376 if (
auto glViewport =
dynamic_cast<QOpenGLWidget *
>(imageView->viewport()))
377 glViewport->makeCurrent();
380 inline void ImageScene::drawBackground(QPainter *painter,
const QRectF &rect)
382 if (syncUploadRequired_)
385 if (
auto image = imageView->Image())
387 syncUploadRequired_ =
false;
390 std::unique_lock<std::mutex> guard(renderMutex_);
391 Render(painter, rect);
Scene to provide a convenient display for an image.
Definition decl_image_scene.hpp:49
class ImageView * ImageView() noexcept
Return the image view associated with this scene.
Definition detail_image_scene.hpp:78
ImageScene(QObject *parent=nullptr)
Definition decl_image_scene.hpp:60
virtual void UploadImage(const Image &image) noexcept
Upload an image.
Definition detail_image_scene.hpp:65
Cvb::UI::UploadMode UploadMode() const noexcept
Get the current upload mode.
Definition decl_image_view.hpp:321
static QSurfaceFormat CreateFormat(int version)
Create a OpenGL format for the given version.
Definition detail_opengl_image_renderer_factory.hpp:35
static std::unique_ptr< OpenGLImageRenderer > CreateRenderer(int version)
Create a renderer.
Definition detail_opengl_image_renderer_factory.hpp:18
Namespace for user interface components.
Definition decl_image_scene.hpp:39
@ Mono
Definition ui.hpp:144
@ RGB
Definition ui.hpp:140
@ Image
Definition detail_ui.hpp:45
RenderEngine
Defines the render engine used for drawing.
Definition ui.hpp:108
@ Raster
Definition ui.hpp:114
@ OpenGL3
Definition ui.hpp:127
@ OpenGL2
Definition ui.hpp:121
Root namespace for the Image Manager interface.
Definition c_bayer_to_rgb.h:17