comparison OrthancServer/OrthancRestApi/OrthancRestResources.cpp @ 1784:2dbf25006f88

".../preview" and ".../image-uint8" can return JPEG images if the HTTP Accept Header asks so
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 18 Nov 2015 09:56:34 +0100
parents 5ad4e4d92ecb
children b530c3dfe2a6
comparison
equal deleted inserted replaced
1783:dbb07eb1a2f3 1784:2dbf25006f88
32 32
33 #include "../PrecompiledHeadersServer.h" 33 #include "../PrecompiledHeadersServer.h"
34 #include "OrthancRestApi.h" 34 #include "OrthancRestApi.h"
35 35
36 #include "../../Core/Logging.h" 36 #include "../../Core/Logging.h"
37 #include "../../Core/HttpServer/HttpContentNegociation.h"
37 #include "../ServerToolbox.h" 38 #include "../ServerToolbox.h"
38 #include "../FromDcmtkBridge.h" 39 #include "../FromDcmtkBridge.h"
39 #include "../ServerContext.h" 40 #include "../ServerContext.h"
40 #include "../SliceOrdering.h" 41 #include "../SliceOrdering.h"
41 42
257 call.GetOutput().AnswerJson(result); 258 call.GetOutput().AnswerJson(result);
258 } 259 }
259 } 260 }
260 261
261 262
262 static void AnswerImage(RestApiGetCall& call, 263 namespace
263 ParsedDicomFile& dicom, 264 {
264 unsigned int frame, 265 class ImageToEncode
265 ImageExtractionMode mode) 266 {
266 { 267 private:
267 typedef std::vector<std::string> MediaRanges; 268 std::string format_;
268 269 std::string encoded_;
269 // Get the HTTP "Accept" header, if any 270 ParsedDicomFile& dicom_;
270 std::string accept = call.GetHttpHeader("accept", "*/*"); 271 unsigned int frame_;
271 272 ImageExtractionMode mode_;
272 MediaRanges mediaRanges; 273
273 Toolbox::TokenizeString(mediaRanges, accept, ','); 274 public:
274 275 ImageToEncode(ParsedDicomFile& dicom,
275 for (MediaRanges::const_reverse_iterator it = mediaRanges.rbegin(); 276 unsigned int frame,
276 it != mediaRanges.rend(); ++it) 277 ImageExtractionMode mode) :
277 { 278 dicom_(dicom),
278 } 279 frame_(frame),
279 280 mode_(mode)
280 throw OrthancException(ErrorCode_NotAcceptable); 281 {
281 282 }
282 std::string image; 283
283 dicom.ExtractPngImage(image, frame, mode); 284 ParsedDicomFile& GetDicom() const
284 call.GetOutput().AnswerBuffer(image, "image/png"); 285 {
286 return dicom_;
287 }
288
289 unsigned int GetFrame() const
290 {
291 return frame_;
292 }
293
294 ImageExtractionMode GetMode() const
295 {
296 return mode_;
297 }
298
299 void SetFormat(const std::string& format)
300 {
301 format_ = format;
302 }
303
304 std::string& GetTarget()
305 {
306 return encoded_;
307 }
308
309 void Answer(RestApiOutput& output)
310 {
311 output.AnswerBuffer(encoded_, format_);
312 }
313 };
314
315 class EncodePng : public HttpContentNegociation::IHandler
316 {
317 private:
318 ImageToEncode& image_;
319
320 public:
321 EncodePng(ImageToEncode& image) : image_(image)
322 {
323 }
324
325 virtual void Handle(const std::string& type,
326 const std::string& subtype)
327 {
328 assert(type == "image");
329 assert(subtype == "png");
330 image_.GetDicom().ExtractPngImage(image_.GetTarget(), image_.GetFrame(), image_.GetMode());
331 image_.SetFormat("image/png");
332 }
333 };
334
335 class EncodeJpeg : public HttpContentNegociation::IHandler
336 {
337 private:
338 ImageToEncode& image_;
339 unsigned int quality_;
340
341 public:
342 EncodeJpeg(ImageToEncode& image,
343 const RestApiGetCall& call) :
344 image_(image)
345 {
346 std::string v = call.GetArgument("quality", "90" /* default JPEG quality */);
347 bool ok = false;
348
349 try
350 {
351 quality_ = boost::lexical_cast<unsigned int>(v);
352 ok = (quality_ >= 0 && quality_ <= 100);
353 }
354 catch (boost::bad_lexical_cast&)
355 {
356 }
357
358 if (!ok)
359 {
360 LOG(ERROR) << "Bad quality for a JPEG encoding (must be a number between 0 and 100): " << v;
361 throw OrthancException(ErrorCode_BadRequest);
362 }
363 }
364
365 virtual void Handle(const std::string& type,
366 const std::string& subtype)
367 {
368 assert(type == "image");
369 assert(subtype == "jpeg");
370 image_.GetDicom().ExtractJpegImage(image_.GetTarget(), image_.GetFrame(), image_.GetMode(), quality_);
371 image_.SetFormat("image/jpeg");
372 }
373 };
285 } 374 }
286 375
287 376
288 template <enum ImageExtractionMode mode> 377 template <enum ImageExtractionMode mode>
289 static void GetImage(RestApiGetCall& call) 378 static void GetImage(RestApiGetCall& call)
308 397
309 ParsedDicomFile dicom(dicomContent); 398 ParsedDicomFile dicom(dicomContent);
310 399
311 try 400 try
312 { 401 {
313 AnswerImage(call, dicom, frame, mode); 402 ImageToEncode image(dicom, frame, mode);
403
404 HttpContentNegociation negociation;
405 EncodePng png(image); negociation.Register("image/png", png);
406 EncodeJpeg jpeg(image, call); negociation.Register("image/jpeg", jpeg);
407
408 if (negociation.Apply(call.GetHttpHeaders()))
409 {
410 image.Answer(call.GetOutput());
411 }
314 } 412 }
315 catch (OrthancException& e) 413 catch (OrthancException& e)
316 { 414 {
317 if (e.GetErrorCode() == ErrorCode_ParameterOutOfRange) 415 if (e.GetErrorCode() == ErrorCode_ParameterOutOfRange)
318 { 416 {