Beispiel #1
0
        /// <summary>
        /// Fills the <see cref="OverlayData"/> property with the overlay(s) that had been encoded
        /// in the <see cref="DicomTags.PixelData"/> of the SOP Instance.  If the image is a
        /// multi-frame, overlay data is extracted from all the frames.
        /// </summary>
        /// <param name="pd">The pixel data that contains the encoded overlay(s).</param>
        /// <exception cref="DicomException">Thrown if <paramref name="pd"/> is not a valid source of embedded overlay data.</exception>
        /// <returns>True if the <see cref="OverlayData"/> was populated with data encoded in the pixel data; False if <see cref="OverlayData"/> is not empty.</returns>
        public unsafe bool ExtractEmbeddedOverlay(DicomUncompressedPixelData pd)
        {
            byte[] overlayData = this.OverlayData;
            if (overlayData != null && overlayData.Length > 0)
            {
                return(false);
            }

            // General sanity checks
            if (pd.SamplesPerPixel > 1)
            {
                throw new DicomException("Unable to convert embedded overlays when Samples Per Pixel > 1");
            }
            if (pd.BitsStored == 8 && pd.BitsAllocated == 8)
            {
                throw new DicomException("Unable to remove overlay with 8 Bits Stored and 8 Bits Allocated");
            }
            if (pd.BitsStored == 16 && pd.BitsAllocated == 16)
            {
                throw new DicomException("Unable to remove overlay with 16 Bits Stored and 16 Bits Allocated");
            }

            if (OverlayBitPosition <= pd.HighBit && OverlayBitPosition >= pd.LowBit)
            {
                throw new DicomException(String.Format("Invalid overlay bit position ({0}); overlay would be in the middle of the pixel data.", OverlayBitPosition));
            }

            int frameSize         = pd.UncompressedFrameSize;
            int overlayDataLength = (int)Math.Ceiling((frameSize * pd.NumberOfFrames) / (pd.BitsAllocated * 1d));
            int frameLength       = frameSize / pd.BytesAllocated;

            // Ensure even length overlay
            if (overlayDataLength % 2 == 1)
            {
                overlayDataLength++;
            }

            overlayData = new byte[overlayDataLength];
            int  overlayOffset = 0;
            byte overlayMask   = 0x01;

            if (pd.BitsAllocated <= 8)
            {
                var embeddedOverlayMask = ((byte)(0x1 << OverlayBitPosition));
                // Embededded overlays must exist for all frames, they can't be for a subset
                for (int i = 0; i < pd.NumberOfFrames; i++)
                {
                    byte[] frameData = pd.GetFrame(i);
                    ExtractEmbeddedOverlay(frameData, frameLength, embeddedOverlayMask, overlayData, ref overlayOffset, ref overlayMask);
                    pd.ReplaceFrame(i, frameData);
                }
            }
            else
            {
                var embeddedOverlayMask = ((ushort)(0x1 << OverlayBitPosition));
                // Embededded overlays must exist for all frames, they can't be for a subset
                for (int i = 0; i < pd.NumberOfFrames; i++)
                {
                    byte[] frameData = pd.GetFrame(i);
                    ExtractEmbeddedOverlay(frameData, frameLength, embeddedOverlayMask, overlayData, ref overlayOffset, ref overlayMask);
                    pd.ReplaceFrame(i, frameData);
                }
            }

            // Assign the new overlay tags
            this.OverlayBitPosition   = 0;
            this.OverlayBitsAllocated = 1;
            if (this.IsBigEndianOW)
            {
                // Just do a bulk swap, performance isn't much of an issue.
                ByteBuffer buffer = new ByteBuffer(overlayData, Endian.Little);
                buffer.Swap2();
                this.OverlayData = buffer.ToBytes();
            }
            else
            {
                this.OverlayData = overlayData;
            }

            // Cleanup Rows/Columns if necessary
            if (this.OverlayColumns == 0)
            {
                this.OverlayColumns = pd.ImageWidth;
            }
            if (this.OverlayRows == 0)
            {
                this.OverlayRows = pd.ImageHeight;
            }

            return(true);
        }