# HG changeset patch # User Sebastien Jodogne # Date 1346664840 -7200 # Node ID ea48f38afe5f57ee7dd537167a04328a2e2a2e97 # Parent c1097a676eca81bf453a4b6011cf8fd4ea6bf508 access to raw images diff -r c1097a676eca -r ea48f38afe5f NEWS --- a/NEWS Fri Aug 31 11:45:48 2012 +0200 +++ b/NEWS Mon Sep 03 11:34:00 2012 +0200 @@ -1,6 +1,7 @@ Pending changes =============== +* Access to the raw PNG images (in 8bpp and 16bpp) * Support of SSL and HTTP Basic Authentication * Change of the licensing of the "Core/SQLite" folder to BSD, (to reflect the original licensing terms of Chromium, from which the diff -r c1097a676eca -r ea48f38afe5f PalantirServer/FromDcmtkBridge.cpp --- a/PalantirServer/FromDcmtkBridge.cpp Fri Aug 31 11:45:48 2012 +0200 +++ b/PalantirServer/FromDcmtkBridge.cpp Mon Sep 03 11:34:00 2012 +0200 @@ -379,12 +379,69 @@ } - void FromDcmtkBridge::ExtractPreviewImage(std::string& result, - DcmDataset& dataset) + static void ExtractPngImagePreview(std::string& result, + DicomIntegerPixelAccessor& accessor) + { + PngWriter w; + + int32_t min, max; + accessor.GetExtremeValues(min, max); + + std::vector image(accessor.GetWidth() * accessor.GetHeight(), 0); + if (min != max) + { + uint8_t* pixel = &image[0]; + for (unsigned int y = 0; y < accessor.GetHeight(); y++) + { + for (unsigned int x = 0; x < accessor.GetWidth(); x++, pixel++) + { + int32_t v = accessor.GetValue(x, y); + *pixel = static_cast( + boost::math::lround(static_cast(v - min) / + static_cast(max - min) * 255.0f)); + } + } + } + + w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), + accessor.GetWidth(), PixelFormat_Grayscale8, &image[0]); + } + + + template + static void ExtractPngImageTruncate(std::string& result, + DicomIntegerPixelAccessor& accessor, + PixelFormat format) + { + PngWriter w; + + std::vector image(accessor.GetWidth() * accessor.GetHeight(), 0); + T* pixel = &image[0]; + for (unsigned int y = 0; y < accessor.GetHeight(); y++) + { + for (unsigned int x = 0; x < accessor.GetWidth(); x++, pixel++) + { + int32_t v = accessor.GetValue(x, y); + if (v < std::numeric_limits::min()) + *pixel = std::numeric_limits::min(); + else if (v > std::numeric_limits::max()) + *pixel = std::numeric_limits::max(); + else + *pixel = static_cast(v); + } + } + + w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), + accessor.GetWidth() * sizeof(T), format, &image[0]); + } + + + void FromDcmtkBridge::ExtractPngImage(std::string& result, + DcmDataset& dataset, + ImageExtractionMode mode) { // See also: http://support.dcmtk.org/wiki/dcmtk/howto/accessing-compressed-data - PngWriter w; std::auto_ptr accessor; DicomMap m; @@ -401,39 +458,55 @@ } } + PixelFormat format; + switch (mode) + { + case ImageExtractionMode_Preview: + case ImageExtractionMode_UInt8: + format = PixelFormat_Grayscale8; + break; + + case ImageExtractionMode_UInt16: + format = PixelFormat_Grayscale16; + break; + + default: + throw PalantirException(ErrorCode_NotImplemented); + } + if (accessor.get() == NULL || accessor->GetWidth() == 0 || accessor->GetHeight() == 0) { - w.WriteToMemory(result, 0, 0, 0, PixelFormat_Grayscale8, NULL); + PngWriter w; + w.WriteToMemory(result, 0, 0, 0, format, NULL); } else { - int32_t min, max; - accessor->GetExtremeValues(min, max); - - std::vector image(accessor->GetWidth() * accessor->GetHeight(), 0); - if (min != max) + switch (mode) { - uint8_t* result = &image[0]; - for (unsigned int y = 0; y < accessor->GetHeight(); y++) - { - for (unsigned int x = 0; x < accessor->GetWidth(); x++, result++) - { - int32_t v = accessor->GetValue(x, y); - *result = static_cast(boost::math::lround(static_cast(v - min) / static_cast(max - min) * 255.0f)); - } - } + case ImageExtractionMode_Preview: + ExtractPngImagePreview(result, *accessor); + break; + + case ImageExtractionMode_UInt8: + ExtractPngImageTruncate(result, *accessor, format); + break; + + case ImageExtractionMode_UInt16: + ExtractPngImageTruncate(result, *accessor, format); + break; + + default: + throw PalantirException(ErrorCode_NotImplemented); } - - w.WriteToMemory(result, accessor->GetWidth(), accessor->GetHeight(), - accessor->GetWidth(), PixelFormat_Grayscale8, &image[0]); } } - void FromDcmtkBridge::ExtractPreviewImage(std::string& result, - const std::string& dicomContent) + void FromDcmtkBridge::ExtractPngImage(std::string& result, + const std::string& dicomContent, + ImageExtractionMode mode) { DcmInputBufferStream is; if (dicomContent.size() > 0) @@ -445,7 +518,7 @@ DcmFileFormat dicom; if (dicom.read(is).good()) { - ExtractPreviewImage(result, *dicom.getDataset()); + ExtractPngImage(result, *dicom.getDataset(), mode); } else { diff -r c1097a676eca -r ea48f38afe5f PalantirServer/FromDcmtkBridge.h --- a/PalantirServer/FromDcmtkBridge.h Fri Aug 31 11:45:48 2012 +0200 +++ b/PalantirServer/FromDcmtkBridge.h Mon Sep 03 11:34:00 2012 +0200 @@ -26,6 +26,13 @@ namespace Palantir { + enum ImageExtractionMode + { + ImageExtractionMode_Preview, + ImageExtractionMode_UInt8, + ImageExtractionMode_UInt16 + }; + class FromDcmtkBridge { public: @@ -43,11 +50,13 @@ const std::string& path, unsigned int maxStringLength = 256); - static void ExtractPreviewImage(std::string& result, - DcmDataset& dataset); + static void ExtractPngImage(std::string& result, + DcmDataset& dataset, + ImageExtractionMode mode); - static void ExtractPreviewImage(std::string& result, - const std::string& dicomContent); + static void ExtractPngImage(std::string& result, + const std::string& dicomContent, + ImageExtractionMode mode); static std::string GetName(const DicomTag& tag); diff -r c1097a676eca -r ea48f38afe5f PalantirServer/PalantirRestApi.cpp --- a/PalantirServer/PalantirRestApi.cpp Fri Aug 31 11:45:48 2012 +0200 +++ b/PalantirServer/PalantirRestApi.cpp Mon Sep 03 11:34:00 2012 +0200 @@ -568,7 +568,9 @@ else if (uri.size() == 3 && uri[0] == "instances" && - uri[2] == "preview") + (uri[2] == "preview" || + uri[2] == "image-uint8" || + uri[2] == "image-uint16")) { std::string uuid; existingResource = index_.GetDicomFile(uuid, uri[1]); @@ -579,7 +581,23 @@ storage_.ReadFile(dicomContent, uuid); try { - FromDcmtkBridge::ExtractPreviewImage(png, dicomContent); + if (uri[2] == "preview") + { + FromDcmtkBridge::ExtractPngImage(png, dicomContent, ImageExtractionMode_Preview); + } + else if (uri[2] == "image-uint8") + { + FromDcmtkBridge::ExtractPngImage(png, dicomContent, ImageExtractionMode_UInt8); + } + else if (uri[2] == "image-uint16") + { + FromDcmtkBridge::ExtractPngImage(png, dicomContent, ImageExtractionMode_UInt16); + } + else + { + throw PalantirException(ErrorCode_InternalError); + } + output.AnswerBufferWithContentType(png, "image/png"); return; }