VinnoImageData.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. namespace fis.Vid
  5. {
  6. public enum OperationMode
  7. {
  8. Open,
  9. Create
  10. }
  11. public enum VidImageFormat
  12. {
  13. Jpeg = 0,
  14. Png = 1,
  15. H264 = 2,
  16. Zip = 3,
  17. Diff = 4,
  18. }
  19. public class VinnoImageData : IDisposable
  20. {
  21. private OperationMode _operationMode;
  22. private readonly Stream _stream;
  23. private readonly VinnoStreamReader _reader;
  24. private readonly VinnoStreamWriter _writer;
  25. private readonly string _filePath;
  26. private readonly List<long> _imagePositionList;
  27. private bool _disposed;
  28. private bool _closed;
  29. private readonly object _addGetLocker = new object();
  30. private const string Header = "VINNO IMAGE DATA";
  31. private const string CacheHeader = "VINNOIMGCACHE";
  32. /// <summary>
  33. /// Gets the version of this image data.
  34. /// </summary>
  35. public int Version { get; }
  36. /// <summary>
  37. /// Gets the image count of this image data.
  38. /// </summary>
  39. public int ImageCount { get; private set; }
  40. /// <summary>
  41. /// Gets the probe information.
  42. /// </summary>
  43. public VinnoProbe Probe { get; private set; }
  44. /// <summary>
  45. /// Gets the image format of this image data.
  46. /// </summary>
  47. public VidImageFormat ImageFormat { get; }
  48. /// <summary>
  49. /// Gets or sets the extended data.
  50. /// </summary>
  51. public byte[] ExtendedData { get; set; }
  52. /// <summary>
  53. /// Create a VINNO Image Data.
  54. /// </summary>
  55. /// <param name="filePath">The file path to read or create.</param>
  56. /// <param name="mode">The operation mode, create to create a vid file, open to open a vid file.</param>
  57. public VinnoImageData(string filePath, OperationMode mode)
  58. {
  59. try
  60. {
  61. ImageFormat = VidImageFormat.Jpeg;
  62. _filePath = filePath;
  63. _operationMode = mode;
  64. ExtendedData = new byte[0];
  65. if (mode == OperationMode.Create)
  66. {
  67. //Create temp file.
  68. var tempFile = _filePath + ".tmp";
  69. _stream = new FileStream(tempFile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
  70. _writer = new VinnoStreamWriter(_stream);
  71. Version = 3;
  72. Probe = null;
  73. _imagePositionList = new List<long>();
  74. ImageCount = 0;
  75. }
  76. else
  77. {
  78. if (!File.Exists(_filePath) && File.Exists(_filePath + ".tmp"))
  79. {
  80. _filePath = _filePath + ".tmp";
  81. }
  82. _stream = new FileStream(_filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
  83. _reader = new VinnoStreamReader(_stream);
  84. var header = _reader.ReadString();
  85. if (header != Header && header != CacheHeader)
  86. {
  87. _stream.Dispose();
  88. throw new InvalidDataException("File is not a VID file.");
  89. }
  90. Version = _reader.ReadInt();
  91. //Get probe info
  92. var probeData = _reader.ReadBytes();
  93. Probe = VinnoProbe.FromBytes(probeData);
  94. ImageFormat = (VidImageFormat)_reader.ReadInt();
  95. ExtendedData = _reader.ReadBytes();
  96. //Get the index list.
  97. _imagePositionList = new List<long>(_reader.ReadLongs());
  98. ImageCount = _imagePositionList.Count;
  99. }
  100. }
  101. catch (Exception ex)
  102. {
  103. _stream?.Dispose();
  104. }
  105. }
  106. /// <summary>
  107. /// Create a VINNO Image Data.
  108. /// </summary>
  109. /// <param name="stream"></param>
  110. public VinnoImageData(Stream stream)
  111. {
  112. try
  113. {
  114. ImageFormat = VidImageFormat.Jpeg;
  115. ExtendedData = new byte[0];
  116. _stream = stream;
  117. _reader = new VinnoStreamReader(_stream);
  118. var header = _reader.ReadString();
  119. if (header != Header)
  120. {
  121. _stream.Dispose();
  122. throw new InvalidDataException("File is not a VID file.");
  123. }
  124. Version = _reader.ReadInt();
  125. //Get probe info
  126. var probeData = _reader.ReadBytes();
  127. Probe = VinnoProbe.FromBytes(probeData);
  128. ImageFormat = (VidImageFormat)_reader.ReadInt();
  129. ExtendedData = _reader.ReadBytes();
  130. //Get the index list.
  131. _imagePositionList = new List<long>(_reader.ReadLongs());
  132. ImageCount = _imagePositionList.Count;
  133. }
  134. catch (Exception ex)
  135. {
  136. _stream?.Dispose();
  137. }
  138. }
  139. /// <summary>
  140. /// Add probe info into vid.
  141. /// </summary>
  142. /// <param name="probe"></param>
  143. public void AddProbe(VinnoProbe probe)
  144. {
  145. Probe = probe;
  146. }
  147. /// <summary>
  148. /// Add dicom info into vid
  149. /// </summary>
  150. /// <param name="extendedData"></param>
  151. public void AddExtendedData(byte[] extendedData)
  152. {
  153. ExtendedData = extendedData;
  154. }
  155. /// <summary>
  156. /// Add one image into vid.
  157. /// </summary>
  158. /// <param name="image"></param>
  159. public void AddImage(VinnoImage image)
  160. {
  161. if (_closed)
  162. {
  163. throw new InvalidOperationException("ImageData closed.");
  164. }
  165. if (_operationMode != OperationMode.Create)
  166. {
  167. throw new InvalidOperationException("Can not add image under open mode.");
  168. }
  169. lock (_addGetLocker)
  170. {
  171. var postion = _stream.Position;
  172. _writer.WriteBytes(image.ToBytes());
  173. _imagePositionList.Add(postion);
  174. ImageCount++;
  175. }
  176. }
  177. /// <summary>
  178. /// Gets one image from the vid.
  179. /// </summary>
  180. /// <param name="index"></param>
  181. /// <returns></returns>
  182. public VinnoImage GetImage(int index)
  183. {
  184. if (_closed)
  185. {
  186. throw new InvalidOperationException("ImageData closed.");
  187. }
  188. if (_operationMode != OperationMode.Open)
  189. {
  190. throw new InvalidOperationException("Can not open image under create mode.");
  191. }
  192. if (index >= ImageCount || index < 0)
  193. {
  194. throw new IndexOutOfRangeException("Can not find image Data");
  195. }
  196. lock (_addGetLocker)
  197. {
  198. //Jump to image.
  199. _stream.Position = _imagePositionList[index];
  200. var imageData = _reader.ReadBytes();
  201. return VinnoImage.FromBytes(imageData);
  202. }
  203. }
  204. public void Close()
  205. {
  206. if (!_closed)
  207. {
  208. lock (_addGetLocker)
  209. {
  210. if (_operationMode == OperationMode.Create && !string.IsNullOrWhiteSpace(_filePath) && ImageCount > 0)
  211. {
  212. using (var stream = File.Create(_filePath))
  213. {
  214. var writer = new VinnoStreamWriter(stream);
  215. writer.WriteString(Header);
  216. writer.WriteInt(Version);
  217. writer.WriteBytes(Probe.ToBytes());
  218. writer.WriteInt((int)ImageFormat);
  219. writer.WriteBytes(ExtendedData);
  220. //Position data length = imagecount(int 4bytes) + imagecount * positionSize(long 8bytes)
  221. var positionsDataLength = _imagePositionList.Count * sizeof(long) + 4;
  222. var offset = stream.Length + positionsDataLength;
  223. for (var i = 0; i < _imagePositionList.Count; i++)
  224. {
  225. _imagePositionList[i] = _imagePositionList[i] + offset;
  226. }
  227. writer.WriteLongs(_imagePositionList.ToArray());
  228. _stream.Position = 0;
  229. _stream.CopyTo(stream);
  230. }
  231. }
  232. _stream?.Dispose();
  233. if (_operationMode == OperationMode.Create && !string.IsNullOrWhiteSpace(_filePath))
  234. {
  235. var tempFile = _filePath + ".tmp";
  236. File.Delete(tempFile);
  237. }
  238. }
  239. _closed = true;
  240. }
  241. }
  242. protected void Dispose(bool disposing)
  243. {
  244. if (!_disposed)
  245. {
  246. Close();
  247. }
  248. _disposed = true;
  249. }
  250. public void Dispose()
  251. {
  252. Dispose(true);
  253. GC.SuppressFinalize(this);
  254. }
  255. }
  256. }