using Adaptation.Shared; using Adaptation.Shared.Methods; using log4net; using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using Tesseract; namespace Adaptation.FileHandlers.jpeg; public class ProcessData : IProcessData { private readonly List _Details; private readonly ILog _Log; public string JobID { get; set; } public string MesEntity { get; set; } public int Red { get; set; } public int Green { get; set; } public string Text { get; set; } public int TotalDelta { get; set; } public string ClosestMatchFileName { get; set; } List Shared.Properties.IProcessData.Details => _Details; public ProcessData(IFileRead fileRead, Logistics logistics, List fileInfoCollection, int startX, int startY, int endX, int endY, int offSetX, int offSetY, Size size, List> colorCollections) { JobID = logistics.JobID; _Details = new List(); MesEntity = logistics.MesEntity; _Log = LogManager.GetLogger(typeof(ProcessData)); Parse(fileRead, fileInfoCollection, startX, startY, endX, endY, offSetX, offSetY, size, colorCollections); } internal static (int, int) GetOffSet(string sourceDirectoryCloaking) { int offSetX; int offSetY; string[] offset = sourceDirectoryCloaking.Split('x'); if (offset.Length != 2 || !int.TryParse(offset[0], out int x) || !int.TryParse(offset[1], out int y)) { offSetX = 0; offSetY = 0; } else { offSetX = x; offSetY = y; } return new(offSetX, offSetY); } private static string Get(string value, bool useSplitForMID) { string result = value; if (useSplitForMID) { if (result.IndexOf(".") > -1) result = result.Split('.')[0].Trim(); if (result.IndexOf("_") > -1) result = result.Split('_')[0].Trim(); if (result.IndexOf("-") > -1) result = result.Split('-')[0].Trim(); } result = string.Concat(result.Substring(0, 1).ToUpper(), result.Substring(1).ToLower()); return result; } string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary reactors) { string result = string.Empty; string filePrefixAsMID; foreach (KeyValuePair keyValuePair in reactors) { foreach (string filePrefix in keyValuePair.Value.Split('|')) { filePrefixAsMID = Get(filePrefix, useSplitForMID: true); if (logistics.MID.StartsWith(filePrefix) || logistics.MID.StartsWith(filePrefixAsMID)) { result = keyValuePair.Key; break; } } } if (string.IsNullOrEmpty(result) && reactors.Count == 1) result = reactors.ElementAt(0).Key; return result; } Tuple> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List fileInfoCollection) { Tuple> results; List tests = new(); foreach (object item in _Details) tests.Add(Test.CDE); List descriptions = fileRead.GetDescriptions(fileRead, tests, this); if (tests.Count != descriptions.Count) throw new Exception(); for (int i = 0; i < tests.Count; i++) { if (descriptions[i] is not Description description) throw new Exception(); if (description.Test != (int)tests[i]) throw new Exception(); } FileInfo fileInfo = new($"{logistics.ReportFullPath}.descriptions.json"); List fileReadDescriptions = (from l in descriptions select (Description)l).ToList(); string json = JsonSerializer.Serialize(fileReadDescriptions, fileReadDescriptions.GetType()); File.WriteAllText(fileInfo.FullName, json); File.SetLastWriteTime(fileInfo.FullName, logistics.DateTimeFromSequence); fileInfoCollection.Add(fileInfo); JsonElement[] jsonElements = JsonSerializer.Deserialize(json) ?? throw new Exception(); results = new Tuple>(logistics.Logistics1[0], tests.ToArray(), jsonElements, fileInfoCollection); return results; } #nullable enable #pragma warning disable CA1416 private static (Size, Color[]) Get(string reportFullPath, int startX, int startY, int endX, int endY, int offSetX, int offSetY) { Color color; List colors = new(); int startXValue = startX + offSetX; int startYValue = startY + offSetY; int endXValue = endX + offSetX; int endYValue = endY + offSetY; using Bitmap? bitmap = Image.FromFile(reportFullPath) as Bitmap; if (bitmap is null) throw new Exception($"Couldn't load image from <{reportFullPath}>"); for (int x = startXValue; x < endXValue; x++) { for (int y = startYValue; y < endYValue; y++) { color = bitmap.GetPixel(x, y); colors.Add(color); } } return new(bitmap.Size, colors.ToArray()); } private static System.Drawing.Imaging.ImageFormat Get(string extension) { System.Drawing.Imaging.ImageFormat imageFormat = extension switch { ".bmp" => System.Drawing.Imaging.ImageFormat.Bmp, ".gif" => System.Drawing.Imaging.ImageFormat.Gif, ".jpeg" => System.Drawing.Imaging.ImageFormat.Jpeg, ".jpg" => System.Drawing.Imaging.ImageFormat.Jpeg, ".png" => System.Drawing.Imaging.ImageFormat.Png, ".tiff" => System.Drawing.Imaging.ImageFormat.Tiff, _ => throw new Exception("Extension not mapped"), }; return imageFormat; } private static (Color[], int, int) Get(IFileRead fileRead, List fileInfoCollection, int startX, int startY, int endX, int endY, int offSetX, int offSetY, string extension, Size size) { Color color; List colors = new(); MemoryStream memoryStream = new(); int startXValue = startX + offSetX; int startYValue = startY + offSetY; int endXValue = endX + offSetX; int endYValue = endY + offSetY; Bitmap selectedBitmap = new(endXValue - startXValue, endYValue - startYValue); System.Drawing.Imaging.ImageFormat imageFormat = Get(extension); using Bitmap? bitmap = Image.FromFile(fileRead.ReportFullPath) as Bitmap; string saveFileName = Path.ChangeExtension(fileRead.ReportFullPath, extension); if (bitmap is null) throw new Exception($"Couldn't load image from <{fileRead.ReportFullPath}>"); if (!size.Equals(bitmap.Size)) throw new Exception("Source size doesn't match master image size "); for (int x = startXValue; x < endXValue; x++) { for (int y = startYValue; y < endYValue; y++) { color = bitmap.GetPixel(x, y); colors.Add(color); selectedBitmap.SetPixel(x - startXValue, y - startYValue, color); } } selectedBitmap.Save(memoryStream, imageFormat); if (!fileRead.IsEAFHosted) { fileInfoCollection.Add(new FileInfo(saveFileName)); SaveToFile(extension, saveFileName, memoryStream); } return new(colors.ToArray(), endXValue - startXValue, endYValue - startYValue); } private static string Get(IFileRead fileRead, string extension, string extra) { string result; string? directoryName = Path.GetDirectoryName(fileRead.ReportFullPath); if (string.IsNullOrEmpty(directoryName)) throw new Exception("Couldn't get directoryName!"); string? fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileRead.ReportFullPath); if (string.IsNullOrEmpty(fileNameWithoutExtension)) throw new Exception("Couldn't get fileNameWithoutExtension!"); result = Path.Combine(directoryName, $"{fileNameWithoutExtension} - {extra}{extension}"); return result; } private static void SaveToFile(string extension, string saveFileName, MemoryStream memoryStream) { System.Drawing.Imaging.ImageFormat imageFormat = extension switch { ".bmp" => System.Drawing.Imaging.ImageFormat.Bmp, ".gif" => System.Drawing.Imaging.ImageFormat.Gif, ".jpeg" => System.Drawing.Imaging.ImageFormat.Jpeg, ".jpg" => System.Drawing.Imaging.ImageFormat.Jpeg, ".png" => System.Drawing.Imaging.ImageFormat.Png, ".tiff" => System.Drawing.Imaging.ImageFormat.Tiff, _ => throw new Exception("Extension not mapped"), }; using Bitmap bitmap = new(memoryStream); bitmap.Save(saveFileName, imageFormat); } #pragma warning restore CA1416 private static void SaveText(int red, int green, string closestMatchFileNameEnding, string textFileName, List<(string File, int TotalDelta)> totalDeltaCollection) { string format = "00000"; List lines = new() { red.ToString(format), green.ToString(format), closestMatchFileNameEnding }; foreach ((string file, int totalDelta) in totalDeltaCollection) { lines.Add(file); lines.Add(totalDelta.ToString(format)); } File.WriteAllLines(textFileName, lines); } internal static List<(string, Size, Color[])> GetColorCollections(int startX, int startY, int endX, int endY, int offSetX, int offSetY, string cellInstanceName, string masterImageDirectory) { List<(string, Size, Color[])> results = new(); (Size Size, Color[] Colors) result; string fileName; string[] files = Directory.GetFiles(masterImageDirectory, "*.jpeg", SearchOption.TopDirectoryOnly); foreach (string file in files) { fileName = Path.GetFileName(file); if (!fileName.StartsWith(cellInstanceName)) continue; result = Get(file, startX, startY, endX, endY, offSetX, offSetY); results.Add(new(file, result.Size, result.Colors)); } return results; } private void Parse(IFileRead fileRead, List fileInfoCollection, int startX, int startY, int endX, int endY, int offSetX, int offSetY, Size size, List> colorCollections) { Red = 0; Green = 0; int delta; Color color; int totalDelta; const int thresHold = 70; const string extension = ".tiff"; List<(string File, int TotalDelta)> totalDeltaCollection = new(); (Color[] sourceColors, int width, int height) = Get(fileRead, fileInfoCollection, startX, startY, endX, endY, offSetX, offSetY, extension, size); foreach ((string file, Color[] colors) in colorCollections) { totalDelta = 0; if (colors.Length != sourceColors.Length) continue; for (int i = 0; i < sourceColors.Length; i++) { color = sourceColors[i]; if (color.R > thresHold) Red += 1; if (color.G > thresHold) Green += 1; delta = color.R - colors[i].R; if (delta > 0) totalDelta += delta; else totalDelta += delta * -1; delta = color.G - colors[i].G; if (delta > 0) totalDelta += delta; else totalDelta += delta * -1; delta = color.B - colors[i].B; if (delta > 0) totalDelta += delta; else totalDelta += delta * -1; } totalDeltaCollection.Add(new(file, totalDelta)); } totalDeltaCollection = (from l in totalDeltaCollection orderby l.TotalDelta select l).ToList(); ClosestMatchFileName = Path.GetFileNameWithoutExtension(totalDeltaCollection[0].File); string[] closestMatchFileNameSplit = ClosestMatchFileName.Split('-'); Text = closestMatchFileNameSplit.Last().TrimStart(); TotalDelta = totalDeltaCollection[0].TotalDelta; string textFileName = Get(fileRead, ".txt", $"{TotalDelta} - {Text}"); if (!fileRead.IsEAFHosted) { _Log.Debug(textFileName); fileInfoCollection.Add(new FileInfo(textFileName)); SaveText(Red, Green, Text, textFileName, totalDeltaCollection); } _Details.Add(Text); } #nullable enable internal static List GetDescriptions(JsonElement[] jsonElements) { List results = new(); Description? description; JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; foreach (JsonElement jsonElement in jsonElements) { if (jsonElement.ValueKind != JsonValueKind.Object) throw new Exception(); description = JsonSerializer.Deserialize(jsonElement.ToString(), jsonSerializerOptions); if (description is null) continue; results.Add(description); } return results; } #pragma warning disable CA1416 private static MemoryStream GetMemoryStream(System.Drawing.Imaging.ImageFormat imageFormat, Bitmap bitmap, int startX, int startY, int endX, int endY, int offSetX, int offSetY) { Color color; int negitiveGrayScale; MemoryStream result = new(); int startXValue = startX + offSetX; int startYValue = startY + offSetY; int endXValue = endX + offSetX; int endYValue = endY + offSetY; using Bitmap selectedBitmap = new(endXValue - startXValue, endYValue - startYValue); for (int x = startXValue; x < endXValue; x++) { for (int y = startYValue; y < endYValue; y++) { color = bitmap.GetPixel(x, y); negitiveGrayScale = 255 - (int)((color.R * 0.3) + (color.G * 0.59) + (color.B * 0.11)); if (negitiveGrayScale < 162) selectedBitmap.SetPixel(x - startXValue, y - startYValue, Color.FromArgb(color.A, 0, 0, 0)); else selectedBitmap.SetPixel(x - startXValue, y - startYValue, Color.FromArgb(color.A, 255, 255, 255)); } } selectedBitmap.Save(result, imageFormat); return result; } private static List GetMemoryStreams(string reportFullPath, string extension) { List results = new(); System.Drawing.Imaging.ImageFormat imageFormat = Get(extension); using Bitmap? bitmap = Image.FromFile(reportFullPath) as Bitmap; if (bitmap is null) throw new Exception($"Couldn't load image from <{reportFullPath}>"); results.Add(GetMemoryStream(imageFormat, bitmap, 6, 130, 791, 953, 0, 0)); results.Add(GetMemoryStream(imageFormat, bitmap, 48, 795, 359, 869, 0, 0)); results.Add(GetMemoryStream(imageFormat, bitmap, 376, 814, 430, 832, 0, 0)); results.Add(GetMemoryStream(imageFormat, bitmap, 373, 793, 433, 874, 0, 0)); return results; } public static List<(float, string, List)> Parse(string reportFullPath) { List<(float, string, List)> results = new(); string text; float pageMeanConfidence; MemoryStream memoryStream; List blocks = new(); const string extension = ".tiff"; StringBuilder stringBuilder = new(); using TesseractEngine engine = new(string.Empty, "eng", EngineMode.Default); List memoryStreams = GetMemoryStreams(reportFullPath, extension); for (int i = 0; i < memoryStreams.Count; i++) { _ = stringBuilder.Clear(); memoryStream = memoryStreams[i]; using Pix img = Pix.LoadFromMemory(memoryStream.GetBuffer()); using Page page = engine.Process(img); text = page.GetText(); pageMeanConfidence = page.GetMeanConfidence(); using ResultIterator iter = page.GetIterator(); iter.Begin(); do { do { do { do { _ = stringBuilder.Append(iter.GetText(PageIteratorLevel.Word)).Append(' '); if (iter.IsAtFinalOf(PageIteratorLevel.TextLine, PageIteratorLevel.Word) && stringBuilder.Length > 0) { blocks.Add(stringBuilder.ToString()); _ = stringBuilder.Clear(); } } while (iter.Next(PageIteratorLevel.TextLine, PageIteratorLevel.Word)); if (iter.IsAtFinalOf(PageIteratorLevel.Para, PageIteratorLevel.TextLine)) _ = stringBuilder.AppendLine(); } while (iter.Next(PageIteratorLevel.Para, PageIteratorLevel.TextLine)); } while (iter.Next(PageIteratorLevel.Block, PageIteratorLevel.Para)); } while (iter.Next(PageIteratorLevel.Block)); if (stringBuilder.Length > 0) blocks.Add(stringBuilder.ToString()); results.Add(new(pageMeanConfidence, text, blocks)); // if (!fileRead.IsEAFHosted) // { // fileInfoCollection.Add(new FileInfo(saveFileName)); SaveToFile(extension, $"{reportFullPath}{i}{extension}", memoryStream); // } } return results; } #pragma warning restore CA1416 public static (float, string, List) Parse(string reportFullPath, List fileInfoCollection, int startX, int startY, int endX, int endY, int offSetX, int offSetY) { (float, string, List) result; List blocks = new(); StringBuilder stringBuilder = new(); using TesseractEngine engine = new(string.Empty, "eng", EngineMode.Default); using Pix img = Pix.LoadFromFile(reportFullPath); using Page page = engine.Process(img); string text = page.GetText(); float pageMeanConfidence = page.GetMeanConfidence(); using ResultIterator iter = page.GetIterator(); iter.Begin(); do { do { do { do { _ = stringBuilder.Append(iter.GetText(PageIteratorLevel.Word)).Append(' '); if (iter.IsAtFinalOf(PageIteratorLevel.TextLine, PageIteratorLevel.Word) && stringBuilder.Length > 0) { blocks.Add(stringBuilder.ToString()); _ = stringBuilder.Clear(); } } while (iter.Next(PageIteratorLevel.TextLine, PageIteratorLevel.Word)); if (iter.IsAtFinalOf(PageIteratorLevel.Para, PageIteratorLevel.TextLine)) _ = stringBuilder.AppendLine(); } while (iter.Next(PageIteratorLevel.Para, PageIteratorLevel.TextLine)); } while (iter.Next(PageIteratorLevel.Block, PageIteratorLevel.Para)); } while (iter.Next(PageIteratorLevel.Block)); if (stringBuilder.Length > 0) blocks.Add(stringBuilder.ToString()); result = new(pageMeanConfidence, text, blocks); return result; } private void Parse(IFileRead fileRead, List fileInfoCollection, int startX, int startY, int endX, int endY, int offSetX, int offSetY) { (float pageMeanConfidence, string text, List blocks) = Parse(fileRead.ReportFullPath, fileInfoCollection, startX, startY, endX, endY, offSetX, offSetY); _Log.Debug(string.Format("Mean confidence: {0}", pageMeanConfidence)); _Log.Debug(string.Format("Text (GetText): \r\n{0}", text)); _Log.Debug("Text (iterator):"); if (blocks.Count == 0) _Details.Add(text); else { blocks = (from l in blocks where l.Split(':').Length == 3 select l).ToList(); if (blocks.Count == 0) _Details.Add(text); else _Details.Add(blocks[0]); } } }