scpformat.cs
来自「ecg tool kit for medical image retrieval」· CS 代码 · 共 919 行 · 第 1/2 页
CS
919 行
/***************************************************************************
Copyright 2004-2005,2008, Thoraxcentrum, Erasmus MC, Rotterdam, The Netherlands
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Written by Maarten JB van Ettinger.
****************************************************************************/
using System;
using System.IO;
using System.Runtime.InteropServices;
using Communication.IO.Tools;
using ECGConversion;
using ECGConversion.ECGDemographics;
using ECGConversion.ECGDiagnostic;
using ECGConversion.ECGGlobalMeasurements;
using ECGConversion.ECGSignals;
namespace ECGConversion.SCP
{
/// <summary>
/// Class containing the entire SCP format.
/// </summary>
public class SCPFormat : IECGFormat, ISignal
{
// settings for support with other readers.
private bool _QRSSubtractionSupport
{
get
{
return _Config["QRS Subtraction"] == null || string.Compare(_Config["QRS Subtraction"], "true", true) == 0;
}
}
private bool _BimodalCompressionUsed
{
get
{
try
{
string temp1 = _Config["Bimodal Comppression Rate"];
if (temp1 == null)
return false;
int temp2 = int.Parse(temp1);
switch (temp2)
{
case 2:case 4:
return true;
default:
break;
}
}
catch {}
return false;
}
}
private int _BimodalCompressionRate
{
get
{
try
{
return int.Parse(_Config["Bimodal Comppression Rate"]);
}
catch {}
return 4;
}
}
private EncodingType _EncodingType
{
get
{
try
{
return (EncodingType) Enum.Parse(typeof(EncodingType), _Config["Compression Type"], true);
}
catch {}
return EncodingType.DefaultHuffman;
}
}
private byte _DifferenceDataSection5Used
{
get
{
try
{
int temp = int.Parse(_Config["Difference Data Median"]);
if ((temp >= 0)
&& (temp <= 2))
return (byte) temp;
}
catch {}
return 2;
}
}
private byte _DifferenceDataSection6Used
{
get
{
try
{
int temp = int.Parse(_Config["Difference Data Rhythm"]);
if ((temp >= 0)
&& (temp <= 2))
return (byte) temp;
}
catch {}
return 2;
}
}
private bool _UseLeadMeasurements
{
get
{
return string.Compare(_Config["Use Lead Measurements"], "true", true) == 0;
}
}
// Static settings of format.
public static byte DefaultSectionVersion = 20;
public static byte DefaultProtocolVersion = 20;
private static int _MinFileLength = 158;
private static int _MinNrSections = 12;
private static int _MinNrWorkingSections = 2;
// data structure of format.
private ushort _CRC = 0;
private int _Length;
private SCPSection[] _Default = { new SCPSection0(),
new SCPSection1(),
new SCPSection2(),
new SCPSection3(),
new SCPSection4(),
new SCPSection5(),
new SCPSection6(),
new SCPSection7(),
new SCPSection8(),
new SCPSectionUnknown(),
new SCPSection10(),
new SCPSection11()};
private SCPSection[] _Manufactor = null;
public SCPFormat()
{
_Config = new ECGConfig(new string[]{"Compression Type", "Difference Data Median", "Difference Data Rhythm", "QRS Subtraction", "Bimodal Comppression Rate", "Use Lead Measurements"}, 3, new ECGConfig.CheckConfigFunction(this._ConfigurationWorks));
_Config["Compression Type"] = EncodingType.DefaultHuffman.ToString();
_Config["Difference Data Median"] = "2";
_Config["Difference Data Rhythm"] = "2";
_Config["QRS Subtraction"] = "false";
_Config["Use Lead Measurements"] = "true";
}
public bool _ConfigurationWorks()
{
try
{
Enum.Parse(typeof(EncodingType), _Config["Compression Type"], true);
int ddm = int.Parse(_Config["Difference Data Median"]),
ddr = int.Parse(_Config["Difference Data Rhythm"]);
if ((ddm >= 0)
&& (ddm <= 2)
&& (ddr >= 0)
&& (ddr <= 2)
&& ((_Config["Use Lead Measurements"] == null)
|| (string.Compare(_Config["Use Lead Measurements"], "true", true) == 0)
|| (string.Compare(_Config["Use Lead Measurements"], "false", true) == 0)))
{
string temp1 = _Config["Bimodal Comppression Rate"];
if (temp1 == null)
return true;
int temp2 = int.Parse(temp1);
switch (temp2)
{
case 1:case 2:case 4:
return true;
default:
break;
}
}
}
catch {}
return false;
}
#region IECGFormat Members
public override int Read(Stream input, int offset)
{
if ((input != null)
&& (input.CanRead))
{
// Reading information from stream to byte array.
input.Seek(offset, SeekOrigin.Begin);
byte[] buffer1 = new byte[Marshal.SizeOf(_CRC) + Marshal.SizeOf(_Length)];
BytesTool.readStream(input, buffer1, 0, buffer1.Length);
int length = (int) BytesTool.readBytes(buffer1, Marshal.SizeOf(_CRC), Marshal.SizeOf(_Length), true);
if ((offset + length) <= input.Length)
{
byte[] buffer2 = new byte[length];
BytesTool.readStream(input, buffer2, buffer1.Length, buffer2.Length - buffer1.Length);
BytesTool.copy(buffer2, 0, buffer1, 0, buffer1.Length);
// Read using function for byte array.
return Read(buffer2, 0) << 1;
}
}
return 0x1;
}
public override int Read(string file, int offset)
{
if (file != null)
{
// Opening stream to file.
Stream read = new FileStream(file, FileMode.Open);
// Read using function for stream.
int err = Read(read, offset);
// Close stream to file.
read.Close();
return err << 1;
}
return 0x1;
}
public override int Read(byte[] buffer, int offset)
{
// Read in pointers (section0)
int err = _Default[0].Read(buffer, offset + Marshal.SizeOf(_CRC) + Marshal.SizeOf(_Length), 0);
if ((err != 0)
|| !(_Default[0] is SCPSection0))
{
return 0x1;
}
SCPSection0 pointers = (SCPSection0) _Default[0];
ushort nrleads = 0;
// set extra space for extra sections.
if (pointers.getNrPointers() > _MinNrSections)
{
_Manufactor = new SCPSection[pointers.getNrPointers() - _MinNrSections];
}
System.Text.Encoding usedEncoding = null;
// read in all section but pointers (section0).
for (int loper=1;loper < pointers.getNrPointers();loper++)
{
// Special case for SCP Section 5 and 6 (they need to know the nr of leads used).
if ((loper < _MinNrSections)
&& (_Default[loper] is SCPSection5))
{
((SCPSection5)_Default[loper]).setNrLeads(nrleads);
}
else if ((loper < _MinNrSections)
&& (_Default[loper] is SCPSection6))
{
((SCPSection6)_Default[loper]).setNrLeads(nrleads);
}
// Section works if length if greater then size of section header.
if (pointers.getLength(loper) > 16)
{
if (loper < _MinNrSections)
{
int ret = _Default[loper].Read(buffer, offset + pointers.getIndex(loper) - 1, pointers.getLength(loper));
if (ret != 0)
{
err |= (0x2 << loper);
}
if (usedEncoding != null)
_Default[loper].SetEncoding(usedEncoding);
}
else
{
_Manufactor[loper - _MinNrSections] = new SCPSectionUnknown();
int ret = _Manufactor[loper - _MinNrSections].Read(buffer, offset + pointers.getIndex(loper) - 1, pointers.getLength(loper));
if (ret != 0)
{
err |= (0x2 << loper);
}
if (usedEncoding != null)
_Manufactor[loper - _MinNrSections].SetEncoding(usedEncoding);
}
}
if ((loper < _MinNrSections)
&& (_Default[loper] is SCPSection1))
{
usedEncoding = ((SCPSection1)_Default[loper]).getLanguageSupportCode();
_Default[0].SetEncoding(usedEncoding);
_Default[1].SetEncoding(usedEncoding);
}
else if ((loper < _MinNrSections)
&& (_Default[loper] is SCPSection3))
{
nrleads = ((SCPSection3)_Default[loper]).getNrLeads();
}
}
return err;
}
public override int Write(string file)
{
if (file != null)
{
// open stream to write to.
Stream output = new FileStream(file, FileMode.Create);
// use write function for streams.
int ret = Write(output);
// close stream after writing.
output.Close();
return ret << 1;
}
return 0x1;
}
public override int Write(Stream output)
{
if ((output != null)
&& (output.CanWrite))
{
// set pointers
setPointers();
byte[] buffer = new byte[getFileSize()];
// use write function for byte arrays.
int err = Write(buffer, 0);
if (err == 0)
{
output.Write(buffer, 0, buffer.Length);
}
return err << 1;
}
return 0x1;
}
public override int Write(byte[] buffer, int offset)
{
// Check if format works.
if (Works())
{
_Length = getFileSize();
if ((buffer != null)
&& ((offset + _Length) <= buffer.Length)
&& (_Default[0] is SCPSection0))
{
// Write length of file.
BytesTool.writeBytes(_Length, buffer, offset + Marshal.SizeOf(_CRC), Marshal.SizeOf(_Length), true);
SCPSection0 pointers = (SCPSection0) _Default[0];
// Write all sections in format.
for (int loper=0;loper < pointers.getNrPointers();loper++)
{
if (loper < _MinNrSections)
{
_Default[loper].Write(buffer, offset + pointers.getIndex(loper) - 1);
}
else if ((pointers.getLength(loper) > SCPSection.Size)
&& (_Manufactor[loper - _MinNrSections] != null))
{
_Manufactor[loper - _MinNrSections].Write(buffer, offset + pointers.getIndex(loper) - 1);
}
}
// Calculate CRC of byte array.
CRCTool crctool = new CRCTool();
crctool.Init(CRCTool.CRCCode.CRC_CCITT);
_CRC = crctool.CalcCRCITT(buffer, offset + Marshal.SizeOf(_CRC), _Length - Marshal.SizeOf(_CRC));
BytesTool.writeBytes(_CRC, buffer, offset, Marshal.SizeOf(_CRC), true);
return 0x0;
}
return 0x2;
}
return 0x1;
}
public override bool CheckFormat(Stream input, int offset)
{
if ((input != null)
&& input.CanRead)
{
byte[] buffer1 = new byte[Marshal.SizeOf(_CRC) + Marshal.SizeOf(_Length)];
input.Seek(offset, SeekOrigin.Begin);
if (BytesTool.readStream(input, buffer1, 0, buffer1.Length) == buffer1.Length)
{
ushort crc = (ushort) BytesTool.readBytes(buffer1, 0, Marshal.SizeOf(_CRC), true);
int length = (int) BytesTool.readBytes(buffer1, Marshal.SizeOf(_CRC), Marshal.SizeOf(_Length), true);
if ((offset + length) <= input.Length
&& (length >= _MinFileLength))
{
byte[] buffer2 = new byte[length];
BytesTool.copy(buffer2, 0, buffer1, 0, buffer1.Length);
BytesTool.readStream(input, buffer2, buffer1.Length, length - buffer1.Length);
buffer1 = null;
return CheckSCP(buffer2, 0, crc, length);
}
}
}
return false;
}
public override bool CheckFormat(string file, int offset)
{
if (file != null)
{
Stream read = new FileStream(file, FileMode.Open);
bool ret = CheckFormat(read, offset);
read.Close();
return ret;
}
return false;
}
public override bool CheckFormat(byte[] buffer, int offset)
{
ushort crc = (ushort) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(_CRC), true);
int length = (int) BytesTool.readBytes(buffer, offset + Marshal.SizeOf(_CRC), Marshal.SizeOf(_Length), true);
if (((offset + length) < buffer.Length)
&& (length < _MinFileLength))
{
return false;
}
return CheckSCP(buffer, offset, crc, length);
}
public override void Anonymous(byte type)
{
if ((_Default[1] != null)
&& (_Default[1].Works())
&& (_Default[1] is SCPSection1))
{
((SCPSection1)_Default[1]).Anonymous(type);
}
}
public override int getFileSize()
{
if (Works()
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?