# HG changeset patch # User Sebastien Jodogne # Date 1447836994 -3600 # Node ID 2dbf25006f888768e5026e4d717f4f4be65f5189 # Parent dbb07eb1a2f33450664b5afe7c43ebc0151cb365 ".../preview" and ".../image-uint8" can return JPEG images if the HTTP Accept Header asks so diff -r dbb07eb1a2f3 -r 2dbf25006f88 NEWS --- a/NEWS Wed Nov 18 09:15:30 2015 +0100 +++ b/NEWS Wed Nov 18 09:56:34 2015 +0100 @@ -13,6 +13,7 @@ * MIME content type can be associated to custom attachments (cf. "UserContentType") * New URIs "/tools/create-archive" and "/tools/create-media" to create ZIP/DICOMDIR from a set of resources +* ".../preview" and ".../image-uint8" can return JPEG images if the HTTP Accept Header asks so Plugins ------- diff -r dbb07eb1a2f3 -r 2dbf25006f88 OrthancServer/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Wed Nov 18 09:15:30 2015 +0100 +++ b/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Wed Nov 18 09:56:34 2015 +0100 @@ -34,6 +34,7 @@ #include "OrthancRestApi.h" #include "../../Core/Logging.h" +#include "../../Core/HttpServer/HttpContentNegociation.h" #include "../ServerToolbox.h" #include "../FromDcmtkBridge.h" #include "../ServerContext.h" @@ -259,29 +260,117 @@ } - static void AnswerImage(RestApiGetCall& call, - ParsedDicomFile& dicom, - unsigned int frame, - ImageExtractionMode mode) + namespace { - typedef std::vector MediaRanges; + class ImageToEncode + { + private: + std::string format_; + std::string encoded_; + ParsedDicomFile& dicom_; + unsigned int frame_; + ImageExtractionMode mode_; + + public: + ImageToEncode(ParsedDicomFile& dicom, + unsigned int frame, + ImageExtractionMode mode) : + dicom_(dicom), + frame_(frame), + mode_(mode) + { + } + + ParsedDicomFile& GetDicom() const + { + return dicom_; + } - // Get the HTTP "Accept" header, if any - std::string accept = call.GetHttpHeader("accept", "*/*"); + unsigned int GetFrame() const + { + return frame_; + } + + ImageExtractionMode GetMode() const + { + return mode_; + } + + void SetFormat(const std::string& format) + { + format_ = format; + } + + std::string& GetTarget() + { + return encoded_; + } + + void Answer(RestApiOutput& output) + { + output.AnswerBuffer(encoded_, format_); + } + }; - MediaRanges mediaRanges; - Toolbox::TokenizeString(mediaRanges, accept, ','); + class EncodePng : public HttpContentNegociation::IHandler + { + private: + ImageToEncode& image_; + + public: + EncodePng(ImageToEncode& image) : image_(image) + { + } - for (MediaRanges::const_reverse_iterator it = mediaRanges.rbegin(); - it != mediaRanges.rend(); ++it) + virtual void Handle(const std::string& type, + const std::string& subtype) + { + assert(type == "image"); + assert(subtype == "png"); + image_.GetDicom().ExtractPngImage(image_.GetTarget(), image_.GetFrame(), image_.GetMode()); + image_.SetFormat("image/png"); + } + }; + + class EncodeJpeg : public HttpContentNegociation::IHandler { - } + private: + ImageToEncode& image_; + unsigned int quality_; - throw OrthancException(ErrorCode_NotAcceptable); + public: + EncodeJpeg(ImageToEncode& image, + const RestApiGetCall& call) : + image_(image) + { + std::string v = call.GetArgument("quality", "90" /* default JPEG quality */); + bool ok = false; - std::string image; - dicom.ExtractPngImage(image, frame, mode); - call.GetOutput().AnswerBuffer(image, "image/png"); + try + { + quality_ = boost::lexical_cast(v); + ok = (quality_ >= 0 && quality_ <= 100); + } + catch (boost::bad_lexical_cast&) + { + } + + if (!ok) + { + LOG(ERROR) << "Bad quality for a JPEG encoding (must be a number between 0 and 100): " << v; + throw OrthancException(ErrorCode_BadRequest); + } + } + + virtual void Handle(const std::string& type, + const std::string& subtype) + { + assert(type == "image"); + assert(subtype == "jpeg"); + image_.GetDicom().ExtractJpegImage(image_.GetTarget(), image_.GetFrame(), image_.GetMode(), quality_); + image_.SetFormat("image/jpeg"); + } + }; } @@ -310,7 +399,16 @@ try { - AnswerImage(call, dicom, frame, mode); + ImageToEncode image(dicom, frame, mode); + + HttpContentNegociation negociation; + EncodePng png(image); negociation.Register("image/png", png); + EncodeJpeg jpeg(image, call); negociation.Register("image/jpeg", jpeg); + + if (negociation.Apply(call.GetHttpHeaders())) + { + image.Answer(call.GetOutput()); + } } catch (OrthancException& e) {