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)