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