Mercurial > hg > orthanc
comparison Core/DicomParsing/FromDcmtkBridge.cpp @ 3748:ca36e3f1112c transcoding
transcoding to uncompressed transfer syntaxes
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 13 Mar 2020 16:50:13 +0100 |
parents | 33c19a6643e1 |
children | 4a25727401cd |
comparison
equal
deleted
inserted
replaced
3747:7b6058f8f7aa | 3748:ca36e3f1112c |
---|---|
118 # include <dcmtk/dcmjpls/djencode.h> | 118 # include <dcmtk/dcmjpls/djencode.h> |
119 # endif | 119 # endif |
120 #endif | 120 #endif |
121 | 121 |
122 | 122 |
123 #include <dcmtk/dcmdata/dcrledrg.h> | |
124 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 | |
125 # include <dcmtk/dcmdata/dcrleerg.h> | |
126 #endif | |
127 | |
128 | |
123 namespace Orthanc | 129 namespace Orthanc |
124 { | 130 { |
125 static bool IsBinaryTag(const DcmTag& key) | 131 static bool IsBinaryTag(const DcmTag& key) |
126 { | 132 { |
127 return (key.isUnknownVR() || | 133 return (key.isUnknownVR() || |
1195 default: | 1201 default: |
1196 throw OrthancException(ErrorCode_ParameterOutOfRange); | 1202 throw OrthancException(ErrorCode_ParameterOutOfRange); |
1197 } | 1203 } |
1198 } | 1204 } |
1199 | 1205 |
1206 | |
1207 | |
1208 static bool SaveToMemoryBufferInternal(std::string& buffer, | |
1209 DcmFileFormat& dicom, | |
1210 E_TransferSyntax xfer) | |
1211 { | |
1212 E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength; | |
1213 | |
1214 // Create a memory buffer with the proper size | |
1215 { | |
1216 const uint32_t estimatedSize = dicom.calcElementLength(xfer, encodingType); // (*) | |
1217 buffer.resize(estimatedSize); | |
1218 } | |
1219 | |
1220 DcmOutputBufferStream ob(&buffer[0], buffer.size()); | |
1221 | |
1222 // Fill the memory buffer with the meta-header and the dataset | |
1223 dicom.transferInit(); | |
1224 OFCondition c = dicom.write(ob, xfer, encodingType, NULL, | |
1225 /*opt_groupLength*/ EGL_recalcGL, | |
1226 /*opt_paddingType*/ EPD_withoutPadding); | |
1227 dicom.transferEnd(); | |
1228 | |
1229 if (c.good()) | |
1230 { | |
1231 // The DICOM file is successfully written, truncate the target | |
1232 // buffer if its size was overestimated by (*) | |
1233 ob.flush(); | |
1234 | |
1235 size_t effectiveSize = static_cast<size_t>(ob.tell()); | |
1236 if (effectiveSize < buffer.size()) | |
1237 { | |
1238 buffer.resize(effectiveSize); | |
1239 } | |
1240 | |
1241 return true; | |
1242 } | |
1243 else | |
1244 { | |
1245 // Error | |
1246 buffer.clear(); | |
1247 return false; | |
1248 } | |
1249 } | |
1250 | |
1251 | |
1200 bool FromDcmtkBridge::SaveToMemoryBuffer(std::string& buffer, | 1252 bool FromDcmtkBridge::SaveToMemoryBuffer(std::string& buffer, |
1201 DcmDataset& dataSet) | 1253 DcmDataset& dataSet) |
1202 { | 1254 { |
1203 // Determine the transfer syntax which shall be used to write the | 1255 // Determine the transfer syntax which shall be used to write the |
1204 // information to the file. We always switch to the Little Endian | 1256 // information to the file. We always switch to the Little Endian |
1219 // No information about the original transfer syntax: This is | 1271 // No information about the original transfer syntax: This is |
1220 // most probably a DICOM dataset that was read from memory. | 1272 // most probably a DICOM dataset that was read from memory. |
1221 xfer = EXS_LittleEndianExplicit; | 1273 xfer = EXS_LittleEndianExplicit; |
1222 } | 1274 } |
1223 | 1275 |
1224 E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength; | |
1225 | |
1226 // Create the meta-header information | 1276 // Create the meta-header information |
1227 DcmFileFormat ff(&dataSet); | 1277 DcmFileFormat ff(&dataSet); |
1228 ff.validateMetaInfo(xfer); | 1278 ff.validateMetaInfo(xfer); |
1229 ff.removeInvalidGroups(); | 1279 ff.removeInvalidGroups(); |
1230 | 1280 |
1231 // Create a memory buffer with the proper size | 1281 return SaveToMemoryBufferInternal(buffer, ff, xfer); |
1232 { | 1282 } |
1233 const uint32_t estimatedSize = ff.calcElementLength(xfer, encodingType); // (*) | 1283 |
1234 buffer.resize(estimatedSize); | 1284 |
1235 } | 1285 bool FromDcmtkBridge::SaveToMemoryBuffer(std::string& buffer, |
1236 | 1286 DcmFileFormat& dicom) |
1237 DcmOutputBufferStream ob(&buffer[0], buffer.size()); | 1287 { |
1238 | 1288 E_TransferSyntax xfer = dicom.getDataset()->getOriginalXfer(); |
1239 // Fill the memory buffer with the meta-header and the dataset | 1289 if (xfer == EXS_Unknown) |
1240 ff.transferInit(); | 1290 { |
1241 OFCondition c = ff.write(ob, xfer, encodingType, NULL, | 1291 throw OrthancException(ErrorCode_InternalError, |
1242 /*opt_groupLength*/ EGL_recalcGL, | 1292 "Cannot write a DICOM instance with unknown transfer syntax"); |
1243 /*opt_paddingType*/ EPD_withoutPadding); | 1293 } |
1244 ff.transferEnd(); | 1294 else if (!dicom.validateMetaInfo(xfer).good()) |
1245 | 1295 { |
1246 if (c.good()) | 1296 throw OrthancException(ErrorCode_InternalError, |
1247 { | 1297 "Cannot setup the transfer syntax to write a DICOM instance"); |
1248 // The DICOM file is successfully written, truncate the target | |
1249 // buffer if its size was overestimated by (*) | |
1250 ob.flush(); | |
1251 | |
1252 size_t effectiveSize = static_cast<size_t>(ob.tell()); | |
1253 if (effectiveSize < buffer.size()) | |
1254 { | |
1255 buffer.resize(effectiveSize); | |
1256 } | |
1257 | |
1258 return true; | |
1259 } | 1298 } |
1260 else | 1299 else |
1261 { | 1300 { |
1262 // Error | 1301 return SaveToMemoryBufferInternal(buffer, dicom, xfer); |
1263 buffer.clear(); | 1302 } |
1264 return false; | 1303 } |
1304 | |
1305 | |
1306 bool FromDcmtkBridge::Transcode(std::string& buffer, | |
1307 DcmFileFormat& dicom, | |
1308 DicomTransferSyntax syntax, | |
1309 const DcmRepresentationParameter* representation) | |
1310 { | |
1311 E_TransferSyntax xfer; | |
1312 if (!LookupDcmtkTransferSyntax(xfer, syntax)) | |
1313 { | |
1314 throw OrthancException(ErrorCode_InternalError); | |
1315 } | |
1316 else | |
1317 { | |
1318 return (dicom.getDataset()->chooseRepresentation(xfer, representation).good() && | |
1319 dicom.getDataset()->canWriteXfer(xfer) && | |
1320 SaveToMemoryBufferInternal(buffer, dicom, xfer)); | |
1265 } | 1321 } |
1266 } | 1322 } |
1267 | 1323 |
1268 | 1324 |
1269 ValueRepresentation FromDcmtkBridge::LookupValueRepresentation(const DicomTag& tag) | 1325 ValueRepresentation FromDcmtkBridge::LookupValueRepresentation(const DicomTag& tag) |
2062 DJDecoderRegistration::registerCodecs(); | 2118 DJDecoderRegistration::registerCodecs(); |
2063 # if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 | 2119 # if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 |
2064 DJEncoderRegistration::registerCodecs(); | 2120 DJEncoderRegistration::registerCodecs(); |
2065 # endif | 2121 # endif |
2066 #endif | 2122 #endif |
2123 | |
2124 LOG(INFO) << "Registering RLE codecs in DCMTK"; | |
2125 DcmRLEDecoderRegistration::registerCodecs(); | |
2126 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 | |
2127 DcmRLEEncoderRegistration::registerCodecs(); | |
2128 #endif | |
2067 } | 2129 } |
2068 | 2130 |
2069 | 2131 |
2070 void FromDcmtkBridge::FinalizeCodecs() | 2132 void FromDcmtkBridge::FinalizeCodecs() |
2071 { | 2133 { |
2081 // Unregister JPEG codecs | 2143 // Unregister JPEG codecs |
2082 DJDecoderRegistration::cleanup(); | 2144 DJDecoderRegistration::cleanup(); |
2083 # if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 | 2145 # if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 |
2084 DJEncoderRegistration::cleanup(); | 2146 DJEncoderRegistration::cleanup(); |
2085 # endif | 2147 # endif |
2148 #endif | |
2149 | |
2150 DcmRLEDecoderRegistration::cleanup(); | |
2151 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1 | |
2152 DcmRLEEncoderRegistration::cleanup(); | |
2086 #endif | 2153 #endif |
2087 } | 2154 } |
2088 | 2155 |
2089 | 2156 |
2090 | 2157 |