123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- namespace fis.Vid
- {
- public enum OperationMode
- {
- Open,
- Create
- }
- public enum VidImageFormat
- {
- Jpeg = 0,
- Png = 1,
- H264 = 2,
- Zip = 3,
- Diff = 4,
- }
- public class VinnoImageData : IDisposable
- {
- private OperationMode _operationMode;
- private readonly Stream _stream;
- private readonly VinnoStreamReader _reader;
- private readonly VinnoStreamWriter _writer;
- private readonly string _filePath;
- private readonly List<long> _imagePositionList;
- private bool _disposed;
- private bool _closed;
- private readonly object _addGetLocker = new object();
- private const string Header = "VINNO IMAGE DATA";
- private const string CacheHeader = "VINNOIMGCACHE";
- /// <summary>
- /// Gets the version of this image data.
- /// </summary>
- public int Version { get; }
- /// <summary>
- /// Gets the image count of this image data.
- /// </summary>
- public int ImageCount { get; private set; }
- /// <summary>
- /// Gets the probe information.
- /// </summary>
- public VinnoProbe Probe { get; private set; }
- /// <summary>
- /// Gets the image format of this image data.
- /// </summary>
- public VidImageFormat ImageFormat { get; }
- /// <summary>
- /// Gets or sets the extended data.
- /// </summary>
- public byte[] ExtendedData { get; set; }
- /// <summary>
- /// Create a VINNO Image Data.
- /// </summary>
- /// <param name="filePath">The file path to read or create.</param>
- /// <param name="mode">The operation mode, create to create a vid file, open to open a vid file.</param>
- public VinnoImageData(string filePath, OperationMode mode)
- {
- try
- {
- ImageFormat = VidImageFormat.Jpeg;
- _filePath = filePath;
- _operationMode = mode;
- ExtendedData = new byte[0];
- if (mode == OperationMode.Create)
- {
- //Create temp file.
- var tempFile = _filePath + ".tmp";
- _stream = new FileStream(tempFile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
- _writer = new VinnoStreamWriter(_stream);
- Version = 3;
- Probe = null;
- _imagePositionList = new List<long>();
- ImageCount = 0;
- }
- else
- {
- if (!File.Exists(_filePath) && File.Exists(_filePath + ".tmp"))
- {
- _filePath = _filePath + ".tmp";
- }
- _stream = new FileStream(_filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
- _reader = new VinnoStreamReader(_stream);
- var header = _reader.ReadString();
- if (header != Header && header != CacheHeader)
- {
- _stream.Dispose();
- throw new InvalidDataException("File is not a VID file.");
- }
- Version = _reader.ReadInt();
- //Get probe info
- var probeData = _reader.ReadBytes();
- Probe = VinnoProbe.FromBytes(probeData);
- ImageFormat = (VidImageFormat)_reader.ReadInt();
- ExtendedData = _reader.ReadBytes();
- //Get the index list.
- _imagePositionList = new List<long>(_reader.ReadLongs());
- ImageCount = _imagePositionList.Count;
- }
- }
- catch (Exception ex)
- {
- _stream?.Dispose();
- }
- }
- /// <summary>
- /// Create a VINNO Image Data.
- /// </summary>
- /// <param name="stream"></param>
- public VinnoImageData(Stream stream)
- {
- try
- {
- ImageFormat = VidImageFormat.Jpeg;
- ExtendedData = new byte[0];
- _stream = stream;
- _reader = new VinnoStreamReader(_stream);
- var header = _reader.ReadString();
- if (header != Header)
- {
- _stream.Dispose();
- throw new InvalidDataException("File is not a VID file.");
- }
- Version = _reader.ReadInt();
- //Get probe info
- var probeData = _reader.ReadBytes();
- Probe = VinnoProbe.FromBytes(probeData);
- ImageFormat = (VidImageFormat)_reader.ReadInt();
- ExtendedData = _reader.ReadBytes();
- //Get the index list.
- _imagePositionList = new List<long>(_reader.ReadLongs());
- ImageCount = _imagePositionList.Count;
- }
- catch (Exception ex)
- {
- _stream?.Dispose();
- }
- }
- /// <summary>
- /// Add probe info into vid.
- /// </summary>
- /// <param name="probe"></param>
- public void AddProbe(VinnoProbe probe)
- {
- Probe = probe;
- }
- /// <summary>
- /// Add dicom info into vid
- /// </summary>
- /// <param name="extendedData"></param>
- public void AddExtendedData(byte[] extendedData)
- {
- ExtendedData = extendedData;
- }
- /// <summary>
- /// Add one image into vid.
- /// </summary>
- /// <param name="image"></param>
- public void AddImage(VinnoImage image)
- {
- if (_closed)
- {
- throw new InvalidOperationException("ImageData closed.");
- }
- if (_operationMode != OperationMode.Create)
- {
- throw new InvalidOperationException("Can not add image under open mode.");
- }
- lock (_addGetLocker)
- {
- var postion = _stream.Position;
- _writer.WriteBytes(image.ToBytes());
- _imagePositionList.Add(postion);
- ImageCount++;
- }
- }
- /// <summary>
- /// Gets one image from the vid.
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public VinnoImage GetImage(int index)
- {
- if (_closed)
- {
- throw new InvalidOperationException("ImageData closed.");
- }
- if (_operationMode != OperationMode.Open)
- {
- throw new InvalidOperationException("Can not open image under create mode.");
- }
- if (index >= ImageCount || index < 0)
- {
- throw new IndexOutOfRangeException("Can not find image Data");
- }
- lock (_addGetLocker)
- {
- //Jump to image.
- _stream.Position = _imagePositionList[index];
- var imageData = _reader.ReadBytes();
- return VinnoImage.FromBytes(imageData);
- }
- }
- public void Close()
- {
- if (!_closed)
- {
- lock (_addGetLocker)
- {
- if (_operationMode == OperationMode.Create && !string.IsNullOrWhiteSpace(_filePath) && ImageCount > 0)
- {
- using (var stream = File.Create(_filePath))
- {
- var writer = new VinnoStreamWriter(stream);
- writer.WriteString(Header);
- writer.WriteInt(Version);
- writer.WriteBytes(Probe.ToBytes());
- writer.WriteInt((int)ImageFormat);
- writer.WriteBytes(ExtendedData);
- //Position data length = imagecount(int 4bytes) + imagecount * positionSize(long 8bytes)
- var positionsDataLength = _imagePositionList.Count * sizeof(long) + 4;
- var offset = stream.Length + positionsDataLength;
- for (var i = 0; i < _imagePositionList.Count; i++)
- {
- _imagePositionList[i] = _imagePositionList[i] + offset;
- }
- writer.WriteLongs(_imagePositionList.ToArray());
- _stream.Position = 0;
- _stream.CopyTo(stream);
- }
- }
- _stream?.Dispose();
- if (_operationMode == OperationMode.Create && !string.IsNullOrWhiteSpace(_filePath))
- {
- var tempFile = _filePath + ".tmp";
- File.Delete(tempFile);
- }
- }
- _closed = true;
- }
- }
- protected void Dispose(bool disposing)
- {
- if (!_disposed)
- {
- Close();
- }
- _disposed = true;
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- }
- }
|