# HG changeset patch # User Sebastien Jodogne # Date 1415024342 -3600 # Node ID f5b0207967bcbd8f4cf36d6c32ece120373b2d80 # Parent bb1ad2fbf914567fe7884cad54174ed13c8a75e8 Fix issue 19 (YBR_FULL are decoded incorrectly) diff -r bb1ad2fbf914 -r f5b0207967bc Core/DicomFormat/DicomImageInformation.cpp --- a/Core/DicomFormat/DicomImageInformation.cpp Mon Nov 03 13:40:14 2014 +0100 +++ b/Core/DicomFormat/DicomImageInformation.cpp Mon Nov 03 15:19:02 2014 +0100 @@ -39,6 +39,7 @@ #include "DicomImageInformation.h" #include "../OrthancException.h" +#include "../Toolbox.h" #include #include #include @@ -53,6 +54,66 @@ try { + std::string p = values.GetValue(DICOM_TAG_PHOTOMETRIC_INTERPRETATION).AsString(); + Toolbox::ToUpperCase(p); + + if (p == "RGB") + { + photometric_ = PhotometricInterpretation_RGB; + } + else if (p == "MONOCHROME1") + { + photometric_ = PhotometricInterpretation_Monochrome1; + } + else if (p == "MONOCHROME2") + { + photometric_ = PhotometricInterpretation_Monochrome2; + } + else if (p == "PALETTE COLOR") + { + photometric_ = PhotometricInterpretation_Palette; + } + else if (p == "HSV") + { + photometric_ = PhotometricInterpretation_HSV; + } + else if (p == "ARGB") + { + photometric_ = PhotometricInterpretation_ARGB; + } + else if (p == "CMYK") + { + photometric_ = PhotometricInterpretation_CMYK; + } + else if (p == "YBR_FULL") + { + photometric_ = PhotometricInterpretation_YBRFull; + } + else if (p == "YBR_FULL_422") + { + photometric_ = PhotometricInterpretation_YBRFull422; + } + else if (p == "YBR_PARTIAL_420") + { + photometric_ = PhotometricInterpretation_YBRPartial420; + } + else if (p == "YBR_PARTIAL_422") + { + photometric_ = PhotometricInterpretation_YBRPartial422; + } + else if (p == "YBR_ICT") + { + photometric_ = PhotometricInterpretation_YBR_ICT; + } + else if (p == "YBR_RCT") + { + photometric_ = PhotometricInterpretation_YBR_RCT; + } + else + { + photometric_ = PhotometricInterpretation_Unknown; + } + width_ = boost::lexical_cast(values.GetValue(DICOM_TAG_COLUMNS).AsString()); height_ = boost::lexical_cast(values.GetValue(DICOM_TAG_ROWS).AsString()); bitsAllocated_ = boost::lexical_cast(values.GetValue(DICOM_TAG_BITS_ALLOCATED).AsString()); @@ -159,30 +220,37 @@ bool DicomImageInformation::ExtractPixelFormat(PixelFormat& format) const { - if (GetBitsStored() == 8 && GetChannelCount() == 1 && !IsSigned()) + if (photometric_ == PhotometricInterpretation_Monochrome1 || + photometric_ == PhotometricInterpretation_Monochrome2) { - format = PixelFormat_Grayscale8; - return true; + if (GetBitsStored() == 8 && GetChannelCount() == 1 && !IsSigned()) + { + format = PixelFormat_Grayscale8; + return true; + } + + if (GetBitsAllocated() == 16 && GetChannelCount() == 1 && !IsSigned()) + { + format = PixelFormat_Grayscale16; + return true; + } + + if (GetBitsAllocated() == 16 && GetChannelCount() == 1 && IsSigned()) + { + format = PixelFormat_SignedGrayscale16; + return true; + } } - if (GetBitsStored() == 8 && GetChannelCount() == 3 && !IsSigned()) + if (GetBitsStored() == 8 && + GetChannelCount() == 3 && + !IsSigned() && + photometric_ == PhotometricInterpretation_RGB) { format = PixelFormat_RGB24; return true; } - if (GetBitsAllocated() == 16 && GetChannelCount() == 1 && !IsSigned()) - { - format = PixelFormat_Grayscale16; - return true; - } - - if (GetBitsAllocated() == 16 && GetChannelCount() == 1 && IsSigned()) - { - format = PixelFormat_SignedGrayscale16; - return true; - } - return false; } } diff -r bb1ad2fbf914 -r f5b0207967bc Core/DicomFormat/DicomImageInformation.h --- a/Core/DicomFormat/DicomImageInformation.h Mon Nov 03 13:40:14 2014 +0100 +++ b/Core/DicomFormat/DicomImageInformation.h Mon Nov 03 15:19:02 2014 +0100 @@ -54,6 +54,8 @@ unsigned int bitsStored_; unsigned int highBit_; + PhotometricInterpretation photometric_; + public: DicomImageInformation(const DicomMap& values); @@ -112,6 +114,11 @@ return highBit_ + 1 - bitsStored_; } + PhotometricInterpretation GetPhotometricInterpretation() const + { + return photometric_; + } + bool ExtractPixelFormat(PixelFormat& format) const; }; } diff -r bb1ad2fbf914 -r f5b0207967bc Core/DicomFormat/DicomMap.cpp --- a/Core/DicomFormat/DicomMap.cpp Mon Nov 03 13:40:14 2014 +0100 +++ b/Core/DicomFormat/DicomMap.cpp Mon Nov 03 15:19:02 2014 +0100 @@ -36,6 +36,7 @@ #include #include #include "DicomString.h" +#include "DicomArray.h" #include "../OrthancException.h" @@ -387,4 +388,11 @@ GetMainDicomTagsInternal(result, ResourceType_Series); GetMainDicomTagsInternal(result, ResourceType_Instance); } + + + void DicomMap::Print(FILE* fp) const + { + DicomArray a(*this); + a.Print(fp); + } } diff -r bb1ad2fbf914 -r f5b0207967bc Core/DicomFormat/DicomMap.h --- a/Core/DicomFormat/DicomMap.h Mon Nov 03 13:40:14 2014 +0100 +++ b/Core/DicomFormat/DicomMap.h Mon Nov 03 15:19:02 2014 +0100 @@ -160,5 +160,7 @@ static void GetMainDicomTags(std::set& result, ResourceType level); static void GetMainDicomTags(std::set& result); + + void Print(FILE* fp) const; }; } diff -r bb1ad2fbf914 -r f5b0207967bc Core/Enumerations.cpp --- a/Core/Enumerations.cpp Mon Nov 03 13:40:14 2014 +0100 +++ b/Core/Enumerations.cpp Mon Nov 03 15:19:02 2014 +0100 @@ -313,6 +313,58 @@ } + const char* EnumerationToString(PhotometricInterpretation photometric) + { + switch (photometric) + { + case PhotometricInterpretation_RGB: + return "RGB"; + + case PhotometricInterpretation_Monochrome1: + return "Monochrome1"; + + case PhotometricInterpretation_Monochrome2: + return "Monochrome2"; + + case PhotometricInterpretation_ARGB: + return "ARGB"; + + case PhotometricInterpretation_CMYK: + return "CMYK"; + + case PhotometricInterpretation_HSV: + return "HSV"; + + case PhotometricInterpretation_Palette: + return "Palette color"; + + case PhotometricInterpretation_YBRFull: + return "YBR full"; + + case PhotometricInterpretation_YBRFull422: + return "YBR full 422"; + + case PhotometricInterpretation_YBRPartial420: + return "YBR partial 420"; + + case PhotometricInterpretation_YBRPartial422: + return "YBR partial 422"; + + case PhotometricInterpretation_YBR_ICT: + return "YBR ICT"; + + case PhotometricInterpretation_YBR_RCT: + return "YBR RCT"; + + case PhotometricInterpretation_Unknown: + return "Unknown"; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + Encoding StringToEncoding(const char* encoding) { std::string s(encoding); diff -r bb1ad2fbf914 -r f5b0207967bc Core/Enumerations.h --- a/Core/Enumerations.h Mon Nov 03 13:40:14 2014 +0100 +++ b/Core/Enumerations.h Mon Nov 03 15:19:02 2014 +0100 @@ -254,6 +254,26 @@ }; + // https://www.dabsoft.ch/dicom/3/C.7.6.3.1.2/ + enum PhotometricInterpretation + { + PhotometricInterpretation_ARGB, // Retired + PhotometricInterpretation_CMYK, // Retired + PhotometricInterpretation_HSV, // Retired + PhotometricInterpretation_Monochrome1, + PhotometricInterpretation_Monochrome2, + PhotometricInterpretation_Palette, + PhotometricInterpretation_RGB, + PhotometricInterpretation_YBRFull, + PhotometricInterpretation_YBRFull422, + PhotometricInterpretation_YBRPartial420, + PhotometricInterpretation_YBRPartial422, + PhotometricInterpretation_YBR_ICT, + PhotometricInterpretation_YBR_RCT, + PhotometricInterpretation_Unknown + }; + + /** * WARNING: Do not change the explicit values in the enumerations * below this point. This would result in incompatible databases @@ -298,6 +318,8 @@ const char* EnumerationToString(Encoding encoding); + const char* EnumerationToString(PhotometricInterpretation photometric); + Encoding StringToEncoding(const char* encoding); ResourceType StringToResourceType(const char* type); diff -r bb1ad2fbf914 -r f5b0207967bc NEWS --- a/NEWS Mon Nov 03 13:40:14 2014 +0100 +++ b/NEWS Mon Nov 03 15:19:02 2014 +0100 @@ -3,6 +3,7 @@ * Download ZIP + DICOMDIR from Orthanc Explorer * Sample plugin framework to serve static resources +* Fix issue 19 (YBR_FULL are decoded incorrectly) * Fix issue 21 (Microsoft Visual Studio precompiled headers) * Fix issue 22 (Error decoding multi-frame instances) * Fix issue 24 (Build fails on OSX when directory has .DS_Store files) diff -r bb1ad2fbf914 -r f5b0207967bc OrthancServer/Internals/DicomImageDecoder.cpp --- a/OrthancServer/Internals/DicomImageDecoder.cpp Mon Nov 03 13:40:14 2014 +0100 +++ b/OrthancServer/Internals/DicomImageDecoder.cpp Mon Nov 03 15:19:02 2014 +0100 @@ -318,7 +318,9 @@ LOG(WARNING) << "Unsupported DICOM image: " << info.GetBitsStored() << "bpp, " << info.GetChannelCount() << " channels, " << (info.IsSigned() ? "signed" : "unsigned") - << (info.IsPlanar() ? ", planar" : ", non-planar"); + << (info.IsPlanar() ? ", planar, " : ", non-planar, ") + << EnumerationToString(info.GetPhotometricInterpretation()) + << " photometric interpretation"; throw OrthancException(ErrorCode_NotImplemented); }