comparison OrthancFramework/Resources/Graveyard/TestTranscoding.cpp @ 4044:d25f4c0fa160 framework

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