public Write ( TransferSyntax syntax, DicomAttributeCollection dataset, DicomWriteOptions options ) : DicomWriteStatus | ||
syntax | TransferSyntax | |
dataset | DicomAttributeCollection | |
options | DicomWriteOptions | |
return | DicomWriteStatus |
public DicomWriteStatus Write(TransferSyntax syntax, DicomAttributeCollection dataset, DicomWriteOptions options)
{
TransferSyntax = syntax;
foreach (DicomAttribute item in dataset)
{
if (item.IsEmpty)
continue;
if (item.Tag.Element == 0x0000)
continue;
if (Flags.IsSet(options, DicomWriteOptions.CalculateGroupLengths)
&& item.Tag.Group != _group)
{
_group = item.Tag.Group;
_writer.Write((ushort) _group);
_writer.Write((ushort) 0x0000);
if (_syntax.ExplicitVr)
{
_writer.Write((byte) 'U');
_writer.Write((byte) 'L');
_writer.Write((ushort) 4);
}
else
{
_writer.Write((uint) 4);
}
_writer.Write((uint) dataset.CalculateGroupWriteLength(_group, _syntax, options));
}
_writer.Write((ushort) item.Tag.Group);
_writer.Write((ushort) item.Tag.Element);
if (_syntax.ExplicitVr)
{
_writer.Write((byte) item.Tag.VR.Name[0]);
_writer.Write((byte) item.Tag.VR.Name[1]);
}
if (item is DicomAttributeSQ)
{
var sq = item as DicomAttributeSQ;
if (_syntax.ExplicitVr)
_writer.Write((ushort) 0x0000);
if (Flags.IsSet(options, DicomWriteOptions.DigitalSignatureMacEncoding))
{
// length field is not written when generating digital signature MAC
}
else if (Flags.IsSet(options, DicomWriteOptions.ExplicitLengthSequence))
{
int hl = _syntax.ExplicitVr ? 12 : 8;
_writer.Write((uint) sq.CalculateWriteLength(_syntax, options & ~DicomWriteOptions.CalculateGroupLengths) - (uint) hl);
}
else
{
_writer.Write((uint) _undefinedLength);
}
foreach (DicomSequenceItem ids in (DicomSequenceItem[]) sq.Values)
{
_writer.Write((ushort) DicomTag.Item.Group);
_writer.Write((ushort) DicomTag.Item.Element);
if (Flags.IsSet(options, DicomWriteOptions.DigitalSignatureMacEncoding))
{
// length field is not written when generating digital signature MAC
}
else if (Flags.IsSet(options, DicomWriteOptions.ExplicitLengthSequenceItem))
{
_writer.Write((uint) ids.CalculateWriteLength(_syntax, options & ~DicomWriteOptions.CalculateGroupLengths));
}
else
{
_writer.Write((uint) _undefinedLength);
}
Write(TransferSyntax, ids, options & ~DicomWriteOptions.CalculateGroupLengths);
if (!Flags.IsSet(options, DicomWriteOptions.ExplicitLengthSequenceItem)
&& !Flags.IsSet(options, DicomWriteOptions.DigitalSignatureMacEncoding))
{
_writer.Write((ushort) DicomTag.ItemDelimitationItem.Group);
_writer.Write((ushort) DicomTag.ItemDelimitationItem.Element);
_writer.Write((uint) 0x00000000);
}
}
if (Flags.IsSet(options, DicomWriteOptions.DigitalSignatureMacEncoding))
{
_writer.Write((ushort) DicomTag.SequenceDelimitationItem.Group);
_writer.Write((ushort) DicomTag.SequenceDelimitationItem.Element);
}
else if (!Flags.IsSet(options, DicomWriteOptions.ExplicitLengthSequence))
{
_writer.Write((ushort) DicomTag.SequenceDelimitationItem.Group);
_writer.Write((ushort) DicomTag.SequenceDelimitationItem.Element);
_writer.Write((uint) 0x00000000);
}
}
else if (item is DicomFragmentSequence)
{
var fs = item as DicomFragmentSequence;
if (_syntax.ExplicitVr)
_writer.Write((ushort) 0x0000);
if (Flags.IsSet(options, DicomWriteOptions.DigitalSignatureMacEncoding))
{
// length field is not written when generating digital signature MAC
}
else
{
_writer.Write((uint) _undefinedLength);
}
_writer.Write((ushort) DicomTag.Item.Group);
_writer.Write((ushort) DicomTag.Item.Element);
if (Flags.IsSet(options, DicomWriteOptions.DigitalSignatureMacEncoding))
{
// length field is not written when generating digital signature MAC
if (fs.HasOffsetTable) fs.OffsetTableBuffer.CopyTo(_writer);
}
else if (Flags.IsSet(options, DicomWriteOptions.WriteFragmentOffsetTable) && fs.HasOffsetTable)
{
_writer.Write((uint) fs.OffsetTableBuffer.Length);
fs.OffsetTableBuffer.CopyTo(_writer);
}
else
{
_writer.Write((uint) 0x00000000);
}
foreach (DicomFragment bb in fs.Fragments)
{
_writer.Write((ushort) DicomTag.Item.Group);
_writer.Write((ushort) DicomTag.Item.Element);
if (Flags.IsSet(options, DicomWriteOptions.DigitalSignatureMacEncoding))
{
// length field is not written when generating digital signature MAC
}
else
{
_writer.Write((uint) bb.Length);
}
bb.GetByteBuffer(_syntax).CopyTo(_writer);
}
if (Flags.IsSet(options, DicomWriteOptions.DigitalSignatureMacEncoding))
{
_writer.Write((ushort) DicomTag.SequenceDelimitationItem.Group);
_writer.Write((ushort) DicomTag.SequenceDelimitationItem.Element);
}
else
{
_writer.Write((ushort) DicomTag.SequenceDelimitationItem.Group);
_writer.Write((ushort) DicomTag.SequenceDelimitationItem.Element);
_writer.Write((uint) 0x00000000);
}
}
else
{
DicomAttribute de = item;
ByteBuffer theData = de.GetByteBuffer(_syntax, dataset.SpecificCharacterSet);
if (_syntax.ExplicitVr)
{
if (de.Tag.VR.Is16BitLengthField)
{
// #10890: Can't encode the value length if the length of the data exceeds max value for a 16-bit field
if (theData.Length > ushort.MaxValue - 1 /* must be even length so max allowed = 65534 */)
throw new DicomDataException(string.Format(
"Value for {0} exceeds maximum stream length allowed for a {1} VR attribute encoded using {2}",
de.Tag, de.Tag.VR, _syntax));
_writer.Write((ushort) theData.Length);
}
else
{
_writer.Write((ushort) 0x0000);
_writer.Write((uint) theData.Length);
}
}
else
{
_writer.Write((uint) theData.Length);
}
if (theData.Length > 0)
theData.CopyTo(_writer);
}
}
return DicomWriteStatus.Success;
}
}
/// <summary> /// Method for sending a DIMSE mesage. /// </summary> /// <param name="pcid"></param> /// <param name="command"></param> /// <param name="dataset"></param> private void SendDimse(byte pcid, DicomAttributeCollection command, DicomAttributeCollection dataset) { try { TransferSyntax ts = _assoc.GetAcceptedTransferSyntax(pcid); uint total = command.CalculateWriteLength(TransferSyntax.ImplicitVrLittleEndian, DicomWriteOptions.Default | DicomWriteOptions.CalculateGroupLengths); if (dataset != null && !dataset.IsEmpty()) total += dataset.CalculateWriteLength(ts, DicomWriteOptions.Default); PDataTFStream pdustream; if (_assoc.RemoteMaximumPduLength == 0 || _assoc.RemoteMaximumPduLength > _assoc.LocalMaximumPduLength) pdustream = new PDataTFStream(this, pcid, _assoc.LocalMaximumPduLength, total, NetworkSettings.Default.CombineCommandDataPdu); else pdustream = new PDataTFStream(this, pcid, _assoc.RemoteMaximumPduLength, total, NetworkSettings.Default.CombineCommandDataPdu); pdustream.OnTick += delegate { OnSendDimseProgress(pcid, command, dataset); if (DimseMessageSending != null) DimseMessageSending(_assoc, pcid, command, dataset); }; // Introduced lock as risk mitigation for ticket #10147. Note that a more thorough locking // mechanism should be developed to work across PDU types, and also should take into account // if we do end up using _multiThreaded = true lock (_writeSyncLock) { LogSendReceive(false, command, dataset); OnSendDimseBegin(pcid, command, dataset); var dsw = new DicomStreamWriter(pdustream); dsw.Write(TransferSyntax.ImplicitVrLittleEndian, command, DicomWriteOptions.Default | DicomWriteOptions.CalculateGroupLengths); if ((dataset != null) && !dataset.IsEmpty()) { pdustream.IsCommand = false; dsw.Write(ts, dataset, DicomWriteOptions.Default); } // flush last pdu pdustream.Flush(true); } _assoc.TotalBytesSent += total; OnDimseSent(pcid, command, dataset); } catch (Exception e) { OnNetworkError(e, true); // TODO // Should we throw another exception here? Should the user know there's an error? They'll get // the error reported to them through the OnNetworkError routine, and throwing an exception here // might cause us to call OnNetworkError a second time, because the exception may be caught at a higher // level // Note, when fixing defect #8184, realized that throwing an exception here would cause // failures in the ImageServer, because there are places where we wouldn't catch the // exception. Should be careful if this is ever introduced back in. //throw new DicomException("Unexpected exception when sending a DIMSE message",e); } }