Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
CaptureCamera.cs
Go to the documentation of this file.
1using System;
4using System.Drawing.Imaging;
5using System.IO;
10using ReLogic.OS;
14
16
17internal class CaptureCamera : IDisposable
18{
31
32 private static bool CameraExists;
33
34 public const int CHUNK_SIZE = 128;
35
36 public const int FRAMEBUFFER_PIXEL_SIZE = 2048;
37
38 public const int INNER_CHUNK_SIZE = 126;
39
40 public const int MAX_IMAGE_SIZE = 4096;
41
42 public const string CAPTURE_DIRECTORY = "Captures";
43
45
47
49
51
53
54 private readonly object _captureLock = new object();
55
56 private bool _isDisposed;
57
59
61
63
64 private byte[] _scaledFrameData;
65
66 private byte[] _outputData;
67
69
71
72 private float _tilesProcessed;
73
74 private float _totalTiles;
75
76 public bool IsCapturing
77 {
78 get
79 {
81 bool result = _activeSettings != null;
83 return result;
84 }
85 }
86
88 {
89 CameraExists = true;
90 _graphics = graphics;
91 _spriteBatch = new SpriteBatch(graphics);
92 try
93 {
94 _frameBuffer = new RenderTarget2D(graphics, 2048, 2048, mipMap: false, graphics.PresentationParameters.BackBufferFormat, DepthFormat.None);
95 _filterFrameBuffer1 = new RenderTarget2D(graphics, 2048, 2048, mipMap: false, graphics.PresentationParameters.BackBufferFormat, DepthFormat.None);
96 _filterFrameBuffer2 = new RenderTarget2D(graphics, 2048, 2048, mipMap: false, graphics.PresentationParameters.BackBufferFormat, DepthFormat.None);
97 }
98 catch
99 {
100 Main.CaptureModeDisabled = true;
101 return;
102 }
104 }
105
106 public void Capture(CaptureSettings settings)
107 {
108 Main.GlobalTimerPaused = true;
110 if (_activeSettings != null)
111 {
112 throw new InvalidOperationException("Capture called while another capture was already active.");
113 }
114 _activeSettings = settings;
116 float num = 1f;
117 if (settings.UseScaling)
118 {
119 if (area.Width * 16 > 4096)
120 {
121 num = 4096f / (float)(area.Width * 16);
122 }
123 if (area.Height * 16 > 4096)
124 {
125 num = Math.Min(num, 4096f / (float)(area.Height * 16));
126 }
127 num = Math.Min(1f, num);
128 _outputImageSize = new Size((int)MathHelper.Clamp((int)(num * (float)(area.Width * 16)), 1f, 4096f), (int)MathHelper.Clamp((int)(num * (float)(area.Height * 16)), 1f, 4096f));
129 _outputData = new byte[4 * _outputImageSize.Width * _outputImageSize.Height];
130 int num2 = (int)Math.Floor(num * 2048f);
131 _scaledFrameData = new byte[4 * num2 * num2];
133 }
134 else
135 {
136 _outputData = new byte[16777216];
137 }
138 _tilesProcessed = 0f;
139 _totalTiles = area.Width * area.Height;
140 for (int i = area.X; i < area.X + area.Width; i += 126)
141 {
142 for (int j = area.Y; j < area.Y + area.Height; j += 126)
143 {
144 int num3 = Math.Min(128, area.X + area.Width - i);
145 int num4 = Math.Min(128, area.Y + area.Height - j);
146 int width = (int)Math.Floor(num * (float)(num3 * 16));
147 int height = (int)Math.Floor(num * (float)(num4 * 16));
148 int x = (int)Math.Floor(num * (float)((i - area.X) * 16));
149 int y = (int)Math.Floor(num * (float)((j - area.Y) * 16));
150 _renderQueue.Enqueue(new CaptureChunk(new Microsoft.Xna.Framework.Rectangle(i, j, num3, num4), new Microsoft.Xna.Framework.Rectangle(x, y, width, height)));
151 }
152 }
154 }
155
156 public void DrawTick()
157 {
159 if (_activeSettings == null)
160 {
161 return;
162 }
164 if (_renderQueue.Count > 0)
165 {
169 Main.instance.TilesRenderer.PrepareForAreaDrawing(captureChunk.Area.Left, captureChunk.Area.Right, captureChunk.Area.Top, captureChunk.Area.Bottom, prepareLazily: false);
170 Main.instance.TilePaintSystem.PrepareAllRequests();
173 if (notRetro)
174 {
175 Microsoft.Xna.Framework.Color clearColor = (_activeSettings.CaptureBackground ? Microsoft.Xna.Framework.Color.Black : Microsoft.Xna.Framework.Color.Transparent);
177 Main.instance.DrawCapture(captureChunk.Area, _activeSettings);
179 }
180 else
181 {
182 Main.instance.DrawCapture(captureChunk.Area, _activeSettings);
183 }
185 {
194 }
195 else
196 {
198 SaveImage(_frameBuffer, captureChunk.ScaledArea.Width, captureChunk.ScaledArea.Height, ImageFormat.Png, _activeSettings.OutputName, captureChunk.Area.X + "-" + captureChunk.Area.Y + ".png");
199 }
200 _tilesProcessed += captureChunk.Area.Width * captureChunk.Area.Height;
201 }
202 if (_renderQueue.Count == 0)
203 {
205 }
207 }
208
210 {
211 fixed (byte* ptr3 = &destinationBuffer[0])
212 {
213 fixed (byte* ptr = &sourceBuffer[0])
214 {
215 byte* ptr2 = ptr;
216 byte* ptr4 = ptr3 + (destinationBufferWidth * area.Y + area.X << 2);
217 for (int i = 0; i < area.Height; i++)
218 {
219 for (int j = 0; j < area.Width; j++)
220 {
221 if (Program.IsXna)
222 {
223 ptr4[2] = *ptr2;
224 ptr4[1] = ptr2[1];
225 *ptr4 = ptr2[2];
226 ptr4[3] = ptr2[3];
227 }
228 else
229 {
230 *ptr4 = *ptr2;
231 ptr4[1] = ptr2[1];
232 ptr4[2] = ptr2[2];
233 ptr4[3] = ptr2[3];
234 }
235 ptr2 += 4;
236 ptr4 += 4;
237 }
238 ptr2 += sourceBufferWidth - area.Width << 2;
239 ptr4 += destinationBufferWidth - area.Width << 2;
240 }
241 }
242 }
243 }
244
245 public float GetProgress()
246 {
248 }
249
250 private bool SaveImage(int width, int height, ImageFormat imageFormat, string filename)
251 {
253 {
254 return false;
255 }
256 try
257 {
258 if (!Platform.IsWindows)
259 {
261 PlatformUtilities.SavePng(stream, width, height, width, height, _outputData);
262 }
263 else
264 {
265 using Bitmap bitmap = new Bitmap(width, height);
266 System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, width, height);
267 BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppPArgb);
268 IntPtr scan = bitmapData.Scan0;
269 Marshal.Copy(_outputData, 0, scan, width * height * 4);
270 bitmap.UnlockBits(bitmapData);
272 bitmap.Dispose();
273 }
274 return true;
275 }
276 catch (Exception value)
277 {
279 return false;
280 }
281 }
282
283 private void SaveImage(Texture2D texture, int width, int height, ImageFormat imageFormat, string foldername, string filename)
284 {
285 string text = Main.SavePath + Path.DirectorySeparatorChar + "Captures" + Path.DirectorySeparatorChar + foldername;
286 string text2 = Path.Combine(text, filename);
288 {
289 return;
290 }
291 if (!Platform.IsWindows)
292 {
293 int elementCount = texture.Width * texture.Height * 4;
294 texture.GetData(_outputData, 0, elementCount);
295 int num = 0;
296 int num2 = 0;
297 for (int i = 0; i < height; i++)
298 {
299 for (int j = 0; j < width; j++)
300 {
302 _outputData[num2 + 1] = _outputData[num + 1];
303 _outputData[num2 + 2] = _outputData[num + 2];
304 _outputData[num2 + 3] = _outputData[num + 3];
305 num += 4;
306 num2 += 4;
307 }
308 num += texture.Width - width << 2;
309 }
311 PlatformUtilities.SavePng(stream, width, height, width, height, _outputData);
312 return;
313 }
314 using Bitmap bitmap = new Bitmap(width, height);
315 System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, width, height);
316 int elementCount2 = texture.Width * texture.Height * 4;
317 texture.GetData(_outputData, 0, elementCount2);
318 int num3 = 0;
319 int num4 = 0;
320 for (int k = 0; k < height; k++)
321 {
322 for (int l = 0; l < width; l++)
323 {
324 byte b = _outputData[num3 + 2];
326 _outputData[num4] = b;
327 _outputData[num4 + 1] = _outputData[num3 + 1];
328 _outputData[num4 + 3] = _outputData[num3 + 3];
329 num3 += 4;
330 num4 += 4;
331 }
332 num3 += texture.Width - width << 2;
333 }
334 BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppPArgb);
335 IntPtr scan = bitmapData.Scan0;
336 Marshal.Copy(_outputData, 0, scan, width * height * 4);
337 bitmap.UnlockBits(bitmapData);
338 bitmap.Save(text2, imageFormat);
339 }
340
341 private void FinishCapture()
342 {
344 {
345 int num = 0;
347 {
348 GC.Collect();
349 Thread.Sleep(5);
350 num++;
351 Console.WriteLine(Language.GetTextValue("Error.CaptureError"));
352 if (num > 5)
353 {
354 Console.WriteLine(Language.GetTextValue("Error.UnableToCapture"));
355 break;
356 }
357 }
358 }
359 _outputData = null;
360 _scaledFrameData = null;
361 Main.GlobalTimerPaused = false;
363 if (_scaledFrameBuffer != null)
364 {
366 _scaledFrameBuffer = null;
367 }
368 _activeSettings = null;
369 }
370
371 public void Dispose()
372 {
373 if (Main.dedServ)
374 {
375 return;
376 }
378 if (_isDisposed)
379 {
381 return;
382 }
386 if (_scaledFrameBuffer != null)
387 {
389 _scaledFrameBuffer = null;
390 }
391 CameraExists = false;
392 _isDisposed = true;
394 }
395}
static readonly BlendState AlphaBlend
Definition BlendState.cs:36
void Clear(ClearOptions options, Vector4 color, float depth, int stencil)
unsafe void SetRenderTarget(RenderTargetCube renderTarget, CubeMapFace cubeMapFace)
override void Dispose([MarshalAs(UnmanagedType.U1)] bool P_0)
static readonly SamplerState AnisotropicClamp
void Draw(Texture2D texture, Vector2 position, Color color)
static float Clamp(float value, float min, float max)
Definition MathHelper.cs:46
static bool IsWindows
Definition Platform.cs:19
static void WriteLine()
Definition Console.cs:733
static void Collect(int generation)
Definition GC.cs:119
Definition GC.cs:8
static FileStream Create(string path)
Definition File.cs:73
static string Combine(string path1, string path2)
Definition Path.cs:304
static readonly char DirectorySeparatorChar
Definition Path.cs:71
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static double Floor(double d)
static void Copy(int[] source, int startIndex, IntPtr destination, int length)
Definition Marshal.cs:800
static void Exit(object obj)
static void Enter(object obj)
static void Sleep(int millisecondsTimeout)
Definition Thread.cs:658
CaptureChunk(Microsoft.Xna.Framework.Rectangle area, Microsoft.Xna.Framework.Rectangle scaledArea)
readonly Microsoft.Xna.Framework.Rectangle ScaledArea
readonly Microsoft.Xna.Framework.Rectangle Area
bool SaveImage(int width, int height, ImageFormat imageFormat, string filename)
void SaveImage(Texture2D texture, int width, int height, ImageFormat imageFormat, string foldername, string filename)
CaptureCamera(GraphicsDevice graphics)
void Capture(CaptureSettings settings)
unsafe void DrawBytesToBuffer(byte[] sourceBuffer, byte[] destinationBuffer, int sourceBufferWidth, int destinationBufferWidth, Microsoft.Xna.Framework.Rectangle area)
static FilterManager Scene
Definition Filters.cs:5
static bool NotRetro
Definition Lighting.cs:64
static string GetTextValue(string key)
Definition Language.cs:15
static bool dedServ
Definition Main.cs:1226
static Main instance
Definition Main.cs:283
static string SavePath
Definition Main.cs:2680
static bool IsXna
Definition Program.cs:21
static void SavePng(Stream stream, int width, int height, int imgWidth, int imgHeight, byte[] data)
static bool TryCreatingDirectory(string folderPath)
Definition Utils.cs:754
static Color Transparent
Definition Color.cs:76