Mercurial > hg > orthanc-stone
comparison Applications/Samples/SingleFrameEditorApplication.h @ 343:712acc87fa2e am-2
text layer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 22 Oct 2018 14:20:39 +0200 |
parents | 4297d6c5eef9 |
children | fdec8e6893cb |
comparison
equal
deleted
inserted
replaced
342:4297d6c5eef9 | 343:712acc87fa2e |
---|---|
26 #include "../../Framework/Toolbox/GeometryToolbox.h" | 26 #include "../../Framework/Toolbox/GeometryToolbox.h" |
27 #include "../../Framework/Toolbox/ImageGeometry.h" | 27 #include "../../Framework/Toolbox/ImageGeometry.h" |
28 #include "../../Framework/Layers/OrthancFrameLayerSource.h" | 28 #include "../../Framework/Layers/OrthancFrameLayerSource.h" |
29 | 29 |
30 #include <Core/DicomFormat/DicomArray.h> | 30 #include <Core/DicomFormat/DicomArray.h> |
31 #include <Core/Images/FontRegistry.h> | |
31 #include <Core/Images/ImageProcessing.h> | 32 #include <Core/Images/ImageProcessing.h> |
32 #include <Core/Images/PamReader.h> | 33 #include <Core/Images/PamReader.h> |
34 #include <Core/Images/PngWriter.h> //TODO | |
33 #include <Core/Logging.h> | 35 #include <Core/Logging.h> |
34 #include <Plugins/Samples/Common/FullOrthancDataset.h> | 36 #include <Plugins/Samples/Common/FullOrthancDataset.h> |
35 #include <Plugins/Samples/Common/DicomDatasetReader.h> | 37 #include <Plugins/Samples/Common/DicomDatasetReader.h> |
36 | 38 |
37 | 39 |
49 | 51 |
50 private: | 52 private: |
51 class Bitmap : public boost::noncopyable | 53 class Bitmap : public boost::noncopyable |
52 { | 54 { |
53 private: | 55 private: |
54 bool visible_; | 56 bool visible_; |
55 std::auto_ptr<Orthanc::ImageAccessor> source_; | 57 bool hasSize_; |
56 std::auto_ptr<Orthanc::ImageAccessor> converted_; // Float32 or RGB24 | 58 unsigned int width_; |
57 std::auto_ptr<Orthanc::Image> alpha_; // Grayscale8 (if any) | 59 unsigned int height_; |
58 std::auto_ptr<DicomFrameConverter> converter_; | 60 bool hasCrop_; |
59 unsigned int width_; | 61 unsigned int cropX_; |
60 unsigned int height_; | 62 unsigned int cropY_; |
61 bool hasCrop_; | 63 unsigned int cropWidth_; |
62 unsigned int cropX_; | 64 unsigned int cropHeight_; |
63 unsigned int cropY_; | 65 Matrix transform_; |
64 unsigned int cropWidth_; | 66 double pixelSpacingX_; |
65 unsigned int cropHeight_; | 67 double pixelSpacingY_; |
66 Matrix transform_; | 68 double panX_; |
67 double pixelSpacingX_; | 69 double panY_; |
68 double pixelSpacingY_; | |
69 double panX_; | |
70 double panY_; | |
71 | 70 |
72 | 71 |
73 void UpdateTransform() | 72 void UpdateTransform() |
74 { | 73 { |
75 transform_ = LinearAlgebra::IdentityMatrix(3); | 74 transform_ = LinearAlgebra::IdentityMatrix(3); |
90 transform_ = LinearAlgebra::Product(m, transform_); | 89 transform_ = LinearAlgebra::Product(m, transform_); |
91 #endif | 90 #endif |
92 } | 91 } |
93 | 92 |
94 | 93 |
95 void ApplyConverter() | |
96 { | |
97 if (source_.get() != NULL && | |
98 converter_.get() != NULL) | |
99 { | |
100 if (width_ != source_->GetWidth() || | |
101 height_ != source_->GetHeight()) | |
102 { | |
103 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
104 } | |
105 | |
106 printf("CONVERTED! %dx%d\n", width_, height_); | |
107 converted_.reset(converter_->ConvertFrame(*source_)); | |
108 } | |
109 } | |
110 | |
111 void AddToExtent(Extent2D& extent, | 94 void AddToExtent(Extent2D& extent, |
112 double x, | 95 double x, |
113 double y) const | 96 double y) const |
114 { | 97 { |
115 Vector p; | 98 Vector p; |
129 | 112 |
130 | 113 |
131 public: | 114 public: |
132 Bitmap() : | 115 Bitmap() : |
133 visible_(true), | 116 visible_(true), |
117 hasSize_(false), | |
134 width_(0), | 118 width_(0), |
135 height_(0), | 119 height_(0), |
136 hasCrop_(false), | 120 hasCrop_(false), |
137 pixelSpacingX_(1), | 121 pixelSpacingX_(1), |
138 pixelSpacingY_(1), | 122 pixelSpacingY_(1), |
140 panY_(0) | 124 panY_(0) |
141 { | 125 { |
142 UpdateTransform(); | 126 UpdateTransform(); |
143 } | 127 } |
144 | 128 |
129 virtual ~Bitmap() | |
130 { | |
131 } | |
132 | |
145 void ResetCrop() | 133 void ResetCrop() |
146 { | 134 { |
147 hasCrop_ = false; | 135 hasCrop_ = false; |
148 } | 136 } |
149 | 137 |
189 { | 177 { |
190 visible_ = visible; | 178 visible_ = visible; |
191 } | 179 } |
192 | 180 |
193 | 181 |
194 static OrthancPlugins::DicomTag ConvertTag(const Orthanc::DicomTag& tag) | 182 void SetSize(unsigned int width, |
195 { | 183 unsigned int height) |
196 return OrthancPlugins::DicomTag(tag.GetGroup(), tag.GetElement()); | 184 { |
197 } | 185 if (hasSize_ && |
198 | 186 (width != width_ || |
199 void SetDicomTags(const OrthancPlugins::FullOrthancDataset& dataset) | 187 height != height_)) |
200 { | 188 { |
201 converter_.reset(new DicomFrameConverter); | 189 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); |
202 converter_->ReadParameters(dataset); | 190 } |
203 ApplyConverter(); | 191 |
204 | 192 hasSize_ = true; |
205 transform_ = LinearAlgebra::IdentityMatrix(3); | 193 width_ = width; |
206 | 194 height_ = height; |
207 std::string tmp; | 195 } |
208 Vector pixelSpacing; | 196 |
209 | 197 |
210 if (dataset.GetStringValue(tmp, ConvertTag(Orthanc::DICOM_TAG_PIXEL_SPACING)) && | 198 void CheckSize(unsigned int width, |
211 LinearAlgebra::ParseVector(pixelSpacing, tmp) && | 199 unsigned int height) |
212 pixelSpacing.size() == 2) | 200 { |
213 { | 201 if (hasSize_ && |
214 pixelSpacingX_ = pixelSpacing[0]; | 202 (width != width_ || |
215 pixelSpacingY_ = pixelSpacing[1]; | 203 height != height_)) |
216 } | 204 { |
217 | 205 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); |
218 static unsigned int c = 0; | 206 } |
219 if (c == 0) | 207 } |
220 { | 208 |
221 panX_ = 400; | |
222 c ++; | |
223 } | |
224 | |
225 OrthancPlugins::DicomDatasetReader reader(dataset); | |
226 | |
227 if (!reader.GetUnsignedIntegerValue(width_, ConvertTag(Orthanc::DICOM_TAG_COLUMNS)) || | |
228 !reader.GetUnsignedIntegerValue(height_, ConvertTag(Orthanc::DICOM_TAG_ROWS))) | |
229 { | |
230 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
231 } | |
232 | |
233 UpdateTransform(); | |
234 } | |
235 | |
236 | |
237 void SetSourceImage(Orthanc::ImageAccessor* image) // Takes ownership | |
238 { | |
239 source_.reset(image); | |
240 ApplyConverter(); | |
241 } | |
242 | |
243 | |
244 bool GetDefaultWindowing(float& center, | |
245 float& width) const | |
246 { | |
247 if (converter_.get() != NULL && | |
248 converter_->HasDefaultWindow()) | |
249 { | |
250 center = static_cast<float>(converter_->GetDefaultWindowCenter()); | |
251 width = static_cast<float>(converter_->GetDefaultWindowWidth()); | |
252 return true; | |
253 } | |
254 else | |
255 { | |
256 return false; | |
257 } | |
258 } | |
259 | |
260 | 209 |
261 Extent2D GetExtent() const | 210 Extent2D GetExtent() const |
262 { | 211 { |
263 Extent2D extent; | 212 Extent2D extent; |
264 | 213 |
268 double dx = static_cast<double>(x) - 0.5; | 217 double dx = static_cast<double>(x) - 0.5; |
269 double dy = static_cast<double>(y) - 0.5; | 218 double dy = static_cast<double>(y) - 0.5; |
270 double dwidth = static_cast<double>(width); | 219 double dwidth = static_cast<double>(width); |
271 double dheight = static_cast<double>(height); | 220 double dheight = static_cast<double>(height); |
272 | 221 |
273 LinearAlgebra::Print(transform_); | |
274 | |
275 AddToExtent(extent, dx, dy); | 222 AddToExtent(extent, dx, dy); |
276 AddToExtent(extent, dx + dwidth, dy); | 223 AddToExtent(extent, dx + dwidth, dy); |
277 AddToExtent(extent, dx, dy + dheight); | 224 AddToExtent(extent, dx, dy + dheight); |
278 AddToExtent(extent, dx + dwidth, dy + dheight); | 225 AddToExtent(extent, dx + dwidth, dy + dheight); |
279 | 226 |
280 return extent; | 227 return extent; |
281 } | 228 } |
282 | 229 |
283 | 230 |
284 void Render(Orthanc::ImageAccessor& buffer, | 231 virtual void Render(Orthanc::ImageAccessor& buffer, |
285 const ViewportGeometry& view) const | 232 const ViewportGeometry& view) const = 0; |
286 { | |
287 if (converted_.get() != NULL) | |
288 { | |
289 Matrix m = LinearAlgebra::Product(view.GetMatrix(), transform_); | |
290 //ApplyProjectiveTransform(buffer, *converted_, m, ImageInterpolation_Bilinear, false); | |
291 ApplyProjectiveTransform(buffer, *converted_, m, ImageInterpolation_Nearest, false); | |
292 } | |
293 } | |
294 | 233 |
295 | 234 |
296 bool Contains(double x, | 235 bool Contains(double x, |
297 double y) const | 236 double y) const |
298 { | 237 { |
326 panY_ = y; | 265 panY_ = y; |
327 UpdateTransform(); | 266 UpdateTransform(); |
328 } | 267 } |
329 | 268 |
330 | 269 |
270 void SetPixelSpacing(double x, | |
271 double y) | |
272 { | |
273 pixelSpacingX_ = x; | |
274 pixelSpacingY_ = y; | |
275 UpdateTransform(); | |
276 } | |
277 | |
278 | |
331 double GetPanX() const | 279 double GetPanX() const |
332 { | 280 { |
333 return panX_; | 281 return panX_; |
334 } | 282 } |
335 | 283 |
336 | 284 |
337 double GetPanY() const | 285 double GetPanY() const |
338 { | 286 { |
339 return panY_; | 287 return panY_; |
340 } | 288 } |
289 | |
290 | |
291 virtual bool GetDefaultWindowing(float& center, | |
292 float& width) const | |
293 { | |
294 return false; | |
295 } | |
296 | |
297 | |
298 const Matrix& GetTransform() const | |
299 { | |
300 return transform_; | |
301 } | |
341 }; | 302 }; |
342 | 303 |
304 | |
305 | |
306 class DicomBitmap : public Bitmap | |
307 { | |
308 private: | |
309 std::auto_ptr<Orthanc::ImageAccessor> source_; // Content of PixelData | |
310 std::auto_ptr<DicomFrameConverter> converter_; | |
311 std::auto_ptr<Orthanc::ImageAccessor> converted_; // Float32 or RGB24 | |
312 | |
313 | |
314 void ApplyConverter() | |
315 { | |
316 if (source_.get() != NULL && | |
317 converter_.get() != NULL) | |
318 { | |
319 converted_.reset(converter_->ConvertFrame(*source_)); | |
320 } | |
321 } | |
322 | |
323 public: | |
324 static OrthancPlugins::DicomTag ConvertTag(const Orthanc::DicomTag& tag) | |
325 { | |
326 return OrthancPlugins::DicomTag(tag.GetGroup(), tag.GetElement()); | |
327 } | |
328 | |
329 void SetDicomTags(const OrthancPlugins::FullOrthancDataset& dataset) | |
330 { | |
331 converter_.reset(new DicomFrameConverter); | |
332 converter_->ReadParameters(dataset); | |
333 ApplyConverter(); | |
334 | |
335 std::string tmp; | |
336 Vector pixelSpacing; | |
337 | |
338 if (dataset.GetStringValue(tmp, ConvertTag(Orthanc::DICOM_TAG_PIXEL_SPACING)) && | |
339 LinearAlgebra::ParseVector(pixelSpacing, tmp) && | |
340 pixelSpacing.size() == 2) | |
341 { | |
342 SetPixelSpacing(pixelSpacing[0], pixelSpacing[1]); | |
343 } | |
344 | |
345 static unsigned int c = 0; | |
346 if (c == 0) | |
347 { | |
348 SetPan(400, 0); | |
349 c ++; | |
350 } | |
351 | |
352 OrthancPlugins::DicomDatasetReader reader(dataset); | |
353 | |
354 unsigned int width, height; | |
355 if (!reader.GetUnsignedIntegerValue(width, ConvertTag(Orthanc::DICOM_TAG_COLUMNS)) || | |
356 !reader.GetUnsignedIntegerValue(height, ConvertTag(Orthanc::DICOM_TAG_ROWS))) | |
357 { | |
358 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
359 } | |
360 else | |
361 { | |
362 SetSize(width, height); | |
363 } | |
364 } | |
365 | |
366 | |
367 void SetSourceImage(Orthanc::ImageAccessor* image) // Takes ownership | |
368 { | |
369 std::auto_ptr<Orthanc::ImageAccessor> raii(image); | |
370 | |
371 if (image == NULL) | |
372 { | |
373 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
374 } | |
375 | |
376 SetSize(image->GetWidth(), image->GetHeight()); | |
377 | |
378 source_ = raii; | |
379 ApplyConverter(); | |
380 } | |
381 | |
382 | |
383 virtual void Render(Orthanc::ImageAccessor& buffer, | |
384 const ViewportGeometry& view) const | |
385 { | |
386 if (converted_.get() != NULL) | |
387 { | |
388 Matrix m = LinearAlgebra::Product(view.GetMatrix(), GetTransform()); | |
389 //ApplyProjectiveTransform(buffer, *converted_, m, ImageInterpolation_Bilinear, false); | |
390 ApplyProjectiveTransform(buffer, *converted_, m, ImageInterpolation_Nearest, false); | |
391 } | |
392 } | |
393 | |
394 | |
395 virtual bool GetDefaultWindowing(float& center, | |
396 float& width) const | |
397 { | |
398 if (converter_.get() != NULL && | |
399 converter_->HasDefaultWindow()) | |
400 { | |
401 center = static_cast<float>(converter_->GetDefaultWindowCenter()); | |
402 width = static_cast<float>(converter_->GetDefaultWindowWidth()); | |
403 return true; | |
404 } | |
405 else | |
406 { | |
407 return false; | |
408 } | |
409 } | |
410 }; | |
411 | |
412 | |
413 | |
414 | |
415 class AlphaBitmap : public Bitmap | |
416 { | |
417 private: | |
418 const BitmapStack& stack_; | |
419 std::auto_ptr<Orthanc::ImageAccessor> alpha_; // Grayscale8 | |
420 bool useWindowing_; | |
421 float foreground_; | |
422 | |
423 public: | |
424 AlphaBitmap(const BitmapStack& stack) : | |
425 stack_(stack), | |
426 useWindowing_(true), | |
427 foreground_(0) | |
428 { | |
429 } | |
430 | |
431 | |
432 void SetForegroundValue(float foreground) | |
433 { | |
434 useWindowing_ = false; | |
435 foreground_ = foreground; | |
436 } | |
437 | |
438 | |
439 void SetAlpha(Orthanc::ImageAccessor* image) | |
440 { | |
441 std::auto_ptr<Orthanc::ImageAccessor> raii(image); | |
442 | |
443 if (image == NULL) | |
444 { | |
445 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
446 } | |
447 | |
448 if (image->GetFormat() != Orthanc::PixelFormat_Grayscale8) | |
449 { | |
450 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
451 } | |
452 | |
453 SetSize(image->GetWidth(), image->GetHeight()); | |
454 alpha_ = raii; | |
455 } | |
456 | |
457 | |
458 void LoadText(const Orthanc::Font& font, | |
459 const std::string& utf8) | |
460 { | |
461 SetAlpha(font.RenderAlpha(utf8)); | |
462 } | |
463 | |
464 | |
465 virtual void Render(Orthanc::ImageAccessor& buffer, | |
466 const ViewportGeometry& view) const | |
467 { | |
468 if (buffer.GetFormat() != Orthanc::PixelFormat_Float32) | |
469 { | |
470 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
471 } | |
472 | |
473 Matrix m = LinearAlgebra::Product(view.GetMatrix(), GetTransform()); | |
474 | |
475 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); | |
476 ApplyProjectiveTransform(tmp, *alpha_, m, ImageInterpolation_Nearest, true /* clear */); | |
477 | |
478 // Blit | |
479 const unsigned int width = buffer.GetWidth(); | |
480 const unsigned int height = buffer.GetHeight(); | |
481 | |
482 float value = foreground_; | |
483 | |
484 if (useWindowing_) | |
485 { | |
486 float center, width; | |
487 if (stack_.GetWindowing(center, width)) | |
488 { | |
489 value = center + width / 2.0f; | |
490 } | |
491 } | |
492 | |
493 for (unsigned int y = 0; y < height; y++) | |
494 { | |
495 float *q = reinterpret_cast<float*>(buffer.GetRow(y)); | |
496 const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y)); | |
497 | |
498 for (unsigned int x = 0; x < width; x++, p++, q++) | |
499 { | |
500 float a = static_cast<float>(*p) / 255.0f; | |
501 | |
502 *q = (a * value + (1.0f - a) * (*q)); | |
503 } | |
504 } | |
505 } | |
506 }; | |
507 | |
508 | |
343 | 509 |
344 typedef std::map<size_t, Bitmap*> Bitmaps; | 510 typedef std::map<size_t, Bitmap*> Bitmaps; |
345 | 511 |
346 OrthancApiClient& orthanc_; | 512 OrthancApiClient& orthanc_; |
347 size_t countBitmaps_; | 513 size_t countBitmaps_; |
372 delete it->second; | 538 delete it->second; |
373 } | 539 } |
374 } | 540 } |
375 | 541 |
376 | 542 |
377 void GetWindowing(float& center, | 543 bool GetWindowing(float& center, |
378 float& width) | 544 float& width) const |
379 { | 545 { |
380 if (hasWindowing_) | 546 if (hasWindowing_) |
381 { | 547 { |
382 center = windowingCenter_; | 548 center = windowingCenter_; |
383 width = windowingWidth_; | 549 width = windowingWidth_; |
550 return true; | |
384 } | 551 } |
385 else | 552 else |
386 { | 553 { |
387 center = 128; | 554 return false; |
388 width = 256; | |
389 } | 555 } |
390 } | 556 } |
391 | 557 |
392 | 558 |
559 size_t LoadText(const Orthanc::Font& font, | |
560 const std::string& utf8, | |
561 double x, | |
562 double y) | |
563 { | |
564 std::auto_ptr<AlphaBitmap> alpha(new AlphaBitmap(*this)); | |
565 alpha->LoadText(font, utf8); | |
566 | |
567 size_t bitmap = countBitmaps_++; | |
568 | |
569 bitmaps_[bitmap] = alpha.release(); | |
570 | |
571 return bitmap; | |
572 } | |
573 | |
574 | |
393 size_t LoadFrame(const std::string& instance, | 575 size_t LoadFrame(const std::string& instance, |
394 unsigned int frame, | 576 unsigned int frame, |
395 bool httpCompression) | 577 bool httpCompression) |
396 { | 578 { |
397 size_t bitmap = countBitmaps_++; | 579 size_t bitmap = countBitmaps_++; |
398 | 580 |
399 bitmaps_[bitmap] = new Bitmap; | 581 bitmaps_[bitmap] = new DicomBitmap; |
400 | 582 |
401 | 583 |
402 { | 584 { |
403 IWebService::Headers headers; | 585 IWebService::Headers headers; |
404 std::string uri = "/instances/" + instance + "/tags"; | 586 std::string uri = "/instances/" + instance + "/tags"; |
439 if (bitmap != bitmaps_.end()) | 621 if (bitmap != bitmaps_.end()) |
440 { | 622 { |
441 assert(bitmap->second != NULL); | 623 assert(bitmap->second != NULL); |
442 | 624 |
443 OrthancPlugins::FullOrthancDataset dicom(message.Answer, message.AnswerSize); | 625 OrthancPlugins::FullOrthancDataset dicom(message.Answer, message.AnswerSize); |
444 bitmap->second->SetDicomTags(dicom); | 626 dynamic_cast<DicomBitmap*>(bitmap->second)->SetDicomTags(dicom); |
445 | 627 |
446 float c, w; | 628 float c, w; |
447 if (!hasWindowing_ && | 629 if (!hasWindowing_ && |
448 bitmap->second->GetDefaultWindowing(c, w)) | 630 bitmap->second->GetDefaultWindowing(c, w)) |
449 { | 631 { |
475 content.assign(reinterpret_cast<const char*>(message.Answer), message.AnswerSize); | 657 content.assign(reinterpret_cast<const char*>(message.Answer), message.AnswerSize); |
476 } | 658 } |
477 | 659 |
478 std::auto_ptr<Orthanc::PamReader> reader(new Orthanc::PamReader); | 660 std::auto_ptr<Orthanc::PamReader> reader(new Orthanc::PamReader); |
479 reader->ReadFromMemory(content); | 661 reader->ReadFromMemory(content); |
480 bitmap->second->SetSourceImage(reader.release()); | 662 dynamic_cast<DicomBitmap*>(bitmap->second)->SetSourceImage(reader.release()); |
481 | 663 |
482 EmitMessage(ContentChangedMessage(*this)); | 664 EmitMessage(ContentChangedMessage(*this)); |
483 } | 665 } |
484 } | 666 } |
485 | 667 |
572 | 754 |
573 | 755 |
574 class MoveBitmapTracker : public IWorldSceneMouseTracker | 756 class MoveBitmapTracker : public IWorldSceneMouseTracker |
575 { | 757 { |
576 private: | 758 private: |
577 WorldSceneWidget& widget_; | |
578 BitmapStack& stack_; | 759 BitmapStack& stack_; |
579 size_t bitmap_; | 760 size_t bitmap_; |
580 double clickX_; | 761 double clickX_; |
581 double clickY_; | 762 double clickY_; |
763 double panX_; | |
764 double panY_; | |
765 bool oneAxis_; | |
582 | 766 |
583 public: | 767 public: |
584 MoveBitmapTracker(WorldSceneWidget& widget, | 768 MoveBitmapTracker(BitmapStack& stack, |
585 BitmapStack& stack, | |
586 size_t bitmap, | 769 size_t bitmap, |
587 double x, | 770 double x, |
588 double y) : | 771 double y, |
589 widget_(widget), | 772 bool oneAxis) : |
590 stack_(stack), | 773 stack_(stack), |
591 bitmap_(bitmap), | 774 bitmap_(bitmap), |
592 clickX_(x), | 775 clickX_(x), |
593 clickY_(y) | 776 clickY_(y), |
594 { | 777 oneAxis_(oneAxis) |
595 double panX, panY; | 778 { |
596 stack.GetPan(panX, panY, bitmap_); | 779 stack.GetPan(panX_, panY_, bitmap_); |
597 clickX_ -= panX; | |
598 clickY_ -= panY; | |
599 } | 780 } |
600 | 781 |
601 virtual bool HasRender() const | 782 virtual bool HasRender() const |
602 { | 783 { |
603 return false; | 784 return false; |
616 virtual void MouseMove(int displayX, | 797 virtual void MouseMove(int displayX, |
617 int displayY, | 798 int displayY, |
618 double sceneX, | 799 double sceneX, |
619 double sceneY) | 800 double sceneY) |
620 { | 801 { |
621 stack_.SetPan(bitmap_, sceneX - clickX_, sceneY - clickY_); | 802 double dx = sceneX - clickX_; |
803 double dy = sceneY - clickY_; | |
804 | |
805 if (oneAxis_) | |
806 { | |
807 if (fabs(dx) > fabs(dy)) | |
808 { | |
809 stack_.SetPan(bitmap_, dx + panX_, panY_); | |
810 } | |
811 else | |
812 { | |
813 stack_.SetPan(bitmap_, panX_, dy + panY_); | |
814 } | |
815 } | |
816 else | |
817 { | |
818 stack_.SetPan(bitmap_, dx + panX_, dy + panY_); | |
819 } | |
622 } | 820 } |
623 }; | 821 }; |
624 | 822 |
625 | 823 |
626 public: | 824 public: |
641 { | 839 { |
642 size_t bitmap; | 840 size_t bitmap; |
643 if (stack_.LookupBitmap(bitmap, x, y)) | 841 if (stack_.LookupBitmap(bitmap, x, y)) |
644 { | 842 { |
645 printf("CLICK on bitmap %d\n", bitmap); | 843 printf("CLICK on bitmap %d\n", bitmap); |
646 return new MoveBitmapTracker(widget, stack_, bitmap, x, y); | 844 return new MoveBitmapTracker(stack_, bitmap, x, y, |
845 (modifiers & KeyboardModifiers_Shift)); | |
647 } | 846 } |
648 else | 847 else |
649 { | 848 { |
650 printf("CLICK outside\n"); | 849 printf("CLICK outside\n"); |
651 return NULL; | 850 return NULL; |
743 stack_.Render(buffer, GetView()); | 942 stack_.Render(buffer, GetView()); |
744 | 943 |
745 // As in GrayscaleFrameRenderer => TODO MERGE | 944 // As in GrayscaleFrameRenderer => TODO MERGE |
746 | 945 |
747 float windowCenter, windowWidth; | 946 float windowCenter, windowWidth; |
748 stack_.GetWindowing(windowCenter, windowWidth); | 947 if (!stack_.GetWindowing(windowCenter, windowWidth)) |
948 { | |
949 windowCenter = 128; | |
950 windowWidth = 256; | |
951 } | |
749 | 952 |
750 float x0 = windowCenter - windowWidth / 2.0f; | 953 float x0 = windowCenter - windowWidth / 2.0f; |
751 float x1 = windowCenter + windowWidth / 2.0f; | 954 float x1 = windowCenter + windowWidth / 2.0f; |
752 | 955 |
753 const unsigned int width = target.GetWidth(); | 956 const unsigned int width = target.GetWidth(); |
963 std::string instance = parameters["instance"].as<std::string>(); | 1166 std::string instance = parameters["instance"].as<std::string>(); |
964 int frame = parameters["frame"].as<unsigned int>(); | 1167 int frame = parameters["frame"].as<unsigned int>(); |
965 | 1168 |
966 orthancApiClient_.reset(new OrthancApiClient(IObserver::broker_, context_->GetWebService())); | 1169 orthancApiClient_.reset(new OrthancApiClient(IObserver::broker_, context_->GetWebService())); |
967 | 1170 |
1171 Orthanc::FontRegistry fonts; | |
1172 fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); | |
1173 | |
968 stack_.reset(new BitmapStack(IObserver::broker_, *orthancApiClient_)); | 1174 stack_.reset(new BitmapStack(IObserver::broker_, *orthancApiClient_)); |
969 stack_->LoadFrame(instance, frame, false); | 1175 stack_->LoadFrame(instance, frame, false); |
970 stack_->LoadFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", frame, false); | 1176 stack_->LoadFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", frame, false); |
1177 stack_->LoadText(fonts.GetFont(0), "Hello\nworld\nBonjour, Alain", 0, -50); | |
971 | 1178 |
972 mainWidget_ = new BitmapStackWidget(IObserver::broker_, *stack_, "main-widget"); | 1179 mainWidget_ = new BitmapStackWidget(IObserver::broker_, *stack_, "main-widget"); |
973 mainWidget_->SetTransmitMouseOver(true); | 1180 mainWidget_->SetTransmitMouseOver(true); |
974 | 1181 |
975 mainWidgetInteractor_.reset(new Interactor(*this)); | 1182 mainWidgetInteractor_.reset(new Interactor(*this)); |