This repository was archived by the owner on Jun 23, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathVidLapseCommon.cs
More file actions
305 lines (266 loc) · 8.95 KB
/
VidLapseCommon.cs
File metadata and controls
305 lines (266 loc) · 8.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using UnityEngine;
namespace VidLapse{
/*!
* \brief Manages recording and writing process of AVI
* \details Manages recording and writing process of AVI
* \author Ernest Mallett
* \date March 2014
* \copyright DarkCloud Games 2014
*/
public partial class VidLapse : MonoBehaviour {
#region Variables
/**
* How many seconds to wait between each shot
* @private
*/
private float _frequency;
/**
* Directory to store shots
* @private
*/
private string _directory;
/**
* Full path and directory
* @private
*/
private string _fullpath;
/**
* Percentage complete of making movie
* @private
*/
private float _complete=0f;
/**
* Number of images stored
* @private
*/
private int _stored=0;
/**
* Can we record?
* @private
*/
private bool _record = true;
/**
* Save the video to desktop?
* @private
*/
private bool _savetodesktop = false;
/**
* Filename to save the completed video as
* @private
*/
private string _Filename="";
/**
* Is the full path of the video set?
* @private
*/
private bool _fullpathset=false;
/**
* What method are we going to use to capture?
* @private
*/
private CaptureMethod _captureMethod = CaptureMethod.Pixels;
/**
* Queue for storing images in memory
* @private
*/
private Queue<byte[]> _imageBytes = new Queue<byte[]>();
/**
* What method are we going to use to capture?
* @private
*/
private SaveMethod _saveMethod = SaveMethod.Disk;
#endregion
/**
* VidLapse Constructor
*/
public VidLapse(){
_frequency=1f;
_directory="VidLapse";
_fullpath=Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
}
/**
* Delete all .png files in the specified directory
* @return void
*/
public void RemoveImages(){
if (_saveMethod == SaveMethod.Disk) {
DirectoryInfo d = new DirectoryInfo(Application.persistentDataPath);
FileInfo[] files = d.GetFiles("*.png");
foreach (FileInfo file in files) {
file.Delete();
}
} else {
_imageBytes = new Queue<byte[]>();
}
}
#region Capture Methods
public void CaptureImages(CaptureMethod capturemethod, SaveMethod savemethod) {
_saveMethod = savemethod;
switch (capturemethod) {
case CaptureMethod.Pixels:
StartCoroutine(ReadPixels());
break;
case CaptureMethod.Tex:
StartCoroutine(RenderToTex());
break;
case CaptureMethod.App:
StartCoroutine(ScreenShot());
break;
}
}
/**
* Take a screenshot using Unity's built-in method
* @return IEnumerator
*/
private IEnumerator ScreenShot(){
_record=true;
while(true){
yield return new WaitForEndOfFrame();
if (!_record) {
break;
}
Application.CaptureScreenshot(Application.persistentDataPath+"/"+DateTime.Now.Day+DateTime.Now.Hour+DateTime.Now.Minute+DateTime.Now.Second+DateTime.Now.Millisecond+".png");
_stored++;
yield return new WaitForSeconds(_frequency);
if (!_record) {
break;
}
}
}
/**
* Take a screenshot by reading screen pixels
* @return IEnumerator
*/
private IEnumerator ReadPixels() {
_record = true;
while (true) {
yield return new WaitForEndOfFrame();
if (!_record) {
break;
}
Texture2D texture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
yield return 0;
byte[] bytes = texture.EncodeToPNG();
if (_saveMethod == SaveMethod.Disk) {
File.WriteAllBytes(Application.persistentDataPath + "/" + DateTime.Now.Day + DateTime.Now.Hour + DateTime.Now.Minute + DateTime.Now.Second + DateTime.Now.Millisecond + ".png", bytes);
DestroyObject(texture);
} else {
_imageBytes.Enqueue(bytes);
}
yield return new WaitForSeconds(_frequency);
if (!_record) {
break;
}
}
}
/**
* Take a screenshot by rendering camera to Texture
* @return IEnumerator
*/
private IEnumerator RenderToTex() {
_record = true;
while (true) {
yield return new WaitForEndOfFrame();
if (!_record) {
break;
}
RenderTexture rt = new RenderTexture(Screen.width, Screen.height, 24);
Texture2D screenShot = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
foreach (Camera cam in Camera.allCameras) {
cam.targetTexture = rt;
cam.Render();
cam.targetTexture = null;
}
RenderTexture.active = rt;
screenShot.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
Camera.main.targetTexture = null;
RenderTexture.active = null;
Destroy(rt);
yield return 0;
byte[] bytes = screenShot.EncodeToPNG();
if (_saveMethod == SaveMethod.Disk) {
File.WriteAllBytes(Application.persistentDataPath + "/" + DateTime.Now.Day + DateTime.Now.Hour + DateTime.Now.Minute + DateTime.Now.Second + DateTime.Now.Millisecond + ".png", bytes);
} else {
_imageBytes.Enqueue(bytes);
}
yield return new WaitForSeconds(_frequency);
if (!_record) {
break;
}
}
}
#endregion
/**
* Convert the Render size to a System rectangle
* @param bounds The Bounds to create a rectangle from
* @return Rectangle A System Rectangle created from the screen bounds
* @private
*/
private System.Drawing.Rectangle BoundsToScreenRect(Bounds bounds)
{
// Get mesh origin and farthest extent (this works best with simple convex meshes)
Vector3 origin = Camera.main.WorldToScreenPoint(new Vector3(bounds.min.x, bounds.max.y, 0f));
Vector3 extent = Camera.main.WorldToScreenPoint(new Vector3(bounds.max.x, bounds.min.y, 0f));
// Create rect in screen space and return - does not account for camera perspective
return new System.Drawing.Rectangle((int)origin.x,(int)Screen.height - (int)origin.y,(int)extent.x - (int)origin.x,(int)origin.y - (int)extent.y);
}
#region Setup Bitmap
/**
* Creates a bitmap from a byte array
* @param arrayin A byte array to use
* @return Bitmap The created Bitmap
* @private
*/
private Bitmap ToBitmap(byte[] arrayin){
MemoryStream ms = new MemoryStream(arrayin);
Image returnimage = Image.FromStream(ms);
Bitmap bitmap = new Bitmap(returnimage);
return bitmap;
}
/**
* Resize the supplied bitmap
* @param original The original bitmap
* @param reducedWidth The width of the new bitmap
* @param reducedHeight The height of the new bitmap
* @return Bitmap The reduced bitmap
* @private
*/
private Bitmap ReduceBitmap(Bitmap original, int reducedWidth, int reducedHeight)
{
var reduced = new Bitmap(reducedWidth, reducedHeight);
using (var dc = System.Drawing.Graphics.FromImage(reduced))
{
dc.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
dc.DrawImage(original, new Rectangle(0, 0, reducedWidth, reducedHeight), new Rectangle(0, 0, original.Width, original.Height), GraphicsUnit.Pixel);
}
return reduced;
}
#endregion
#region Getters/Setters
/**
* Gets the video creation progress
* @return float Progress of video creation
* @note Currently not functional will fix in later update
*/
public float VideoProgress{
get{return _complete;}
private set{_complete=value;}
}
/**
* Gets/Sets the current state of recroding
* @return bool Whether or not the system is recording
*/
public bool Record{
get{return _record;}
set{_record=value;}
}
#endregion
}
}