# HG changeset patch # User Sebastien Jodogne # Date 1481903054 -3600 # Node ID 3d83d34cd4dbc9063b8b44e662dbaed88ad1e2ba # Parent 319b8c45c2310eb02c82425b937805878f258d8b sync, optimizations diff -r 319b8c45c231 -r 3d83d34cd4db Applications/ApplicationToolbox.cpp --- a/Applications/ApplicationToolbox.cpp Fri Dec 16 14:55:19 2016 +0100 +++ b/Applications/ApplicationToolbox.cpp Fri Dec 16 16:44:14 2016 +0100 @@ -28,6 +28,17 @@ #include #include +#include + + +static bool DisplayPerformanceWarning() +{ + (void) DisplayPerformanceWarning; // Disable warning about unused function + LOG(WARNING) << "Performance warning in whole-slide imaging: " + << "Non-release build, runtime debug assertions are turned on"; + return true; +} + namespace OrthancWSI { @@ -39,6 +50,7 @@ Orthanc::HttpClient::InitializeOpenSsl(); Orthanc::HttpClient::GlobalInitialize(); Orthanc::FromDcmtkBridge::InitializeDictionary(false /* don't load private dictionary */); + assert(DisplayPerformanceWarning()); } diff -r 319b8c45c231 -r 3d83d34cd4db Framework/ImageToolbox.cpp --- a/Framework/ImageToolbox.cpp Fri Dec 16 14:55:19 2016 +0100 +++ b/Framework/ImageToolbox.cpp Fri Dec 16 16:44:14 2016 +0100 @@ -221,9 +221,11 @@ unsigned int y, unsigned int channel, int offsetX, - int offsetY) + int offsetY, + unsigned int bytesPerPixel) { - assert(channel < source.GetBytesPerPixel()); + assert(bytesPerPixel == source.GetBytesPerPixel()); + assert(channel < bytesPerPixel); assert(source.GetFormat() == Orthanc::PixelFormat_Grayscale8 || source.GetFormat() == Orthanc::PixelFormat_RGB24 || source.GetFormat() == Orthanc::PixelFormat_RGBA32); // 16bpp is unsupported @@ -255,14 +257,15 @@ } return *(reinterpret_cast(source.GetConstBuffer()) + - y * source.GetPitch() + x * source.GetBytesPerPixel() + channel); + y * source.GetPitch() + x * bytesPerPixel + channel); } static uint8_t SmoothPixelValue(const Orthanc::ImageAccessor& source, unsigned int x, unsigned int y, - unsigned int channel) + unsigned int channel, + unsigned int bytesPerPixel) { static const uint32_t kernel[5] = { 1, 4, 6, 4, 1 }; static const uint32_t normalization = 2 * (1 + 4 + 6 + 4 + 1); @@ -272,13 +275,13 @@ // Horizontal smoothing for (int offset = -2; offset <= 2; offset++) { - accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, offset, 0); + accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, offset, 0, bytesPerPixel); } // Vertical smoothing for (int offset = -2; offset <= 2; offset++) { - accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, 0, offset); + accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, 0, offset, bytesPerPixel); } return static_cast(accumulator / normalization); @@ -307,6 +310,8 @@ source.GetWidth() / 2, source.GetHeight() / 2)); + unsigned int bytesPerPixel = source.GetBytesPerPixel(); + for (unsigned int y = 0; y < source.GetHeight() / 2; y++) { uint8_t* q = reinterpret_cast(result->GetRow(y)); @@ -317,11 +322,11 @@ { if (smooth) { - q[c] = SmoothPixelValue(source, 2 * x, 2 * y, c); + q[c] = SmoothPixelValue(source, 2 * x, 2 * y, c, bytesPerPixel); } else { - q[c] = GetPixelValue(source, 2 * x, 2 * y, c, 0, 0); + q[c] = GetPixelValue(source, 2 * x, 2 * y, c, 0, 0, bytesPerPixel); } } } diff -r 319b8c45c231 -r 3d83d34cd4db Framework/Inputs/DicomPyramidInstance.cpp --- a/Framework/Inputs/DicomPyramidInstance.cpp Fri Dec 16 14:55:19 2016 +0100 +++ b/Framework/Inputs/DicomPyramidInstance.cpp Fri Dec 16 16:44:14 2016 +0100 @@ -40,8 +40,8 @@ { using namespace OrthancPlugins; - DicomDatasetReader header(new FullOrthancDataset - (orthanc, "/instances/" + instanceId + "/header")); + FullOrthancDataset dataset(orthanc, "/instances/" + instanceId + "/header"); + DicomDatasetReader header(dataset); std::string s = Orthanc::Toolbox::StripSpaces (header.GetMandatoryStringValue(DICOM_TAG_TRANSFER_SYNTAX_UID)); @@ -131,7 +131,8 @@ { using namespace OrthancPlugins; - DicomDatasetReader reader(new FullOrthancDataset(orthanc, "/instances/" + instanceId + "/tags")); + FullOrthancDataset dataset(orthanc, "/instances/" + instanceId + "/tags"); + DicomDatasetReader reader(dataset); if (reader.GetMandatoryStringValue(DICOM_TAG_SOP_CLASS_UID) != "1.2.840.10008.5.1.4.1.1.77.1.6" || reader.GetMandatoryStringValue(DICOM_TAG_MODALITY) != "SM") diff -r 319b8c45c231 -r 3d83d34cd4db Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp --- a/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp Fri Dec 16 14:55:19 2016 +0100 +++ b/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp Fri Dec 16 16:44:14 2016 +0100 @@ -68,20 +68,31 @@ } - DicomDatasetReader::DicomDatasetReader(IDicomDataset* dataset) : // takes ownership + DicomDatasetReader::DicomDatasetReader(const IDicomDataset& dataset) : dataset_(dataset) { - if (dataset == NULL) + } + + + std::string DicomDatasetReader::GetStringValue(const DicomPath& path, + const std::string& defaultValue) const + { + std::string s; + if (dataset_.GetStringValue(s, path)) { - ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); + return s; + } + else + { + return defaultValue; } } - + std::string DicomDatasetReader::GetMandatoryStringValue(const DicomPath& path) const { std::string s; - if (dataset_->GetStringValue(s, path)) + if (dataset_.GetStringValue(s, path)) { return s; } @@ -92,12 +103,22 @@ } - int DicomDatasetReader::GetIntegerValue(const DicomPath& path) + template + static T GetValueInternal(const IDicomDataset& dataset, + const DicomPath& path) { try { - std::string s = StripSpaces(GetMandatoryStringValue(path)); - return boost::lexical_cast(s); + std::string s; + + if (dataset.GetStringValue(s, path)) + { + return boost::lexical_cast(StripSpaces(s)); + } + else + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InexistentTag); + } } catch (boost::bad_lexical_cast&) { @@ -106,10 +127,16 @@ } - unsigned int DicomDatasetReader::GetUnsignedIntegerValue(const DicomPath& path) + int DicomDatasetReader::GetIntegerValue(const DicomPath& path) const + { + return GetValueInternal(dataset_, path); + } + + + unsigned int DicomDatasetReader::GetUnsignedIntegerValue(const DicomPath& path) const { int value = GetIntegerValue(path); - + if (value >= 0) { return static_cast(value); @@ -119,4 +146,16 @@ ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); } } + + + float DicomDatasetReader::GetFloatValue(const DicomPath& path) const + { + return GetValueInternal(dataset_, path); + } + + + double DicomDatasetReader::GetDoubleValue(const DicomPath& path) const + { + return GetValueInternal(dataset_, path); + } } diff -r 319b8c45c231 -r 3d83d34cd4db Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h --- a/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h Fri Dec 16 14:55:19 2016 +0100 +++ b/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h Fri Dec 16 16:44:14 2016 +0100 @@ -35,26 +35,34 @@ #include "IDicomDataset.h" #include +#include namespace OrthancPlugins { class DicomDatasetReader : public boost::noncopyable { private: - std::auto_ptr dataset_; + const IDicomDataset& dataset_; public: - DicomDatasetReader(IDicomDataset* dataset); // takes ownership + DicomDatasetReader(const IDicomDataset& dataset); - IDicomDataset& GetDataset() const + const IDicomDataset& GetDataset() const { - return *dataset_; + return dataset_; } + std::string GetStringValue(const DicomPath& path, + const std::string& defaultValue) const; + std::string GetMandatoryStringValue(const DicomPath& path) const; - int GetIntegerValue(const DicomPath& path); + int GetIntegerValue(const DicomPath& path) const; + + unsigned int GetUnsignedIntegerValue(const DicomPath& path) const; - unsigned int GetUnsignedIntegerValue(const DicomPath& path); + float GetFloatValue(const DicomPath& path) const; + + double GetDoubleValue(const DicomPath& path) const; }; } diff -r 319b8c45c231 -r 3d83d34cd4db Resources/Orthanc/Plugins/Samples/Common/DicomTag.h --- a/Resources/Orthanc/Plugins/Samples/Common/DicomTag.h Fri Dec 16 14:55:19 2016 +0100 +++ b/Resources/Orthanc/Plugins/Samples/Common/DicomTag.h Fri Dec 16 16:44:14 2016 +0100 @@ -77,19 +77,27 @@ static const DicomTag DICOM_TAG_BITS_STORED(0x0028, 0x0101); + static const DicomTag DICOM_TAG_COLUMNS(0x0028, 0x0011); static const DicomTag DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021e); - static const DicomTag DICOM_TAG_COLUMNS(0x0028, 0x0011); + static const DicomTag DICOM_TAG_IMAGE_ORIENTATION_PATIENT(0x0020, 0x0037); + static const DicomTag DICOM_TAG_IMAGE_POSITION_PATIENT(0x0020, 0x0032); static const DicomTag DICOM_TAG_MODALITY(0x0008, 0x0060); static const DicomTag DICOM_TAG_NUMBER_OF_FRAMES(0x0028, 0x0008); static const DicomTag DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE(0x5200, 0x9230); static const DicomTag DICOM_TAG_PHOTOMETRIC_INTERPRETATION(0x0028, 0x0004); static const DicomTag DICOM_TAG_PIXEL_REPRESENTATION(0x0028, 0x0103); + static const DicomTag DICOM_TAG_PIXEL_SPACING(0x0028, 0x0030); static const DicomTag DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE(0x0048, 0x021a); - static const DicomTag DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021f); + static const DicomTag DICOM_TAG_RESCALE_INTERCEPT(0x0028, 0x1052); + static const DicomTag DICOM_TAG_RESCALE_SLOPE(0x0028, 0x1053); static const DicomTag DICOM_TAG_ROWS(0x0028, 0x0010); + static const DicomTag DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021f); + static const DicomTag DICOM_TAG_SAMPLES_PER_PIXEL(0x0028, 0x0002); + static const DicomTag DICOM_TAG_SLICE_THICKNESS(0x0018, 0x0050); static const DicomTag DICOM_TAG_SOP_CLASS_UID(0x0008, 0x0016); - static const DicomTag DICOM_TAG_SAMPLES_PER_PIXEL(0x0028, 0x0002); static const DicomTag DICOM_TAG_TOTAL_PIXEL_MATRIX_COLUMNS(0x0048, 0x0006); static const DicomTag DICOM_TAG_TOTAL_PIXEL_MATRIX_ROWS(0x0048, 0x0007); static const DicomTag DICOM_TAG_TRANSFER_SYNTAX_UID(0x0002, 0x0010); + static const DicomTag DICOM_TAG_WINDOW_CENTER(0x0028, 0x1050); + static const DicomTag DICOM_TAG_WINDOW_WIDTH(0x0028, 0x1051); } diff -r 319b8c45c231 -r 3d83d34cd4db TODO --- a/TODO Fri Dec 16 14:55:19 2016 +0100 +++ b/TODO Fri Dec 16 16:44:14 2016 +0100 @@ -16,6 +16,7 @@ ----------- * Check out rapidjson: https://github.com/miloyip/nativejson-benchmark +* Optimize ImageToolbox::Set() and ImageToolbox::Halve() -------------