ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
UIImage.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 // 4293: Filament's utils/algorithm.h utils::details::clz() does strange
11 // things with MSVC. Somehow sizeof(unsigned int) > 4, but its size is
12 // 32 so that x >> 32 gives a warning. (Or maybe the compiler can't
13 // determine the if statement does not run.)
14 // 4146: PixelBufferDescriptor assert unsigned is positive before subtracting
15 // but MSVC can't figure that out.
16 #ifdef _MSC_VER
17 #pragma warning(push)
18 #pragma warning(disable : 4293 4146)
19 #endif // _MSC_VER
20 
21 #include <filament/Texture.h>
22 
23 #ifdef _MSC_VER
24 #pragma warning(pop)
25 #endif // _MSC_VER
26 
27 #include <Image.h>
28 #include <ImageIO.h>
29 
30 #include <string>
31 
32 #include "t/geometry/Image.h"
36 
37 namespace cloudViewer {
38 namespace visualization {
39 namespace gui {
40 
41 struct UIImage::Impl {
42  std::string image_path_;
44  std::shared_ptr<geometry::Image> image_data_; // temporary storage
45  std::shared_ptr<t::geometry::Image> timage_data_; // temporary storage
46  float image_width_;
48  float u0_;
49  float v0_;
50  float u1_;
51  float v1_;
53  renderer_; // nullptr if texture_ isn't ours
55 };
56 
57 UIImage::UIImage(const char* image_path) : impl_(new UIImage::Impl()) {
58  impl_->image_path_ = image_path;
59  impl_->image_data_ = io::CreateImageFromFile(image_path);
60  if (impl_->image_data_) {
61  if (impl_->image_data_ && impl_->image_data_->width_ == 0 &&
62  impl_->image_data_->height_ == 0) {
63  impl_->image_data_.reset();
64  } else {
65  impl_->image_width_ = float(impl_->image_data_->width_);
66  impl_->image_height_ = float(impl_->image_data_->height_);
67  }
68  }
69  impl_->u0_ = 0.0f;
70  impl_->v0_ = 0.0f;
71  impl_->u1_ = 1.0f;
72  impl_->v1_ = 1.0f;
73  impl_->renderer_ = nullptr;
74 }
75 
76 UIImage::UIImage(std::shared_ptr<geometry::Image> image)
77  : impl_(new UIImage::Impl()) {
78  impl_->image_data_ = image;
79  if (impl_->image_data_) {
80  if (impl_->image_data_ && impl_->image_data_->width_ == 0 &&
81  impl_->image_data_->height_ == 0) {
82  impl_->image_data_.reset();
83  } else {
84  impl_->image_width_ = float(impl_->image_data_->width_);
85  impl_->image_height_ = float(impl_->image_data_->height_);
86  }
87  }
88  impl_->u0_ = 0.0f;
89  impl_->v0_ = 0.0f;
90  impl_->u1_ = 1.0f;
91  impl_->v1_ = 1.0f;
92  impl_->renderer_ = nullptr;
93 }
94 
95 UIImage::UIImage(std::shared_ptr<t::geometry::Image> image)
96  : impl_(new UIImage::Impl()) {
97  impl_->timage_data_ = image;
98  if (impl_->timage_data_->IsEmpty()) {
99  impl_->timage_data_.reset();
100  } else {
101  impl_->image_width_ = float(impl_->timage_data_->GetCols());
102  impl_->image_height_ = float(impl_->timage_data_->GetRows());
103  }
104  impl_->u0_ = 0.0f;
105  impl_->v0_ = 0.0f;
106  impl_->u1_ = 1.0f;
107  impl_->v1_ = 1.0f;
108  impl_->renderer_ = nullptr;
109 }
110 
112  float u0 /*= 0.0f*/,
113  float v0 /*= 0.0f*/,
114  float u1 /*= 1.0f*/,
115  float v1 /*= 1.0f*/)
116  : impl_(new UIImage::Impl()) {
117  auto& resource_manager =
119  auto tex_weak = resource_manager.GetTexture(texture_id);
120  auto tex_sh = tex_weak.lock();
121  if (tex_sh) {
122  float uvw = u1 - u0;
123  float uvh = v1 - v0;
124  impl_->image_width_ = uvw * float(tex_sh->getWidth());
125  impl_->image_height_ = uvh * float(tex_sh->getHeight());
126  }
127  impl_->u0_ = u0;
128  impl_->v0_ = v0;
129  impl_->u1_ = u1;
130  impl_->v1_ = v1;
131  impl_->renderer_ = nullptr;
132  impl_->texture_ = texture_id;
133 }
134 
136  if (impl_->renderer_) {
137  impl_->renderer_->RemoveTexture(impl_->texture_);
138  }
139 }
140 
141 void UIImage::UpdateImage(std::shared_ptr<geometry::Image> image) {
142  impl_->image_data_ = image;
143  impl_->timage_data_.reset();
144 }
145 
146 void UIImage::UpdateImage(std::shared_ptr<t::geometry::Image> image) {
147  impl_->image_data_.reset();
148  impl_->timage_data_ = image;
149 }
150 
151 void UIImage::SetScaling(Scaling scaling) { impl_->scaling_ = scaling; }
152 
153 UIImage::Scaling UIImage::GetScaling() const { return impl_->scaling_; }
154 
156  const Widget::Constraints& constraints) const {
157  if (impl_->image_width_ != 0.0f && impl_->image_height_ != 0.0f) {
158  if (impl_->scaling_ == Scaling::ASPECT &&
159  (constraints.width < impl_->image_width_ ||
160  constraints.height < impl_->image_height_)) {
161  float aspect = impl_->image_width_ / impl_->image_height_;
162  float w_at_height = float(constraints.height) * aspect;
163  float h_at_width = float(constraints.width) / aspect;
164  if (w_at_height <= constraints.width) {
165  return Size(int(std::round(w_at_height)), constraints.height);
166  } else {
167  return Size(constraints.width, int(std::round(h_at_width)));
168  }
169  } else {
170  return Size(int(std::round(impl_->image_width_)),
171  int(std::round(impl_->image_height_)));
172  }
173  } else {
174  return Size(0, 0);
175  }
176 }
177 
179  visualization::rendering::Renderer& renderer, const Rect& frame) const {
181 
182  if (impl_->image_data_) { // Legacy Image
183  if (impl_->texture_ == visualization::rendering::TextureHandle::kBad) {
184  impl_->texture_ = renderer.AddTexture(impl_->image_data_);
185  if (impl_->texture_ !=
187  impl_->renderer_ = &renderer;
188  impl_->image_width_ = float(impl_->image_data_->width_);
189  impl_->image_height_ = float(impl_->image_data_->height_);
190  params.image_size_changed = true;
191  } else {
192  impl_->texture_ = visualization::rendering::TextureHandle();
193  }
194  } else {
195  if (!renderer.UpdateTexture(impl_->texture_, impl_->image_data_,
196  false)) {
197  impl_->texture_ = renderer.AddTexture(impl_->image_data_);
198  impl_->image_width_ = float(impl_->image_data_->width_);
199  impl_->image_height_ = float(impl_->image_data_->height_);
200  params.image_size_changed = true;
201  }
202  }
203  impl_->image_data_.reset();
204  } else if (impl_->timage_data_) { // TGeoemetry Image
205  if (impl_->texture_ == visualization::rendering::TextureHandle::kBad) {
206  impl_->texture_ = renderer.AddTexture(*impl_->timage_data_.get());
207  if (impl_->texture_ !=
209  impl_->renderer_ = &renderer;
210  impl_->image_width_ = float(impl_->timage_data_->GetCols());
211  impl_->image_height_ = float(impl_->timage_data_->GetRows());
212  params.image_size_changed = true;
213  } else {
214  impl_->texture_ = visualization::rendering::TextureHandle();
215  }
216  } else {
217  if (!renderer.UpdateTexture(impl_->texture_, *impl_->timage_data_,
218  false)) {
219  impl_->texture_ =
220  renderer.AddTexture(*impl_->timage_data_.get());
221  impl_->image_width_ = float(impl_->timage_data_->GetCols());
222  impl_->image_height_ = float(impl_->timage_data_->GetRows());
223  params.image_size_changed = true;
224  }
225  }
226  impl_->timage_data_.reset();
227  }
228 
229  params.texture = impl_->texture_;
230 
231  float width_px = impl_->image_width_;
232  float height_px = impl_->image_height_;
233  if (impl_->texture_ != visualization::rendering::TextureHandle::kBad) {
234  switch (impl_->scaling_) {
235  case Scaling::NONE: {
236  float w = std::min(float(frame.width), width_px);
237  float h = std::min(float(frame.height), height_px);
238  params.width = w;
239  params.height = h;
240  params.u0 = impl_->u0_;
241  params.v0 = impl_->v0_;
242  params.u1 =
243  impl_->u0_ + (impl_->u1_ - impl_->u0_) * w / width_px;
244  params.v1 =
245  impl_->v0_ + (impl_->v1_ - impl_->v0_) * h / height_px;
246  break;
247  }
248  case Scaling::ANY:
249  params.width = float(frame.width);
250  params.height = float(frame.height);
251  params.u0 = impl_->u0_;
252  params.v0 = impl_->v0_;
253  params.u1 = impl_->u1_;
254  params.v1 = impl_->v1_;
255  break;
256  case Scaling::ASPECT: {
257  float aspect = width_px / height_px;
258  float w_at_height = float(frame.height) * aspect;
259  float h_at_width = float(frame.width) / aspect;
260  if (w_at_height <= frame.width) {
261  params.width = w_at_height;
262  params.height = float(frame.height);
263  } else {
264  params.width = float(frame.width);
265  params.height = h_at_width;
266  }
267  params.u0 = impl_->u0_;
268  params.v0 = impl_->v0_;
269  params.u1 = impl_->u1_;
270  params.v1 = impl_->v1_;
271  break;
272  }
273  }
274  float x = std::max(0.0f, (float(frame.width) - params.width) / 2.0f);
275  float y = std::max(0.0f, (float(frame.height) - params.height) / 2.0f);
276  params.pos_x = frame.x + x;
277  params.pos_y = frame.y + y;
278  } else {
279  params.pos_x = float(frame.x);
280  params.pos_y = float(frame.y);
281  params.width = float(frame.width);
282  params.height = float(frame.height);
283  params.u0 = 0.0f;
284  params.v0 = 0.0f;
285  params.u1 = 1.0f;
286  params.v1 = 1.0f;
287  }
288 
289  return params;
290 }
291 
292 } // namespace gui
293 } // namespace visualization
294 } // namespace cloudViewer
Rect frame
std::shared_ptr< core::Tensor > image
cmdLineReadable * params[]
UIImage(const char *image_path)
Definition: UIImage.cpp:57
Size CalcPreferredSize(const LayoutContext &context, const Widget::Constraints &constraints) const
Definition: UIImage.cpp:155
@ ASPECT
Scales to any size and aspect ratio.
DrawParams CalcDrawParams(visualization::rendering::Renderer &renderer, const Rect &frame) const
Definition: UIImage.cpp:178
void UpdateImage(std::shared_ptr< geometry::Image > image)
Definition: UIImage.cpp:141
static FilamentResourceManager & GetResourceManager()
virtual bool UpdateTexture(TextureHandle texture, const std::shared_ptr< geometry::Image > image, bool srgb)=0
virtual TextureHandle AddTexture(const ResourceLoadRequest &request, bool srgb=false)=0
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
float scaling
Definition: Window.cpp:78
ImGuiContext * context
Definition: Window.cpp:76
std::shared_ptr< geometry::Image > CreateImageFromFile(const std::string &filename)
REHandle< EntityType::Texture > TextureHandle
Generic file read and write utility for python interface.
std::shared_ptr< t::geometry::Image > timage_data_
Definition: UIImage.cpp:45
visualization::rendering::TextureHandle texture_
Definition: UIImage.cpp:54
visualization::rendering::Renderer * renderer_
Definition: UIImage.cpp:53
std::shared_ptr< geometry::Image > image_data_
Definition: UIImage.cpp:44