# HG changeset patch # User Sebastien Jodogne # Date 1584084699 -3600 # Node ID 875308321fa8a12fde8c3def34f80562f05b647f # Parent e5713a9acebd632c56d0048dc96a9efed77b4ac7# Parent 113a7b994a12f824b1297d7bffee111ae3d258cc merge diff -r e5713a9acebd -r 875308321fa8 CMakeLists.txt --- a/CMakeLists.txt Wed Mar 11 14:35:32 2020 +0100 +++ b/CMakeLists.txt Fri Mar 13 08:31:39 2020 +0100 @@ -25,6 +25,9 @@ set(ENABLE_WEB_SERVER ON) set(ENABLE_ZLIB ON) +# To test transcoding +#set(ENABLE_DCMTK_TRANSCODING ON) + set(HAS_EMBEDDED_RESOURCES ON) diff -r e5713a9acebd -r 875308321fa8 Core/DicomParsing/FromDcmtkBridge.cpp --- a/Core/DicomParsing/FromDcmtkBridge.cpp Wed Mar 11 14:35:32 2020 +0100 +++ b/Core/DicomParsing/FromDcmtkBridge.cpp Fri Mar 13 08:31:39 2020 +0100 @@ -2081,7 +2081,7 @@ // Unregister JPEG codecs DJDecoderRegistration::cleanup(); # if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 - DJDecoderRegistration::cleanup(); + DJEncoderRegistration::cleanup(); # endif #endif } diff -r e5713a9acebd -r 875308321fa8 Core/DicomParsing/FromDcmtkBridge.h --- a/Core/DicomParsing/FromDcmtkBridge.h Wed Mar 11 14:35:32 2020 +0100 +++ b/Core/DicomParsing/FromDcmtkBridge.h Fri Mar 13 08:31:39 2020 +0100 @@ -271,7 +271,10 @@ ITagVisitor& visitor, Encoding defaultEncoding); - static bool GetDcmtkTransferSyntax(E_TransferSyntax& target, - DicomTransferSyntax syntax); + static bool LookupDcmtkTransferSyntax(E_TransferSyntax& target, + DicomTransferSyntax source); + + static bool LookupOrthancTransferSyntax(DicomTransferSyntax& target, + E_TransferSyntax source); }; } diff -r e5713a9acebd -r 875308321fa8 Core/DicomParsing/FromDcmtkBridge_TransferSyntaxes.impl.h --- a/Core/DicomParsing/FromDcmtkBridge_TransferSyntaxes.impl.h Wed Mar 11 14:35:32 2020 +0100 +++ b/Core/DicomParsing/FromDcmtkBridge_TransferSyntaxes.impl.h Fri Mar 13 08:31:39 2020 +0100 @@ -34,10 +34,10 @@ namespace Orthanc { - bool GetDcmtkTransferSyntax(E_TransferSyntax& target, - DicomTransferSyntax syntax) + bool FromDcmtkBridge::LookupDcmtkTransferSyntax(E_TransferSyntax& target, + DicomTransferSyntax source) { - switch (syntax) + switch (source) { case DicomTransferSyntax_LittleEndianImplicit: target = EXS_LittleEndianImplicit; @@ -207,4 +207,179 @@ return false; } } + + + bool FromDcmtkBridge::LookupOrthancTransferSyntax(DicomTransferSyntax& target, + E_TransferSyntax source) + { + switch (source) + { + case EXS_LittleEndianImplicit: + target = DicomTransferSyntax_LittleEndianImplicit; + return true; + + case EXS_LittleEndianExplicit: + target = DicomTransferSyntax_LittleEndianExplicit; + return true; + + case EXS_DeflatedLittleEndianExplicit: + target = DicomTransferSyntax_DeflatedLittleEndianExplicit; + return true; + + case EXS_BigEndianExplicit: + target = DicomTransferSyntax_BigEndianExplicit; + return true; + + case EXS_JPEGProcess1: + target = DicomTransferSyntax_JPEGProcess1; + return true; + + case EXS_JPEGProcess2_4: + target = DicomTransferSyntax_JPEGProcess2_4; + return true; + + case EXS_JPEGProcess3_5: + target = DicomTransferSyntax_JPEGProcess3_5; + return true; + + case EXS_JPEGProcess6_8: + target = DicomTransferSyntax_JPEGProcess6_8; + return true; + + case EXS_JPEGProcess7_9: + target = DicomTransferSyntax_JPEGProcess7_9; + return true; + + case EXS_JPEGProcess10_12: + target = DicomTransferSyntax_JPEGProcess10_12; + return true; + + case EXS_JPEGProcess11_13: + target = DicomTransferSyntax_JPEGProcess11_13; + return true; + + case EXS_JPEGProcess14: + target = DicomTransferSyntax_JPEGProcess14; + return true; + + case EXS_JPEGProcess15: + target = DicomTransferSyntax_JPEGProcess15; + return true; + + case EXS_JPEGProcess16_18: + target = DicomTransferSyntax_JPEGProcess16_18; + return true; + + case EXS_JPEGProcess17_19: + target = DicomTransferSyntax_JPEGProcess17_19; + return true; + + case EXS_JPEGProcess20_22: + target = DicomTransferSyntax_JPEGProcess20_22; + return true; + + case EXS_JPEGProcess21_23: + target = DicomTransferSyntax_JPEGProcess21_23; + return true; + + case EXS_JPEGProcess24_26: + target = DicomTransferSyntax_JPEGProcess24_26; + return true; + + case EXS_JPEGProcess25_27: + target = DicomTransferSyntax_JPEGProcess25_27; + return true; + + case EXS_JPEGProcess28: + target = DicomTransferSyntax_JPEGProcess28; + return true; + + case EXS_JPEGProcess29: + target = DicomTransferSyntax_JPEGProcess29; + return true; + + case EXS_JPEGProcess14SV1: + target = DicomTransferSyntax_JPEGProcess14SV1; + return true; + + case EXS_JPEGLSLossless: + target = DicomTransferSyntax_JPEGLSLossless; + return true; + + case EXS_JPEGLSLossy: + target = DicomTransferSyntax_JPEGLSLossy; + return true; + + case EXS_JPEG2000LosslessOnly: + target = DicomTransferSyntax_JPEG2000LosslessOnly; + return true; + + case EXS_JPEG2000: + target = DicomTransferSyntax_JPEG2000; + return true; + + case EXS_JPEG2000MulticomponentLosslessOnly: + target = DicomTransferSyntax_JPEG2000MulticomponentLosslessOnly; + return true; + + case EXS_JPEG2000Multicomponent: + target = DicomTransferSyntax_JPEG2000Multicomponent; + return true; + + case EXS_JPIPReferenced: + target = DicomTransferSyntax_JPIPReferenced; + return true; + + case EXS_JPIPReferencedDeflate: + target = DicomTransferSyntax_JPIPReferencedDeflate; + return true; + + case EXS_MPEG2MainProfileAtMainLevel: + target = DicomTransferSyntax_MPEG2MainProfileAtMainLevel; + return true; + + case EXS_MPEG2MainProfileAtHighLevel: + target = DicomTransferSyntax_MPEG2MainProfileAtHighLevel; + return true; + + case EXS_MPEG4HighProfileLevel4_1: + target = DicomTransferSyntax_MPEG4HighProfileLevel4_1; + return true; + + case EXS_MPEG4BDcompatibleHighProfileLevel4_1: + target = DicomTransferSyntax_MPEG4BDcompatibleHighProfileLevel4_1; + return true; + + case EXS_MPEG4HighProfileLevel4_2_For2DVideo: + target = DicomTransferSyntax_MPEG4HighProfileLevel4_2_For2DVideo; + return true; + + case EXS_MPEG4HighProfileLevel4_2_For3DVideo: + target = DicomTransferSyntax_MPEG4HighProfileLevel4_2_For3DVideo; + return true; + + case EXS_MPEG4StereoHighProfileLevel4_2: + target = DicomTransferSyntax_MPEG4StereoHighProfileLevel4_2; + return true; + +#if DCMTK_VERSION_NUMBER >= 362 + case EXS_HEVCMainProfileLevel5_1: + target = DicomTransferSyntax_HEVCMainProfileLevel5_1; + return true; +#endif + +#if DCMTK_VERSION_NUMBER >= 362 + case EXS_HEVCMain10ProfileLevel5_1: + target = DicomTransferSyntax_HEVCMain10ProfileLevel5_1; + return true; +#endif + + case EXS_RLELossless: + target = DicomTransferSyntax_RLELossless; + return true; + + default: + return false; + } + } } diff -r e5713a9acebd -r 875308321fa8 Core/DicomParsing/Internals/DicomFrameIndex.cpp --- a/Core/DicomParsing/Internals/DicomFrameIndex.cpp Wed Mar 11 14:35:32 2020 +0100 +++ b/Core/DicomParsing/Internals/DicomFrameIndex.cpp Fri Mar 13 08:31:39 2020 +0100 @@ -68,7 +68,10 @@ uint32_t length = item->getLength(); if (length == 0) { - table.clear(); + // Degenerate case: Empty offset table means only one frame + // that overlaps all the fragments + table.resize(1); + table[0] = 0; return; } @@ -146,7 +149,6 @@ throw OrthancException(ErrorCode_BadFileFormat); } - // Loop over the fragments (ignoring the offset table). This is // an alternative, faster implementation to DCMTK's // "DcmCodec::determineStartFragment()". @@ -318,46 +320,10 @@ }; - - bool DicomFrameIndex::IsVideo(DcmFileFormat& dicom) + unsigned int DicomFrameIndex::GetFramesCount(DcmDataset& dicom) { - // Retrieve the transfer syntax from the DICOM header - const char* value = NULL; - if (!dicom.getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, value).good() || - value == NULL) - { - return false; - } - - const std::string transferSyntax(value); - - // Video standards supported in DICOM 2016a - // http://dicom.nema.org/medical/dicom/2016a/output/html/part05.html - if (transferSyntax == "1.2.840.10008.1.2.4.100" || // MPEG2 MP@ML option of ISO/IEC MPEG2 - transferSyntax == "1.2.840.10008.1.2.4.101" || // MPEG2 MP@HL option of ISO/IEC MPEG2 - transferSyntax == "1.2.840.10008.1.2.4.102" || // MPEG-4 AVC/H.264 High Profile / Level 4.1 of ITU-T H.264 - transferSyntax == "1.2.840.10008.1.2.4.103" || // MPEG-4 AVC/H.264 BD-compat High Profile / Level 4.1 of ITU-T H.264 - transferSyntax == "1.2.840.10008.1.2.4.104" || // MPEG-4 AVC/H.264 High Profile / Level 4.2 of ITU-T H.264 - transferSyntax == "1.2.840.10008.1.2.4.105" || // MPEG-4 AVC/H.264 High Profile / Level 4.2 of ITU-T H.264 - transferSyntax == "1.2.840.10008.1.2.4.106") // MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2 of the ITU-T H.264 - { - return true; - } - - return false; - } - - - unsigned int DicomFrameIndex::GetFramesCount(DcmFileFormat& dicom) - { - // Assume 1 frame for video transfer syntaxes - if (IsVideo(dicom)) - { - return 1; - } - const char* tmp = NULL; - if (!dicom.getDataset()->findAndGetString(DCM_NumberOfFrames, tmp).good() || + if (!dicom.findAndGetString(DCM_NumberOfFrames, tmp).good() || tmp == NULL) { return 1; @@ -378,12 +344,12 @@ } else { - return count; + return static_cast(count); } } - DicomFrameIndex::DicomFrameIndex(DcmFileFormat& dicom) + DicomFrameIndex::DicomFrameIndex(DcmDataset& dicom) { countFrames_ = GetFramesCount(dicom); if (countFrames_ == 0) @@ -392,10 +358,8 @@ return; } - DcmDataset& dataset = *dicom.getDataset(); - // Test whether this image is composed of a sequence of fragments - DcmPixelSequence* pixelSequence = FromDcmtkBridge::GetPixelSequence(dataset); + DcmPixelSequence* pixelSequence = FromDcmtkBridge::GetPixelSequence(dicom); if (pixelSequence != NULL) { index_.reset(new FragmentIndex(pixelSequence, countFrames_)); @@ -404,18 +368,18 @@ // Extract information about the image structure DicomMap tags; - FromDcmtkBridge::ExtractDicomSummary(tags, dataset); + FromDcmtkBridge::ExtractDicomSummary(tags, dicom); DicomImageInformation information(tags); // Access to the raw pixel data - if (DicomImageDecoder::IsPsmctRle1(dataset)) + if (DicomImageDecoder::IsPsmctRle1(dicom)) { - index_.reset(new PsmctRle1Index(dataset, countFrames_, information.GetFrameSize())); + index_.reset(new PsmctRle1Index(dicom, countFrames_, information.GetFrameSize())); } else { - index_.reset(new UncompressedIndex(dataset, countFrames_, information.GetFrameSize())); + index_.reset(new UncompressedIndex(dicom, countFrames_, information.GetFrameSize())); } } diff -r e5713a9acebd -r 875308321fa8 Core/DicomParsing/Internals/DicomFrameIndex.h --- a/Core/DicomParsing/Internals/DicomFrameIndex.h Wed Mar 11 14:35:32 2020 +0100 +++ b/Core/DicomParsing/Internals/DicomFrameIndex.h Fri Mar 13 08:31:39 2020 +0100 @@ -67,7 +67,7 @@ unsigned int countFrames_; public: - DicomFrameIndex(DcmFileFormat& dicom); + DicomFrameIndex(DcmDataset& dicom); unsigned int GetFramesCount() const { @@ -77,8 +77,6 @@ void GetRawFrame(std::string& frame, unsigned int index) const; - static bool IsVideo(DcmFileFormat& dicom); - - static unsigned int GetFramesCount(DcmFileFormat& dicom); + static unsigned int GetFramesCount(DcmDataset& dicom); }; } diff -r e5713a9acebd -r 875308321fa8 Core/DicomParsing/Internals/DicomImageDecoder.cpp --- a/Core/DicomParsing/Internals/DicomImageDecoder.cpp Wed Mar 11 14:35:32 2020 +0100 +++ b/Core/DicomParsing/Internals/DicomImageDecoder.cpp Fri Mar 13 08:31:39 2020 +0100 @@ -34,6 +34,8 @@ #include "../../PrecompiledHeaders.h" #include "DicomImageDecoder.h" +#include "../ParsedDicomFile.h" + /*========================================================================= @@ -84,7 +86,6 @@ #include "../../DicomFormat/DicomIntegerPixelAccessor.h" #include "../ToDcmtkBridge.h" #include "../FromDcmtkBridge.h" -#include "../ParsedDicomFile.h" #if ORTHANC_ENABLE_PNG == 1 # include "../../Images/PngWriter.h" @@ -98,7 +99,6 @@ #include #include -#include #include #include #include @@ -662,7 +662,20 @@ ImageAccessor* DicomImageDecoder::Decode(ParsedDicomFile& dicom, unsigned int frame) { - DcmDataset& dataset = *dicom.GetDcmtkObject().getDataset(); + if (dicom.GetDcmtkObject().getDataset() == NULL) + { + throw OrthancException(ErrorCode_InternalError); + } + else + { + return Decode(*dicom.GetDcmtkObject().getDataset(), frame); + } + } + + + ImageAccessor* DicomImageDecoder::Decode(DcmDataset& dataset, + unsigned int frame) + { E_TransferSyntax syntax = dataset.getOriginalXfer(); /** diff -r e5713a9acebd -r 875308321fa8 Core/DicomParsing/Internals/DicomImageDecoder.h --- a/Core/DicomParsing/Internals/DicomImageDecoder.h Wed Mar 11 14:35:32 2020 +0100 +++ b/Core/DicomParsing/Internals/DicomImageDecoder.h Fri Mar 13 08:31:39 2020 +0100 @@ -34,7 +34,7 @@ #pragma once #include "../../Compatibility.h" -#include "../ParsedDicomFile.h" +#include "../../Images/ImageAccessor.h" #include @@ -62,6 +62,8 @@ namespace Orthanc { + class ParsedDicomFile; + class DicomImageDecoder : public boost::noncopyable { private: @@ -102,6 +104,9 @@ static ImageAccessor *Decode(ParsedDicomFile& dicom, unsigned int frame); + static ImageAccessor *Decode(DcmDataset& dataset, + unsigned int frame); + static void ExtractPamImage(std::string& result, std::unique_ptr& image, ImageExtractionMode mode, diff -r e5713a9acebd -r 875308321fa8 Core/DicomParsing/ParsedDicomFile.cpp --- a/Core/DicomParsing/ParsedDicomFile.cpp Wed Mar 11 14:35:32 2020 +0100 +++ b/Core/DicomParsing/ParsedDicomFile.cpp Fri Mar 13 08:31:39 2020 +0100 @@ -1557,7 +1557,9 @@ { if (pimpl_->frameIndex_.get() == NULL) { - pimpl_->frameIndex_.reset(new DicomFrameIndex(*pimpl_->file_)); + assert(pimpl_->file_ != NULL && + pimpl_->file_->getDataset() != NULL); + pimpl_->frameIndex_.reset(new DicomFrameIndex(*pimpl_->file_->getDataset())); } pimpl_->frameIndex_->GetRawFrame(target, frameId); @@ -1589,7 +1591,9 @@ unsigned int ParsedDicomFile::GetFramesCount() const { - return DicomFrameIndex::GetFramesCount(*pimpl_->file_); + assert(pimpl_->file_ != NULL && + pimpl_->file_->getDataset() != NULL); + return DicomFrameIndex::GetFramesCount(*pimpl_->file_->getDataset()); } diff -r e5713a9acebd -r 875308321fa8 Resources/GenerateTransferSyntaxesDcmtk.mustache --- a/Resources/GenerateTransferSyntaxesDcmtk.mustache Wed Mar 11 14:35:32 2020 +0100 +++ b/Resources/GenerateTransferSyntaxesDcmtk.mustache Fri Mar 13 08:31:39 2020 +0100 @@ -34,10 +34,10 @@ namespace Orthanc { - bool GetDcmtkTransferSyntax(E_TransferSyntax& target, - DicomTransferSyntax syntax) + bool FromDcmtkBridge::LookupDcmtkTransferSyntax(E_TransferSyntax& target, + DicomTransferSyntax source) { - switch (syntax) + switch (source) { {{#Syntaxes}} {{#DCMTK}} @@ -57,4 +57,29 @@ return false; } } + + + bool FromDcmtkBridge::LookupOrthancTransferSyntax(DicomTransferSyntax& target, + E_TransferSyntax source) + { + switch (source) + { + {{#Syntaxes}} + {{#DCMTK}} + {{#SinceDCMTK}} +#if DCMTK_VERSION_NUMBER >= {{SinceDCMTK}} + {{/SinceDCMTK}} + case {{DCMTK}}: + target = DicomTransferSyntax_{{Value}}; + return true; + {{#SinceDCMTK}} +#endif + {{/SinceDCMTK}} + + {{/DCMTK}} + {{/Syntaxes}} + default: + return false; + } + } } diff -r e5713a9acebd -r 875308321fa8 UnitTestsSources/FromDcmtkTests.cpp --- a/UnitTestsSources/FromDcmtkTests.cpp Wed Mar 11 14:35:32 2020 +0100 +++ b/UnitTestsSources/FromDcmtkTests.cpp Fri Mar 13 08:31:39 2020 +0100 @@ -1917,7 +1917,186 @@ #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 +#include "../Core/DicomParsing/Internals/DicomFrameIndex.h" + #include +#include +#include + + +namespace Orthanc +{ + class IDicomTranscoder : public boost::noncopyable + { + public: + virtual ~IDicomTranscoder() + { + } + + virtual DicomTransferSyntax GetTransferSyntax() = 0; + + virtual std::string GetSopClassUid() = 0; + + virtual std::string GetSopInstanceUid() = 0; + + virtual unsigned int GetFramesCount() = 0; + + virtual ImageAccessor* DecodeFrame(unsigned int frame) = 0; + + virtual void GetCompressedFrame(std::string& target, + unsigned int frame) = 0; + + virtual IDicomTranscoder* Transcode(std::set syntaxes, + bool allowNewSopInstanceUid) = 0; + }; + + + class DcmtkTranscoder : public IDicomTranscoder + { + private: + std::unique_ptr dicom_; + std::unique_ptr index_; + DicomTransferSyntax transferSyntax_; + std::string sopClassUid_; + std::string sopInstanceUid_; + + void Setup(DcmFileFormat* dicom) + { + dicom_.reset(dicom); + + if (dicom == NULL || + dicom_->getDataset() == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + + DcmDataset& dataset = *dicom_->getDataset(); + index_.reset(new DicomFrameIndex(dataset)); + + E_TransferSyntax xfer = dataset.getOriginalXfer(); + if (xfer == EXS_Unknown) + { + dataset.updateOriginalXfer(); + xfer = dataset.getOriginalXfer(); + if (xfer == EXS_Unknown) + { + throw OrthancException(ErrorCode_BadFileFormat, + "Cannot determine the transfer syntax of the DICOM instance"); + } + } + + if (!FromDcmtkBridge::LookupOrthancTransferSyntax(transferSyntax_, xfer)) + { + throw OrthancException( + ErrorCode_BadFileFormat, + "Unsupported transfer syntax: " + boost::lexical_cast(xfer)); + } + + const char* a = NULL; + const char* b = NULL; + + if (!dataset.findAndGetString(DCM_SOPClassUID, a).good() || + !dataset.findAndGetString(DCM_SOPInstanceUID, b).good() || + a == NULL || + b == NULL) + { + throw OrthancException(ErrorCode_BadFileFormat, + "Missing SOP class/instance UID in DICOM instance"); + } + + sopClassUid_.assign(a); + sopInstanceUid_.assign(b); + } + + public: + DcmtkTranscoder(DcmFileFormat* dicom) // Takes ownership + { + Setup(dicom); + } + + DcmtkTranscoder(const void* dicom, + size_t size) + { + Setup(FromDcmtkBridge::LoadFromMemoryBuffer(dicom, size)); + } + + virtual DicomTransferSyntax GetTransferSyntax() ORTHANC_OVERRIDE + { + return transferSyntax_; + } + + virtual std::string GetSopClassUid() ORTHANC_OVERRIDE + { + return sopClassUid_; + } + + virtual std::string GetSopInstanceUid() ORTHANC_OVERRIDE + { + return sopInstanceUid_; + } + + virtual unsigned int GetFramesCount() ORTHANC_OVERRIDE + { + return index_->GetFramesCount(); + } + + virtual ImageAccessor* DecodeFrame(unsigned int frame) ORTHANC_OVERRIDE + { + assert(dicom_->getDataset() != NULL); + return DicomImageDecoder::Decode(*dicom_->getDataset(), frame); + } + + virtual void GetCompressedFrame(std::string& target, + unsigned int frame) ORTHANC_OVERRIDE + { +#if 1 + index_->GetRawFrame(target, frame); + printf("%d: %d\n", frame, target.size()); +#endif + +#if 1 + assert(dicom_->getDataset() != NULL); + DcmDataset& dataset = *dicom_->getDataset(); + + DcmPixelSequence* pixelSequence = FromDcmtkBridge::GetPixelSequence(dataset); + + if (pixelSequence != NULL && + frame == 0 && + pixelSequence->card() != GetFramesCount() + 1) + { + printf("COMPRESSED\n"); + + // Check out "djcodecd.cc" + + printf("%d fragments\n", pixelSequence->card()); + + // Skip the first fragment, that is the offset table + for (unsigned long i = 1; ;i++) + { + DcmPixelItem *fragment = NULL; + if (pixelSequence->getItem(fragment, i).good()) + { + printf("fragment %d %d\n", i, fragment->getLength()); + } + else + { + break; + } + } + } +#endif + } + + virtual IDicomTranscoder* Transcode(std::set syntaxes, + bool allowNewSopInstanceUid) ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_NotImplemented); + } + }; +} + + + static bool Transcode(std::string& buffer, DcmDataset& dataSet, @@ -1991,44 +2170,97 @@ #include "dcmtk/dcmjpeg/djrploss.h" /* for DJ_RPLossy */ #include "dcmtk/dcmjpeg/djrplol.h" /* for DJ_RPLossless */ +#include + + +static void TestFile(const std::string& path) +{ + printf("** %s\n", path.c_str()); + + std::string s; + SystemToolbox::ReadFile(s, path); + + Orthanc::DcmtkTranscoder transcoder(s.c_str(), s.size()); + + printf("[%s] [%s] [%s] %d\n", GetTransferSyntaxUid(transcoder.GetTransferSyntax()), + transcoder.GetSopClassUid().c_str(), transcoder.GetSopInstanceUid().c_str(), + transcoder.GetFramesCount()); + + for (size_t i = 0; i < transcoder.GetFramesCount(); i++) + { + std::string f; + transcoder.GetCompressedFrame(f, i); + + if (i == 0) + { + static unsigned int i = 0; + char buf[1024]; + sprintf(buf, "/tmp/frame-%06d.dcm", i++); + printf(">> %s\n", buf); + Orthanc::SystemToolbox::WriteFile(f, buf); + } + } + + printf("\n"); +} + TEST(Toto, Transcode) { - OFLog::configure(OFLogger::DEBUG_LOG_LEVEL); - std::string s; - //SystemToolbox::ReadFile(s, "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/1.2.840.10008.1.2.4.50.dcm"); - //SystemToolbox::ReadFile(s, "/home/jodogne/DICOM/Alain.dcm"); - SystemToolbox::ReadFile(s, "/home/jodogne/Subversion/orthanc-tests/Database/Brainix/Epi/IM-0001-0002.dcm"); + if (0) + { + OFLog::configure(OFLogger::DEBUG_LOG_LEVEL); - std::auto_ptr dicom(FromDcmtkBridge::LoadFromMemoryBuffer(s.c_str(), s.size())); + std::string s; + //SystemToolbox::ReadFile(s, "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/1.2.840.10008.1.2.4.50.dcm"); + //SystemToolbox::ReadFile(s, "/home/jodogne/DICOM/Alain.dcm"); + SystemToolbox::ReadFile(s, "/home/jodogne/Subversion/orthanc-tests/Database/Brainix/Epi/IM-0001-0002.dcm"); - // less /home/jodogne/Downloads/dcmtk-3.6.4/dcmdata/include/dcmtk/dcmdata/dcxfer.h - printf(">> %d\n", dicom->getDataset()->getOriginalXfer()); // => 4 == EXS_JPEGProcess1 + std::auto_ptr dicom(FromDcmtkBridge::LoadFromMemoryBuffer(s.c_str(), s.size())); - const DcmRepresentationParameter *p; + // less /home/jodogne/Downloads/dcmtk-3.6.4/dcmdata/include/dcmtk/dcmdata/dcxfer.h + printf(">> %d\n", dicom->getDataset()->getOriginalXfer()); // => 4 == EXS_JPEGProcess1 + + const DcmRepresentationParameter *p; #if 0 - E_TransferSyntax target = EXS_LittleEndianExplicit; - p = NULL; + E_TransferSyntax target = EXS_LittleEndianExplicit; + p = NULL; #elif 1 - E_TransferSyntax target = EXS_JPEGProcess14SV1; - DJ_RPLossless rp_lossless(6, 0); - p = &rp_lossless; + E_TransferSyntax target = EXS_JPEGProcess14SV1; + DJ_RPLossless rp_lossless(6, 0); + p = &rp_lossless; #else - E_TransferSyntax target = EXS_JPEGProcess1; - DJ_RPLossy rp_lossy(90); // quality - p = &rp_lossy; + E_TransferSyntax target = EXS_JPEGProcess1; + DJ_RPLossy rp_lossy(90); // quality + p = &rp_lossy; #endif - //E_TransferSyntax target = EXS_LittleEndianImplicit; - - ASSERT_TRUE(dicom->getDataset()->chooseRepresentation(target, p).good()); - ASSERT_TRUE(dicom->getDataset()->canWriteXfer(target)); + ASSERT_TRUE(dicom->getDataset()->chooseRepresentation(target, p).good()); + ASSERT_TRUE(dicom->getDataset()->canWriteXfer(target)); + + std::string t; + ASSERT_TRUE(Transcode(t, *dicom->getDataset(), target)); + + SystemToolbox::WriteFile(s, "source.dcm"); + SystemToolbox::WriteFile(t, "target.dcm"); + } - std::string t; - ASSERT_TRUE(Transcode(t, *dicom->getDataset(), target)); + if (1) + { + const char* const PATH = "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes"; + + for (boost::filesystem::directory_iterator it(PATH); + it != boost::filesystem::directory_iterator(); ++it) + { + if (boost::filesystem::is_regular_file(it->status())) + { + TestFile(it->path().string()); + } + } - SystemToolbox::WriteFile(s, "source.dcm"); - SystemToolbox::WriteFile(t, "target.dcm"); + TestFile("/home/jodogne/Subversion/orthanc-tests/Database/Multiframe.dcm"); + TestFile("/home/jodogne/Subversion/orthanc-tests/Database/Issue44/Monochrome1-Jpeg.dcm"); + } } #endif