scpsection2.cs

来自「ecg tool kit for medical image retrieval」· CS 代码 · 共 1,006 行 · 第 1/2 页

CS
1,006
字号
				int currentBit = 0;

				// Make buffer for worst case.
				byte[] buffer = new byte[((time * 26) >> 3) + 1];

				// For each sample do encode.
				for (int currentTime=0;currentTime < time;currentTime++)
				{
					short code = 0;

					// Encode Differences.
					switch (difference)
					{
						case 0:
							code = data[currentTime];
						break;
						case 1:
							code = (short) ((currentTime < 1) ? data[currentTime] : data[currentTime] - data[currentTime - 1]);
						break;
						case 2:
							code = (short) ((currentTime < 2) ? data[currentTime] : data[currentTime] - (data[currentTime - 1] << 1) + data[currentTime - 2]);
						break;
						default:
							// Undefined difference used exit empty.
							return null;
					}

					// Do inhouse encode
                    //System.Diagnostics.Debug.WriteLine("Begin inhouse!"+code.ToString());
                    if ( code == -32768) code = 32767;
                    if (Math.Abs(code) <= 8)
					{
                      //  System.Diagnostics.Debug.WriteLine("Begin !");
						// if code 0 then add one 0 bit.
						if (code == 0)
						{
							buffer[currentBit >> 3] <<= 1;
							currentBit++;
						}
						else
						{
							// add absolute number of 1 bits.
							int codeAbs = Math.Abs(code);
							for (int loper=0;loper < codeAbs;loper++)
							{
								buffer[currentBit >> 3] <<= 1;
								buffer[currentBit >> 3] |= 1;
								currentBit++;
							}

							// add one 0 bit.
							buffer[currentBit >> 3] <<= 1;
							currentBit++;

							// add one more bit for positive of negative
							buffer[currentBit >> 3] <<= 1;
							if (code < 0)
							{
								buffer[currentBit >> 3] |= 1;
							}
							currentBit++;
						}
					}
					else
					{
                        //System.Diagnostics.Debug.WriteLine("esle!");
                        
                        // Code doesn't fit in normal table do special.
						// First add nine 1 bits.
						for (int loper=0;loper < 9;loper++)
						{
							buffer[currentBit >> 3] <<= 1;
							buffer[currentBit >> 3] |= 1;
							currentBit++;
						}

						// Add one more bit depending on size of code
						buffer[currentBit >> 3] <<= 1;
						int extraLength = 8;
						if (!((code <= 127) && (code >= -128)))
						{
							buffer[currentBit >> 3] |= 1;
							extraLength = 16;
						}
						currentBit++;

						// Add bits for extra code.
						for (extraLength--;extraLength >= 0;extraLength--)
						{
							buffer[currentBit >> 3] <<= 1;
							buffer[currentBit >> 3] |= (byte)((code >> extraLength) & 0x1);
							currentBit++;
                            int currentBitShift = currentBit >> 3;
						}
                    }
                }

				// Shift end to right position.
				if ((currentBit & 0x7) != 0x0)
				{
					buffer[(currentBit >> 3)] <<= (0x8 - (currentBit & 0x7));
					currentBit += (0x8 - (currentBit & 0x7));
				}

				// Allocate a fitting buffer
				ret = new byte[(currentBit >> 3)];

				// Copy worst case buffer in fitting buffer.
				for (int loper = 0;loper < ret.Length;loper++)
				{
					ret[loper] = buffer[loper];
				}
			}
			return ret;
		}
		/// <summary>
		/// Function to encode signal using the huffman table.
		/// </summary>
		/// <param name="data">signal to read from</param>
		/// <param name="time">number of samples to use</param>
		/// <param name="quanta">sample distance in signal</param>
		/// <param name="usedTable">table to use for encoding</param>
		/// <param name="difference">difference to use durring decoding</param>
		/// <returns>byte array containing encoded data</returns>
		private byte[] HuffmanTableEncode(short[] data, int time, short usedTable, byte difference)
		{
			byte[] ret = null;

			// Check if input makes sense
			if ((data != null)
			&&	(time <= data.Length))
			{
				// Initialize some handy variables
				int currentBit = 0;

				// Make buffer for worst case.
				byte[] buffer = null;

				if ((usedTable >= 0)
				&&  (usedTable < _Tables.Length)
				&&  (usedTable != _Selected))
				{
					uint code = 0;
					int len = 0;

					// get TableSwap position in HuffmanTable.
					int p = getTableSwap(usedTable);

					// Check if table swap is possible in this table.
					if (p >= 0)
					{
						// Store needed data from swap HuffmanStruct.
						code = _Tables[_Selected][p].code;
						len = _Tables[_Selected][p].entire;

						// set currently selected table.
						_Selected = usedTable;
					}

					// allocate buffer for worstcase.
					buffer = new byte[((len + (time * getWorstCase())) >> 3) + 1];

					// add table swap.
					for (len--;len >= 0;len--)
					{
						buffer[currentBit >> 3] <<= 1;
						buffer[currentBit >> 3] |= (byte)((code >> len) & 0x1);
						currentBit++;
					}
				}
				else
				{
					// No tables swap, so only space needed for worst case.
					buffer = new byte[((time * getWorstCase()) >> 3) + 1];
				}

				// For each sample do encode.
				for (int currentTime=0;currentTime < time;currentTime++)
				{
					short code = 0;

					// Encode Differences.
					switch (difference)
					{
						case 0:
							code = data[currentTime];
							break;
						case 1:
							code = (short) ((currentTime < 1) ? data[currentTime] : data[currentTime] - data[currentTime - 1]);
							break;
						case 2:
							code = (short) ((currentTime < 2) ? data[currentTime] : data[currentTime] - (data[currentTime - 1] << 1) + data[currentTime - 2]);
							break;
						default:
							// Undefined difference used exit empty.
							return null;
					}

					// Call Interpetting data to get an hit.
					SCPHuffmanStruct h = InterpettingData(code);
					if (h == null)
					{
						// not hit table or data must be wrong.
						return null;
					}

					// Push in the code.
					for (int loper=(h.prefix-1);loper >= 0;loper--)
					{
						buffer[currentBit >> 3] <<= 1;
						buffer[currentBit >> 3] |= (byte)((h.code >> loper) & 0x1);
						currentBit++;
					}

					// Push in the extra code, for special case.
					uint now = (uint) (code - h.value);
					for (int loper=(h.entire - h.prefix - 1);loper >= 0;loper--)
					{
						buffer[currentBit >> 3] <<= 1;
						buffer[currentBit >> 3] |= (byte)((code >> loper) & 0x1);
						currentBit++;
					}
				}

				// Shift end to right position.
				if ((currentBit & 0x7) != 0x0)
				{
					buffer[(currentBit >> 3)] <<= (0x8 - (currentBit & 0x7));
					currentBit += (0x8 - (currentBit & 0x7));
				}

				// Allocate a fitting buffer
				ret = new byte[(currentBit >> 3)];

				// Copy worst case buffer in fitting buffer.
				for (int loper = 0;loper < ret.Length;loper++)
				{
					ret[loper] = buffer[loper];
				}
			}
			return ret;
		}
		/// <summary>
		/// Function to find corresponding HuffmanStruct with value.
		/// </summary>
		/// <param name="value">value to search</param>
		/// <returns>corresponding HuffmanStruct</returns>
		private SCPHuffmanStruct InterpettingData(short value)
		{
			// Check if selected Table exists
			if ((_Tables != null)
			&&	(_Tables[_Selected] != null))
			{
				// Search in structs of table.
				for (int loper=0;loper < _Tables[_Selected].Length;loper++)
				{
					SCPHuffmanStruct h = _Tables[_Selected][loper];
					// -1, because it can be positive and negative
					int extra = (h.entire - h.prefix - 1);

					// Check if value is equal to struct.
					if ((h.value == value)
					&&  (h.tablemode != 0))
					{
						return h;
					}
					// Check if value fits in special case.
					else if ((extra > 0)
						&&	 ((value - h.value) < (0x1 << extra))
						&&   ((value - h.value) >= -(0x1 << extra))
						&&	 (h.tablemode != 0))
					{
						return h;
					}
				}
			}
			return null;
		}
		/// <summary>
		/// Function to store signal using no compression.
		/// </summary>
		/// <param name="data">signal to read from</param>
		/// <param name="time">number of samples to use</param>
		/// <param name="quanta">sample distance in signal</param>
		/// <param name="difference">difference to use durring decoding</param>
		/// <returns>byte array containing encoded data</returns>
		public static byte[] NoEncode(short[] data, int time, byte difference)
		{
			// Check if input data makes sense.
			if ((data != null)
			&&	(time <= data.Length))
			{
				// Initializing some handy variables
				int offset = 0;
				int sizeOfSample = Marshal.SizeOf(typeof(short));

				// Make buffer to contain samples
				byte[] ret = new byte[time * sizeOfSample];


				// For each sample do encode.
				for (int currentTime=0;currentTime < time;currentTime++)
				{
					short code = 0;

					// Encode Differences.
					switch (difference)
					{
						case 0:
							code = data[currentTime];
							break;
						case 1:
							code = (short) ((currentTime < 1) ? data[currentTime] : data[currentTime] - data[currentTime - 1]);
							break;
						case 2:
							code = (short) ((currentTime < 2) ? data[currentTime] : data[currentTime] - (data[currentTime - 1] << 1) + data[currentTime - 2]);
							break;
						default:
							// Undefined difference used exit empty.
							return null;
					}

					// Write data in buffer.
					BytesTool.writeBytes(code, ret, offset, sizeOfSample, true);
					offset += sizeOfSample;
				}
				return ret;
			}
			return null;
		}
		/// <summary>
		/// Resets the current selected HuffmanTable
		/// </summary>
		public void ResetSelect()
		{
			if (Works())
			{
				_Selected = 0;
			}
		}
		/// <summary>
		/// Function to get position of table swap.
		/// </summary>
		/// <param name="table">prefered table</param>
		/// <returns>position in current table</returns>
		private int getTableSwap(int table)
		{
			if (Works()
			&&  (table < _Tables.Length)
			&&	(_Selected < _Tables.Length))
			{
				for (int loper=0;loper < _Tables[_Selected].Length;loper++)
				{
					if (_Tables[_Selected][loper].tablemode == 0
					&&  _Tables[_Selected][loper].value == (table + 1))
					{
						return loper;
					}
				}
			}
			return -1;
		}
		/// <summary>
		/// Function to get binary length of worst case of selected table.
		/// </summary>
		/// <returns>length of worst case</returns>
		private int getWorstCase()
		{
			int worst = -1;
			if (Works())
			{
				if (this._NrTables == _DefaultTable)
				{
					worst = 26;
				}
				else if (_NrTables == 0)
				{
					worst = 16;
				}
				else
				{
					for (int loper=0;loper < _Tables[_Selected].Length;loper++)
					{
						if (_Tables[_Selected][loper].entire > worst)
						{
							worst = _Tables[_Selected][loper].entire;
						}
					}
				}
			}
			return worst;
		}
		/// <summary>
		/// Function to set standard huffman table.
		/// </summary>
		public void UseStandard()
		{
			_NrTables = _DefaultTable;
		}
		/// <summary>
		/// Function to set no huffman encoding.
		/// </summary>
		public void UseNoHuffman()
		{
			_NrTables = 0;
		}
		/// <summary>
		/// Class that contains a SCP Huffman struct
		/// </summary>
		[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
		public class SCPHuffmanStruct
		{
			public byte prefix;
			public byte entire;
			public byte tablemode;
			public short value;
			public uint code;
			public SCPHuffmanStruct()
			{}
			public SCPHuffmanStruct(byte prefix, byte entire, byte tablemode, short value, uint code)
			{
				this.prefix = prefix;
				this.entire = entire;
				this.tablemode = tablemode;
				this.value = value;
				this.code = code;
			}
			/// <summary>
			/// Function to read an SCP huffman struct.
			/// </summary>
			/// <param name="buffer">byte array to read from</param>
			/// <param name="offset">position to start reading</param>
			/// <returns>0 on success</returns>
			public int Read(byte[] buffer, int offset)
			{
				if ((offset + Marshal.SizeOf(this)) > buffer.Length)
				{
					return 0x1;
				}

				prefix = (byte) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(prefix), true);
				offset += Marshal.SizeOf(prefix);
				entire = (byte) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(entire), true);
				offset += Marshal.SizeOf(entire);
				tablemode = (byte) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(tablemode), true);
				offset += Marshal.SizeOf(tablemode);
				value = (short) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(value), true);
				offset += Marshal.SizeOf(value);
				uint tempCode = (byte) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(code), true);
				offset += Marshal.SizeOf(code);

				// Have to reverse the code, because SCP stores it that way.
				code = 0;
				for (int loper=prefix;loper > 0;loper--)
				{
					code <<= 1;
					code |= (tempCode & 0x1);
					tempCode >>= 1;
				}

				return 0x0;
			}
			/// <summary>
			/// Function to write SCP huffman struct.
			/// </summary>
			/// <param name="buffer">byte array to write into</param>
			/// <param name="offset">position to start writing</param>
			/// <returns>0 on success</returns>
			public int Write(byte[] buffer, int offset)
			{
				if ((offset + Marshal.SizeOf(this)) > buffer.Length)
				{
					return 0x1;
				}

				BytesTool.writeBytes(prefix, buffer, offset, Marshal.SizeOf(prefix), true);
				offset += Marshal.SizeOf(prefix);
				BytesTool.writeBytes(entire, buffer, offset, Marshal.SizeOf(entire), true);
				offset += Marshal.SizeOf(entire);
				BytesTool.writeBytes(tablemode, buffer, offset, Marshal.SizeOf(tablemode), true);
				offset += Marshal.SizeOf(tablemode);
				BytesTool.writeBytes(value, buffer, offset, Marshal.SizeOf(value), true);
				offset += Marshal.SizeOf(value);

				// Have to reverse the code, becaus SCP stores it that way.
				uint tempCode1 = code;
				uint tempCode2 = 0;
				for (int loper=prefix;loper > 0;loper--)
				{
					tempCode2 <<= 1;
					tempCode2 |= (tempCode1 & 0x1);
					tempCode1 >>= 1;
				}

				BytesTool.writeBytes((int)tempCode2, buffer, offset, Marshal.SizeOf(code), true);
				offset += Marshal.SizeOf(code);

				return 0x0;
			}
		}
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?