Mercurial > hg > orthanc
comparison UnitTestsSources/FromDcmtkTests.cpp @ 3886:b808958dff2a transcoding
transcoding to jpeg-ls
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 05 May 2020 16:03:46 +0200 |
parents | e23026566536 |
children | 25c122277f53 |
comparison
equal
deleted
inserted
replaced
3885:e23026566536 | 3886:b808958dff2a |
---|---|
1925 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 | 1925 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 |
1926 | 1926 |
1927 #include "../Core/DicomNetworking/DicomStoreUserConnection.h" | 1927 #include "../Core/DicomNetworking/DicomStoreUserConnection.h" |
1928 | 1928 |
1929 #include <dcmtk/dcmjpeg/djrploss.h> // for DJ_RPLossy | 1929 #include <dcmtk/dcmjpeg/djrploss.h> // for DJ_RPLossy |
1930 #include <dcmtk/dcmjpeg/djrplol.h> // for DJ_RPLossless | 1930 //#include <dcmtk/dcmjpeg/djrplol.h> // for DJ_RPLossless |
1931 #include <dcmtk/dcmjpls/djrparam.h> // for DJLSRepresentationParameter | |
1931 | 1932 |
1932 | 1933 |
1933 #if !defined(ORTHANC_ENABLE_DCMTK_JPEG) | 1934 #if !defined(ORTHANC_ENABLE_DCMTK_JPEG) |
1934 # error Macro ORTHANC_ENABLE_DCMTK_JPEG must be defined | 1935 # error Macro ORTHANC_ENABLE_DCMTK_JPEG must be defined |
1935 #endif | 1936 #endif |
2093 throw OrthancException(ErrorCode_BadFileFormat, | 2094 throw OrthancException(ErrorCode_BadFileFormat, |
2094 "Missing \"Bits Stored\" tag in DICOM instance"); | 2095 "Missing \"Bits Stored\" tag in DICOM instance"); |
2095 } | 2096 } |
2096 } | 2097 } |
2097 | 2098 |
2099 static std::string GetSopInstanceUid(DcmDataset& dataset) | |
2100 { | |
2101 const char* v = NULL; | |
2102 | |
2103 if (dataset.findAndGetString(DCM_SOPInstanceUID, v).good() && | |
2104 v != NULL) | |
2105 { | |
2106 return std::string(v); | |
2107 } | |
2108 else | |
2109 { | |
2110 throw OrthancException(ErrorCode_BadFileFormat, "File without SOP instance UID"); | |
2111 } | |
2112 } | |
2113 | |
2114 static void CheckSopInstanceUid(DcmFileFormat& dicom, | |
2115 const std::string& sopInstanceUid, | |
2116 bool mustEqual) | |
2117 { | |
2118 if (dicom.getDataset() == NULL) | |
2119 { | |
2120 throw OrthancException(ErrorCode_InternalError); | |
2121 } | |
2122 | |
2123 bool ok; | |
2124 | |
2125 if (mustEqual) | |
2126 { | |
2127 ok = (GetSopInstanceUid(*dicom.getDataset()) == sopInstanceUid); | |
2128 } | |
2129 else | |
2130 { | |
2131 ok = (GetSopInstanceUid(*dicom.getDataset()) != sopInstanceUid); | |
2132 } | |
2133 | |
2134 if (!ok) | |
2135 { | |
2136 throw OrthancException(ErrorCode_InternalError, | |
2137 mustEqual ? "The SOP instance UID has changed unexpectedly during transcoding" : | |
2138 "The SOP instance UID has not changed as expected during transcoding"); | |
2139 } | |
2140 } | |
2141 | |
2098 public: | 2142 public: |
2099 DcmtkTranscoder() : | 2143 DcmtkTranscoder() : |
2100 lossyQuality_(90) | 2144 lossyQuality_(90) |
2101 { | 2145 { |
2102 } | 2146 } |
2156 throw OrthancException(ErrorCode_BadFileFormat, | 2200 throw OrthancException(ErrorCode_BadFileFormat, |
2157 "Cannot determine the transfer syntax"); | 2201 "Cannot determine the transfer syntax"); |
2158 } | 2202 } |
2159 | 2203 |
2160 const uint16_t bitsStored = GetBitsStored(*dicom.getDataset()); | 2204 const uint16_t bitsStored = GetBitsStored(*dicom.getDataset()); |
2205 std::string sourceSopInstanceUid = GetSopInstanceUid(*dicom.getDataset()); | |
2161 | 2206 |
2162 if (allowedSyntaxes.find(syntax) != allowedSyntaxes.end()) | 2207 if (allowedSyntaxes.find(syntax) != allowedSyntaxes.end()) |
2163 { | 2208 { |
2164 // No transcoding is needed | 2209 // No transcoding is needed |
2165 return true; | 2210 return true; |
2166 } | 2211 } |
2167 | 2212 |
2168 if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianImplicit) != allowedSyntaxes.end() && | 2213 if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianImplicit) != allowedSyntaxes.end() && |
2169 FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianImplicit, NULL)) | 2214 FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianImplicit, NULL)) |
2170 { | 2215 { |
2216 CheckSopInstanceUid(dicom, sourceSopInstanceUid, true); | |
2171 return true; | 2217 return true; |
2172 } | 2218 } |
2173 | 2219 |
2174 if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianExplicit) != allowedSyntaxes.end() && | 2220 if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianExplicit) != allowedSyntaxes.end() && |
2175 FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianExplicit, NULL)) | 2221 FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianExplicit, NULL)) |
2176 { | 2222 { |
2223 CheckSopInstanceUid(dicom, sourceSopInstanceUid, true); | |
2177 return true; | 2224 return true; |
2178 } | 2225 } |
2179 | 2226 |
2180 if (allowedSyntaxes.find(DicomTransferSyntax_BigEndianExplicit) != allowedSyntaxes.end() && | 2227 if (allowedSyntaxes.find(DicomTransferSyntax_BigEndianExplicit) != allowedSyntaxes.end() && |
2181 FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_BigEndianExplicit, NULL)) | 2228 FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_BigEndianExplicit, NULL)) |
2182 { | 2229 { |
2230 CheckSopInstanceUid(dicom, sourceSopInstanceUid, true); | |
2183 return true; | 2231 return true; |
2184 } | 2232 } |
2185 | 2233 |
2186 if (allowedSyntaxes.find(DicomTransferSyntax_DeflatedLittleEndianExplicit) != allowedSyntaxes.end() && | 2234 if (allowedSyntaxes.find(DicomTransferSyntax_DeflatedLittleEndianExplicit) != allowedSyntaxes.end() && |
2187 FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_DeflatedLittleEndianExplicit, NULL)) | 2235 FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_DeflatedLittleEndianExplicit, NULL)) |
2188 { | 2236 { |
2237 CheckSopInstanceUid(dicom, sourceSopInstanceUid, true); | |
2189 return true; | 2238 return true; |
2190 } | 2239 } |
2191 | 2240 |
2192 #if ORTHANC_ENABLE_JPEG == 1 | 2241 #if ORTHANC_ENABLE_DCMTK_JPEG == 1 |
2193 if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess1) != allowedSyntaxes.end() && | 2242 if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess1) != allowedSyntaxes.end() && |
2194 allowNewSopInstanceUid && | 2243 allowNewSopInstanceUid && |
2195 bitsStored == 8) | 2244 bitsStored == 8) |
2196 { | 2245 { |
2197 DJ_RPLossy rpLossy(lossyQuality_); | 2246 DJ_RPLossy parameters(lossyQuality_); |
2198 | 2247 |
2199 if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess1, &rpLossy)) | 2248 if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess1, ¶meters)) |
2200 { | 2249 { |
2250 CheckSopInstanceUid(dicom, sourceSopInstanceUid, false); | |
2201 return true; | 2251 return true; |
2202 } | 2252 } |
2203 } | 2253 } |
2204 #endif | 2254 #endif |
2205 | 2255 |
2206 #if ORTHANC_ENABLE_JPEG == 1 | 2256 #if ORTHANC_ENABLE_DCMTK_JPEG == 1 |
2207 if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess2_4) != allowedSyntaxes.end() && | 2257 if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess2_4) != allowedSyntaxes.end() && |
2208 allowNewSopInstanceUid && | 2258 allowNewSopInstanceUid && |
2209 bitsStored <= 12) | 2259 bitsStored <= 12) |
2210 { | 2260 { |
2211 DJ_RPLossy rpLossy(lossyQuality_); | 2261 DJ_RPLossy parameters(lossyQuality_); |
2212 if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess2_4, &rpLossy)) | 2262 if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess2_4, ¶meters)) |
2213 { | 2263 { |
2264 CheckSopInstanceUid(dicom, sourceSopInstanceUid, false); | |
2265 return true; | |
2266 } | |
2267 } | |
2268 #endif | |
2269 | |
2270 #if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1 | |
2271 if (allowedSyntaxes.find(DicomTransferSyntax_JPEGLSLossless) != allowedSyntaxes.end()) | |
2272 { | |
2273 // Check out "dcmjpls/apps/dcmcjpls.cc" | |
2274 DJLSRepresentationParameter parameters(2 /* opt_nearlossless_deviation */, | |
2275 OFTrue /* opt_useLosslessProcess */); | |
2276 | |
2277 /** | |
2278 * WARNING: This call results in a segmentation fault if using | |
2279 * the DCMTK package 3.6.2 from Ubuntu 18.04. | |
2280 **/ | |
2281 if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGLSLossless, ¶meters)) | |
2282 { | |
2283 CheckSopInstanceUid(dicom, sourceSopInstanceUid, true); | |
2284 return true; | |
2285 } | |
2286 } | |
2287 #endif | |
2288 | |
2289 #if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1 | |
2290 if (allowNewSopInstanceUid && | |
2291 allowedSyntaxes.find(DicomTransferSyntax_JPEGLSLossy) != allowedSyntaxes.end()) | |
2292 { | |
2293 // Check out "dcmjpls/apps/dcmcjpls.cc" | |
2294 DJLSRepresentationParameter parameters(2 /* opt_nearlossless_deviation */, | |
2295 OFFalse /* opt_useLosslessProcess */); | |
2296 | |
2297 /** | |
2298 * WARNING: This call results in a segmentation fault if using | |
2299 * the DCMTK package 3.6.2 from Ubuntu 18.04. | |
2300 **/ | |
2301 if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGLSLossy, ¶meters)) | |
2302 { | |
2303 CheckSopInstanceUid(dicom, sourceSopInstanceUid, false); | |
2214 return true; | 2304 return true; |
2215 } | 2305 } |
2216 } | 2306 } |
2217 #endif | 2307 #endif |
2218 | 2308 |
2231 scu.SetCommonClassesProposed(false); | 2321 scu.SetCommonClassesProposed(false); |
2232 scu.SetRetiredBigEndianProposed(true); | 2322 scu.SetRetiredBigEndianProposed(true); |
2233 | 2323 |
2234 DcmtkTranscoder transcoder; | 2324 DcmtkTranscoder transcoder; |
2235 | 2325 |
2236 for (int j = 0; j < 2; j++) | 2326 //for (int j = 0; j < 2; j++) |
2237 for (int i = 0; i <= DicomTransferSyntax_XML; i++) | 2327 for (int i = 0; i <= DicomTransferSyntax_XML; i++) |
2238 { | 2328 { |
2239 DicomTransferSyntax a = (DicomTransferSyntax) i; | 2329 DicomTransferSyntax a = (DicomTransferSyntax) i; |
2240 | 2330 |
2241 std::string path = ("/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/" + | 2331 std::string path = ("/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/" + |
2266 } | 2356 } |
2267 } | 2357 } |
2268 } | 2358 } |
2269 | 2359 |
2270 | 2360 |
2361 | |
2362 | |
2363 TEST(Toto, DISABLED_Transcode4) | |
2364 { | |
2365 std::string source; | |
2366 Orthanc::SystemToolbox::ReadFile(source, "/home/jodogne/Subversion/orthanc-tests/Database/KarstenHilbertRF.dcm"); | |
2367 | |
2368 std::unique_ptr<DcmFileFormat> toto(FromDcmtkBridge::LoadFromMemoryBuffer(source.c_str(), source.size())); | |
2369 DicomTransferSyntax sourceSyntax; | |
2370 ASSERT_TRUE(FromDcmtkBridge::LookupOrthancTransferSyntax(sourceSyntax, *toto)); | |
2371 | |
2372 DcmtkTranscoder transcoder; | |
2373 | |
2374 for (int i = 0; i <= DicomTransferSyntax_XML; i++) | |
2375 { | |
2376 DicomTransferSyntax a = (DicomTransferSyntax) i; | |
2377 std::set<DicomTransferSyntax> s; | |
2378 s.insert(a); | |
2379 std::unique_ptr<DcmFileFormat> transcoded(transcoder.Transcode(source.c_str(), source.size(), s, true)); | |
2380 if (transcoded.get() == NULL) | |
2381 { | |
2382 printf("**************** CANNOT: [%s] => [%s]\n", | |
2383 GetTransferSyntaxUid(sourceSyntax), GetTransferSyntaxUid(a)); | |
2384 } | |
2385 else | |
2386 { | |
2387 std::string t; | |
2388 FromDcmtkBridge::SaveToMemoryBuffer(t, *transcoded->getDataset()); | |
2389 printf("SIZE: %lu\n", t.size()); | |
2390 | |
2391 const char* v = NULL; | |
2392 transcoded->getDataset()->findAndGetString(DCM_SOPInstanceUID, v); | |
2393 if (std::string(v) != "1.3.12.2.1107.5.12.1.2013021918595000.1.1") | |
2394 { | |
2395 printf("CHANGED SOP INSTANCE UID\n"); | |
2396 } | |
2397 } | |
2398 } | |
2399 } | |
2400 | |
2401 | |
2271 #endif | 2402 #endif |