comparison OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp @ 5129:16138d6d568d

fix decoding of RLE images for which the "Planar Configuration" tag (0028,0006) equals 1
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 22 Dec 2022 15:28:14 +0100
parents 5e7404f23fa8
children 0ea402b4d901
comparison
equal deleted inserted replaced
5128:ede035d48b8e 5129:16138d6d568d
642 642
643 return target.release(); 643 return target.release();
644 } 644 }
645 645
646 646
647 static ImageAccessor* DecodePlanarConfiguration(const ImageAccessor& source)
648 {
649 /**
650 * This function will interleave the RGB channels, if the source
651 * DICOM image has the "Planar Configuration" (0028,0006) tag that
652 * equals 1. This process was not applied to images using the RLE
653 * codec, which led to the following issue:
654 * https://groups.google.com/g/orthanc-users/c/CSVWfRasSR0/m/y1XDRXVnAgAJ
655 **/
656
657 const unsigned int height = source.GetHeight();
658 const unsigned int width = source.GetWidth();
659 const size_t size = static_cast<size_t>(height) * static_cast<size_t>(width);
660
661 if (source.GetFormat() != PixelFormat_RGB24 ||
662 3 * width != source.GetPitch())
663 {
664 throw OrthancException(ErrorCode_NotImplemented);
665 }
666
667 std::unique_ptr<ImageAccessor> target(new Image(PixelFormat_RGB24, width, height, false));
668
669 const uint8_t* red = reinterpret_cast<const uint8_t*>(source.GetConstBuffer());
670 const uint8_t* green = red + size;
671 const uint8_t* blue = red + 2 * size;
672
673 for (unsigned int y = 0; y < height; y++)
674 {
675 uint8_t* interleaved = reinterpret_cast<uint8_t*>(target->GetRow(y));
676 for (unsigned int x = 0; x < width; x++)
677 {
678 interleaved[0] = *red;
679 interleaved[1] = *green;
680 interleaved[2] = *blue;
681 interleaved += 3;
682 red++;
683 green++;
684 blue++;
685 }
686 }
687
688 return target.release();
689 }
690
691
647 ImageAccessor* DicomImageDecoder::ApplyCodec 692 ImageAccessor* DicomImageDecoder::ApplyCodec
648 (const DcmCodec& codec, 693 (const DcmCodec& codec,
649 const DcmCodecParameter& parameters, 694 const DcmCodecParameter& parameters,
650 const DcmRepresentationParameter& representationParameter, 695 const DcmRepresentationParameter& representationParameter,
651 DcmDataset& dataset, 696 DcmDataset& dataset,
698 { 743 {
699 throw OrthancException(ErrorCode_BadFileFormat, 744 throw OrthancException(ErrorCode_BadFileFormat,
700 "Cannot decode a non-palette image"); 745 "Cannot decode a non-palette image");
701 } 746 }
702 747
703 return target.release(); 748 if (target->GetFormat() == PixelFormat_RGB24 &&
749 Orthanc::Toolbox::StripSpaces(decompressedColorModel.c_str()) == "RGB" &&
750 info.IsPlanar())
751 {
752 return DecodePlanarConfiguration(*target);
753 }
754 else
755 {
756 return target.release();
757 }
704 } 758 }
705 } 759 }
706 760
707 761
708 static void UndoBigEndianSwapping(ImageAccessor& decoded) 762 static void UndoBigEndianSwapping(ImageAccessor& decoded)