comparison Framework/Layers/OrthancFrameLayerSource.cpp @ 65:885932a893de wasm

OrthancFrameLayerSource
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 16 May 2017 22:12:41 +0200
parents
children 298f375dcb68
comparison
equal deleted inserted replaced
64:394e63010e02 65:885932a893de
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017 Osimis, Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "OrthancFrameLayerSource.h"
23
24 #include "FrameRenderer.h"
25 #include "../../Resources/Orthanc/Core/Images/PngReader.h"
26 #include "../../Resources/Orthanc/Core/Logging.h"
27 #include "../../Resources/Orthanc/Core/OrthancException.h"
28 #include "../Toolbox/DicomFrameConverter.h"
29
30 #include <boost/lexical_cast.hpp>
31
32
33 namespace OrthancStone
34 {
35 class OrthancFrameLayerSource::Operation : public Orthanc::IDynamicObject
36 {
37 private:
38 Content content_;
39 SliceGeometry viewportSlice_;
40
41 public:
42 Operation(Content content) : content_(content)
43 {
44 }
45
46 void SetViewportSlice(const SliceGeometry& slice)
47 {
48 viewportSlice_ = slice;
49 }
50
51 const SliceGeometry& GetViewportSlice() const
52 {
53 return viewportSlice_;
54 }
55
56 Content GetContent() const
57 {
58 return content_;
59 }
60 };
61
62
63 OrthancFrameLayerSource::OrthancFrameLayerSource(IWebService& orthanc,
64 const std::string& instanceId,
65 unsigned int frame) :
66 orthanc_(orthanc),
67 instanceId_(instanceId),
68 frame_(frame)
69 {
70 orthanc_.ScheduleGetRequest(*this,
71 "/instances/" + instanceId + "/tags",
72 new Operation(Content_Tags));
73 }
74
75
76 void OrthancFrameLayerSource::SetObserver(IObserver& observer)
77 {
78 LayerSourceBase::SetObserver(observer);
79
80 if (dataset_.get() != NULL)
81 {
82 NotifySourceChange();
83 }
84 }
85
86 void OrthancFrameLayerSource::NotifyError(const std::string& uri,
87 Orthanc::IDynamicObject* payload)
88 {
89 LOG(ERROR) << "Cannot download " << uri;
90 }
91
92 void OrthancFrameLayerSource::NotifySuccess(const std::string& uri,
93 const void* answer,
94 size_t answerSize,
95 Orthanc::IDynamicObject* payload)
96 {
97 std::auto_ptr<Operation> operation(reinterpret_cast<Operation*>(payload));
98
99 if (operation.get() == NULL)
100 {
101 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
102 }
103 else if (operation->GetContent() == Content_Tags)
104 {
105 dataset_.reset(new OrthancPlugins::FullOrthancDataset(answer, answerSize));
106
107 DicomFrameConverter converter;
108 converter.ReadParameters(*dataset_);
109 format_ = converter.GetExpectedPixelFormat();
110
111 NotifySourceChange();
112 }
113 else if (operation->GetContent() == Content_Frame)
114 {
115 std::auto_ptr<Orthanc::PngReader> image(new Orthanc::PngReader);
116 image->ReadFromMemory(answer, answerSize);
117
118 if (format_ == Orthanc::PixelFormat_SignedGrayscale16)
119 {
120 if (image->GetFormat() == Orthanc::PixelFormat_Grayscale16)
121 {
122 image->SetFormat(Orthanc::PixelFormat_SignedGrayscale16);
123 }
124 else
125 {
126 NotifyLayerReady(NULL, *this, operation->GetViewportSlice());
127 }
128 }
129
130 SliceGeometry frameSlice(*dataset_);
131 NotifyLayerReady(FrameRenderer::CreateRenderer(image.release(),
132 operation->GetViewportSlice(),
133 frameSlice, *dataset_, 1, 1, true),
134 *this, operation->GetViewportSlice());
135 }
136 else
137 {
138 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
139 }
140 }
141
142
143 bool OrthancFrameLayerSource::GetExtent(double& x1,
144 double& y1,
145 double& x2,
146 double& y2,
147 const SliceGeometry& viewportSlice /* ignored */)
148 {
149 if (dataset_.get() == NULL)
150 {
151 return false;
152 }
153 else
154 {
155 // Assume that PixelSpacingX == PixelSpacingY == 1
156
157 OrthancPlugins::DicomDatasetReader reader(*dataset_);
158
159 unsigned int width, height;
160
161 if (!reader.GetUnsignedIntegerValue(width, OrthancPlugins::DICOM_TAG_COLUMNS) ||
162 !reader.GetUnsignedIntegerValue(height, OrthancPlugins::DICOM_TAG_ROWS))
163 {
164 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
165 }
166
167 x1 = 0;
168 y1 = 0;
169 x2 = static_cast<double>(width);
170 y2 = static_cast<double>(height);
171
172 return true;
173 }
174 }
175
176
177 void OrthancFrameLayerSource::ScheduleLayerCreation(const SliceGeometry& viewportSlice)
178 {
179 if (dataset_.get() == NULL)
180 {
181 NotifyLayerReady(NULL, *this, viewportSlice);
182 }
183 else
184 {
185 std::string uri = ("/instances/" + instanceId_ + "/frames/" +
186 boost::lexical_cast<std::string>(frame_));
187
188 std::string compressed;
189
190 switch (format_)
191 {
192 case Orthanc::PixelFormat_RGB24:
193 uri += "/preview";
194 break;
195
196 case Orthanc::PixelFormat_Grayscale16:
197 uri += "/image-uint16";
198 break;
199
200 case Orthanc::PixelFormat_SignedGrayscale16:
201 uri += "/image-int16";
202 break;
203
204 default:
205 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
206 }
207
208 std::auto_ptr<Operation> operation(new Operation(Content_Frame));
209 operation->SetViewportSlice(viewportSlice);
210 orthanc_.ScheduleGetRequest(*this, uri, operation.release());
211 }
212 }
213 }