/// <summary> /// Try to extract thumbnails from a given file /// </summary> /// <param name="reader">Stream reader to read from</param> /// <param name="codeParserBuffer">Read buffer</param> /// <param name="parsedFileInfo">File information</param> /// <param name="code">Code instance to reuse</param> /// <returns>Asynchronous task</returns> public static async Task ProcessAsync(StreamReader reader, CodeParserBuffer codeParserBuffer, ParsedFileInfo parsedFileInfo, Code code) { _logger.Info($"Processing Image {parsedFileInfo.FileName}"); StringBuilder imageBuffer = new(); code.Reset(); //Keep reading the data from the file while (codeParserBuffer.GetPosition(reader) < reader.BaseStream.Length) { Program.CancellationToken.ThrowIfCancellationRequested(); if (!await DuetAPI.Commands.Code.ParseAsync(reader, code, codeParserBuffer)) { continue; } //Icon data goes until the first line of executable code. if (code.Type == CodeType.Comment) { imageBuffer.Append(code.Comment.Trim()); code.Reset(); } else { try { ParsedThumbnail thumbnail = ReadImage(imageBuffer.ToString()); parsedFileInfo.Thumbnails.Add(thumbnail); _logger.Error("Icon Thumbnails Found"); } catch { //throw it away } return; } } }
/// <summary> /// Parse the file for thumbnails /// </summary> /// <param name="reader">Stream reader</param> /// <param name="partialFileInfo">G-code file information</param> /// <returns>Asynchronous task</returns> /// <remarks> /// This functionality should be moved to ParseHeader in the long term /// </remarks> private static async Task ParseThumbnails(StreamReader reader, ParsedFileInfo parsedFileInfo) { Code code = new Code(); CodeParserBuffer codeParserBuffer = new CodeParserBuffer(Settings.FileBufferSize, true); bool imageFound = false; int encodedLength = 0; StringBuilder encodedImage = new StringBuilder(); reader.BaseStream.Seek(0, SeekOrigin.Begin); ParsedThumbnail thumbnail = null; while (codeParserBuffer.GetPosition(reader) < reader.BaseStream.Length) { Program.CancellationToken.ThrowIfCancellationRequested(); if (!await DuetAPI.Commands.Code.ParseAsync(reader, code, codeParserBuffer)) { continue; } if (code.Type != CodeType.Comment) { return; } if (string.IsNullOrEmpty(code.Comment)) { code.Reset(); continue; } if (code.Comment.Contains("thumbnail begin", StringComparison.InvariantCultureIgnoreCase)) { //Exit if we find another start tag before ending the previous image if (imageFound) { return; } string[] thumbnailTokens = code.Comment.Trim().Split(' '); //Stop processing since the thumbnail may be corrupt. if (thumbnailTokens.Length != 4) { return; } string[] dimensions = thumbnailTokens[2].Split('x'); if (dimensions.Length != 2) { continue; } imageFound = true; thumbnail = new ParsedThumbnail { Width = int.Parse(dimensions[0]), Height = int.Parse(dimensions[1]) }; encodedLength = int.Parse(thumbnailTokens[3]); encodedImage.Clear(); code.Reset(); continue; } else if (code.Comment.Contains("thumbnail end", StringComparison.InvariantCultureIgnoreCase)) { if (encodedImage.Length == encodedLength) { thumbnail.EncodedImage = "data:image/png;base64," + encodedImage.ToString(); parsedFileInfo.Thumbnails.Add(thumbnail); } thumbnail = null; imageFound = false; } else if (imageFound) { encodedImage.Append(code.Comment.Trim()); } code.Reset(); } }