2 using System.Collections.Generic;
3 using System.Diagnostics;
6 using System.Threading;
7 using System.Threading.Tasks;
12 public class Snapshotter
15 public string chunkPath;
16 public ColumnsMetadata cols;
18 public int NorthEdge => cols.North_mostChunk;
19 public int WestEdge => cols.West_mostChunk;
20 public int Width => (cols.East_mostChunk - WestEdge + 1);
21 public int Height => (cols.South_mostChunk - NorthEdge + 1);
23 public Snapshotter(string path, string chunkPath, ColumnsMetadata cols, int chunkSize)
25 this.path = Path.Combine(path, "snapshot.png");
26 this.chunkPath = Path.Combine(path, chunkPath);
28 this.chunkSize = chunkSize;
32 /// takes a snapshot. this should be called from an extra thread.
34 /// <param name="path">path to the map dir</param>
35 /// <param name="chunkPath">name of the chunks dir part thing</param>
36 /// <param name="cols"></param>
37 /// <param name="chunkSize"></param>
38 public async void Take()
40 var t = new Stopwatch();
42 Console.WriteLine("snapshot started");
44 ImageInfo info = new ImageInfo(Width * chunkSize, Height * chunkSize, 8, false);
45 PngWriter snapWriter = FileHelper.CreatePngWriter(path, info, true);
46 snapWriter.CompLevel = 5;
47 snapWriter.CompressionStrategy = Hjg.Pngcs.Zlib.EDeflateCompressStrategy.Filtered;
51 group ch by ch.Location.Y into g
54 // that sorts things in ascending order so we can only create (chunkSize) lines at once
55 int row = 0, lastPosY = 0, posY = 0;
56 foreach (var chunkGroup in orderedList)
58 // oh god here we go...
59 posY = chunkGroup.Key - NorthEdge;
60 var delta = posY - lastPosY;
63 // if there is more than 1 blank step then the gap needs to be filled.
64 for (int i = 1; i < delta; i++)
66 byte[] blankLine = new byte[info.BytesPerRow];
67 for (int j = 0; j < chunkSize; j++)
68 snapWriter.WriteRowByte(blankLine, row++);
71 var inGroup = (await ReadAllInGroup(chunkGroup)).ToArray();
73 for (int r = 0; r < chunkSize; r++)
75 var line = new byte[info.BytesPerRow];
76 for (int chunk = 0; chunk < inGroup.Length; chunk++)
78 var posX = inGroup[chunk].Key * chunkSize * info.BytesPixel;
79 inGroup[chunk].Value?[r].CopyTo(line, posX);
81 snapWriter.WriteRowByte(line, row++);
84 snapWriter.ShouldCloseStream = true;
91 Console.WriteLine("Snapshot exception!");
93 Console.WriteLine($"snapshot finished in {t.ElapsedMilliseconds}");
96 private async Task<Dictionary<int, byte[][]>> ReadAllInGroup(IGrouping<int, ColumnMeta> group)
98 var taskGroup = new Dictionary<int, byte[][]>(group.Count());
99 foreach (var shardMeta in group)
101 var shardPath = Path.Combine(chunkPath, $"{shardMeta.Location.X}_{shardMeta.Location.Y}.png");
102 taskGroup.Add(shardMeta.Location.X - WestEdge, await ReadNoThrow(shardPath));
107 private async Task<byte[][]> ReadNoThrow(string readPath)
111 return await Task.Run(() => FileHelper.CreatePngReader(readPath).ReadRowsByte().ScanlinesB);
115 Console.WriteLine(e.Message);
117 } // do nothing on error