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