Mercurial > hg > orthanc
comparison Resources/Graveyard/TestTranscoding.cpp @ 3884:83061cdc7703 transcoding
moving old tests to the graveyard
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 05 May 2020 14:37:29 +0200 |
parents | |
children | e23026566536 |
comparison
equal
deleted
inserted
replaced
3883:795c9ca5eb91 | 3884:83061cdc7703 |
---|---|
1 #include <dcmtk/dcmdata/dcostrmb.h> | |
2 #include <dcmtk/dcmdata/dcpixel.h> | |
3 #include <dcmtk/dcmdata/dcpxitem.h> | |
4 | |
5 #include "../Core/DicomParsing/Internals/DicomFrameIndex.h" | |
6 | |
7 namespace Orthanc | |
8 { | |
9 class IParsedDicomImage : public boost::noncopyable | |
10 { | |
11 public: | |
12 virtual ~IParsedDicomImage() | |
13 { | |
14 } | |
15 | |
16 virtual DicomTransferSyntax GetTransferSyntax() = 0; | |
17 | |
18 virtual std::string GetSopClassUid() = 0; | |
19 | |
20 virtual std::string GetSopInstanceUid() = 0; | |
21 | |
22 virtual unsigned int GetFramesCount() = 0; | |
23 | |
24 // Can return NULL, for compressed transfer syntaxes | |
25 virtual ImageAccessor* GetUncompressedFrame(unsigned int frame) = 0; | |
26 | |
27 virtual void GetCompressedFrame(std::string& target, | |
28 unsigned int frame) = 0; | |
29 | |
30 virtual void WriteToMemoryBuffer(std::string& target) = 0; | |
31 }; | |
32 | |
33 | |
34 class IDicomImageReader : public boost::noncopyable | |
35 { | |
36 public: | |
37 virtual ~IDicomImageReader() | |
38 { | |
39 } | |
40 | |
41 virtual IParsedDicomImage* Read(const void* data, | |
42 size_t size) = 0; | |
43 | |
44 virtual IParsedDicomImage* Transcode(const void* data, | |
45 size_t size, | |
46 DicomTransferSyntax syntax, | |
47 bool allowNewSopInstanceUid) = 0; | |
48 }; | |
49 | |
50 | |
51 class DcmtkImageReader : public IDicomImageReader | |
52 { | |
53 private: | |
54 class Image : public IParsedDicomImage | |
55 { | |
56 private: | |
57 std::unique_ptr<DcmFileFormat> dicom_; | |
58 std::unique_ptr<DicomFrameIndex> index_; | |
59 DicomTransferSyntax transferSyntax_; | |
60 std::string sopClassUid_; | |
61 std::string sopInstanceUid_; | |
62 | |
63 static std::string GetStringTag(DcmDataset& dataset, | |
64 const DcmTagKey& tag) | |
65 { | |
66 const char* value = NULL; | |
67 | |
68 if (!dataset.findAndGetString(tag, value).good() || | |
69 value == NULL) | |
70 { | |
71 throw OrthancException(ErrorCode_BadFileFormat, | |
72 "Missing SOP class/instance UID in DICOM instance"); | |
73 } | |
74 else | |
75 { | |
76 return std::string(value); | |
77 } | |
78 } | |
79 | |
80 public: | |
81 Image(DcmFileFormat* dicom, | |
82 DicomTransferSyntax syntax) : | |
83 dicom_(dicom), | |
84 transferSyntax_(syntax) | |
85 { | |
86 if (dicom == NULL || | |
87 dicom_->getDataset() == NULL) | |
88 { | |
89 throw OrthancException(ErrorCode_NullPointer); | |
90 } | |
91 | |
92 DcmDataset& dataset = *dicom_->getDataset(); | |
93 index_.reset(new DicomFrameIndex(dataset)); | |
94 | |
95 sopClassUid_ = GetStringTag(dataset, DCM_SOPClassUID); | |
96 sopInstanceUid_ = GetStringTag(dataset, DCM_SOPInstanceUID); | |
97 } | |
98 | |
99 virtual DicomTransferSyntax GetTransferSyntax() ORTHANC_OVERRIDE | |
100 { | |
101 return transferSyntax_; | |
102 } | |
103 | |
104 virtual std::string GetSopClassUid() ORTHANC_OVERRIDE | |
105 { | |
106 return sopClassUid_; | |
107 } | |
108 | |
109 virtual std::string GetSopInstanceUid() ORTHANC_OVERRIDE | |
110 { | |
111 return sopInstanceUid_; | |
112 } | |
113 | |
114 virtual unsigned int GetFramesCount() ORTHANC_OVERRIDE | |
115 { | |
116 return index_->GetFramesCount(); | |
117 } | |
118 | |
119 virtual void WriteToMemoryBuffer(std::string& target) ORTHANC_OVERRIDE | |
120 { | |
121 assert(dicom_.get() != NULL); | |
122 if (!FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom_, transferSyntax_)) | |
123 { | |
124 throw OrthancException(ErrorCode_InternalError, | |
125 "Cannot write the DICOM instance to a memory buffer"); | |
126 } | |
127 } | |
128 | |
129 virtual ImageAccessor* GetUncompressedFrame(unsigned int frame) ORTHANC_OVERRIDE | |
130 { | |
131 assert(dicom_.get() != NULL && | |
132 dicom_->getDataset() != NULL); | |
133 return DicomImageDecoder::Decode(*dicom_->getDataset(), frame); | |
134 } | |
135 | |
136 virtual void GetCompressedFrame(std::string& target, | |
137 unsigned int frame) ORTHANC_OVERRIDE | |
138 { | |
139 assert(index_.get() != NULL); | |
140 index_->GetRawFrame(target, frame); | |
141 } | |
142 }; | |
143 | |
144 unsigned int lossyQuality_; | |
145 | |
146 static DicomTransferSyntax DetectTransferSyntax(DcmFileFormat& dicom) | |
147 { | |
148 if (dicom.getDataset() == NULL) | |
149 { | |
150 throw OrthancException(ErrorCode_InternalError); | |
151 } | |
152 | |
153 DcmDataset& dataset = *dicom.getDataset(); | |
154 | |
155 E_TransferSyntax xfer = dataset.getCurrentXfer(); | |
156 if (xfer == EXS_Unknown) | |
157 { | |
158 dataset.updateOriginalXfer(); | |
159 xfer = dataset.getCurrentXfer(); | |
160 if (xfer == EXS_Unknown) | |
161 { | |
162 throw OrthancException(ErrorCode_BadFileFormat, | |
163 "Cannot determine the transfer syntax of the DICOM instance"); | |
164 } | |
165 } | |
166 | |
167 DicomTransferSyntax syntax; | |
168 if (FromDcmtkBridge::LookupOrthancTransferSyntax(syntax, xfer)) | |
169 { | |
170 return syntax; | |
171 } | |
172 else | |
173 { | |
174 throw OrthancException( | |
175 ErrorCode_BadFileFormat, | |
176 "Unsupported transfer syntax: " + boost::lexical_cast<std::string>(xfer)); | |
177 } | |
178 } | |
179 | |
180 | |
181 static uint16_t GetBitsStored(DcmFileFormat& dicom) | |
182 { | |
183 if (dicom.getDataset() == NULL) | |
184 { | |
185 throw OrthancException(ErrorCode_InternalError); | |
186 } | |
187 | |
188 uint16_t bitsStored; | |
189 if (dicom.getDataset()->findAndGetUint16(DCM_BitsStored, bitsStored).good()) | |
190 { | |
191 return bitsStored; | |
192 } | |
193 else | |
194 { | |
195 throw OrthancException(ErrorCode_BadFileFormat, | |
196 "Missing \"Bits Stored\" tag in DICOM instance"); | |
197 } | |
198 } | |
199 | |
200 | |
201 public: | |
202 DcmtkImageReader() : | |
203 lossyQuality_(90) | |
204 { | |
205 } | |
206 | |
207 void SetLossyQuality(unsigned int quality) | |
208 { | |
209 if (quality <= 0 || | |
210 quality > 100) | |
211 { | |
212 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
213 } | |
214 else | |
215 { | |
216 lossyQuality_ = quality; | |
217 } | |
218 } | |
219 | |
220 unsigned int GetLossyQuality() const | |
221 { | |
222 return lossyQuality_; | |
223 } | |
224 | |
225 virtual IParsedDicomImage* Read(const void* data, | |
226 size_t size) | |
227 { | |
228 std::unique_ptr<DcmFileFormat> dicom(FromDcmtkBridge::LoadFromMemoryBuffer(data, size)); | |
229 if (dicom.get() == NULL) | |
230 { | |
231 throw OrthancException(ErrorCode_BadFileFormat); | |
232 } | |
233 | |
234 DicomTransferSyntax transferSyntax = DetectTransferSyntax(*dicom); | |
235 | |
236 return new Image(dicom.release(), transferSyntax); | |
237 } | |
238 | |
239 virtual IParsedDicomImage* Transcode(const void* data, | |
240 size_t size, | |
241 DicomTransferSyntax syntax, | |
242 bool allowNewSopInstanceUid) | |
243 { | |
244 std::unique_ptr<DcmFileFormat> dicom(FromDcmtkBridge::LoadFromMemoryBuffer(data, size)); | |
245 if (dicom.get() == NULL) | |
246 { | |
247 throw OrthancException(ErrorCode_BadFileFormat); | |
248 } | |
249 | |
250 const uint16_t bitsStored = GetBitsStored(*dicom); | |
251 | |
252 if (syntax == DetectTransferSyntax(*dicom)) | |
253 { | |
254 // No transcoding is needed | |
255 return new Image(dicom.release(), syntax); | |
256 } | |
257 | |
258 if (syntax == DicomTransferSyntax_LittleEndianImplicit && | |
259 FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_LittleEndianImplicit, NULL)) | |
260 { | |
261 return new Image(dicom.release(), syntax); | |
262 } | |
263 | |
264 if (syntax == DicomTransferSyntax_LittleEndianExplicit && | |
265 FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_LittleEndianExplicit, NULL)) | |
266 { | |
267 return new Image(dicom.release(), syntax); | |
268 } | |
269 | |
270 if (syntax == DicomTransferSyntax_BigEndianExplicit && | |
271 FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_BigEndianExplicit, NULL)) | |
272 { | |
273 return new Image(dicom.release(), syntax); | |
274 } | |
275 | |
276 if (syntax == DicomTransferSyntax_DeflatedLittleEndianExplicit && | |
277 FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_DeflatedLittleEndianExplicit, NULL)) | |
278 { | |
279 return new Image(dicom.release(), syntax); | |
280 } | |
281 | |
282 #if ORTHANC_ENABLE_JPEG == 1 | |
283 if (syntax == DicomTransferSyntax_JPEGProcess1 && | |
284 allowNewSopInstanceUid && | |
285 bitsStored == 8) | |
286 { | |
287 DJ_RPLossy rpLossy(lossyQuality_); | |
288 | |
289 if (FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_JPEGProcess1, &rpLossy)) | |
290 { | |
291 return new Image(dicom.release(), syntax); | |
292 } | |
293 } | |
294 #endif | |
295 | |
296 #if ORTHANC_ENABLE_JPEG == 1 | |
297 if (syntax == DicomTransferSyntax_JPEGProcess2_4 && | |
298 allowNewSopInstanceUid && | |
299 bitsStored <= 12) | |
300 { | |
301 DJ_RPLossy rpLossy(lossyQuality_); | |
302 if (FromDcmtkBridge::Transcode(*dicom, DicomTransferSyntax_JPEGProcess2_4, &rpLossy)) | |
303 { | |
304 return new Image(dicom.release(), syntax); | |
305 } | |
306 } | |
307 #endif | |
308 | |
309 //LOG(INFO) << "Unable to transcode DICOM image using the built-in reader"; | |
310 return NULL; | |
311 } | |
312 }; | |
313 | |
314 | |
315 | |
316 class IDicomTranscoder1 : public boost::noncopyable | |
317 { | |
318 public: | |
319 virtual ~IDicomTranscoder1() | |
320 { | |
321 } | |
322 | |
323 virtual DcmFileFormat& GetDicom() = 0; | |
324 | |
325 virtual DicomTransferSyntax GetTransferSyntax() = 0; | |
326 | |
327 virtual std::string GetSopClassUid() = 0; | |
328 | |
329 virtual std::string GetSopInstanceUid() = 0; | |
330 | |
331 virtual unsigned int GetFramesCount() = 0; | |
332 | |
333 virtual ImageAccessor* DecodeFrame(unsigned int frame) = 0; | |
334 | |
335 virtual void GetCompressedFrame(std::string& target, | |
336 unsigned int frame) = 0; | |
337 | |
338 // NB: Transcoding can change the value of "GetSopInstanceUid()" | |
339 // and "GetTransferSyntax()" if lossy compression is applied | |
340 virtual bool Transcode(std::string& target, | |
341 DicomTransferSyntax syntax, | |
342 bool allowNewSopInstanceUid) = 0; | |
343 | |
344 virtual void WriteToMemoryBuffer(std::string& target) = 0; | |
345 }; | |
346 | |
347 | |
348 class DcmtkTranscoder2 : public IDicomTranscoder1 | |
349 { | |
350 private: | |
351 std::unique_ptr<DcmFileFormat> dicom_; | |
352 std::unique_ptr<DicomFrameIndex> index_; | |
353 DicomTransferSyntax transferSyntax_; | |
354 std::string sopClassUid_; | |
355 std::string sopInstanceUid_; | |
356 uint16_t bitsStored_; | |
357 unsigned int lossyQuality_; | |
358 | |
359 static std::string GetStringTag(DcmDataset& dataset, | |
360 const DcmTagKey& tag) | |
361 { | |
362 const char* value = NULL; | |
363 | |
364 if (!dataset.findAndGetString(tag, value).good() || | |
365 value == NULL) | |
366 { | |
367 throw OrthancException(ErrorCode_BadFileFormat, | |
368 "Missing SOP class/instance UID in DICOM instance"); | |
369 } | |
370 else | |
371 { | |
372 return std::string(value); | |
373 } | |
374 } | |
375 | |
376 void Setup(DcmFileFormat* dicom) | |
377 { | |
378 lossyQuality_ = 90; | |
379 | |
380 dicom_.reset(dicom); | |
381 | |
382 if (dicom == NULL || | |
383 dicom_->getDataset() == NULL) | |
384 { | |
385 throw OrthancException(ErrorCode_NullPointer); | |
386 } | |
387 | |
388 DcmDataset& dataset = *dicom_->getDataset(); | |
389 index_.reset(new DicomFrameIndex(dataset)); | |
390 | |
391 E_TransferSyntax xfer = dataset.getCurrentXfer(); | |
392 if (xfer == EXS_Unknown) | |
393 { | |
394 dataset.updateOriginalXfer(); | |
395 xfer = dataset.getCurrentXfer(); | |
396 if (xfer == EXS_Unknown) | |
397 { | |
398 throw OrthancException(ErrorCode_BadFileFormat, | |
399 "Cannot determine the transfer syntax of the DICOM instance"); | |
400 } | |
401 } | |
402 | |
403 if (!FromDcmtkBridge::LookupOrthancTransferSyntax(transferSyntax_, xfer)) | |
404 { | |
405 throw OrthancException( | |
406 ErrorCode_BadFileFormat, | |
407 "Unsupported transfer syntax: " + boost::lexical_cast<std::string>(xfer)); | |
408 } | |
409 | |
410 if (!dataset.findAndGetUint16(DCM_BitsStored, bitsStored_).good()) | |
411 { | |
412 throw OrthancException(ErrorCode_BadFileFormat, | |
413 "Missing \"Bits Stored\" tag in DICOM instance"); | |
414 } | |
415 | |
416 sopClassUid_ = GetStringTag(dataset, DCM_SOPClassUID); | |
417 sopInstanceUid_ = GetStringTag(dataset, DCM_SOPInstanceUID); | |
418 } | |
419 | |
420 public: | |
421 DcmtkTranscoder2(DcmFileFormat* dicom) // Takes ownership | |
422 { | |
423 Setup(dicom); | |
424 } | |
425 | |
426 DcmtkTranscoder2(const void* dicom, | |
427 size_t size) | |
428 { | |
429 Setup(FromDcmtkBridge::LoadFromMemoryBuffer(dicom, size)); | |
430 } | |
431 | |
432 void SetLossyQuality(unsigned int quality) | |
433 { | |
434 if (quality <= 0 || | |
435 quality > 100) | |
436 { | |
437 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
438 } | |
439 else | |
440 { | |
441 lossyQuality_ = quality; | |
442 } | |
443 } | |
444 | |
445 unsigned int GetLossyQuality() const | |
446 { | |
447 return lossyQuality_; | |
448 } | |
449 | |
450 unsigned int GetBitsStored() const | |
451 { | |
452 return bitsStored_; | |
453 } | |
454 | |
455 virtual DcmFileFormat& GetDicom() | |
456 { | |
457 assert(dicom_ != NULL); | |
458 return *dicom_; | |
459 } | |
460 | |
461 virtual DicomTransferSyntax GetTransferSyntax() ORTHANC_OVERRIDE | |
462 { | |
463 return transferSyntax_; | |
464 } | |
465 | |
466 virtual std::string GetSopClassUid() ORTHANC_OVERRIDE | |
467 { | |
468 return sopClassUid_; | |
469 } | |
470 | |
471 virtual std::string GetSopInstanceUid() ORTHANC_OVERRIDE | |
472 { | |
473 return sopInstanceUid_; | |
474 } | |
475 | |
476 virtual unsigned int GetFramesCount() ORTHANC_OVERRIDE | |
477 { | |
478 return index_->GetFramesCount(); | |
479 } | |
480 | |
481 virtual void WriteToMemoryBuffer(std::string& target) ORTHANC_OVERRIDE | |
482 { | |
483 if (!FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom_)) | |
484 { | |
485 throw OrthancException(ErrorCode_InternalError, | |
486 "Cannot write the DICOM instance to a memory buffer"); | |
487 } | |
488 } | |
489 | |
490 virtual ImageAccessor* DecodeFrame(unsigned int frame) ORTHANC_OVERRIDE | |
491 { | |
492 assert(dicom_->getDataset() != NULL); | |
493 return DicomImageDecoder::Decode(*dicom_->getDataset(), frame); | |
494 } | |
495 | |
496 virtual void GetCompressedFrame(std::string& target, | |
497 unsigned int frame) ORTHANC_OVERRIDE | |
498 { | |
499 index_->GetRawFrame(target, frame); | |
500 } | |
501 | |
502 virtual bool Transcode(std::string& target, | |
503 DicomTransferSyntax syntax, | |
504 bool allowNewSopInstanceUid) ORTHANC_OVERRIDE | |
505 { | |
506 assert(dicom_ != NULL && | |
507 dicom_->getDataset() != NULL); | |
508 | |
509 if (syntax == GetTransferSyntax()) | |
510 { | |
511 printf("NO TRANSCODING\n"); | |
512 | |
513 // No change in the transfer syntax => simply serialize the current dataset | |
514 WriteToMemoryBuffer(target); | |
515 return true; | |
516 } | |
517 | |
518 printf(">> %d\n", bitsStored_); | |
519 | |
520 if (syntax == DicomTransferSyntax_LittleEndianImplicit && | |
521 FromDcmtkBridge::Transcode(*dicom_, syntax, NULL) && | |
522 FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom_, syntax)) | |
523 { | |
524 transferSyntax_ = DicomTransferSyntax_LittleEndianImplicit; | |
525 return true; | |
526 } | |
527 | |
528 if (syntax == DicomTransferSyntax_LittleEndianExplicit && | |
529 FromDcmtkBridge::Transcode(*dicom_, syntax, NULL) && | |
530 FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom_, syntax)) | |
531 { | |
532 transferSyntax_ = DicomTransferSyntax_LittleEndianExplicit; | |
533 return true; | |
534 } | |
535 | |
536 if (syntax == DicomTransferSyntax_BigEndianExplicit && | |
537 FromDcmtkBridge::Transcode(*dicom_, syntax, NULL) && | |
538 FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom_, syntax)) | |
539 { | |
540 transferSyntax_ = DicomTransferSyntax_BigEndianExplicit; | |
541 return true; | |
542 } | |
543 | |
544 if (syntax == DicomTransferSyntax_DeflatedLittleEndianExplicit && | |
545 FromDcmtkBridge::Transcode(*dicom_, syntax, NULL) && | |
546 FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom_, syntax)) | |
547 { | |
548 transferSyntax_ = DicomTransferSyntax_DeflatedLittleEndianExplicit; | |
549 return true; | |
550 } | |
551 | |
552 #if ORTHANC_ENABLE_JPEG == 1 | |
553 if (syntax == DicomTransferSyntax_JPEGProcess1 && | |
554 allowNewSopInstanceUid && | |
555 GetBitsStored() == 8) | |
556 { | |
557 DJ_RPLossy rpLossy(lossyQuality_); | |
558 | |
559 if (FromDcmtkBridge::Transcode(*dicom_, syntax, &rpLossy) && | |
560 FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom_, syntax)) | |
561 { | |
562 transferSyntax_ = DicomTransferSyntax_JPEGProcess1; | |
563 sopInstanceUid_ = GetStringTag(*dicom_->getDataset(), DCM_SOPInstanceUID); | |
564 return true; | |
565 } | |
566 } | |
567 #endif | |
568 | |
569 #if ORTHANC_ENABLE_JPEG == 1 | |
570 if (syntax == DicomTransferSyntax_JPEGProcess2_4 && | |
571 allowNewSopInstanceUid && | |
572 GetBitsStored() <= 12) | |
573 { | |
574 DJ_RPLossy rpLossy(lossyQuality_); | |
575 if (FromDcmtkBridge::Transcode(*dicom_, syntax, &rpLossy) && | |
576 FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom_, syntax)) | |
577 { | |
578 transferSyntax_ = DicomTransferSyntax_JPEGProcess2_4; | |
579 sopInstanceUid_ = GetStringTag(*dicom_->getDataset(), DCM_SOPInstanceUID); | |
580 return true; | |
581 } | |
582 } | |
583 #endif | |
584 | |
585 return false; | |
586 } | |
587 }; | |
588 } | |
589 | |
590 | |
591 | |
592 | |
593 #include <boost/filesystem.hpp> | |
594 | |
595 | |
596 static void TestFile(const std::string& path) | |
597 { | |
598 static unsigned int count = 0; | |
599 count++; | |
600 | |
601 | |
602 printf("** %s\n", path.c_str()); | |
603 | |
604 std::string s; | |
605 SystemToolbox::ReadFile(s, path); | |
606 | |
607 Orthanc::DcmtkTranscoder2 transcoder(s.c_str(), s.size()); | |
608 | |
609 /*if (transcoder.GetBitsStored() != 8) // TODO | |
610 return; */ | |
611 | |
612 { | |
613 char buf[1024]; | |
614 sprintf(buf, "/tmp/source-%06d.dcm", count); | |
615 printf(">> %s\n", buf); | |
616 Orthanc::SystemToolbox::WriteFile(s, buf); | |
617 } | |
618 | |
619 printf("[%s] [%s] [%s] %d %d\n", GetTransferSyntaxUid(transcoder.GetTransferSyntax()), | |
620 transcoder.GetSopClassUid().c_str(), transcoder.GetSopInstanceUid().c_str(), | |
621 transcoder.GetFramesCount(), transcoder.GetTransferSyntax()); | |
622 | |
623 for (size_t i = 0; i < transcoder.GetFramesCount(); i++) | |
624 { | |
625 std::string f; | |
626 transcoder.GetCompressedFrame(f, i); | |
627 | |
628 if (i == 0) | |
629 { | |
630 char buf[1024]; | |
631 sprintf(buf, "/tmp/frame-%06d.raw", count); | |
632 printf(">> %s\n", buf); | |
633 Orthanc::SystemToolbox::WriteFile(f, buf); | |
634 } | |
635 } | |
636 | |
637 { | |
638 std::string t; | |
639 transcoder.WriteToMemoryBuffer(t); | |
640 | |
641 Orthanc::DcmtkTranscoder2 transcoder2(t.c_str(), t.size()); | |
642 printf(">> %d %d ; %lu bytes\n", transcoder.GetTransferSyntax(), transcoder2.GetTransferSyntax(), t.size()); | |
643 } | |
644 | |
645 { | |
646 std::string a = transcoder.GetSopInstanceUid(); | |
647 DicomTransferSyntax b = transcoder.GetTransferSyntax(); | |
648 | |
649 DicomTransferSyntax syntax = DicomTransferSyntax_JPEGProcess2_4; | |
650 //DicomTransferSyntax syntax = DicomTransferSyntax_LittleEndianExplicit; | |
651 | |
652 std::string t; | |
653 bool ok = transcoder.Transcode(t, syntax, true); | |
654 printf("Transcoding: %d\n", ok); | |
655 | |
656 if (ok) | |
657 { | |
658 printf("[%s] => [%s]\n", a.c_str(), transcoder.GetSopInstanceUid().c_str()); | |
659 printf("[%s] => [%s]\n", GetTransferSyntaxUid(b), | |
660 GetTransferSyntaxUid(transcoder.GetTransferSyntax())); | |
661 | |
662 { | |
663 char buf[1024]; | |
664 sprintf(buf, "/tmp/transcoded-%06d.dcm", count); | |
665 printf(">> %s\n", buf); | |
666 Orthanc::SystemToolbox::WriteFile(t, buf); | |
667 } | |
668 | |
669 Orthanc::DcmtkTranscoder2 transcoder2(t.c_str(), t.size()); | |
670 printf(" => transcoded transfer syntax %d ; %lu bytes\n", transcoder2.GetTransferSyntax(), t.size()); | |
671 } | |
672 } | |
673 | |
674 printf("\n"); | |
675 } | |
676 | |
677 TEST(Toto, DISABLED_Transcode) | |
678 { | |
679 //OFLog::configure(OFLogger::DEBUG_LOG_LEVEL); | |
680 | |
681 if (1) | |
682 { | |
683 const char* const PATH = "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes"; | |
684 | |
685 for (boost::filesystem::directory_iterator it(PATH); | |
686 it != boost::filesystem::directory_iterator(); ++it) | |
687 { | |
688 if (boost::filesystem::is_regular_file(it->status())) | |
689 { | |
690 TestFile(it->path().string()); | |
691 } | |
692 } | |
693 } | |
694 | |
695 if (0) | |
696 { | |
697 TestFile("/home/jodogne/Subversion/orthanc-tests/Database/Multiframe.dcm"); | |
698 TestFile("/home/jodogne/Subversion/orthanc-tests/Database/Issue44/Monochrome1-Jpeg.dcm"); | |
699 } | |
700 | |
701 if (0) | |
702 { | |
703 TestFile("/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/1.2.840.10008.1.2.1.dcm"); | |
704 } | |
705 } | |
706 | |
707 | |
708 TEST(Toto, DISABLED_Transcode2) | |
709 { | |
710 for (int i = 0; i <= DicomTransferSyntax_XML; i++) | |
711 { | |
712 DicomTransferSyntax a = (DicomTransferSyntax) i; | |
713 | |
714 std::string path = ("/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/" + | |
715 std::string(GetTransferSyntaxUid(a)) + ".dcm"); | |
716 if (Orthanc::SystemToolbox::IsRegularFile(path)) | |
717 { | |
718 printf("\n======= %s\n", GetTransferSyntaxUid(a)); | |
719 | |
720 std::string source; | |
721 Orthanc::SystemToolbox::ReadFile(source, path); | |
722 | |
723 DcmtkImageReader reader; | |
724 | |
725 { | |
726 std::unique_ptr<IParsedDicomImage> image( | |
727 reader.Read(source.c_str(), source.size())); | |
728 ASSERT_TRUE(image.get() != NULL); | |
729 ASSERT_EQ(a, image->GetTransferSyntax()); | |
730 | |
731 std::string target; | |
732 image->WriteToMemoryBuffer(target); | |
733 } | |
734 | |
735 for (int j = 0; j <= DicomTransferSyntax_XML; j++) | |
736 { | |
737 DicomTransferSyntax b = (DicomTransferSyntax) j; | |
738 //if (a == b) continue; | |
739 | |
740 std::unique_ptr<IParsedDicomImage> image( | |
741 reader.Transcode(source.c_str(), source.size(), b, true)); | |
742 if (image.get() != NULL) | |
743 { | |
744 printf("[%s] -> [%s]\n", GetTransferSyntaxUid(a), GetTransferSyntaxUid(b)); | |
745 | |
746 std::string target; | |
747 image->WriteToMemoryBuffer(target); | |
748 | |
749 char buf[1024]; | |
750 sprintf(buf, "/tmp/%s-%s.dcm", GetTransferSyntaxUid(a), GetTransferSyntaxUid(b)); | |
751 | |
752 SystemToolbox::WriteFile(target, buf); | |
753 } | |
754 else if (a != DicomTransferSyntax_JPEG2000 && | |
755 a != DicomTransferSyntax_JPEG2000LosslessOnly) | |
756 { | |
757 ASSERT_TRUE(b != DicomTransferSyntax_LittleEndianImplicit && | |
758 b != DicomTransferSyntax_LittleEndianExplicit && | |
759 b != DicomTransferSyntax_BigEndianExplicit && | |
760 b != DicomTransferSyntax_DeflatedLittleEndianExplicit); | |
761 } | |
762 } | |
763 } | |
764 } | |
765 } | |
766 | |
767 | |
768 #include "../Core/DicomNetworking/DicomAssociation.h" | |
769 #include "../Core/DicomNetworking/DicomControlUserConnection.h" | |
770 #include "../Core/DicomNetworking/DicomStoreUserConnection.h" | |
771 | |
772 TEST(Toto, DISABLED_DicomAssociation) | |
773 { | |
774 DicomAssociationParameters params; | |
775 params.SetLocalApplicationEntityTitle("ORTHANC"); | |
776 params.SetRemoteApplicationEntityTitle("PACS"); | |
777 params.SetRemotePort(2001); | |
778 | |
779 #if 0 | |
780 DicomAssociation assoc; | |
781 assoc.ProposeGenericPresentationContext(UID_StorageCommitmentPushModelSOPClass); | |
782 assoc.ProposeGenericPresentationContext(UID_VerificationSOPClass); | |
783 assoc.ProposePresentationContext(UID_ComputedRadiographyImageStorage, | |
784 DicomTransferSyntax_JPEGProcess1); | |
785 assoc.ProposePresentationContext(UID_ComputedRadiographyImageStorage, | |
786 DicomTransferSyntax_JPEGProcess2_4); | |
787 assoc.ProposePresentationContext(UID_ComputedRadiographyImageStorage, | |
788 DicomTransferSyntax_JPEG2000); | |
789 | |
790 assoc.Open(params); | |
791 | |
792 int presID = ASC_findAcceptedPresentationContextID(&assoc.GetDcmtkAssociation(), UID_ComputedRadiographyImageStorage); | |
793 printf(">> %d\n", presID); | |
794 | |
795 std::map<DicomTransferSyntax, uint8_t> pc; | |
796 printf(">> %d\n", assoc.LookupAcceptedPresentationContext(pc, UID_ComputedRadiographyImageStorage)); | |
797 | |
798 for (std::map<DicomTransferSyntax, uint8_t>::const_iterator | |
799 it = pc.begin(); it != pc.end(); ++it) | |
800 { | |
801 printf("[%s] => %d\n", GetTransferSyntaxUid(it->first), it->second); | |
802 } | |
803 #else | |
804 { | |
805 DicomControlUserConnection assoc(params); | |
806 | |
807 try | |
808 { | |
809 printf(">> %d\n", assoc.Echo()); | |
810 } | |
811 catch (OrthancException&) | |
812 { | |
813 } | |
814 } | |
815 | |
816 params.SetRemoteApplicationEntityTitle("PACS"); | |
817 params.SetRemotePort(2000); | |
818 | |
819 { | |
820 DicomControlUserConnection assoc(params); | |
821 printf(">> %d\n", assoc.Echo()); | |
822 } | |
823 | |
824 #endif | |
825 } | |
826 | |
827 static void TestTranscode(DicomStoreUserConnection& scu, | |
828 const std::string& sopClassUid, | |
829 DicomTransferSyntax transferSyntax) | |
830 { | |
831 std::set<DicomTransferSyntax> accepted; | |
832 | |
833 scu.LookupTranscoding(accepted, sopClassUid, transferSyntax); | |
834 if (accepted.empty()) | |
835 { | |
836 throw OrthancException(ErrorCode_NetworkProtocol, | |
837 "The SOP class is not supported by the remote modality"); | |
838 } | |
839 | |
840 { | |
841 unsigned int count = 0; | |
842 for (std::set<DicomTransferSyntax>::const_iterator | |
843 it = accepted.begin(); it != accepted.end(); ++it) | |
844 { | |
845 LOG(INFO) << "available for transcoding " << (count++) << ": " << sopClassUid | |
846 << " / " << GetTransferSyntaxUid(*it); | |
847 } | |
848 } | |
849 | |
850 if (accepted.find(transferSyntax) != accepted.end()) | |
851 { | |
852 printf("**** OK, without transcoding !! [%s]\n", GetTransferSyntaxUid(transferSyntax)); | |
853 } | |
854 else | |
855 { | |
856 // Transcoding - only in Orthanc >= 1.7.0 | |
857 | |
858 const DicomTransferSyntax uncompressed[] = { | |
859 DicomTransferSyntax_LittleEndianImplicit, // Default transfer syntax | |
860 DicomTransferSyntax_LittleEndianExplicit, | |
861 DicomTransferSyntax_BigEndianExplicit | |
862 }; | |
863 | |
864 bool found = false; | |
865 for (size_t i = 0; i < 3; i++) | |
866 { | |
867 if (accepted.find(uncompressed[i]) != accepted.end()) | |
868 { | |
869 printf("**** TRANSCODING to %s\n", GetTransferSyntaxUid(uncompressed[i])); | |
870 found = true; | |
871 break; | |
872 } | |
873 } | |
874 | |
875 if (!found) | |
876 { | |
877 printf("**** KO KO KO\n"); | |
878 } | |
879 } | |
880 } | |
881 | |
882 | |
883 TEST(Toto, DISABLED_Store) | |
884 { | |
885 DicomAssociationParameters params; | |
886 params.SetLocalApplicationEntityTitle("ORTHANC"); | |
887 params.SetRemoteApplicationEntityTitle("STORESCP"); | |
888 params.SetRemotePort(2000); | |
889 | |
890 DicomStoreUserConnection assoc(params); | |
891 assoc.RegisterStorageClass(UID_MRImageStorage, DicomTransferSyntax_JPEGProcess1); | |
892 assoc.RegisterStorageClass(UID_MRImageStorage, DicomTransferSyntax_JPEGProcess2_4); | |
893 //assoc.RegisterStorageClass(UID_MRImageStorage, DicomTransferSyntax_LittleEndianExplicit); | |
894 | |
895 //assoc.SetUncompressedSyntaxesProposed(false); // Necessary for transcoding | |
896 assoc.SetCommonClassesProposed(false); | |
897 assoc.SetRetiredBigEndianProposed(true); | |
898 TestTranscode(assoc, UID_MRImageStorage, DicomTransferSyntax_LittleEndianExplicit); | |
899 TestTranscode(assoc, UID_MRImageStorage, DicomTransferSyntax_JPEG2000); | |
900 TestTranscode(assoc, UID_MRImageStorage, DicomTransferSyntax_JPEG2000); | |
901 } | |
902 | |
903 | |
904 TEST(Toto, DISABLED_Store2) | |
905 { | |
906 DicomAssociationParameters params; | |
907 params.SetLocalApplicationEntityTitle("ORTHANC"); | |
908 params.SetRemoteApplicationEntityTitle("STORESCP"); | |
909 params.SetRemotePort(2000); | |
910 | |
911 DicomStoreUserConnection assoc(params); | |
912 //assoc.SetCommonClassesProposed(false); | |
913 assoc.SetRetiredBigEndianProposed(true); | |
914 | |
915 std::string s; | |
916 Orthanc::SystemToolbox::ReadFile(s, "/tmp/i/" + std::string(GetTransferSyntaxUid(DicomTransferSyntax_BigEndianExplicit)) +".dcm"); | |
917 | |
918 std::string c, i; | |
919 assoc.Store(c, i, s.c_str(), s.size()); | |
920 printf("[%s] [%s]\n", c.c_str(), i.c_str()); | |
921 } | |
922 |