/// <summary> /// Contructor from a <see cref="DicomCompressedPixelData"/> instance. /// </summary> /// <param name="compressedPixelData"></param> public DicomUncompressedPixelData(DicomCompressedPixelData compressedPixelData) : base(compressedPixelData) { if (BitsAllocated > 8) { _pd = new DicomAttributeOW(DicomTags.PixelData); } else { var pdTag = DicomTagDictionary.GetDicomTag(DicomTags.PixelData); var obTag = new DicomTag(DicomTags.PixelData, pdTag.Name, pdTag.VariableName, DicomVr.OBvr, pdTag.MultiVR, pdTag.VMLow, pdTag.VMHigh, pdTag.Retired); _pd = new DicomAttributeOB(obTag); } InitializeFrameData(this, _pd); }
public void ChangeTransferSyntax(TransferSyntax newTransferSyntax, IDicomCodec inputCodec, DicomCodecParameters inputParameters) { IDicomCodec codec = inputCodec; DicomCodecParameters parameters = inputParameters; if (newTransferSyntax.Encapsulated && TransferSyntax.Encapsulated) throw new DicomCodecException("Source and destination transfer syntaxes encapsulated"); if (newTransferSyntax.Encapsulated) { if (codec == null) { codec = DicomCodecRegistry.GetCodec(newTransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", newTransferSyntax); throw new DicomCodecException("No registered codec for: " + newTransferSyntax.Name); } } if (parameters == null) parameters = DicomCodecRegistry.GetCodecParameters(newTransferSyntax, DataSet); DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) throw new DicomCodecException("Sop pixel data has no valid value and cannot be compressed."); new OverlayPlaneModuleIod(DataSet).ExtractEmbeddedOverlays(); var pd = new DicomUncompressedPixelData(DataSet); using (var pixelStream = ((DicomAttributeBinary) pixelData).AsStream()) { //Before compression, make the pixel data more "typical", so it's harder to mess up the codecs. //NOTE: Could combine mask and align into one method so we're not iterating twice, but I prefer having the methods separate. if (DicomUncompressedPixelData.RightAlign(pixelStream, pd.BitsAllocated, pd.BitsStored, pd.HighBit)) { var newHighBit = (ushort) (pd.HighBit - pd.LowBit); Platform.Log(LogLevel.Debug, "Right aligned pixel data (High Bit: {0}->{1}).", pd.HighBit, newHighBit); pd.HighBit = newHighBit; //correct high bit after right-aligning. DataSet[DicomTags.HighBit].SetUInt16(0, newHighBit); } if (DicomUncompressedPixelData.ZeroUnusedBits(pixelStream, pd.BitsAllocated, pd.BitsStored, pd.HighBit)) { Platform.Log(LogLevel.Debug, "Zeroed some unused bits before compression."); } } // Set transfer syntax before compression, the codecs need it. var fragments = new DicomCompressedPixelData(pd) { TransferSyntax = newTransferSyntax }; codec.Encode(pd, fragments, parameters); fragments.UpdateMessage(this); //TODO: should we validate the number of frames in the compressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) throw new DicomCodecException("Sop has no pixel data after compression."); } else { //A bit cheap, but check for basic image attributes - if any exist // and are non-empty, there should probably be pixel data too. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); TransferSyntax = newTransferSyntax; } } else { if (codec == null) { codec = DicomCodecRegistry.GetCodec(TransferSyntax); if (codec == null) { Platform.Log(LogLevel.Error, "Unable to get registered codec for {0}", TransferSyntax); throw new DicomCodecException("No registered codec for: " + TransferSyntax.Name); } if (parameters == null) parameters = DicomCodecRegistry.GetCodecParameters(TransferSyntax, DataSet); } DicomAttribute pixelData; if (DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData)) { if (pixelData.IsNull) throw new DicomCodecException("Sop pixel data has no valid value and cannot be decompressed."); var fragments = new DicomCompressedPixelData(DataSet); var pd = new DicomUncompressedPixelData(fragments); codec.Decode(fragments, pd, parameters); pd.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; pd.UpdateMessage(this); //TODO: should we validate the number of frames in the decompressed data? if (!DataSet.TryGetAttribute(DicomTags.PixelData, out pixelData) || pixelData.IsNull) throw new DicomCodecException("Sop has no pixel data after decompression."); } else { //NOTE: doing this for consistency, really. DicomAttribute attribute; if (DataSet.TryGetAttribute(DicomTags.Rows, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Rows is non-empty), but has no pixel data."); if (DataSet.TryGetAttribute(DicomTags.Columns, out attribute) && !attribute.IsNull) throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; } } }