public void DecodeFrame(int frame, DicomCompressedPixelData oldPixelData, DicomUncompressedPixelData newPixelData, DicomCodecParameters parameters) { DicomRleCodecParameters rleParams = parameters as DicomRleCodecParameters ?? new DicomRleCodecParameters(); int pixelCount = oldPixelData.ImageWidth * oldPixelData.ImageHeight; int numberOfSegments = oldPixelData.BytesAllocated * oldPixelData.SamplesPerPixel; int segmentLength = (pixelCount & 1) == 1 ? pixelCount + 1 : pixelCount; byte[] segment = new byte[segmentLength]; byte[] frameData = new byte[oldPixelData.UncompressedFrameSize]; IList <DicomFragment> rleData = oldPixelData.GetFrameFragments(frame); RLEDecoder decoder = new RLEDecoder(rleData); if (decoder.NumberOfSegments != numberOfSegments) { throw new DicomCodecException("Unexpected number of RLE segments!"); } for (int s = 0; s < numberOfSegments; s++) { decoder.DecodeSegment(s, segment); int sample = s / oldPixelData.BytesAllocated; int sabyte = s % oldPixelData.BytesAllocated; int pos; int offset; if (newPixelData.PlanarConfiguration == 0) { pos = sample * oldPixelData.BytesAllocated; offset = oldPixelData.SamplesPerPixel * oldPixelData.BytesAllocated; } else { pos = sample * oldPixelData.BytesAllocated * pixelCount; offset = oldPixelData.BytesAllocated; } if (rleParams.ReverseByteOrder) { pos += sabyte; } else { pos += oldPixelData.BytesAllocated - sabyte - 1; } for (int p = 0; p < pixelCount; p++) { frameData[pos] = segment[p]; pos += offset; } } newPixelData.AppendFrame(frameData); }
public DicomCompressCommand(DicomMessageBase file, TransferSyntax syntax, IDicomCodec codec, DicomCodecParameters parms) : base("DICOM Compress Command", true) { _file = file; _syntax = syntax; _codec = codec; _parms = parms; }
public void DecodeFrame(int frame, DicomCompressedPixelData oldPixelData, DicomUncompressedPixelData newPixelData, DicomCodecParameters parameters) { using (var input = new MemoryStream(oldPixelData.GetFrameFragmentData(frame))) using (var gzipStream = new GZipStream(input, CompressionMode.Decompress, false)) { var data = new byte[oldPixelData.UncompressedFrameSize]; gzipStream.Read(data, 0, data.Length); newPixelData.AppendFrame(data); } }
public void DecodeFrame(int frame, DicomCompressedPixelData oldPixelData, DicomUncompressedPixelData newPixelData, DicomCodecParameters parameters) { if (oldPixelData.UncompressedFrameSize%2 == 1) { using (var stream = new MemoryStream(oldPixelData.GetFrameFragmentData(frame))) { var data = new byte[oldPixelData.UncompressedFrameSize]; stream.Read(data, 0, data.Length); newPixelData.AppendFrame(data); } } else { newPixelData.AppendFrame(oldPixelData.GetFrameFragmentData(frame)); } }
public void Encode(DicomUncompressedPixelData oldPixelData, DicomCompressedPixelData newPixelData, DicomCodecParameters parameters) { for (var n = 0; n < oldPixelData.NumberOfFrames; ++n) { using (var output = new MemoryStream()) { using (var gzipStream = new GZipStream(output, CompressionMode.Compress, true)) { var data = oldPixelData.GetFrame(n); gzipStream.Write(data, 0, data.Length); } // if the compressed stream is odd length, append an extra byte - gzip will know that it's padding during decompression if (output.Length%2 == 1) output.WriteByte(0); newPixelData.AddFrameFragment(output.ToArray()); } } }
public DicomCompressCommand(DicomMessageBase file, XmlDocument parms, bool failOnCodecException) : base("DICOM Compress Command", true) { _file = file; _failOnCodecException = failOnCodecException; XmlElement element = parms.DocumentElement; string syntax = element.Attributes["syntax"].Value; _syntax = TransferSyntax.GetTransferSyntax(syntax); if (_syntax == null) { string failureDescription = String.Format("Invalid transfer syntax in compression command: {0}", element.Attributes["syntax"].Value); Platform.Log(LogLevel.Error, "Error with input syntax: {0}", failureDescription); throw new DicomCodecException(failureDescription); } IDicomCodecFactory[] codecs = DicomCodecRegistry.GetCodecFactories(); IDicomCodecFactory theCodecFactory = null; foreach (IDicomCodecFactory codec in codecs) { if (codec.CodecTransferSyntax.Equals(_syntax)) { theCodecFactory = codec; break; } } if (theCodecFactory == null) { string failureDescription = String.Format("Unable to find codec for compression: {0}", _syntax.Name); Platform.Log(LogLevel.Error, "Error with compression input parameters: {0}", failureDescription); throw new DicomCodecException(failureDescription); } _codec = theCodecFactory.GetDicomCodec(); _parms = theCodecFactory.GetCodecParameters(parms); }
/// <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) { Platform.Log(LogLevel.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 Encode(DicomUncompressedPixelData oldPixelData, DicomCompressedPixelData newPixelData, DicomCodecParameters parameters) { if (oldPixelData.UncompressedFrameSize%2 == 1) { for (var n = 0; n < oldPixelData.NumberOfFrames; ++n) { using (var stream = new MemoryStream()) { var data = oldPixelData.GetFrame(n); stream.Write(data, 0, data.Length); stream.WriteByte(0); // must pad fragments to even length newPixelData.AddFrameFragment(stream.ToArray()); } } } else { for (var n = 0; n < oldPixelData.NumberOfFrames; ++n) { newPixelData.AddFrameFragment(oldPixelData.GetFrame(n)); } } }
public void Encode(DicomUncompressedPixelData oldPixelData, DicomCompressedPixelData newPixelData, DicomCodecParameters parameters) { for (var n = 0; n < oldPixelData.NumberOfFrames; ++n) { using (var output = new MemoryStream()) { using (var gzipStream = new GZipStream(output, CompressionMode.Compress, true)) { var data = oldPixelData.GetFrame(n); gzipStream.Write(data, 0, data.Length); } // if the compressed stream is odd length, append an extra byte - gzip will know that it's padding during decompression if (output.Length % 2 == 1) { output.WriteByte(0); } newPixelData.AddFrameFragment(output.ToArray()); } } }
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); var rawPixelData = (byte[])pixelData.Values; //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(rawPixelData, 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(rawPixelData, 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; } } }
public void DecodeFrame(int frame, DicomCompressedPixelData oldPixelData, DicomUncompressedPixelData newPixelData, DicomCodecParameters parameters) { if (oldPixelData.UncompressedFrameSize % 2 == 1) { using (var stream = new MemoryStream(oldPixelData.GetFrameFragmentData(frame))) { var data = new byte[oldPixelData.UncompressedFrameSize]; stream.Read(data, 0, data.Length); newPixelData.AppendFrame(data); } } else { newPixelData.AppendFrame(oldPixelData.GetFrameFragmentData(frame)); } }
public void Encode(DicomUncompressedPixelData oldPixelData, DicomCompressedPixelData newPixelData, DicomCodecParameters parameters) { DicomRleCodecParameters rleParams = parameters as DicomRleCodecParameters; if (rleParams == null) throw new DicomCodecException("Unexpected RLE Codec parameters"); // Convert to RGB if (oldPixelData.HasPaletteColorLut && parameters.ConvertPaletteToRGB) { oldPixelData.ConvertPaletteColorToRgb(); newPixelData.HasPaletteColorLut = false; newPixelData.SamplesPerPixel = oldPixelData.SamplesPerPixel; newPixelData.PlanarConfiguration = oldPixelData.PlanarConfiguration; newPixelData.PhotometricInterpretation = oldPixelData.PhotometricInterpretation; } int pixelCount = oldPixelData.ImageWidth * oldPixelData.ImageHeight; int numberOfSegments = oldPixelData.BytesAllocated * oldPixelData.SamplesPerPixel; for (int i = 0; i < oldPixelData.NumberOfFrames; i++) { RLEEncoder encoder = new RLEEncoder(); byte[] frameData = oldPixelData.GetFrame(i); for (int s = 0; s < numberOfSegments; s++) { encoder.NextSegment(); int sample = s / oldPixelData.BytesAllocated; int sabyte = s % oldPixelData.BytesAllocated; int pos; int offset; if (newPixelData.PlanarConfiguration == 0) { pos = sample * oldPixelData.BytesAllocated; offset = numberOfSegments; } else { pos = sample * oldPixelData.BytesAllocated * pixelCount; offset = oldPixelData.BytesAllocated; } if (rleParams.ReverseByteOrder) pos += sabyte; else pos += oldPixelData.BytesAllocated - sabyte - 1; for (int p = 0; p < pixelCount; p++) { if (pos >= frameData.Length) throw new DicomCodecException(""); encoder.Encode(frameData[pos]); pos += offset; } encoder.Flush(); } encoder.MakeEvenLength(); newPixelData.AddFrameFragment(encoder.GetBuffer()); } }
public void Encode(DicomUncompressedPixelData oldPixelData, DicomCompressedPixelData newPixelData, DicomCodecParameters parameters) { DicomRleCodecParameters rleParams = parameters as DicomRleCodecParameters ?? new DicomRleCodecParameters(); // Convert to RGB if (oldPixelData.HasPaletteColorLut && parameters.ConvertPaletteToRGB) { oldPixelData.ConvertPaletteColorToRgb(); newPixelData.HasPaletteColorLut = false; newPixelData.SamplesPerPixel = oldPixelData.SamplesPerPixel; newPixelData.PlanarConfiguration = oldPixelData.PlanarConfiguration; newPixelData.PhotometricInterpretation = oldPixelData.PhotometricInterpretation; } int pixelCount = oldPixelData.ImageWidth * oldPixelData.ImageHeight; int numberOfSegments = oldPixelData.BytesAllocated * oldPixelData.SamplesPerPixel; for (int i = 0; i < oldPixelData.NumberOfFrames; i++) { RLEEncoder encoder = new RLEEncoder(); byte[] frameData = oldPixelData.GetFrame(i); for (int s = 0; s < numberOfSegments; s++) { encoder.NextSegment(); int sample = s / oldPixelData.BytesAllocated; int sabyte = s % oldPixelData.BytesAllocated; int pos; int offset; if (newPixelData.PlanarConfiguration == 0) { pos = sample * oldPixelData.BytesAllocated; offset = numberOfSegments; } else { pos = sample * oldPixelData.BytesAllocated * pixelCount; offset = oldPixelData.BytesAllocated; } if (rleParams.ReverseByteOrder) { pos += sabyte; } else { pos += oldPixelData.BytesAllocated - sabyte - 1; } for (int p = 0; p < pixelCount; p++) { if (pos >= frameData.Length) { throw new DicomCodecException(""); } encoder.Encode(frameData[pos]); pos += offset; } encoder.Flush(); } encoder.MakeEvenLength(); newPixelData.AddFrameFragment(encoder.GetBuffer()); } }
public void Decode(DicomCompressedPixelData oldPixelData, DicomUncompressedPixelData newPixelData, DicomCodecParameters parameters) { for (var n = 0; n < oldPixelData.NumberOfFrames; ++n) { DecodeFrame(n, oldPixelData, newPixelData, parameters); } }
public void DecodeFrame(int frame, DicomCompressedPixelData oldPixelData, DicomUncompressedPixelData newPixelData, DicomCodecParameters parameters) { DicomRleCodecParameters rleParams = parameters as DicomRleCodecParameters; if (rleParams == null) throw new DicomCodecException("Unexpected RLE Codec parameters"); int pixelCount = oldPixelData.ImageWidth * oldPixelData.ImageHeight; int numberOfSegments = oldPixelData.BytesAllocated * oldPixelData.SamplesPerPixel; int segmentLength = (pixelCount & 1) == 1 ? pixelCount + 1 : pixelCount; byte[] segment = new byte[segmentLength]; byte[] frameData = new byte[oldPixelData.UncompressedFrameSize]; IList<DicomFragment> rleData = oldPixelData.GetFrameFragments(frame); RLEDecoder decoder = new RLEDecoder(rleData); if (decoder.NumberOfSegments != numberOfSegments) throw new DicomCodecException("Unexpected number of RLE segments!"); for (int s = 0; s < numberOfSegments; s++) { decoder.DecodeSegment(s, segment); int sample = s / oldPixelData.BytesAllocated; int sabyte = s % oldPixelData.BytesAllocated; int pos; int offset; if (newPixelData.PlanarConfiguration == 0) { pos = sample * oldPixelData.BytesAllocated; offset = oldPixelData.SamplesPerPixel * oldPixelData.BytesAllocated; } else { pos = sample * oldPixelData.BytesAllocated * pixelCount; offset = oldPixelData.BytesAllocated; } if (rleParams.ReverseByteOrder) pos += sabyte; else pos += oldPixelData.BytesAllocated - sabyte - 1; for (int p = 0; p < pixelCount; p++) { frameData[pos] = segment[p]; pos += offset; } } newPixelData.AppendFrame(frameData); }
public void Encode(DicomUncompressedPixelData oldPixelData, DicomCompressedPixelData newPixelData, DicomCodecParameters parameters) { if (oldPixelData.UncompressedFrameSize % 2 == 1) { for (var n = 0; n < oldPixelData.NumberOfFrames; ++n) { using (var stream = new MemoryStream()) { var data = oldPixelData.GetFrame(n); stream.Write(data, 0, data.Length); stream.WriteByte(0); // must pad fragments to even length newPixelData.AddFrameFragment(stream.ToArray()); } } } else { for (var n = 0; n < oldPixelData.NumberOfFrames; ++n) { newPixelData.AddFrameFragment(oldPixelData.GetFrame(n)); } } }
public void Decode(DicomCompressedPixelData oldPixelData, DicomUncompressedPixelData newPixelData, DicomCodecParameters parameters) { for (var n = 0; n < oldPixelData.NumberOfFrames; ++n) DecodeFrame(n, oldPixelData, newPixelData, parameters); }
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."); } DicomUncompressedPixelData pd = new DicomUncompressedPixelData(DataSet); DicomCompressedPixelData fragments = new DicomCompressedPixelData(pd); // Set before compression, the codecs need it. fragments.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."); } DicomCompressedPixelData fragments = new DicomCompressedPixelData(DataSet); DicomUncompressedPixelData pd = new DicomUncompressedPixelData(fragments); codec.Decode(fragments, pd, parameters); pd.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; } } }