You can generate an image, but this requires a bit more work. As you pointed out, you cannot just save the whole image. So I changed the save logic to scroll the image and save 60 lines at a time. Note that I call GC.Collect 3 times to go through all 3 generations of GC and get rid of all memory allocations.
static IEnumerable<ExtendedImage> GetImageSegments(LockScreenTile tileControl) { const int segmentMaxHight = 60; var aggregatePixelHeight = (int)tileControl.ActualHeight; tileControl.LayoutRoot.Height = aggregatePixelHeight; for (int row = 0; row < aggregatePixelHeight; row += segmentMaxHight) { tileControl.LayoutRoot.Margin = new Thickness(0, -row, 0, 0); tileControl.Height = Math.Min(segmentMaxHight, aggregatePixelHeight - row); yield return tileControl.ToExtendedImage(); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); } }
ExtendedImage comes from the ImageTools library. And as soon as I get an enumerated back, I call PNG compression (which I fixed to continue using fragments of the image):
var segments = GetImageSegments(tileControl); double pixelRatio = (template.PixelWidth) / tileControl.ActualWidth; segments.SaveToPngImage( aggregatePixelHeight: (int)(savedActualHeight * pixelRatio), pixelWidth: template.PixelWidth, densityX: template.DensityX, densityY: template.DensityY, directoryName: tileDirectoryName, filePath: filePath);
Finally, SaveToPngImage uses the PngEncoder from ImageTools, which I changed:
private void WriteDataChunks(IEnumerable<ExtendedImage> verticalImageSegments) { byte[] compressedBytes; MemoryStream underlyingMemoryStream = null; DeflaterOutputStream compressionStream = null; try { underlyingMemoryStream = new MemoryStream(); compressionStream = new DeflaterOutputStream(underlyingMemoryStream); foreach (var verticalImageSegment in verticalImageSegments) { byte[] pixels = verticalImageSegment.Pixels; var data = new byte[verticalImageSegment.PixelWidth*verticalImageSegment.PixelHeight*4 + verticalImageSegment.PixelHeight]; int rowLength = verticalImageSegment.PixelWidth*4 + 1; for (int y = 0; y < verticalImageSegment.PixelHeight; y++) { byte compression = 0; if (y > 0) { compression = 2; } data[y*rowLength] = compression; for (int x = 0; x < verticalImageSegment.PixelWidth; x++) {
Vlad source share