Blue Brain BioExplorer
SnapshotTask.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2018, EPFL/Blue Brain Project
3  * All rights reserved. Do not distribute without permission.
4  * Responsible Author: Daniel.Nachbaur@epfl.ch
5  *
6  * This file is part of Blue Brain BioExplorer <https://github.com/BlueBrain/BioExplorer>
7  *
8  * This library is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License version 3.0 as published
10  * by the Free Software Foundation.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 #pragma once
23 
24 #include "ImageGenerator.h"
25 
34 
36 
37 #include <fstream>
38 
39 namespace core
40 {
42 {
43  std::unique_ptr<AnimationParameters> animParams;
44  std::unique_ptr<GeometryParameters> geometryParams;
45  std::unique_ptr<VolumeParameters> volumeParams;
46  std::unique_ptr<FieldParameters> fieldParams;
47  std::unique_ptr<Renderer> renderer;
48  std::unique_ptr<Camera> camera;
51  size_t quality{100};
52  std::string format; // FreeImage formats apply
53  std::string name;
54  std::string filePath;
55 };
56 
62 {
63 public:
64  SnapshotFunctor(Engine& engine, SnapshotParams&& params, ImageGenerator& imageGenerator)
65  : _params(std::move(params))
66  , _camera(engine.createCamera())
67  , _imageGenerator(imageGenerator)
68  , _engine(engine)
69  {
70  auto& applicationParameters = engine.getParametersManager().getApplicationParameters();
71  const auto& engineName = applicationParameters.getEngine();
72  if (engineName == ENGINE_OPTIX_6)
73  CORE_THROW("Snapshot are currently not supported by the " + engineName + " engine");
74 
75  const auto& parametersManager = engine.getParametersManager();
76  if (_params.animParams == nullptr)
77  {
78  _params.animParams = std::make_unique<AnimationParameters>(parametersManager.getAnimationParameters());
79  }
80 
81  if (_params.geometryParams == nullptr)
82  {
83  _params.geometryParams = std::make_unique<GeometryParameters>(parametersManager.getGeometryParameters());
84  }
85 
86  if (_params.volumeParams == nullptr)
87  {
88  _params.volumeParams = std::make_unique<VolumeParameters>(parametersManager.getVolumeParameters());
89  }
90 
91  if (_params.fieldParams == nullptr)
92  {
93  _params.fieldParams = std::make_unique<FieldParameters>(parametersManager.getFieldParameters());
94  }
95 
96  _scene = engine.createScene(*_params.animParams, *_params.geometryParams, *_params.volumeParams,
97  *_params.fieldParams);
98 
99  if (_params.camera)
100  {
101  *_camera = *_params.camera;
102  _camera->setCurrentType(engine.getCamera().getCurrentType());
103  _camera->clonePropertiesFrom(engine.getCamera());
104  }
105  else
106  *_camera = engine.getCamera();
107 
108  _renderer = engine.createRenderer(*_params.animParams, parametersManager.getRenderingParameters());
109 
110  const auto& renderer = engine.getRenderer();
111  _renderer->setCurrentType(renderer.getCurrentType());
112  _renderer->clonePropertiesFrom(renderer);
113 
114  _scene->copyFrom(engine.getScene());
115  }
116 
118  {
119  _scene->commit();
120 
121  _camera->updateProperty(CAMERA_PROPERTY_ASPECT_RATIO.name, double(_params.size.x) / _params.size.y);
122  _camera->commit();
123 
124  _renderer->setSamplesPerPixel(1);
125  _renderer->setSubsampling(1);
126  _renderer->setCamera(_camera);
127  _renderer->setEngine(&_engine);
128  _renderer->commit();
129 
130  std::stringstream msg;
131  msg << "Render snapshot";
132  if (!_params.name.empty())
133  msg << " " << string_utils::shortenString(_params.name);
134  msg << " ...";
135 
136  const auto isStereo = _camera->hasProperty(CAMERA_PROPERTY_STEREO.name) &&
137  _camera->getProperty<bool>(CAMERA_PROPERTY_STEREO.name);
138  const auto names = isStereo ? strings{"0L", "0R"} : strings{DEFAULT};
139  std::vector<FrameBufferPtr> frameBuffers;
140  for (const auto& name : names)
141  frameBuffers.push_back(_engine.createFrameBuffer(name, _params.size, FrameBufferFormat::rgba_i8));
142 
143  while (frameBuffers[0]->numAccumFrames() != size_t(_params.samplesPerPixel))
144  {
145  for (auto frameBuffer : frameBuffers)
146  {
147  _camera->setBufferTarget(frameBuffer->getName());
148  _camera->markModified(false);
149  _camera->commit();
150  _camera->resetModified();
151  _renderer->render(frameBuffer);
152  frameBuffer->incrementAccumFrames();
153  }
154 
155  progress(msg.str(), 1.f / frameBuffers[0]->numAccumFrames(),
156  float(frameBuffers[0]->numAccumFrames()) / _params.samplesPerPixel);
157  }
158 
159  if (!_params.filePath.empty() && frameBuffers.size() == 1)
160  {
161  auto& fb = *frameBuffers[0];
162  _writeToDisk(fb);
163 
165  }
166  else
167  return _imageGenerator.createImage(frameBuffers, _params.format, _params.quality);
168  }
169 
170 private:
171  void _writeToDisk(FrameBuffer& fb)
172  {
173  auto image = fb.getImage();
174  auto fif = _params.format == "jpg" ? FIF_JPEG : FreeImage_GetFIFFromFormat(_params.format.c_str());
175 
176  if (fif == FIF_JPEG)
177  image.reset(FreeImage_ConvertTo24Bits(image.get()));
178  else if (fif == FIF_UNKNOWN)
179  {
180  std::cerr << "Unknown format: " << _params.format << std::endl;
181  return;
182  }
183 
184  int flags = _params.quality;
185  if (fif == FIF_TIFF)
186  flags = TIFF_NONE;
187 
188  core::freeimage::MemoryPtr memory(FreeImage_OpenMemory());
189 
190  FreeImage_SaveToMemory(fif, image.get(), memory.get(), flags);
191 
192  BYTE* pixels = nullptr;
193  DWORD numPixels = 0;
194  FreeImage_AcquireMemory(memory.get(), &pixels, &numPixels);
195 
196  std::ofstream file;
197  const std::string path = _params.filePath + "." + _params.format;
198  file.open(path, std::ios_base::binary);
199  if (!file.is_open())
200  {
201  std::cerr << "Failed to create " << path << std::endl;
202  return;
203  }
204 
205  file.write((char*)pixels, numPixels);
206  file.close();
207  }
208 
209  SnapshotParams _params;
210  FrameBufferPtr _frameBuffer;
211  CameraPtr _camera;
212  RendererPtr _renderer;
213  ScenePtr _scene;
214  ImageGenerator& _imageGenerator;
215  Engine& _engine;
216 };
217 } // namespace core
Provides an abstract implementation of a ray-tracing engine.
Definition: Engine.h:59
virtual PLATFORM_API FrameBufferPtr createFrameBuffer(const std::string &name, const Vector2ui &frameSize, FrameBufferFormat frameBufferFormat) const =0
Factory method to create an engine-specific framebuffer.
PLATFORM_API const auto & getParametersManager() const
Returns the parameter manager.
Definition: Engine.h:210
virtual PLATFORM_API ScenePtr createScene(AnimationParameters &animationParameters, GeometryParameters &geometryParameters, VolumeParameters &volumeParameters, FieldParameters &fieldParameters) const =0
Factory method to create an engine-specific scene.
PLATFORM_API Renderer & getRenderer()
Returns the renderer.
Definition: Engine.cpp:72
PLATFORM_API Scene & getScene()
Returns the scene.
Definition: Engine.h:147
virtual PLATFORM_API RendererPtr createRenderer(const AnimationParameters &animationParameters, const RenderingParameters &renderingParameters) const =0
Factory method to create an engine-specific renderer.
PLATFORM_API const Camera & getCamera() const
Returns the camera.
Definition: Engine.h:161
This class represents a frame buffer for an engine specific code. It provides an API for utilizing an...
Definition: FrameBuffer.h:39
PLATFORM_API freeimage::ImagePtr getImage()
Get the Image object.
Definition: FrameBuffer.cpp:49
ImageBase64 createImage(FrameBuffer &frameBuffer, const std::string &format, uint8_t quality)
const std::string & getCurrentType() const
SnapshotFunctor(Engine &engine, SnapshotParams &&params, ImageGenerator &imageGenerator)
Definition: SnapshotTask.h:64
ImageGenerator::ImageBase64 operator()()
Definition: SnapshotTask.h:117
void progress(const std::string &message, const float increment, const float amount)
Definition: TaskFunctor.h:58
std::unique_ptr< FIMEMORY, MemoryDeleter > MemoryPtr
Definition: ImageUtils.h:50
std::string shortenString(const std::string &string, const size_t maxLength)
Definition: StringUtils.cpp:37
std::shared_ptr< Camera > CameraPtr
Definition: Types.h:93
std::shared_ptr< Renderer > RendererPtr
Definition: Types.h:97
std::shared_ptr< FrameBuffer > FrameBufferPtr
Definition: Types.h:100
std::shared_ptr< Scene > ScenePtr
Definition: Types.h:88
glm::vec< 2, uint32_t > Vector2ui
Definition: MathTypes.h:133
#define CORE_THROW(__msg)
Definition: Logs.h:42
std::vector< std::string > strings
Definition: Types.h:44
std::unique_ptr< Renderer > renderer
Definition: SnapshotTask.h:47
std::unique_ptr< VolumeParameters > volumeParams
Definition: SnapshotTask.h:45
std::string filePath
Definition: SnapshotTask.h:54
std::unique_ptr< FieldParameters > fieldParams
Definition: SnapshotTask.h:46
std::unique_ptr< AnimationParameters > animParams
Definition: SnapshotTask.h:43
std::unique_ptr< GeometryParameters > geometryParams
Definition: SnapshotTask.h:44
std::unique_ptr< Camera > camera
Definition: SnapshotTask.h:48
std::string format
Definition: SnapshotTask.h:52