private void InitializeFrameData(DicomUncompressedPixelData owner, DicomElement pixelDataElement) { var obAttrib = pixelDataElement as DicomElementOb; if (obAttrib != null && obAttrib.StreamLength > 0) { for (var n = 0; n < NumberOfFrames; ++n) { _fd.Add(new FrameDataOB(owner, obAttrib, n)); } } var owAttrib = pixelDataElement as DicomElementOw; if (owAttrib != null && owAttrib.StreamLength > 0) { for (var n = 0; n < NumberOfFrames; ++n) { _fd.Add(new FrameDataOW(owner, owAttrib, n)); } } }
/// <summary> /// Get a specific frame's data in uncompressed format. /// </summary> /// <remarks> /// <para> /// If a DICOM file is loaded with the <see cref="DicomReadOptions.StorePixelDataReferences"/> /// option set, this method will only load the specific frame's data from the source file to /// do the decompress, thus reducing memory usage to only the frame being decompressed. /// </para> /// </remarks> /// <param name="frame">A zero offset frame to request.</param> /// <param name="photometricInterpretation">The photometric interpretation of the output data</param> /// <returns>A byte array containing the frame.</returns> public override byte[] GetFrame(int frame, out string photometricInterpretation) { DicomUncompressedPixelData pd = new DicomUncompressedPixelData(this); IDicomCodec codec = DicomCodecRegistry.GetCodec(TransferSyntax); if (codec == null) { LogAdapter.Logger.Error("Unable to get registered codec for {0}", TransferSyntax); throw new DicomCodecException("No registered codec for: " + TransferSyntax.Name); } DicomCodecParameters parameters = DicomCodecRegistry.GetCodecParameters(TransferSyntax, null); codec.DecodeFrame(frame, this, pd, parameters); pd.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; photometricInterpretation = pd.PhotometricInterpretation; return(pd.GetData()); }
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) { LogAdapter.Logger.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); } DicomElement 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 = ((DicomElementBinary)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); LogAdapter.Logger.Warn("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)) { LogAdapter.Logger.Warn("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. DicomElement element; if (DataSet.TryGetAttribute(DicomTags.Rows, out element) && !element.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 element) && !element.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) { LogAdapter.Logger.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); } } DicomElement 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. DicomElement element; if (DataSet.TryGetAttribute(DicomTags.Rows, out element) && !element.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 element) && !element.IsNull) { throw new DicomCodecException("Suspect Sop appears to be an image (Columns is non-empty), but has no pixel data."); } TransferSyntax = TransferSyntax.ExplicitVrLittleEndian; } } }
/// <summary> /// Constructor from a <see cref="DicomUncompressedPixelData"/> instance. /// </summary> /// <param name="pd">The uuncompressed pixel data attribute to initialize the object from.</param> public DicomCompressedPixelData(DicomUncompressedPixelData pd) : base(pd) { _sq = new DicomFragmentSequence(DicomTags.PixelData); }