public void TestNormalizePixelData16Signed() { const int bitsAllocated = 16; var bitsStored = 16; var highBit = 15; var pixelData = ShortToBytes(0, 32767, -32768); var expected = (byte[])pixelData.Clone(); DicomUncompressedPixelData.NormalizePixelData(pixelData, bitsAllocated, bitsStored, highBit, true); AssertBytesEqual(expected, pixelData, "16-bit Signed (BitsStored={0} HighBit={1})", bitsStored, highBit); bitsStored = 15; highBit = 14; pixelData = ShortToBytes(0, BinaryToShort("0100000000000000"), BinaryToShort("0011111111111111")); expected = ShortToBytes(0, BinaryToShort("1100000000000000"), BinaryToShort("0011111111111111")); DicomUncompressedPixelData.NormalizePixelData(pixelData, bitsAllocated, bitsStored, highBit, true); AssertBytesEqual(expected, pixelData, "16-bit Signed (BitsStored={0} HighBit={1})", bitsStored, highBit); bitsStored = 15; highBit = 15; pixelData = ShortToBytes(0, BinaryToShort("1111111111111110"), BinaryToShort("0111111111111110")); expected = ShortToBytes(0, BinaryToShort("1111111111111111"), BinaryToShort("0011111111111111")); DicomUncompressedPixelData.NormalizePixelData(pixelData, bitsAllocated, bitsStored, highBit, true); AssertBytesEqual(expected, pixelData, "16-bit Signed (BitsStored={0} HighBit={1})", bitsStored, highBit); bitsStored = 12; highBit = 14; pixelData = ShortToBytes(0, BinaryToShort("1111111111111111"), BinaryToShort("0111111111111110")); expected = ShortToBytes(0, BinaryToShort("1111111111111111"), BinaryToShort("1111111111111111")); DicomUncompressedPixelData.NormalizePixelData(pixelData, bitsAllocated, bitsStored, highBit, true); AssertBytesEqual(expected, pixelData, "16-bit Signed (BitsStored={0} HighBit={1})", bitsStored, highBit); }
/// <summary> /// Normalizes grayscale pixel data by masking out non-data bits and shifting the data bits to start at the lowest bit position. /// </summary> /// <remarks> /// <para> /// The pixel data is normalized such that the effective high bit is precisely 1 less than bits stored. /// Filling of the high-order non-data bits is performed according to the sign of the pixel value when /// the pixel representation is signed, and always with 0 when the pixel reresentation is unsigned. /// </para> /// <para> /// The provided <paramref name="dicomAttributeProvider"/> is <b>not</b> updated with the effective high bit, /// nor is the <see cref="DicomTags.PixelData"/> attribute updated in any way. The only change is to the given /// pixel data buffer such that pixels can be read, 8 or 16 bits at a time, and interpreted immediately as /// <see cref="byte"/> or <see cref="ushort"/> (or their signed equivalents <see cref="sbyte"/> and <see cref="short"/>). /// </para> /// </remarks> /// <param name="dicomAttributeProvider">A dataset containing information about the representation of pixels in the <paramref name="pixelData"/>.</param> /// <param name="pixelData">The pixel data buffer to normalize (for 16-bit samples, the data should be in machine order).</param> protected internal static void NormalizeGrayscalePixels(IDicomAttributeProvider dicomAttributeProvider, byte[] pixelData) { //TODO (CR Orion): these are retrieved again with default values directly below. if (dicomAttributeProvider[DicomTags.BitsAllocated].IsEmpty) { const string msg = "BitsAllocated must not be empty."; throw new ArgumentNullException("dicomAttributeProvider", msg); } if (dicomAttributeProvider[DicomTags.BitsStored].IsEmpty) { const string msg = "BitsStored must not be empty."; throw new ArgumentNullException("dicomAttributeProvider", msg); } int bitsAllocated = dicomAttributeProvider[DicomTags.BitsAllocated].GetInt32(0, -1); int bitsStored = dicomAttributeProvider[DicomTags.BitsStored].GetInt32(0, -1); int highBit = dicomAttributeProvider[DicomTags.HighBit].GetInt32(0, bitsStored - 1); bool isSigned = dicomAttributeProvider[DicomTags.PixelRepresentation].GetInt32(0, 0) > 0; if (bitsAllocated != 8 && bitsAllocated != 16) { const string msg = "BitsAllocated must be either 8 or 16."; throw new ArgumentException(msg, "dicomAttributeProvider"); } if (bitsAllocated == 16 && pixelData.Length % 2 != 0) { const string msg = "Pixel data length must be even."; throw new ArgumentException(msg, "pixelData"); } if (highBit + 1 < bitsStored || highBit >= bitsAllocated) { highBit = bitsStored - 1; // #10029 - if high bit is out of range for some reason, just assume bits stored - 1 (which is probably the case for 99% of all DICOM images) } DicomUncompressedPixelData.NormalizePixelData(pixelData, bitsAllocated, bitsStored, highBit, isSigned); }
public void TestNormalizePixelData8Signed() { const int bitsAllocated = 8; var bitsStored = 8; var highBit = 7; var pixelData = SByteToBytes(BinaryToSByte("10000000"), 0, BinaryToSByte("01111111")); var expected = (byte[])pixelData.Clone(); DicomUncompressedPixelData.NormalizePixelData(pixelData, bitsAllocated, bitsStored, highBit, true); AssertBytesEqual(expected, pixelData, "8-bit Signed (BitsStored={0} HighBit={1})", bitsStored, highBit); bitsStored = 7; highBit = 6; pixelData = new byte[] { 0, BinaryToByte("01000000"), BinaryToByte("00111111") }; expected = new byte[] { 0, BinaryToByte("11000000"), BinaryToByte("00111111") }; DicomUncompressedPixelData.NormalizePixelData(pixelData, bitsAllocated, bitsStored, highBit, true); AssertBytesEqual(expected, pixelData, "8-bit Signed (BitsStored={0} HighBit={1})", bitsStored, highBit); bitsStored = 7; highBit = 7; pixelData = new byte[] { 0, BinaryToByte("11111110"), BinaryToByte("01111110") }; expected = new byte[] { 0, BinaryToByte("11111111"), BinaryToByte("00111111") }; DicomUncompressedPixelData.NormalizePixelData(pixelData, bitsAllocated, bitsStored, highBit, true); AssertBytesEqual(expected, pixelData, "8-bit Signed (BitsStored={0} HighBit={1})", bitsStored, highBit); bitsStored = 5; highBit = 6; pixelData = new byte[] { 0, BinaryToByte("11111111"), BinaryToByte("01111110") }; expected = new byte[] { 0, BinaryToByte("11111111"), BinaryToByte("11111111") }; DicomUncompressedPixelData.NormalizePixelData(pixelData, bitsAllocated, bitsStored, highBit, true); AssertBytesEqual(expected, pixelData, "8-bit Signed (BitsStored={0} HighBit={1})", bitsStored, highBit); }