Guest User

Untitled

a guest
Apr 26th, 2018
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.00 KB | None | 0 0
  1. using System;
  2. using System.IO;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Graphics;
  5. using SixLabors.ImageSharp;
  6. using SixLabors.ImageSharp.Formats.Gif;
  7. using SixLabors.ImageSharp.PixelFormats;
  8.  
  9. namespace ImageSharpMg
  10. {
  11. /// <summary>
  12. /// Store a number of frames as <see cref="Color"/> arrays. Supports exporting single
  13. /// frames as a png image or multiple frames as a gif using ImageSharp.
  14. /// </summary>
  15. public class FrameStore
  16. {
  17. /// <summary>
  18. /// Width of the frames in pixels.
  19. /// </summary>
  20. public int Width { get; }
  21.  
  22. /// <summary>
  23. /// Height of the frames in pixels.
  24. /// </summary>
  25. public int Height { get; }
  26.  
  27. /// <summary>
  28. /// The stored frames.
  29. /// </summary>
  30. public Color[][] Frames { get; }
  31.  
  32. private readonly Rgba32[] _rgbaBuffer;
  33. private int _frameIndex;
  34.  
  35. /// <summary>
  36. /// Number of frames that can be stored.
  37. /// </summary>
  38. public int FrameCapacity => Frames.Length;
  39.  
  40. /// <summary>
  41. /// Number of stored frames.
  42. /// </summary>
  43. public int FrameCount { get; private set; }
  44.  
  45. /// <summary>
  46. /// Create a new <see cref="FrameStore"/>.
  47. /// </summary>
  48. /// <param name="capacity">Number of frames to store.</param>
  49. /// <param name="width">Width of each frame.</param>
  50. /// <param name="height">Height of each frame.</param>
  51. /// <exception cref="ArgumentOutOfRangeException">
  52. /// If <paramref name="capacity"/>, <paramref name="width"/> or <paramref name="height"/>
  53. /// are less than or equal to zero.
  54. /// </exception>
  55. public FrameStore(int capacity, int width, int height)
  56. {
  57. if (capacity <= 0)
  58. throw new ArgumentOutOfRangeException(nameof(capacity), "Capacity should be larger than zero.");
  59. if (width <= 0)
  60. throw new ArgumentOutOfRangeException(nameof(width), "Width should be larger than zero.");
  61. if (height <= 0)
  62. throw new ArgumentOutOfRangeException(nameof(height), "Height should be larger than zero.");
  63. Width = width;
  64. Height = height;
  65. Frames = new Color[capacity][];
  66. var frameSize = width * height;
  67. for (var i = 0; i < capacity; i++)
  68. Frames[i] = new Color[frameSize];
  69. _rgbaBuffer = new Rgba32[frameSize];
  70. }
  71.  
  72. /// <summary>
  73. /// Add a frame at the end of the store.
  74. /// </summary>
  75. /// <param name="frame">The frame to add.</param>
  76. /// <exception cref="ArgumentException">If the frame size does not match.</exception>
  77. public void PushFrame(Color[] frame)
  78. {
  79. if (Frames.Length < Width * Height)
  80. throw new ArgumentException("Frame has less pixels than expected.", nameof(Frames));
  81. for (var i = 0; i < Width * Height; i++)
  82. Frames[_frameIndex][i] = frame[i];
  83. _frameIndex = (_frameIndex + 1) % FrameCapacity;
  84. if (FrameCount < FrameCapacity)
  85. FrameCount++;
  86. }
  87.  
  88. /// <summary>
  89. /// Add a frame at the end of the store.
  90. /// </summary>
  91. /// <param name="frame">The frame to add.</param>
  92. public void PushFrame(Texture2D frame)
  93. {
  94. if (frame == null)
  95. throw new ArgumentNullException(nameof(frame));
  96. frame.GetData(Frames[_frameIndex]);
  97. _frameIndex = (_frameIndex + 1) % FrameCapacity;
  98. if (FrameCount < FrameCapacity)
  99. FrameCount++;
  100. }
  101.  
  102. /// <summary>
  103. /// Export a frame as a PNG image.
  104. /// </summary>
  105. /// <param name="path">Path to write the image to.</param>
  106. /// <param name="index">Index of the frame.</param>
  107. public void ExportFrame(string path, int index)
  108. {
  109. using (var stream = File.OpenWrite(path))
  110. ExportFrame(stream, index);
  111. }
  112.  
  113. /// <summary>
  114. /// Export a frame as a PNG image.
  115. /// </summary>
  116. /// <param name="output">Stream to write the image to.</param>
  117. /// <param name="index">Index of the frame.</param>
  118. public void ExportFrame(Stream output, int index)
  119. {
  120. if (index < 0)
  121. throw new ArgumentOutOfRangeException();
  122. if (index >= FrameCount)
  123. throw new ArgumentOutOfRangeException();
  124.  
  125. var frameIndex = (_frameIndex + index) % FrameCapacity;
  126. ConvertColorData(Frames[frameIndex], _rgbaBuffer);
  127. using (var image = Image.LoadPixelData(_rgbaBuffer, Width, Height))
  128. image.SaveAsPng(output);
  129. }
  130.  
  131. /// <summary>
  132. /// Export frames from the store as a GIF.
  133. /// </summary>
  134. /// <param name="path">Path to write the GIF to.</param>
  135. /// <param name="frameDelay">Delay between frames in units of 10ms.</param>
  136. /// <param name="start">First frame to export.</param>
  137. /// <param name="count">Number of frames to export.</param>
  138. public void ExportGif(string path, int frameDelay, int start = 0, int count = -1)
  139. {
  140. using (var stream = File.OpenWrite(path))
  141. ExportGif(stream, frameDelay, start, count);
  142. }
  143.  
  144. /// <summary>
  145. /// Export frames from the store as a GIF.
  146. /// </summary>
  147. /// <param name="output">Stream to write the GIF to.</param>
  148. /// <param name="frameDelay">Delay between frames in units of 10ms.</param>
  149. /// <param name="start">First frame to export.</param>
  150. /// <param name="count">Number of frames to export.</param>
  151. public void ExportGif(Stream output, int frameDelay, int start = 0, int count = -1)
  152. {
  153. if (start < 0)
  154. throw new ArgumentOutOfRangeException();
  155. if (start + count > FrameCount)
  156. throw new ArgumentOutOfRangeException();
  157.  
  158. if (count < 0)
  159. count = FrameCapacity;
  160.  
  161. using (var image = new Image<Rgba32>(Width, Height))
  162. {
  163. var frames = image.Frames;
  164. for (var i = start + 1; i <= count; i++)
  165. {
  166. var frameIndex = (_frameIndex + i) % FrameCapacity;
  167. ConvertColorData(Frames[frameIndex], _rgbaBuffer);
  168. var frame = frames.AddFrame(_rgbaBuffer);
  169. frame.MetaData.FrameDelay = frameDelay;
  170. }
  171.  
  172. // remove the frame created with image creation
  173. frames.RemoveFrame(0);
  174. var encoder = new GifEncoder();
  175. image.SaveAsGif(output, encoder);
  176. }
  177. }
  178.  
  179. private static void ConvertColorData(Color[] mgBuffer, Rgba32[] isBuffer)
  180. {
  181. for (var i = 0; i < mgBuffer.Length; i++)
  182. {
  183. var c = mgBuffer[i];
  184. isBuffer[i] = new Rgba32(c.R, c.G, c.B, c.A);
  185. }
  186. }
  187. }
  188. }
Add Comment
Please, Sign In to add comment