Mercurial > hg > orthanc
changeset 883:50106e80555a
integration jpeg -> mainline
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sat, 14 Jun 2014 15:50:02 +0200 |
parents | b5f10a8c96a6 (diff) c9034d80775d (current diff) |
children | cd8a69aa4093 816dccaeb7cf |
files | |
diffstat | 20 files changed, 259 insertions(+), 95 deletions(-) [+] |
line wrap: on
line diff
--- a/Core/ChunkedBuffer.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/Core/ChunkedBuffer.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -65,6 +65,15 @@ } + void ChunkedBuffer::AddChunk(const std::string& chunk) + { + if (chunk.size() > 0) + { + AddChunk(&chunk[0], chunk.size()); + } + } + + void ChunkedBuffer::Flatten(std::string& result) { result.resize(numBytes_);
--- a/Core/ChunkedBuffer.h Sat Jun 14 15:44:28 2014 +0200 +++ b/Core/ChunkedBuffer.h Sat Jun 14 15:50:02 2014 +0200 @@ -64,6 +64,8 @@ void AddChunk(const char* chunkData, size_t chunkSize); + void AddChunk(const std::string& chunk); + void Flatten(std::string& result); }; }
--- a/Core/ImageFormats/ImageAccessor.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/Core/ImageFormats/ImageAccessor.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -34,13 +34,72 @@ #include "ImageAccessor.h" #include "../OrthancException.h" +#include "../ChunkedBuffer.h" #include <stdint.h> #include <cassert> #include <glog/logging.h> +#include <boost/lexical_cast.hpp> namespace Orthanc { + template <typename PixelType> + static void ToMatlabStringInternal(ChunkedBuffer& target, + const ImageAccessor& source) + { + target.AddChunk("double([ "); + + for (unsigned int y = 0; y < source.GetHeight(); y++) + { + const PixelType* p = reinterpret_cast<const PixelType*>(source.GetConstRow(y)); + + std::string s; + if (y > 0) + { + s = "; "; + } + + s.reserve(source.GetWidth() * 8); + + for (unsigned int x = 0; x < source.GetWidth(); x++, p++) + { + s += boost::lexical_cast<std::string>(static_cast<int>(*p)) + " "; + } + + target.AddChunk(s); + } + + target.AddChunk("])"); + } + + + static void RGB24ToMatlabString(ChunkedBuffer& target, + const ImageAccessor& source) + { + assert(source.GetFormat() == PixelFormat_RGB24); + + target.AddChunk("double(permute(reshape([ "); + + for (unsigned int y = 0; y < source.GetHeight(); y++) + { + const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y)); + + std::string s; + s.reserve(source.GetWidth() * 3 * 8); + + for (unsigned int x = 0; x < 3 * source.GetWidth(); x++, p++) + { + s += boost::lexical_cast<std::string>(static_cast<int>(*p)) + " "; + } + + target.AddChunk(s); + } + + target.AddChunk("], [ 3 " + boost::lexical_cast<std::string>(source.GetHeight()) + + " " + boost::lexical_cast<std::string>(source.GetWidth()) + " ]), [ 3 2 1 ]))"); + } + + void* ImageAccessor::GetBuffer() const { if (readOnly_) @@ -128,4 +187,35 @@ assert(GetBytesPerPixel(format_) * width_ <= pitch_); } + + + void ImageAccessor::ToMatlabString(std::string& target) const + { + ChunkedBuffer buffer; + + switch (GetFormat()) + { + case PixelFormat_Grayscale8: + ToMatlabStringInternal<uint8_t>(buffer, *this); + break; + + case PixelFormat_Grayscale16: + ToMatlabStringInternal<uint16_t>(buffer, *this); + break; + + case PixelFormat_SignedGrayscale16: + ToMatlabStringInternal<int16_t>(buffer, *this); + break; + + case PixelFormat_RGB24: + RGB24ToMatlabString(buffer, *this); + break; + + default: + throw OrthancException(ErrorCode_NotImplemented); + } + + buffer.Flatten(target); + } + }
--- a/Core/ImageFormats/ImageAccessor.h Sat Jun 14 15:44:28 2014 +0200 +++ b/Core/ImageFormats/ImageAccessor.h Sat Jun 14 15:50:02 2014 +0200 @@ -106,5 +106,7 @@ unsigned int height, unsigned int pitch, void *buffer); + + void ToMatlabString(std::string& target) const; }; }
--- a/Core/ImageFormats/ImageProcessing.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/Core/ImageFormats/ImageProcessing.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -151,11 +151,11 @@ if (v > maxValue) { - *p = maxValue; + *p = std::numeric_limits<PixelType>::max(); } else if (v < minValue) { - *p = minValue; + *p = std::numeric_limits<PixelType>::min(); } else { @@ -189,11 +189,11 @@ if (v > maxValue) { - *p = maxValue; + *p = std::numeric_limits<PixelType>::max(); } else if (v < minValue) { - *p = minValue; + *p = std::numeric_limits<PixelType>::min(); } else {
--- a/LinuxCompilation.txt Sat Jun 14 15:44:28 2014 +0200 +++ b/LinuxCompilation.txt Sat Jun 14 15:50:02 2014 +0200 @@ -73,6 +73,8 @@ -DUSE_SYSTEM_DCMTK=OFF \ -DUSE_SYSTEM_MONGOOSE=OFF \ -DUSE_SYSTEM_JSONCPP=OFF \ + -DENABLE_JPEG=OFF \ + -DENABLE_JPEG_LOSSLESS=OFF \ ~/Orthanc @@ -89,6 +91,8 @@ -DUSE_SYSTEM_GOOGLE_LOG=OFF \ -DUSE_SYSTEM_MONGOOSE=OFF \ -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON \ + -DENABLE_JPEG=OFF \ + -DENABLE_JPEG_LOSSLESS=OFF \ ~/Orthanc @@ -104,6 +108,8 @@ # cmake -DALLOW_DOWNLOADS=ON \ -DUSE_SYSTEM_MONGOOSE=OFF \ -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON \ + -DENABLE_JPEG=OFF \ + -DENABLE_JPEG_LOSSLESS=OFF \ ~/Orthanc Note: Have also a look at the official package: @@ -124,6 +130,8 @@ -DUSE_SYSTEM_JSONCPP=OFF \ -DUSE_SYSTEM_GOOGLE_LOG=OFF \ -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON \ + -DENABLE_JPEG=OFF \ + -DENABLE_JPEG_LOSSLESS=OFF \ ~/Orthanc @@ -171,6 +179,8 @@ -DALLOW_DOWNLOADS=ON \ -DUSE_SYSTEM_MONGOOSE=OFF \ -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON \ + -DENABLE_JPEG=OFF \ + -DENABLE_JPEG_LOSSLESS=OFF \ ~/Orthanc @@ -183,8 +193,10 @@ gtest-devel libpng-devel libsqlite3x-devel libuuid-devel \ mongoose-devel openssl-devel jsoncpp-devel lua-devel -# cmake ~/Orthanc - +# cmake -DENABLE_JPEG=OFF \ + -DENABLE_JPEG_LOSSLESS=OFF \ + ~/Orthanc + Note: Have also a look at the official package: http://pkgs.fedoraproject.org/cgit/orthanc.git/tree/?h=f18
--- a/NEWS Sat Jun 14 15:44:28 2014 +0200 +++ b/NEWS Sat Jun 14 15:50:02 2014 +0200 @@ -1,7 +1,13 @@ Pending changes in the mainline =============================== + + +Version 0.7.6 (2014/06/11) +========================== + * Support of JPEG and JPEG-LS decompression +* Download DICOM images as Matlab/Octave arrays * Precompiled headers for Microsoft Visual Studio
--- a/OrthancCppClient/OrthancCppClient.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancCppClient/OrthancCppClient.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -35,6 +35,7 @@ * avoid problems with precompiled headers. **/ +#include "../Core/ChunkedBuffer.cpp" #include "../Core/Enumerations.cpp" #include "../Core/HttpClient.cpp" #include "../Core/ImageFormats/ImageAccessor.cpp"
--- a/OrthancCppClient/SharedLibrary/AUTOGENERATED/ExternC.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/ExternC.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -1486,12 +1486,12 @@ LAAW_EXPORT_DLL_API const char* LAAW_CALL_CONVENTION LAAW_EXTERNC_GetFileVersion() { - return "0.7.0.5"; + return "0.7.0.6"; } LAAW_EXPORT_DLL_API const char* LAAW_CALL_CONVENTION LAAW_EXTERNC_GetFullVersion() { - return "0.7.5"; + return "0.7.6"; } LAAW_EXPORT_DLL_API void LAAW_CALL_CONVENTION LAAW_EXTERNC_FreeString(char* str)
--- a/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.rc Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.rc Sat Jun 14 15:50:02 2014 +0200 @@ -1,7 +1,7 @@ #include <winver.h> VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,7,0,5 + FILEVERSION 0,7,0,6 PRODUCTVERSION 0,7,0,0 FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL @@ -10,10 +10,10 @@ BEGIN BLOCK "040904E4" BEGIN - VALUE "Comments", "Release 0.7.5" + VALUE "Comments", "Release 0.7.6" VALUE "CompanyName", "CHU of Liege" VALUE "FileDescription", "Native client to the REST API of Orthanc" - VALUE "FileVersion", "0.7.0.5" + VALUE "FileVersion", "0.7.0.6" VALUE "InternalName", "OrthancClient" VALUE "LegalCopyright", "(c) 2012-2014, Sebastien Jodogne, CHU of Liege" VALUE "LegalTrademarks", "Licensing information is available on https://code.google.com/p/orthanc/"
--- a/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.rc Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.rc Sat Jun 14 15:50:02 2014 +0200 @@ -1,7 +1,7 @@ #include <winver.h> VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,7,0,5 + FILEVERSION 0,7,0,6 PRODUCTVERSION 0,7,0,0 FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL @@ -10,10 +10,10 @@ BEGIN BLOCK "040904E4" BEGIN - VALUE "Comments", "Release 0.7.5" + VALUE "Comments", "Release 0.7.6" VALUE "CompanyName", "CHU of Liege" VALUE "FileDescription", "Native client to the REST API of Orthanc" - VALUE "FileVersion", "0.7.0.5" + VALUE "FileVersion", "0.7.0.6" VALUE "InternalName", "OrthancClient" VALUE "LegalCopyright", "(c) 2012-2014, Sebastien Jodogne, CHU of Liege" VALUE "LegalTrademarks", "Licensing information is available on https://code.google.com/p/orthanc/"
--- a/OrthancCppClient/SharedLibrary/Product.json Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancCppClient/SharedLibrary/Product.json Sat Jun 14 15:50:02 2014 +0200 @@ -4,5 +4,5 @@ "Company" : "CHU of Liege", "Copyright" : "(c) 2012-2014, Sebastien Jodogne, CHU of Liege", "Legal" : "Licensing information is available on https://code.google.com/p/orthanc/", - "Version" : "0.7.5" + "Version" : "0.7.6" }
--- a/OrthancServer/DicomProtocol/ReusableDicomUserConnection.h Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancServer/DicomProtocol/ReusableDicomUserConnection.h Sat Jun 14 15:50:02 2014 +0200 @@ -90,7 +90,7 @@ unsigned int GetMillisecondsBeforeClose() const { - return timeBeforeClose_.total_milliseconds(); + return static_cast<unsigned int>(timeBeforeClose_.total_milliseconds()); } void SetMillisecondsBeforeClose(unsigned int ms);
--- a/OrthancServer/FromDcmtkBridge.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancServer/FromDcmtkBridge.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -428,71 +428,6 @@ } - void FromDcmtkBridge::ExtractPngImage(std::string& result, - DcmDataset& dataset, - unsigned int frame, - ImageExtractionMode mode) - { - ImageBuffer tmp; - bool ok = false; - - switch (mode) - { - case ImageExtractionMode_UInt8: - ok = DicomImageDecoder::DecodeAndTruncate(tmp, dataset, frame, PixelFormat_Grayscale8); - break; - - case ImageExtractionMode_UInt16: - ok = DicomImageDecoder::DecodeAndTruncate(tmp, dataset, frame, PixelFormat_Grayscale16); - break; - - case ImageExtractionMode_Int16: - ok = DicomImageDecoder::DecodeAndTruncate(tmp, dataset, frame, PixelFormat_SignedGrayscale16); - break; - - case ImageExtractionMode_Preview: - ok = DicomImageDecoder::DecodePreview(tmp, dataset, frame); - break; - - default: - throw OrthancException(ErrorCode_ParameterOutOfRange); - } - - if (!ok) - { - throw OrthancException(ErrorCode_BadFileFormat); - } - - ImageAccessor accessor(tmp.GetAccessor()); - PngWriter writer; - writer.WriteToMemory(result, accessor); - } - - - void FromDcmtkBridge::ExtractPngImage(std::string& result, - const std::string& dicomContent, - unsigned int frame, - ImageExtractionMode mode) - { - DcmInputBufferStream is; - if (dicomContent.size() > 0) - { - is.setBuffer(&dicomContent[0], dicomContent.size()); - } - is.setEos(); - - DcmFileFormat dicom; - if (dicom.read(is).good()) - { - ExtractPngImage(result, *dicom.getDataset(), frame, mode); - } - else - { - throw OrthancException(ErrorCode_BadFileFormat); - } - } - - std::string FromDcmtkBridge::GetName(const DicomTag& t) {
--- a/OrthancServer/FromDcmtkBridge.h Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancServer/FromDcmtkBridge.h Sat Jun 14 15:50:02 2014 +0200 @@ -58,16 +58,6 @@ const std::string& path, unsigned int maxStringLength = 256); - static void ExtractPngImage(std::string& result, - DcmDataset& dataset, - unsigned int frame, - ImageExtractionMode mode); - - static void ExtractPngImage(std::string& result, - const std::string& dicomContent, - unsigned int frame, - ImageExtractionMode mode); - static std::string GetName(const DicomTag& tag); static DicomTag ParseTag(const char* name);
--- a/OrthancServer/Internals/DicomImageDecoder.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancServer/Internals/DicomImageDecoder.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -77,6 +77,9 @@ +#include "../PrecompiledHeadersServer.h" +#include "DicomImageDecoder.h" + #include "../../Core/OrthancException.h" #include "../../Core/ImageFormats/ImageProcessing.h" #include "../../Core/ImageFormats/PngWriter.h" // TODO REMOVE THIS @@ -323,7 +326,7 @@ << (info.IsPlanar() ? ", planar" : ", non-planar"); throw OrthancException(ErrorCode_NotImplemented); } - + target.SetHeight(info.GetHeight()); target.SetWidth(info.GetWidth()); target.SetFormat(format); @@ -659,7 +662,7 @@ } else { - ImageProcessing::ShiftScale(sourceAccessor, -a, 255.0f / static_cast<float>(b - a)); + ImageProcessing::ShiftScale(sourceAccessor, static_cast<float>(-a), 255.0f / static_cast<float>(b - a)); if (source.GetFormat() == PixelFormat_Grayscale8) {
--- a/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -202,9 +202,11 @@ std::string dicomContent, png; context.ReadFile(dicomContent, publicId, FileContentType_Dicom); + ParsedDicomFile dicom(dicomContent); + try { - FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, mode); + dicom.ExtractPngImage(png, frame, mode); call.GetOutput().AnswerBuffer(png, "image/png"); } catch (OrthancException& e) @@ -228,6 +230,39 @@ } + static void GetMatlabImage(RestApi::GetCall& call) + { + ServerContext& context = OrthancRestApi::GetContext(call); + + std::string frameId = call.GetUriComponent("frame", "0"); + + unsigned int frame; + try + { + frame = boost::lexical_cast<unsigned int>(frameId); + } + catch (boost::bad_lexical_cast) + { + return; + } + + std::string publicId = call.GetUriComponent("id", ""); + std::string dicomContent; + context.ReadFile(dicomContent, publicId, FileContentType_Dicom); + + ParsedDicomFile dicom(dicomContent); + ImageBuffer buffer; + dicom.ExtractImage(buffer, frame); + + ImageAccessor accessor(buffer.GetConstAccessor()); + + std::string result; + accessor.ToMatlabString(result); + + call.GetOutput().AnswerBuffer(result, "text/plain"); + } + + static void GetResourceStatistics(RestApi::GetCall& call) { @@ -587,10 +622,12 @@ Register("/instances/{id}/frames/{frame}/image-uint8", GetImage<ImageExtractionMode_UInt8>); Register("/instances/{id}/frames/{frame}/image-uint16", GetImage<ImageExtractionMode_UInt16>); Register("/instances/{id}/frames/{frame}/image-int16", GetImage<ImageExtractionMode_Int16>); + Register("/instances/{id}/frames/{frame}/matlab", GetMatlabImage); Register("/instances/{id}/preview", GetImage<ImageExtractionMode_Preview>); Register("/instances/{id}/image-uint8", GetImage<ImageExtractionMode_UInt8>); Register("/instances/{id}/image-uint16", GetImage<ImageExtractionMode_UInt16>); Register("/instances/{id}/image-int16", GetImage<ImageExtractionMode_Int16>); + Register("/instances/{id}/matlab", GetMatlabImage); Register("/patients/{id}/protected", IsProtectedPatient); Register("/patients/{id}/protected", SetPatientProtection);
--- a/OrthancServer/ParsedDicomFile.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancServer/ParsedDicomFile.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -82,8 +82,10 @@ #include "FromDcmtkBridge.h" #include "ToDcmtkBridge.h" +#include "Internals/DicomImageDecoder.h" #include "../Core/Toolbox.h" #include "../Core/OrthancException.h" +#include "../Core/ImageFormats/ImageBuffer.h" #include "../Core/ImageFormats/PngWriter.h" #include "../Core/Uuid.h" #include "../Core/DicomFormat/DicomString.h" @@ -1214,4 +1216,67 @@ throw OrthancException(ErrorCode_InternalError); } } + + + void ParsedDicomFile::ExtractImage(ImageBuffer& result, + unsigned int frame) + { + DcmDataset& dataset = *pimpl_->file_->getDataset(); + + if (!DicomImageDecoder::Decode(result, dataset, frame)) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } + + + void ParsedDicomFile::ExtractImage(ImageBuffer& result, + unsigned int frame, + ImageExtractionMode mode) + { + DcmDataset& dataset = *pimpl_->file_->getDataset(); + + bool ok = false; + + switch (mode) + { + case ImageExtractionMode_UInt8: + ok = DicomImageDecoder::DecodeAndTruncate(result, dataset, frame, PixelFormat_Grayscale8); + break; + + case ImageExtractionMode_UInt16: + ok = DicomImageDecoder::DecodeAndTruncate(result, dataset, frame, PixelFormat_Grayscale16); + break; + + case ImageExtractionMode_Int16: + ok = DicomImageDecoder::DecodeAndTruncate(result, dataset, frame, PixelFormat_SignedGrayscale16); + break; + + case ImageExtractionMode_Preview: + ok = DicomImageDecoder::DecodePreview(result, dataset, frame); + break; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + if (!ok) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } + + + void ParsedDicomFile::ExtractPngImage(std::string& result, + unsigned int frame, + ImageExtractionMode mode) + { + ImageBuffer buffer; + ExtractImage(buffer, frame, mode); + + ImageAccessor accessor(buffer.GetConstAccessor()); + PngWriter writer; + writer.WriteToMemory(result, accessor); + } + }
--- a/OrthancServer/ParsedDicomFile.h Sat Jun 14 15:44:28 2014 +0200 +++ b/OrthancServer/ParsedDicomFile.h Sat Jun 14 15:50:02 2014 +0200 @@ -36,6 +36,7 @@ #include "../Core/RestApi/RestApiOutput.h" #include "ServerEnumerations.h" #include "../Core/ImageFormats/ImageAccessor.h" +#include "../Core/ImageFormats/ImageBuffer.h" namespace Orthanc { @@ -92,6 +93,17 @@ void EmbedImage(const ImageAccessor& accessor); void EmbedImage(const std::string& dataUriScheme); + + void ExtractImage(ImageBuffer& result, + unsigned int frame); + + void ExtractImage(ImageBuffer& result, + unsigned int frame, + ImageExtractionMode mode); + + void ExtractPngImage(std::string& result, + unsigned int frame, + ImageExtractionMode mode); }; }
--- a/UnitTestsSources/SQLite.cpp Sat Jun 14 15:44:28 2014 +0200 +++ b/UnitTestsSources/SQLite.cpp Sat Jun 14 15:50:02 2014 +0200 @@ -316,7 +316,7 @@ ASSERT_EQ(42ll, s.ColumnInt64(1)); ASSERT_TRUE(s.Step()); ASSERT_EQ(SQLite::COLUMN_TYPE_FLOAT, s.GetColumnType(1)); - ASSERT_FLOAT_EQ(42.5, s.ColumnDouble(1)); + ASSERT_DOUBLE_EQ(42.5, s.ColumnDouble(1)); ASSERT_TRUE(s.Step()); ASSERT_EQ(SQLite::COLUMN_TYPE_TEXT, s.GetColumnType(1)); ASSERT_EQ("Hello", s.ColumnString(1));