Mercurial > hg > orthanc
changeset 5363:3c8286e5d07b multiple-jpeg-decoders
wip: try to add a jpeg decoder without colorspace conversion: not working now
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -552,7 +552,7 @@ targetSyntaxes.insert(preferredTransferSyntax); attemptedSyntaxes.insert(preferredTransferSyntax); - success = transcoder.Transcode(transcoded, source, targetSyntaxes, true); + success = transcoder.Transcode(transcoded, source, targetSyntaxes, true, true); isDestructiveCompressionAllowed = true; } @@ -583,7 +583,7 @@ if (!targetSyntaxes.empty()) { - success = transcoder.Transcode(transcoded, source, targetSyntaxes, false); + success = transcoder.Transcode(transcoded, source, targetSyntaxes, false, true); isDestructiveCompressionAllowed = false; } }
--- a/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -87,7 +87,8 @@ bool DcmtkTranscoder::InplaceTranscode(DicomTransferSyntax& selectedSyntax /* out */, DcmFileFormat& dicom, const std::set<DicomTransferSyntax>& allowedSyntaxes, - bool allowNewSopInstanceUid) + bool allowNewSopInstanceUid, + bool enableColorMapConversion) { if (dicom.getDataset() == NULL) { @@ -111,28 +112,28 @@ } if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianImplicit) != allowedSyntaxes.end() && - FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianImplicit, NULL)) + FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianImplicit, NULL, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_LittleEndianImplicit; return true; } if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianExplicit) != allowedSyntaxes.end() && - FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianExplicit, NULL)) + FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianExplicit, NULL, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_LittleEndianExplicit; return true; } if (allowedSyntaxes.find(DicomTransferSyntax_BigEndianExplicit) != allowedSyntaxes.end() && - FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_BigEndianExplicit, NULL)) + FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_BigEndianExplicit, NULL, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_BigEndianExplicit; return true; } if (allowedSyntaxes.find(DicomTransferSyntax_DeflatedLittleEndianExplicit) != allowedSyntaxes.end() && - FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_DeflatedLittleEndianExplicit, NULL)) + FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_DeflatedLittleEndianExplicit, NULL, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_DeflatedLittleEndianExplicit; return true; @@ -146,7 +147,7 @@ // Check out "dcmjpeg/apps/dcmcjpeg.cc" DJ_RPLossy parameters(lossyQuality_); - if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess1, ¶meters)) + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess1, ¶meters, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_JPEGProcess1; return true; @@ -161,7 +162,7 @@ { // Check out "dcmjpeg/apps/dcmcjpeg.cc" DJ_RPLossy parameters(lossyQuality_); - if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess2_4, ¶meters)) + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess2_4, ¶meters, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_JPEGProcess2_4; return true; @@ -175,7 +176,7 @@ // Check out "dcmjpeg/apps/dcmcjpeg.cc" DJ_RPLossless parameters(6 /* opt_selection_value */, 0 /* opt_point_transform */); - if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess14, ¶meters)) + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess14, ¶meters, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_JPEGProcess14; return true; @@ -189,7 +190,7 @@ // Check out "dcmjpeg/apps/dcmcjpeg.cc" DJ_RPLossless parameters(6 /* opt_selection_value */, 0 /* opt_point_transform */); - if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess14SV1, ¶meters)) + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess14SV1, ¶meters, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_JPEGProcess14SV1; return true; @@ -208,7 +209,7 @@ * WARNING: This call results in a segmentation fault if using * the DCMTK package 3.6.2 from Ubuntu 18.04. **/ - if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGLSLossless, ¶meters)) + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGLSLossless, ¶meters, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_JPEGLSLossless; return true; @@ -228,7 +229,7 @@ * WARNING: This call results in a segmentation fault if using * the DCMTK package 3.6.2 from Ubuntu 18.04. **/ - if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGLSLossy, ¶meters)) + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGLSLossy, ¶meters, enableColorMapConversion)) { selectedSyntax = DicomTransferSyntax_JPEGLSLossy; return true; @@ -274,7 +275,8 @@ bool DcmtkTranscoder::Transcode(DicomImage& target, DicomImage& source /* in, "GetParsed()" possibly modified */, const std::set<DicomTransferSyntax>& allowedSyntaxes, - bool allowNewSopInstanceUid) + bool allowNewSopInstanceUid, + bool enableColorMapConversion) { target.Clear(); @@ -320,7 +322,7 @@ return true; } else if (InplaceTranscode(targetSyntax, source.GetParsed(), - allowedSyntaxes, allowNewSopInstanceUid)) + allowedSyntaxes, allowNewSopInstanceUid, enableColorMapConversion)) { // Sanity check DicomTransferSyntax targetSyntax2;
--- a/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h Tue Jul 11 10:25:58 2023 +0200 @@ -43,7 +43,8 @@ bool InplaceTranscode(DicomTransferSyntax& selectedSyntax /* out */, DcmFileFormat& dicom, const std::set<DicomTransferSyntax>& allowedSyntaxes, - bool allowNewSopInstanceUid); + bool allowNewSopInstanceUid, + bool enableColorMapConversion); public: DcmtkTranscoder(); @@ -57,6 +58,7 @@ virtual bool Transcode(DicomImage& target, DicomImage& source /* in, "GetParsed()" possibly modified */, const std::set<DicomTransferSyntax>& allowedSyntaxes, - bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; + bool allowNewSopInstanceUid, + bool enableColorMapConversion) ORTHANC_OVERRIDE; }; }
--- a/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -100,9 +100,12 @@ #if ORTHANC_ENABLE_DCMTK_JPEG == 1 # include <dcmtk/dcmjpeg/djdecode.h> +# include <dcmtk/dcmjpeg/djcparam.h> +# include <dcmtk/dcmjpeg/djdecbas.h> # if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 # include <dcmtk/dcmjpeg/djencode.h> # endif + #endif #if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1 @@ -125,6 +128,41 @@ namespace Orthanc { +#if ORTHANC_ENABLE_DCMTK_JPEG == 1 +/** representation parameter for JPEG compression without colorspace conversion. + */ +class DcmJpegNoConversionRepresentationParameter: public DcmRepresentationParameter +{ +public: + + DcmJpegNoConversionRepresentationParameter() + {} + + DcmJpegNoConversionRepresentationParameter(const DcmJpegNoConversionRepresentationParameter& arg) + {} + + virtual ~DcmJpegNoConversionRepresentationParameter() + {} + + virtual DcmRepresentationParameter *clone() const + { + return new DcmJpegNoConversionRepresentationParameter(); + } + + virtual const char *className() const + { + return "DcmJpegNoConversion"; + } + + virtual OFBool operator==(const DcmRepresentationParameter &arg) const + { + return arg.className() == className(); + } + +}; +#endif + + static bool IsBinaryTag(const DcmTag& key) { return (key.isUnknownVR() || @@ -1653,7 +1691,8 @@ bool FromDcmtkBridge::Transcode(DcmFileFormat& dicom, DicomTransferSyntax syntax, - const DcmRepresentationParameter* representation) + const DcmRepresentationParameter* representation, + bool enableColorMapConversion) { E_TransferSyntax xfer; if (!LookupDcmtkTransferSyntax(xfer, syntax)) @@ -1665,6 +1704,27 @@ DicomTransferSyntax sourceSyntax; bool known = LookupOrthancTransferSyntax(sourceSyntax, dicom); + if (enableColorMapConversion && representation == NULL) + { + DcmJpegNoConversionRepresentationParameter param; + return Transcode(dicom, syntax, ¶m, enableColorMapConversion); + } + + // DJCodecParameter* cp = new DJCodecParameter( + // ECC_lossyYCbCr, // ignored, compression only + // EDC_never, + // EUC_default, + // EPC_default, + // OFFalse, + // OFFalse, + // OFFalse); + + // // baseline JPEG + // DJDecoderBaseline* decbas = new DJDecoderBaseline(); + // if (decbas) DcmCodecList::registerCodec(decbas, NULL, cp); + + + if (!dicom.chooseRepresentation(xfer, representation).good() || !dicom.canWriteXfer(xfer) || !dicom.validateMetaInfo(xfer, EWM_updateMeta).good()) @@ -2468,6 +2528,25 @@ #if ORTHANC_ENABLE_DCMTK_JPEG == 1 CLOG(INFO, DICOM) << "Registering JPEG codecs in DCMTK"; DJDecoderRegistration::registerCodecs(); + + // register a "no colorspace conversion" codec (this is a copy of part of DJDecoderRegistration::registerCodecs()) + TODO: this does not work -> ask DCMTK forum + DJCodecParameter* cp = new DJCodecParameter( + ECC_lossyYCbCr, // ignored, compression only + EDC_never, + EUC_default, + EPC_default, + OFFalse, + OFFalse, + OFFalse); + + // // baseline JPEG + DJDecoderBaseline* decbas = new DJDecoderBaseline(); + if (decbas) + { + DcmCodecList::registerCodec(decbas, new DcmJpegNoConversionRepresentationParameter(), cp); + } + # if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 DJEncoderRegistration::registerCodecs(); # endif
--- a/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h Tue Jul 11 10:25:58 2023 +0200 @@ -205,7 +205,8 @@ static bool Transcode(DcmFileFormat& dicom, DicomTransferSyntax syntax, - const DcmRepresentationParameter* representation); + const DcmRepresentationParameter* representation, + bool enableColorMapConversion); static ValueRepresentation Convert(DcmEVR vr);
--- a/OrthancFramework/Sources/DicomParsing/IDicomTranscoder.h Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancFramework/Sources/DicomParsing/IDicomTranscoder.h Tue Jul 11 10:25:58 2023 +0200 @@ -113,7 +113,8 @@ virtual bool Transcode(DicomImage& target, DicomImage& source /* in, "GetParsed()" possibly modified */, const std::set<DicomTransferSyntax>& allowedSyntaxes, - bool allowNewSopInstanceUid) = 0; + bool allowNewSopInstanceUid, + bool enableColorMapConversion) = 0; static std::string GetSopInstanceUid(DcmFileFormat& dicom); };
--- a/OrthancFramework/Sources/DicomParsing/MemoryBufferTranscoder.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancFramework/Sources/DicomParsing/MemoryBufferTranscoder.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -59,7 +59,8 @@ bool MemoryBufferTranscoder::Transcode(DicomImage& target, DicomImage& source, const std::set<DicomTransferSyntax>& allowedSyntaxes, - bool allowNewSopInstanceUid) + bool allowNewSopInstanceUid, + bool /* enableColorMapConversion not supported yet */ ) { target.Clear();
--- a/OrthancFramework/Sources/DicomParsing/MemoryBufferTranscoder.h Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancFramework/Sources/DicomParsing/MemoryBufferTranscoder.h Tue Jul 11 10:25:58 2023 +0200 @@ -41,6 +41,7 @@ virtual bool Transcode(DicomImage& target /* out */, DicomImage& source, const std::set<DicomTransferSyntax>& allowedSyntaxes, - bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; + bool allowNewSopInstanceUid, + bool /* enableColorMapConversion not supported yet */) ORTHANC_OVERRIDE; }; }
--- a/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -3615,7 +3615,7 @@ IDicomTranscoder::DicomImage source, target; source.AcquireParsed(dynamic_cast<DcmFileFormat*>(toto->clone())); - if (!transcoder.Transcode(target, source, s, true)) + if (!transcoder.Transcode(target, source, s, true, true)) { printf("**************** CANNOT: [%s] => [%s]\n", GetTransferSyntaxUid(sourceSyntax), GetTransferSyntaxUid(a));
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -5384,15 +5384,31 @@ const _OrthancPluginCreateDicomInstance& p = *reinterpret_cast<const _OrthancPluginCreateDicomInstance*>(parameters); + if (p.transferSyntax == NULL) + { + throw OrthancException(ErrorCode_ParameterOutOfRange, "Unsupported NULL transfer syntax"); + } + + std::vector<std::string> transferSyntaxArgs; + Toolbox::TokenizeString(transferSyntaxArgs, std::string(p.transferSyntax), ';'); + DicomTransferSyntax transferSyntax; - if (p.transferSyntax == NULL || - !LookupTransferSyntax(transferSyntax, p.transferSyntax)) + if (transferSyntaxArgs.size() == 0 || !LookupTransferSyntax(transferSyntax, transferSyntaxArgs[0])) { throw OrthancException(ErrorCode_ParameterOutOfRange, "Unsupported transfer syntax: " + std::string(p.transferSyntax == NULL ? "(null)" : p.transferSyntax)); } else { + bool enableColorMapConversion = true; + for (size_t i = 1; i < transferSyntaxArgs.size(); ++i) + { + if (transferSyntaxArgs[i] == "disable-color-map-conversion") + { + enableColorMapConversion = false; + } + } + std::set<DicomTransferSyntax> syntaxes; syntaxes.insert(transferSyntax); @@ -5405,7 +5421,7 @@ { PImpl::ServerContextLock lock(*pimpl_); success = lock.GetContext().Transcode( - transcoded, source, syntaxes, true /* allow new sop */); + transcoded, source, syntaxes, true /* allow new sop */, enableColorMapConversion); } if (success)
--- a/OrthancServer/Sources/OrthancGetRequestHandler.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancServer/Sources/OrthancGetRequestHandler.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -313,7 +313,7 @@ std::set<DicomTransferSyntax> ts; ts.insert(selectedSyntax); - if (context_.Transcode(transcoded, source, ts, true)) + if (context_.Transcode(transcoded, source, ts, true, true)) { // Transcoding has succeeded DcmDataset *stDetailTmp = NULL;
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -216,7 +216,7 @@ std::set<DicomTransferSyntax> s; s.insert(targetSyntax); - if (context.Transcode(transcoded, source, s, true)) + if (context.Transcode(transcoded, source, s, true, true)) { call.GetOutput().AnswerBuffer(transcoded.GetBufferData(), transcoded.GetBufferSize(), MimeType_Dicom);
--- a/OrthancServer/Sources/ServerContext.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancServer/Sources/ServerContext.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -863,7 +863,7 @@ source.SetExternalBuffer(dicom->GetBufferData(), dicom->GetBufferSize()); IDicomTranscoder::DicomImage transcoded; - if (Transcode(transcoded, source, syntaxes, true /* allow new SOP instance UID */)) + if (Transcode(transcoded, source, syntaxes, true /* allow new SOP instance UID */, true /* enableColorMapConversion*/)) { std::unique_ptr<ParsedDicomFile> tmp(transcoded.ReleaseAsParsedDicomFile()); @@ -1924,11 +1924,12 @@ bool ServerContext::Transcode(DicomImage& target, DicomImage& source /* in, "GetParsed()" possibly modified */, const std::set<DicomTransferSyntax>& allowedSyntaxes, - bool allowNewSopInstanceUid) + bool allowNewSopInstanceUid, + bool enableColorMapConversion) { if (builtinDecoderTranscoderOrder_ == BuiltinDecoderTranscoderOrder_Before) { - if (dcmtkTranscoder_->Transcode(target, source, allowedSyntaxes, allowNewSopInstanceUid)) + if (dcmtkTranscoder_->Transcode(target, source, allowedSyntaxes, allowNewSopInstanceUid, enableColorMapConversion)) { return true; } @@ -1938,7 +1939,7 @@ if (HasPlugins() && GetPlugins().HasCustomTranscoder()) { - if (GetPlugins().Transcode(target, source, allowedSyntaxes, allowNewSopInstanceUid)) + if (GetPlugins().Transcode(target, source, allowedSyntaxes, allowNewSopInstanceUid, enableColorMapConversion)) { return true; } @@ -1952,7 +1953,7 @@ if (builtinDecoderTranscoderOrder_ == BuiltinDecoderTranscoderOrder_After) { - return dcmtkTranscoder_->Transcode(target, source, allowedSyntaxes, allowNewSopInstanceUid); + return dcmtkTranscoder_->Transcode(target, source, allowedSyntaxes, allowNewSopInstanceUid, enableColorMapConversion); } else {
--- a/OrthancServer/Sources/ServerContext.h Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancServer/Sources/ServerContext.h Tue Jul 11 10:25:58 2023 +0200 @@ -544,7 +544,8 @@ virtual bool Transcode(DicomImage& target, DicomImage& source /* in, "GetParsed()" possibly modified */, const std::set<DicomTransferSyntax>& allowedSyntaxes, - bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; + bool allowNewSopInstanceUid, + bool enableColorMapConversion) ORTHANC_OVERRIDE; bool IsTranscodeDicomProtocol() const {
--- a/OrthancServer/Sources/ServerJobs/ArchiveJob.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancServer/Sources/ServerJobs/ArchiveJob.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -110,7 +110,7 @@ IDicomTranscoder::DicomImage source, transcoded; source.SetExternalBuffer(sourceBuffer); - if (context_.Transcode(transcoded, source, syntaxes, true /* allow new SOP instance UID */)) + if (context_.Transcode(transcoded, source, syntaxes, true /* allow new SOP instance UID */, true /* enableColorMapConversion*/)) { transcodedBuffer.assign(reinterpret_cast<const char*>(transcoded.GetBufferData()), transcoded.GetBufferSize()); return true;
--- a/OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -68,7 +68,7 @@ IDicomTranscoder::DicomImage source, transcoded; source.SetExternalBuffer(dicom); - if (context_.Transcode(transcoded, source, syntaxes, true)) + if (context_.Transcode(transcoded, source, syntaxes, true, true)) { body.assign(reinterpret_cast<const char*>(transcoded.GetBufferData()), transcoded.GetBufferSize());
--- a/OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp Thu Jul 06 21:08:05 2023 +0200 +++ b/OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp Tue Jul 11 10:25:58 2023 +0200 @@ -247,7 +247,7 @@ source.AcquireParsed(*modified); // "modified" is invalid below this point IDicomTranscoder::DicomImage transcoded; - if (GetContext().Transcode(transcoded, source, syntaxes, true)) + if (GetContext().Transcode(transcoded, source, syntaxes, true, true)) { modified.reset(transcoded.ReleaseAsParsedDicomFile());