Mercurial > hg > orthanc
comparison OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp @ 4529:5774fe497ff2
fix decoding of images on big-endian architectures
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 24 Feb 2021 21:06:34 +0100 |
parents | d9473bd5ed43 |
children | 4cfd96732076 |
comparison
equal
deleted
inserted
replaced
4528:93a51d228d80 | 4529:5774fe497ff2 |
---|---|
89 | 89 |
90 #include <dcmtk/dcmdata/dcdeftag.h> | 90 #include <dcmtk/dcmdata/dcdeftag.h> |
91 #include <dcmtk/dcmdata/dcrleccd.h> | 91 #include <dcmtk/dcmdata/dcrleccd.h> |
92 #include <dcmtk/dcmdata/dcrlecp.h> | 92 #include <dcmtk/dcmdata/dcrlecp.h> |
93 #include <dcmtk/dcmdata/dcrlerp.h> | 93 #include <dcmtk/dcmdata/dcrlerp.h> |
94 #include <dcmtk/dcmdata/dcswap.h> | |
94 | 95 |
95 #if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1 | 96 #if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1 |
96 # include <dcmtk/dcmjpeg/djrplol.h> | 97 # include <dcmtk/dcmjpeg/djrplol.h> |
97 # include <dcmtk/dcmjpls/djcodecd.h> | 98 # include <dcmtk/dcmjpls/djcodecd.h> |
98 # include <dcmtk/dcmjpls/djcparam.h> | 99 # include <dcmtk/dcmjpls/djcparam.h> |
120 # define EXS_JPEGProcess14SV1 EXS_JPEGProcess14SV1TransferSyntax | 121 # define EXS_JPEGProcess14SV1 EXS_JPEGProcess14SV1TransferSyntax |
121 #endif | 122 #endif |
122 | 123 |
123 namespace Orthanc | 124 namespace Orthanc |
124 { | 125 { |
126 static const Endianness ENDIANNESS = Toolbox::DetectEndianness(); | |
125 static const DicomTag DICOM_TAG_CONTENT(0x07a1, 0x100a); | 127 static const DicomTag DICOM_TAG_CONTENT(0x07a1, 0x100a); |
126 static const DicomTag DICOM_TAG_COMPRESSION_TYPE(0x07a1, 0x1011); | 128 static const DicomTag DICOM_TAG_COMPRESSION_TYPE(0x07a1, 0x1011); |
127 | 129 |
128 | 130 |
129 bool DicomImageDecoder::IsPsmctRle1(DcmDataset& dataset) | 131 bool DicomImageDecoder::IsPsmctRle1(DcmDataset& dataset) |
554 info.GetWidth(), | 556 info.GetWidth(), |
555 info.GetHeight(), | 557 info.GetHeight(), |
556 info.GetWidth() * GetBytesPerPixel(sourceFormat), | 558 info.GetWidth() * GetBytesPerPixel(sourceFormat), |
557 buffer + frame * frameSize); | 559 buffer + frame * frameSize); |
558 | 560 |
559 ImageProcessing::Convert(*target, sourceImage); | 561 switch (ENDIANNESS) |
562 { | |
563 case Endianness_Little: | |
564 ImageProcessing::Convert(*target, sourceImage); | |
565 break; | |
566 | |
567 case Endianness_Big: | |
568 { | |
569 // We cannot do byte swapping directly on the constant DcmDataset | |
570 std::unique_ptr<ImageAccessor> copy(Image::Clone(sourceImage)); | |
571 ImageProcessing::SwapEndianness(*copy); | |
572 ImageProcessing::Convert(*target, *copy); | |
573 break; | |
574 } | |
575 | |
576 default: | |
577 throw OrthancException(ErrorCode_InternalError); | |
578 } | |
579 | |
560 ImageProcessing::ShiftRight(*target, info.GetShift()); | 580 ImageProcessing::ShiftRight(*target, info.GetShift()); |
561 fastVersionSuccess = true; | 581 fastVersionSuccess = true; |
562 } | 582 } |
563 } | 583 } |
564 catch (OrthancException&) | 584 catch (OrthancException&) |
658 return target.release(); | 678 return target.release(); |
659 } | 679 } |
660 } | 680 } |
661 | 681 |
662 | 682 |
683 static void UndoBigEndianSwapping(ImageAccessor& decoded) | |
684 { | |
685 if (ENDIANNESS == Endianness_Big && | |
686 decoded.GetFormat() == PixelFormat_Grayscale8) | |
687 { | |
688 /** | |
689 * Undo the call to "swapIfNecessary()" that is done in | |
690 * "dcmjpeg/libsrc/djcodecd.cc" and "dcmjpls/libsrc/djcodecd.cc" | |
691 * if "jpeg->bytesPerSample() == 1", presumably because DCMTK | |
692 * plans for DICOM-to-DICOM conversion | |
693 **/ | |
694 if (decoded.GetPitch() % 2 == 0) | |
695 { | |
696 swapBytes(decoded.GetBuffer(), decoded.GetPitch() * decoded.GetHeight(), sizeof(uint16_t)); | |
697 } | |
698 else | |
699 { | |
700 throw OrthancException(ErrorCode_InternalError, "Cannot swap the bytes of an image that has an odd width"); | |
701 } | |
702 } | |
703 } | |
704 | |
705 | |
663 ImageAccessor* DicomImageDecoder::Decode(DcmDataset& dataset, | 706 ImageAccessor* DicomImageDecoder::Decode(DcmDataset& dataset, |
664 unsigned int frame) | 707 unsigned int frame) |
665 { | 708 { |
666 E_TransferSyntax syntax = dataset.getCurrentXfer(); | 709 E_TransferSyntax syntax = dataset.getCurrentXfer(); |
667 | 710 |
708 | 751 |
709 default: | 752 default: |
710 throw OrthancException(ErrorCode_InternalError); | 753 throw OrthancException(ErrorCode_InternalError); |
711 } | 754 } |
712 | 755 |
713 return ApplyCodec(*decoder, parameters, representationParameter, dataset, frame); | 756 std::unique_ptr<ImageAccessor> result(ApplyCodec(*decoder, parameters, representationParameter, dataset, frame)); |
757 UndoBigEndianSwapping(*result); // New in Orthanc 1.9.1 to decode on big-endian architectures | |
758 return result.release(); | |
714 } | 759 } |
715 #endif | 760 #endif |
716 | 761 |
717 | 762 |
718 #if ORTHANC_ENABLE_DCMTK_JPEG == 1 | 763 #if ORTHANC_ENABLE_DCMTK_JPEG == 1 |
769 break; | 814 break; |
770 | 815 |
771 default: | 816 default: |
772 throw OrthancException(ErrorCode_InternalError); | 817 throw OrthancException(ErrorCode_InternalError); |
773 } | 818 } |
774 | 819 |
775 return ApplyCodec(*decoder, parameters, representationParameter, dataset, frame); | 820 std::unique_ptr<ImageAccessor> result(ApplyCodec(*decoder, parameters, representationParameter, dataset, frame)); |
821 UndoBigEndianSwapping(*result); // New in Orthanc 1.9.1 to decode on big-endian architectures | |
822 return result.release(); | |
776 } | 823 } |
777 #endif | 824 #endif |
778 | 825 |
779 | 826 |
780 if (syntax == EXS_RLELossless) | 827 if (syntax == EXS_RLELossless) |