comparison UnitTestsSources/FromDcmtkTests.cpp @ 3896:210af28c4087 transcoding

merge
author Alain Mazy <alain@mazy.be>
date Thu, 07 May 2020 11:32:15 +0200
parents 8f7ad4989fec
children 6762a97deabc
comparison
equal deleted inserted replaced
3895:37cf1889667a 3896:210af28c4087
1922 1922
1923 1923
1924 1924
1925 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 1925 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1
1926 1926
1927 #include "../Core/DicomParsing/Internals/DicomFrameIndex.h" 1927 #include "../Core/DicomNetworking/DicomStoreUserConnection.h"
1928 1928 #include "../Core/DicomParsing/DcmtkTranscoder.h"
1929 #include <dcmtk/dcmdata/dcostrmb.h> 1929
1930 #include <dcmtk/dcmdata/dcpixel.h> 1930 TEST(Toto, DISABLED_Transcode3)
1931 #include <dcmtk/dcmdata/dcpxitem.h> 1931 {
1932 #include <dcmtk/dcmjpeg/djrploss.h> // for DJ_RPLossy 1932 DicomAssociationParameters p;
1933 #include <dcmtk/dcmjpeg/djrplol.h> // for DJ_RPLossless 1933 p.SetRemotePort(2000);
1934 1934
1935 1935 DicomStoreUserConnection scu(p);
1936 namespace Orthanc 1936 scu.SetCommonClassesProposed(false);
1937 { 1937 scu.SetRetiredBigEndianProposed(true);
1938 class IDicomTranscoder : public boost::noncopyable 1938
1939 { 1939 DcmtkTranscoder transcoder;
1940 public: 1940
1941 virtual ~IDicomTranscoder() 1941 for (int j = 0; j < 2; j++)
1942 { 1942 for (int i = 0; i <= DicomTransferSyntax_XML; i++)
1943 } 1943 {
1944 1944 DicomTransferSyntax a = (DicomTransferSyntax) i;
1945 virtual DcmFileFormat& GetDicom() = 0; 1945
1946 1946 std::string path = ("/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/" +
1947 virtual DicomTransferSyntax GetTransferSyntax() = 0; 1947 std::string(GetTransferSyntaxUid(a)) + ".dcm");
1948 1948 if (Orthanc::SystemToolbox::IsRegularFile(path))
1949 virtual std::string GetSopClassUid() = 0;
1950
1951 virtual std::string GetSopInstanceUid() = 0;
1952
1953 virtual unsigned int GetFramesCount() = 0;
1954
1955 virtual ImageAccessor* DecodeFrame(unsigned int frame) = 0;
1956
1957 virtual void GetCompressedFrame(std::string& target,
1958 unsigned int frame) = 0;
1959
1960 // NB: Transcoding can change the value of "GetSopInstanceUid()"
1961 // and "GetTransferSyntax()" if lossy compression is applied
1962 virtual bool Transcode(std::string& target,
1963 std::set<DicomTransferSyntax> syntaxes,
1964 bool allowNewSopInstanceUid) = 0;
1965
1966 virtual void WriteToMemoryBuffer(std::string& target) = 0;
1967 };
1968
1969
1970 class DcmtkTranscoder : public IDicomTranscoder
1971 {
1972 private:
1973 std::unique_ptr<DcmFileFormat> dicom_;
1974 std::unique_ptr<DicomFrameIndex> index_;
1975 DicomTransferSyntax transferSyntax_;
1976 std::string sopClassUid_;
1977 std::string sopInstanceUid_;
1978 uint16_t bitsStored_;
1979 unsigned int lossyQuality_;
1980
1981 static std::string GetStringTag(DcmDataset& dataset,
1982 const DcmTagKey& tag)
1983 {
1984 const char* value = NULL;
1985
1986 if (!dataset.findAndGetString(tag, value).good() ||
1987 value == NULL)
1988 { 1949 {
1989 throw OrthancException(ErrorCode_BadFileFormat, 1950 printf("\n======= %s\n", GetTransferSyntaxUid(a));
1990 "Missing SOP class/instance UID in DICOM instance"); 1951
1952 std::string source;
1953 Orthanc::SystemToolbox::ReadFile(source, path);
1954
1955 std::string c, i;
1956 try
1957 {
1958 scu.Transcode(c, i, transcoder, source.c_str(), source.size(), false, "", 0);
1959 }
1960 catch (OrthancException& e)
1961 {
1962 if (e.GetErrorCode() == ErrorCode_NotImplemented)
1963 {
1964 LOG(ERROR) << "cannot transcode " << GetTransferSyntaxUid(a);
1965 }
1966 else
1967 {
1968 throw e;
1969 }
1970 }
1971 }
1972 }
1973 }
1974
1975
1976 TEST(Toto, DISABLED_Transcode4)
1977 {
1978 std::string source;
1979 Orthanc::SystemToolbox::ReadFile(source, "/home/jodogne/Subversion/orthanc-tests/Database/KarstenHilbertRF.dcm");
1980
1981 std::unique_ptr<DcmFileFormat> toto(FromDcmtkBridge::LoadFromMemoryBuffer(source.c_str(), source.size()));
1982 DicomTransferSyntax sourceSyntax;
1983 ASSERT_TRUE(FromDcmtkBridge::LookupOrthancTransferSyntax(sourceSyntax, *toto));
1984
1985 DcmtkTranscoder transcoder;
1986
1987 for (int i = 0; i <= DicomTransferSyntax_XML; i++)
1988 {
1989 DicomTransferSyntax a = (DicomTransferSyntax) i;
1990 std::set<DicomTransferSyntax> s;
1991 s.insert(a);
1992
1993 std::string t;
1994
1995 bool hasSopInstanceUidChanged;
1996
1997 if (!transcoder.TranscodeToBuffer(t, hasSopInstanceUidChanged, source.c_str(), source.size(), s, true))
1998 {
1999 printf("**************** CANNOT: [%s] => [%s]\n",
2000 GetTransferSyntaxUid(sourceSyntax), GetTransferSyntaxUid(a));
2001 }
2002 else
2003 {
2004 bool lossy = (a == DicomTransferSyntax_JPEGProcess1 ||
2005 a == DicomTransferSyntax_JPEGProcess2_4 ||
2006 a == DicomTransferSyntax_JPEGLSLossy);
2007
2008 printf("SIZE: %lu\n", t.size());
2009 if (hasSopInstanceUidChanged)
2010 {
2011 ASSERT_TRUE(lossy);
1991 } 2012 }
1992 else 2013 else
1993 { 2014 {
1994 return std::string(value); 2015 ASSERT_FALSE(lossy);
1995 } 2016 }
1996 } 2017 }
1997 2018 }
1998 void Setup(DcmFileFormat* dicom) 2019 }
1999 {
2000 lossyQuality_ = 90;
2001
2002 dicom_.reset(dicom);
2003
2004 if (dicom == NULL ||
2005 dicom_->getDataset() == NULL)
2006 {
2007 throw OrthancException(ErrorCode_NullPointer);
2008 }
2009
2010 DcmDataset& dataset = *dicom_->getDataset();
2011 index_.reset(new DicomFrameIndex(dataset));
2012
2013 E_TransferSyntax xfer = dataset.getOriginalXfer();
2014 if (xfer == EXS_Unknown)
2015 {
2016 dataset.updateOriginalXfer();
2017 xfer = dataset.getOriginalXfer();
2018 if (xfer == EXS_Unknown)
2019 {
2020 throw OrthancException(ErrorCode_BadFileFormat,
2021 "Cannot determine the transfer syntax of the DICOM instance");
2022 }
2023 }
2024
2025 if (!FromDcmtkBridge::LookupOrthancTransferSyntax(transferSyntax_, xfer))
2026 {
2027 throw OrthancException(
2028 ErrorCode_BadFileFormat,
2029 "Unsupported transfer syntax: " + boost::lexical_cast<std::string>(xfer));
2030 }
2031
2032 if (!dataset.findAndGetUint16(DCM_BitsStored, bitsStored_).good())
2033 {
2034 throw OrthancException(ErrorCode_BadFileFormat,
2035 "Missing \"Bits Stored\" tag in DICOM instance");
2036 }
2037
2038 sopClassUid_ = GetStringTag(dataset, DCM_SOPClassUID);
2039 sopInstanceUid_ = GetStringTag(dataset, DCM_SOPInstanceUID);
2040 }
2041
2042 public:
2043 DcmtkTranscoder(DcmFileFormat* dicom) // Takes ownership
2044 {
2045 Setup(dicom);
2046 }
2047
2048 DcmtkTranscoder(const void* dicom,
2049 size_t size)
2050 {
2051 Setup(FromDcmtkBridge::LoadFromMemoryBuffer(dicom, size));
2052 }
2053
2054 void SetLossyQuality(unsigned int quality)
2055 {
2056 if (quality <= 0 ||
2057 quality > 100)
2058 {
2059 throw OrthancException(ErrorCode_ParameterOutOfRange);
2060 }
2061 else
2062 {
2063 lossyQuality_ = quality;
2064 }
2065 }
2066
2067 unsigned int GetLossyQuality() const
2068 {
2069 return lossyQuality_;
2070 }
2071
2072 unsigned int GetBitsStored() const
2073 {
2074 return bitsStored_;
2075 }
2076
2077 virtual DcmFileFormat& GetDicom()
2078 {
2079 assert(dicom_ != NULL);
2080 return *dicom_;
2081 }
2082
2083 virtual DicomTransferSyntax GetTransferSyntax() ORTHANC_OVERRIDE
2084 {
2085 return transferSyntax_;
2086 }
2087
2088 virtual std::string GetSopClassUid() ORTHANC_OVERRIDE
2089 {
2090 return sopClassUid_;
2091 }
2092
2093 virtual std::string GetSopInstanceUid() ORTHANC_OVERRIDE
2094 {
2095 return sopInstanceUid_;
2096 }
2097
2098 virtual unsigned int GetFramesCount() ORTHANC_OVERRIDE
2099 {
2100 return index_->GetFramesCount();
2101 }
2102
2103 virtual void WriteToMemoryBuffer(std::string& target) ORTHANC_OVERRIDE
2104 {
2105 if (!FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom_))
2106 {
2107 throw OrthancException(ErrorCode_InternalError,
2108 "Cannot write the DICOM instance to a memory buffer");
2109 }
2110 }
2111
2112 virtual ImageAccessor* DecodeFrame(unsigned int frame) ORTHANC_OVERRIDE
2113 {
2114 assert(dicom_->getDataset() != NULL);
2115 return DicomImageDecoder::Decode(*dicom_->getDataset(), frame);
2116 }
2117
2118 virtual void GetCompressedFrame(std::string& target,
2119 unsigned int frame) ORTHANC_OVERRIDE
2120 {
2121 index_->GetRawFrame(target, frame);
2122 }
2123
2124 virtual bool Transcode(std::string& target,
2125 std::set<DicomTransferSyntax> syntaxes,
2126 bool allowNewSopInstanceUid) ORTHANC_OVERRIDE
2127 {
2128 assert(dicom_ != NULL &&
2129 dicom_->getDataset() != NULL);
2130
2131 if (syntaxes.find(GetTransferSyntax()) != syntaxes.end())
2132 {
2133 printf("NO TRANSCODING\n");
2134
2135 // No change in the transfer syntax => simply serialize the current dataset
2136 WriteToMemoryBuffer(target);
2137 return true;
2138 }
2139
2140 printf(">> %d\n", bitsStored_);
2141
2142 DJ_RPLossy rpLossy(lossyQuality_);
2143
2144 if (syntaxes.find(DicomTransferSyntax_LittleEndianImplicit) != syntaxes.end() &&
2145 FromDcmtkBridge::Transcode(target, *dicom_, DicomTransferSyntax_LittleEndianImplicit, NULL))
2146 {
2147 transferSyntax_ = DicomTransferSyntax_LittleEndianImplicit;
2148 return true;
2149 }
2150 else if (syntaxes.find(DicomTransferSyntax_LittleEndianExplicit) != syntaxes.end() &&
2151 FromDcmtkBridge::Transcode(target, *dicom_, DicomTransferSyntax_LittleEndianExplicit, NULL))
2152 {
2153 transferSyntax_ = DicomTransferSyntax_LittleEndianExplicit;
2154 return true;
2155 }
2156 else if (syntaxes.find(DicomTransferSyntax_BigEndianExplicit) != syntaxes.end() &&
2157 FromDcmtkBridge::Transcode(target, *dicom_, DicomTransferSyntax_BigEndianExplicit, NULL))
2158 {
2159 transferSyntax_ = DicomTransferSyntax_BigEndianExplicit;
2160 return true;
2161 }
2162 else if (syntaxes.find(DicomTransferSyntax_JPEGProcess1) != syntaxes.end() &&
2163 allowNewSopInstanceUid &&
2164 GetBitsStored() == 8 &&
2165 FromDcmtkBridge::Transcode(target, *dicom_, DicomTransferSyntax_JPEGProcess1, &rpLossy))
2166 {
2167 transferSyntax_ = DicomTransferSyntax_JPEGProcess1;
2168 sopInstanceUid_ = GetStringTag(*dicom_->getDataset(), DCM_SOPInstanceUID);
2169 return true;
2170 }
2171 else if (syntaxes.find(DicomTransferSyntax_JPEGProcess2_4) != syntaxes.end() &&
2172 allowNewSopInstanceUid &&
2173 GetBitsStored() <= 12 &&
2174 FromDcmtkBridge::Transcode(target, *dicom_, DicomTransferSyntax_JPEGProcess2_4, &rpLossy))
2175 {
2176 transferSyntax_ = DicomTransferSyntax_JPEGProcess2_4;
2177 sopInstanceUid_ = GetStringTag(*dicom_->getDataset(), DCM_SOPInstanceUID);
2178 return true;
2179 }
2180 else
2181 {
2182 return false;
2183 }
2184 }
2185 };
2186 }
2187
2188
2189
2190
2191 static bool Transcode(std::string& buffer,
2192 DcmDataset& dataSet,
2193 E_TransferSyntax xfer)
2194 {
2195 // Determine the transfer syntax which shall be used to write the
2196 // information to the file. We always switch to the Little Endian
2197 // syntax, with explicit length.
2198
2199 // http://support.dcmtk.org/docs/dcxfer_8h-source.html
2200
2201
2202 /**
2203 * Note that up to Orthanc 0.7.1 (inclusive), the
2204 * "EXS_LittleEndianExplicit" was always used to save the DICOM
2205 * dataset into memory. We now keep the original transfer syntax
2206 * (if available).
2207 **/
2208 //E_TransferSyntax xfer = dataSet.getOriginalXfer();
2209 if (xfer == EXS_Unknown)
2210 {
2211 // No information about the original transfer syntax: This is
2212 // most probably a DICOM dataset that was read from memory.
2213 xfer = EXS_LittleEndianExplicit;
2214 }
2215
2216 E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength;
2217
2218 // Create the meta-header information
2219 DcmFileFormat ff(&dataSet);
2220 ff.validateMetaInfo(xfer);
2221 ff.removeInvalidGroups();
2222
2223 // Create a memory buffer with the proper size
2224 {
2225 const uint32_t estimatedSize = ff.calcElementLength(xfer, encodingType); // (*)
2226 buffer.resize(estimatedSize);
2227 }
2228
2229 DcmOutputBufferStream ob(&buffer[0], buffer.size());
2230
2231 // Fill the memory buffer with the meta-header and the dataset
2232 ff.transferInit();
2233 OFCondition c = ff.write(ob, xfer, encodingType, NULL,
2234 /*opt_groupLength*/ EGL_recalcGL,
2235 /*opt_paddingType*/ EPD_withoutPadding);
2236 ff.transferEnd();
2237
2238 if (c.good())
2239 {
2240 // The DICOM file is successfully written, truncate the target
2241 // buffer if its size was overestimated by (*)
2242 ob.flush();
2243
2244 size_t effectiveSize = static_cast<size_t>(ob.tell());
2245 if (effectiveSize < buffer.size())
2246 {
2247 buffer.resize(effectiveSize);
2248 }
2249
2250 return true;
2251 }
2252 else
2253 {
2254 // Error
2255 buffer.clear();
2256 return false;
2257 }
2258 }
2259
2260
2261 #include <boost/filesystem.hpp>
2262
2263
2264 static void TestFile(const std::string& path)
2265 {
2266 static unsigned int count = 0;
2267 count++;
2268
2269
2270 printf("** %s\n", path.c_str());
2271
2272 std::string s;
2273 SystemToolbox::ReadFile(s, path);
2274
2275 Orthanc::DcmtkTranscoder transcoder(s.c_str(), s.size());
2276
2277 /*if (transcoder.GetBitsStored() != 8) // TODO
2278 return; */
2279
2280 {
2281 char buf[1024];
2282 sprintf(buf, "/tmp/source-%06d.dcm", count);
2283 printf(">> %s\n", buf);
2284 Orthanc::SystemToolbox::WriteFile(s, buf);
2285 }
2286
2287 printf("[%s] [%s] [%s] %d %d\n", GetTransferSyntaxUid(transcoder.GetTransferSyntax()),
2288 transcoder.GetSopClassUid().c_str(), transcoder.GetSopInstanceUid().c_str(),
2289 transcoder.GetFramesCount(), transcoder.GetTransferSyntax());
2290
2291 for (size_t i = 0; i < transcoder.GetFramesCount(); i++)
2292 {
2293 std::string f;
2294 transcoder.GetCompressedFrame(f, i);
2295
2296 if (i == 0)
2297 {
2298 char buf[1024];
2299 sprintf(buf, "/tmp/frame-%06d.raw", count);
2300 printf(">> %s\n", buf);
2301 Orthanc::SystemToolbox::WriteFile(f, buf);
2302 }
2303 }
2304
2305 {
2306 std::string t;
2307 transcoder.WriteToMemoryBuffer(t);
2308
2309 Orthanc::DcmtkTranscoder transcoder2(t.c_str(), t.size());
2310 printf(">> %d %d ; %lu bytes\n", transcoder.GetTransferSyntax(), transcoder2.GetTransferSyntax(), t.size());
2311 }
2312
2313 {
2314 std::string a = transcoder.GetSopInstanceUid();
2315 DicomTransferSyntax b = transcoder.GetTransferSyntax();
2316
2317 std::set<DicomTransferSyntax> syntaxes;
2318 syntaxes.insert(DicomTransferSyntax_JPEGProcess2_4);
2319 //syntaxes.insert(DicomTransferSyntax_LittleEndianExplicit);
2320
2321 std::string t;
2322 bool ok = transcoder.Transcode(t, syntaxes, true);
2323 printf("Transcoding: %d\n", ok);
2324
2325 if (ok)
2326 {
2327 printf("[%s] => [%s]\n", a.c_str(), transcoder.GetSopInstanceUid().c_str());
2328 printf("[%s] => [%s]\n", GetTransferSyntaxUid(b),
2329 GetTransferSyntaxUid(transcoder.GetTransferSyntax()));
2330
2331 {
2332 char buf[1024];
2333 sprintf(buf, "/tmp/transcoded-%06d.dcm", count);
2334 printf(">> %s\n", buf);
2335 Orthanc::SystemToolbox::WriteFile(t, buf);
2336 }
2337
2338 Orthanc::DcmtkTranscoder transcoder2(t.c_str(), t.size());
2339 printf(" => transcoded transfer syntax %d ; %lu bytes\n", transcoder2.GetTransferSyntax(), t.size());
2340 }
2341 }
2342
2343 printf("\n");
2344 }
2345
2346 TEST(Toto, DISABLED_Transcode)
2347 {
2348 //OFLog::configure(OFLogger::DEBUG_LOG_LEVEL);
2349
2350 if (0)
2351 {
2352 std::string s;
2353 //SystemToolbox::ReadFile(s, "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/1.2.840.10008.1.2.4.50.dcm");
2354 //SystemToolbox::ReadFile(s, "/home/jodogne/DICOM/Alain.dcm");
2355 //SystemToolbox::ReadFile(s, "/home/jodogne/Subversion/orthanc-tests/Database/Brainix/Epi/IM-0001-0002.dcm");
2356 SystemToolbox::ReadFile(s, "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/1.2.840.10008.1.2.1.dcm");
2357
2358 std::unique_ptr<DcmFileFormat> dicom(FromDcmtkBridge::LoadFromMemoryBuffer(s.c_str(), s.size()));
2359
2360 // less /home/jodogne/Downloads/dcmtk-3.6.4/dcmdata/include/dcmtk/dcmdata/dcxfer.h
2361 printf(">> %d\n", dicom->getDataset()->getOriginalXfer()); // => 4 == EXS_JPEGProcess1
2362
2363 const DcmRepresentationParameter *p;
2364
2365 #if 0
2366 E_TransferSyntax target = EXS_LittleEndianExplicit;
2367 p = NULL;
2368 #elif 0
2369 E_TransferSyntax target = EXS_JPEGProcess14SV1;
2370 DJ_RPLossless rp_lossless(6, 0);
2371 p = &rp_lossless;
2372 #else
2373 E_TransferSyntax target = EXS_JPEGProcess1;
2374 DJ_RPLossy rp_lossy(90); // quality
2375 p = &rp_lossy;
2376 #endif
2377
2378 ASSERT_TRUE(dicom->getDataset()->chooseRepresentation(target, p).good());
2379 ASSERT_TRUE(dicom->getDataset()->canWriteXfer(target));
2380
2381 std::string t;
2382 ASSERT_TRUE(Transcode(t, *dicom->getDataset(), target));
2383
2384 SystemToolbox::WriteFile(s, "source.dcm");
2385 SystemToolbox::WriteFile(t, "target.dcm");
2386 }
2387
2388 if (1)
2389 {
2390 const char* const PATH = "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes";
2391
2392 for (boost::filesystem::directory_iterator it(PATH);
2393 it != boost::filesystem::directory_iterator(); ++it)
2394 {
2395 if (boost::filesystem::is_regular_file(it->status()))
2396 {
2397 TestFile(it->path().string());
2398 }
2399 }
2400 }
2401
2402 if (0)
2403 {
2404 TestFile("/home/jodogne/Subversion/orthanc-tests/Database/Multiframe.dcm");
2405 TestFile("/home/jodogne/Subversion/orthanc-tests/Database/Issue44/Monochrome1-Jpeg.dcm");
2406 }
2407
2408 if (0)
2409 {
2410 TestFile("/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/1.2.840.10008.1.2.1.dcm");
2411 }
2412 }
2413
2414
2415
2416 #include "../Core/DicomNetworking/DicomAssociation.h"
2417 #include "../Core/DicomNetworking/DicomControlUserConnection.h"
2418 #include "../Core/DicomNetworking/DicomStoreUserConnection.h"
2419
2420 TEST(Toto, DISABLED_DicomAssociation)
2421 {
2422 DicomAssociationParameters params;
2423 params.SetLocalApplicationEntityTitle("ORTHANC");
2424 params.SetRemoteApplicationEntityTitle("PACS");
2425 params.SetRemotePort(2001);
2426
2427 #if 0
2428 DicomAssociation assoc;
2429 assoc.ProposeGenericPresentationContext(UID_StorageCommitmentPushModelSOPClass);
2430 assoc.ProposeGenericPresentationContext(UID_VerificationSOPClass);
2431 assoc.ProposePresentationContext(UID_ComputedRadiographyImageStorage,
2432 DicomTransferSyntax_JPEGProcess1);
2433 assoc.ProposePresentationContext(UID_ComputedRadiographyImageStorage,
2434 DicomTransferSyntax_JPEGProcess2_4);
2435 assoc.ProposePresentationContext(UID_ComputedRadiographyImageStorage,
2436 DicomTransferSyntax_JPEG2000);
2437
2438 assoc.Open(params);
2439
2440 int presID = ASC_findAcceptedPresentationContextID(&assoc.GetDcmtkAssociation(), UID_ComputedRadiographyImageStorage);
2441 printf(">> %d\n", presID);
2442
2443 std::map<DicomTransferSyntax, uint8_t> pc;
2444 printf(">> %d\n", assoc.LookupAcceptedPresentationContext(pc, UID_ComputedRadiographyImageStorage));
2445
2446 for (std::map<DicomTransferSyntax, uint8_t>::const_iterator
2447 it = pc.begin(); it != pc.end(); ++it)
2448 {
2449 printf("[%s] => %d\n", GetTransferSyntaxUid(it->first), it->second);
2450 }
2451 #else
2452 {
2453 DicomControlUserConnection assoc(params);
2454
2455 try
2456 {
2457 printf(">> %d\n", assoc.Echo());
2458 }
2459 catch (OrthancException&)
2460 {
2461 }
2462 }
2463
2464 params.SetRemoteApplicationEntityTitle("PACS");
2465 params.SetRemotePort(2000);
2466
2467 {
2468 DicomControlUserConnection assoc(params);
2469 printf(">> %d\n", assoc.Echo());
2470 }
2471 2020
2472 #endif 2021 #endif
2473 }
2474
2475 static void TestTranscode(DicomStoreUserConnection& scu,
2476 const std::string& sopClassUid,
2477 DicomTransferSyntax transferSyntax)
2478 {
2479 uint8_t id;
2480
2481 if (scu.NegotiatePresentationContext(id, sopClassUid, transferSyntax))
2482 {
2483 printf("**** OK, without transcoding !! %d\n", id);
2484 }
2485 else
2486 {
2487 // Transcoding - only in Orthanc >= 1.7.0
2488
2489 const DicomTransferSyntax uncompressed[] = {
2490 DicomTransferSyntax_LittleEndianImplicit, // Default transfer syntax
2491 DicomTransferSyntax_LittleEndianExplicit,
2492 DicomTransferSyntax_BigEndianExplicit
2493 };
2494
2495 bool found = false;
2496 for (size_t i = 0; i < 3; i++)
2497 {
2498 if (scu.LookupPresentationContext(id, sopClassUid, uncompressed[i]))
2499 {
2500 printf("**** TRANSCODING to %s => %d\n",
2501 GetTransferSyntaxUid(uncompressed[i]), id);
2502 found = true;
2503 break;
2504 }
2505 }
2506
2507 if (!found)
2508 {
2509 printf("**** KO KO KO\n");
2510 }
2511 }
2512 }
2513
2514
2515 TEST(Toto, DISABLED_Store)
2516 {
2517 DicomAssociationParameters params;
2518 params.SetLocalApplicationEntityTitle("ORTHANC");
2519 params.SetRemoteApplicationEntityTitle("STORESCP");
2520 params.SetRemotePort(2000);
2521
2522 DicomStoreUserConnection assoc(params);
2523 assoc.RegisterStorageClass(UID_MRImageStorage, DicomTransferSyntax_JPEGProcess1);
2524 assoc.RegisterStorageClass(UID_MRImageStorage, DicomTransferSyntax_JPEGProcess2_4);
2525 //assoc.RegisterStorageClass(UID_MRImageStorage, DicomTransferSyntax_LittleEndianExplicit);
2526
2527 //assoc.SetUncompressedSyntaxesProposed(false); // Necessary for transcoding
2528 //assoc.SetCommonClassesProposed(false);
2529 TestTranscode(assoc, UID_MRImageStorage, DicomTransferSyntax_JPEG2000);
2530 TestTranscode(assoc, UID_MRImageStorage, DicomTransferSyntax_LittleEndianExplicit);
2531 }
2532
2533
2534 TEST(Toto, DISABLED_Store2)
2535 {
2536 DicomAssociationParameters params;
2537 params.SetLocalApplicationEntityTitle("ORTHANC");
2538 params.SetRemoteApplicationEntityTitle("STORESCP");
2539 params.SetRemotePort(2000);
2540
2541 DicomStoreUserConnection assoc(params);
2542 //assoc.SetCommonClassesProposed(false);
2543 assoc.SetRetiredBigEndianProposed(true);
2544
2545 std::string s;
2546 Orthanc::SystemToolbox::ReadFile(s, "/tmp/i/" + std::string(GetTransferSyntaxUid(DicomTransferSyntax_BigEndianExplicit)) +".dcm");
2547
2548 std::string c, i;
2549 assoc.Store(c, i, s.c_str(), s.size());
2550 printf("[%s] [%s]\n", c.c_str(), i.c_str());
2551 }
2552
2553 #endif