# HG changeset patch # User Sebastien Jodogne # Date 1588680707 -7200 # Node ID 795c9ca5eb91ab68008fcf0beae27720a21aa681 # Parent 9045757384624dccf21a18d7f573a287d5401471 DANGEROUS changeset: replaced "getOriginalXfer()" by "getCurrentXfer()" throughout Orthanc diff -r 904575738462 -r 795c9ca5eb91 Core/DicomParsing/FromDcmtkBridge.cpp --- a/Core/DicomParsing/FromDcmtkBridge.cpp Tue May 05 12:29:33 2020 +0200 +++ b/Core/DicomParsing/FromDcmtkBridge.cpp Tue May 05 14:11:47 2020 +0200 @@ -1290,7 +1290,7 @@ * dataset into memory. We now keep the original transfer syntax * (if available). **/ - E_TransferSyntax xfer = dataSet.getOriginalXfer(); + E_TransferSyntax xfer = dataSet.getCurrentXfer(); if (xfer == EXS_Unknown) { // No information about the original transfer syntax: This is @@ -1310,7 +1310,7 @@ bool FromDcmtkBridge::SaveToMemoryBuffer(std::string& buffer, DcmFileFormat& dicom) { - E_TransferSyntax xfer = dicom.getDataset()->getOriginalXfer(); + E_TransferSyntax xfer = dicom.getDataset()->getCurrentXfer(); if (xfer == EXS_Unknown) { throw OrthancException(ErrorCode_InternalError, @@ -1338,7 +1338,7 @@ throw OrthancException(ErrorCode_InternalError); } else - { + { if (!dicom.getDataset()->chooseRepresentation(xfer, representation).good() || !dicom.getDataset()->canWriteXfer(xfer) || !dicom.validateMetaInfo(xfer, EWM_updateMeta).good()) @@ -1348,6 +1348,20 @@ else { dicom.removeInvalidGroups(); + + DicomTransferSyntax sourceSyntax; + if (LookupOrthancTransferSyntax(sourceSyntax, dicom)) + { + LOG(INFO) << "Transcoded an image from transfer syntax " + << GetTransferSyntaxUid(sourceSyntax) << " to " + << GetTransferSyntaxUid(syntax); + } + else + { + LOG(INFO) << "Transcoded an image from unknown transfer syntax to " + << GetTransferSyntaxUid(syntax); + } + return true; } } @@ -1808,7 +1822,7 @@ DcmPixelData& pixelData = dynamic_cast(*element); DcmPixelSequence* pixelSequence = NULL; if (!pixelData.getEncapsulatedRepresentation - (dataset.getOriginalXfer(), NULL, pixelSequence).good()) + (dataset.getCurrentXfer(), NULL, pixelSequence).good()) { return NULL; } @@ -2670,7 +2684,7 @@ DcmDataset& dataset = *dicom.getDataset(); - E_TransferSyntax xfer = dataset.getOriginalXfer(); + E_TransferSyntax xfer = dataset.getCurrentXfer(); if (xfer == EXS_Unknown) { dataset.updateOriginalXfer(); diff -r 904575738462 -r 795c9ca5eb91 Core/DicomParsing/Internals/DicomImageDecoder.cpp --- a/Core/DicomParsing/Internals/DicomImageDecoder.cpp Tue May 05 12:29:33 2020 +0200 +++ b/Core/DicomParsing/Internals/DicomImageDecoder.cpp Tue May 05 14:11:47 2020 +0200 @@ -676,7 +676,7 @@ ImageAccessor* DicomImageDecoder::Decode(DcmDataset& dataset, unsigned int frame) { - E_TransferSyntax syntax = dataset.getOriginalXfer(); + E_TransferSyntax syntax = dataset.getCurrentXfer(); /** * Deal with uncompressed, raw images. diff -r 904575738462 -r 795c9ca5eb91 Core/DicomParsing/ParsedDicomFile.cpp --- a/Core/DicomParsing/ParsedDicomFile.cpp Tue May 05 12:29:33 2020 +0200 +++ b/Core/DicomParsing/ParsedDicomFile.cpp Tue May 05 14:11:47 2020 +0200 @@ -456,7 +456,7 @@ const UriComponents& uri) { DcmItem* dicom = pimpl_->file_->getDataset(); - E_TransferSyntax transferSyntax = pimpl_->file_->getDataset()->getOriginalXfer(); + E_TransferSyntax transferSyntax = pimpl_->file_->getDataset()->getCurrentXfer(); // Special case: Accessing the pixel data if (uri.size() == 1 || @@ -1564,7 +1564,7 @@ pimpl_->frameIndex_->GetRawFrame(target, frameId); - E_TransferSyntax transferSyntax = pimpl_->file_->getDataset()->getOriginalXfer(); + E_TransferSyntax transferSyntax = pimpl_->file_->getDataset()->getCurrentXfer(); switch (transferSyntax) { case EXS_JPEGProcess1: @@ -1625,7 +1625,7 @@ bool ParsedDicomFile::LookupTransferSyntax(std::string& result) { - // TODO - Shouldn't "dataset.getOriginalXfer()" be used instead of + // TODO - Shouldn't "dataset.getCurrentXfer()" be used instead of // using the meta header? const char* value = NULL; diff -r 904575738462 -r 795c9ca5eb91 UnitTestsSources/FromDcmtkTests.cpp --- a/UnitTestsSources/FromDcmtkTests.cpp Tue May 05 12:29:33 2020 +0200 +++ b/UnitTestsSources/FromDcmtkTests.cpp Tue May 05 14:11:47 2020 +0200 @@ -2091,11 +2091,11 @@ DcmDataset& dataset = *dicom.getDataset(); - E_TransferSyntax xfer = dataset.getOriginalXfer(); + E_TransferSyntax xfer = dataset.getCurrentXfer(); if (xfer == EXS_Unknown) { dataset.updateOriginalXfer(); - xfer = dataset.getOriginalXfer(); + xfer = dataset.getCurrentXfer(); if (xfer == EXS_Unknown) { throw OrthancException(ErrorCode_BadFileFormat, @@ -2327,11 +2327,11 @@ DcmDataset& dataset = *dicom_->getDataset(); index_.reset(new DicomFrameIndex(dataset)); - E_TransferSyntax xfer = dataset.getOriginalXfer(); + E_TransferSyntax xfer = dataset.getCurrentXfer(); if (xfer == EXS_Unknown) { dataset.updateOriginalXfer(); - xfer = dataset.getOriginalXfer(); + xfer = dataset.getCurrentXfer(); if (xfer == EXS_Unknown) { throw OrthancException(ErrorCode_BadFileFormat, @@ -2869,13 +2869,22 @@ { } + /** + * Transcoding flavor that creates a new parsed DICOM file. A + * "std::set<>" is used to give the possible plugin the + * possibility to do a single parsing for all the possible + * transfer syntaxes. + **/ virtual DcmFileFormat* Transcode(const void* buffer, size_t size, const std::set& allowedSyntaxes, bool allowNewSopInstanceUid) = 0; - // In-place transcoding. This method can return "false" if not supported, - // in which case the "Transcode()" method should be used. + /** + * In-place transcoding. This method is used first during + * C-STORE. It can return "false" if inplace is not supported, in + * which case the "Transcode()" method should be used. + **/ virtual bool InplaceTranscode(DcmFileFormat& dicom, const std::set& allowedSyntaxes, bool allowNewSopInstanceUid) = 0; @@ -2943,7 +2952,9 @@ transcoded.reset(transcoder.Transcode(buffer, size, uncompressedSyntaxes, false)); } - // The "dicom" variable must not be used below this point + // WARNING: The "dicom" variable must not be used below this + // point. The "sopInstanceUid" might also have changed (if + // using lossy compression). if (transcoded == NULL || transcoded->getDataset() == NULL) @@ -2971,6 +2982,17 @@ } } } + + static void Store(std::string& sopClassUid /* out */, + std::string& sopInstanceUid /* out */, + DicomStoreUserConnection& connection, + IDicomTranscoder& transcoder, + const void* buffer, + size_t size) + { + Store(sopClassUid, sopInstanceUid, connection, transcoder, + buffer, size, "", 0 /* Not a C-MOVE */); + } }; @@ -3048,73 +3070,107 @@ throw OrthancException(ErrorCode_InternalError); } + DicomTransferSyntax syntax; + if (!FromDcmtkBridge::LookupOrthancTransferSyntax(syntax, dicom)) + { + throw OrthancException(ErrorCode_BadFileFormat, + "Cannot determine the transfer syntax"); + } + const uint16_t bitsStored = GetBitsStored(*dicom.getDataset()); -#if 0 - - if (syntax == DetectTransferSyntax(*dicom)) + if (allowedSyntaxes.find(syntax) != allowedSyntaxes.end()) { // No transcoding is needed - return new Image(dicom.release(), syntax); + return true; } - if (syntax == DicomTransferSyntax_LittleEndianImplicit && - FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_LittleEndianImplicit, NULL)) + if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianImplicit) != allowedSyntaxes.end() && + FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianImplicit, NULL)) { - return new Image(dicom.release(), syntax); + return true; } - if (syntax == DicomTransferSyntax_LittleEndianExplicit && - FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_LittleEndianExplicit, NULL)) + if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianExplicit) != allowedSyntaxes.end() && + FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianExplicit, NULL)) { - return new Image(dicom.release(), syntax); + return true; } - if (syntax == DicomTransferSyntax_BigEndianExplicit && - FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_BigEndianExplicit, NULL)) + if (allowedSyntaxes.find(DicomTransferSyntax_BigEndianExplicit) != allowedSyntaxes.end() && + FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_BigEndianExplicit, NULL)) { - return new Image(dicom.release(), syntax); + return true; } - if (syntax == DicomTransferSyntax_DeflatedLittleEndianExplicit && - FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_DeflatedLittleEndianExplicit, NULL)) + if (allowedSyntaxes.find(DicomTransferSyntax_DeflatedLittleEndianExplicit) != allowedSyntaxes.end() && + FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_DeflatedLittleEndianExplicit, NULL)) { - return new Image(dicom.release(), syntax); + return true; } #if ORTHANC_ENABLE_JPEG == 1 - if (syntax == DicomTransferSyntax_JPEGProcess1 && + if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess1) != allowedSyntaxes.end() && allowNewSopInstanceUid && bitsStored == 8) { DJ_RPLossy rpLossy(lossyQuality_); - if (FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_JPEGProcess1, &rpLossy)) + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess1, &rpLossy)) { - return new Image(dicom.release(), syntax); + return true; } } #endif #if ORTHANC_ENABLE_JPEG == 1 - if (syntax == DicomTransferSyntax_JPEGProcess2_4 && + if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess2_4) != allowedSyntaxes.end() && allowNewSopInstanceUid && bitsStored <= 12) { DJ_RPLossy rpLossy(lossyQuality_); - if (FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_JPEGProcess2_4, &rpLossy)) + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess2_4, &rpLossy)) { - return new Image(dicom.release(), syntax); + return true; } } #endif -#endif - return false; } }; } +TEST(Toto, DISABLED_Transcode3) +{ + DicomAssociationParameters p; + p.SetRemotePort(2000); + + DcmtkTranscoder transcoder; + + for (int i = 0; i <= DicomTransferSyntax_XML; i++) + { + DicomTransferSyntax a = (DicomTransferSyntax) i; + + std::string path = ("/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/" + + std::string(GetTransferSyntaxUid(a)) + ".dcm"); + if (Orthanc::SystemToolbox::IsRegularFile(path)) + { + printf("\n======= %s\n", GetTransferSyntaxUid(a)); + + std::string source; + Orthanc::SystemToolbox::ReadFile(source, path); + + DicomStoreUserConnection scu(p); + scu.SetCommonClassesProposed(false); + scu.SetRetiredBigEndianProposed(true); + + std::string c, i; + IDicomTranscoder::Store(c, i, scu, transcoder, source.c_str(), source.size()); + } + } +} + + #endif