// todo not used, remove? //private static Rectangle letterRect(Bitmap source, int hStart, int hEnd) //{ // int startWhite = -1, endWhite = -1; // for (int j = 0; j < source.Height; j++) // { // for (int i = hStart; i < hEnd; i++) // { // if (startWhite == -1 && source.GetPixel(i, j).R == 255) // { // startWhite = j; // } // if (endWhite == -1 && source.GetPixel(i, (source.Height - j) - 1).R == 255) // { // endWhite = (source.Height - j); // } // if (startWhite != -1 && endWhite != -1) // return new Rectangle(hStart, startWhite, hEnd - hStart, endWhite - startWhite); // } // } // return Rectangle.Empty; //} public double[] doOCR(out string OCRText, out string dinoName, out string species, out string ownerName, out string tribeName, out Sex sex, string useImageFilePath = "", bool changeForegroundWindow = true) { string finishedText = ""; dinoName = ""; species = ""; ownerName = ""; tribeName = ""; sex = Sex.Unknown; double[] finalValues = new double[1] { 0 }; Bitmap screenshotbmp; ocrControl.debugPanel.Controls.Clear(); ocrControl.ClearLists(); if (System.IO.File.Exists(useImageFilePath)) { screenshotbmp = (Bitmap)Image.FromFile(useImageFilePath); } else { // grab screenshot from ark screenshotbmp = Win32Stuff.GetSreenshotOfProcess(screenCaptureApplicationName, waitBeforeScreenCapture, true); } if (screenshotbmp == null) { OCRText = "Error: no image for OCR. Is ARK running?"; return(finalValues); } if (!setResolution(screenshotbmp)) { OCRText = "Error while calibrating: probably game-resolution is not supported by this OCR-configuration.\nThe tested image has a resolution of " + screenshotbmp.Width.ToString() + "×" + screenshotbmp.Height.ToString() + " px."; return(finalValues); } // TODO resize image according to resize-factor. used for large screenshots if (ocrConfig.resize != 1 && ocrConfig.resize > 0) { Bitmap resized = new Bitmap((int)(ocrConfig.resize * ocrConfig.resolutionWidth), (int)(ocrConfig.resize * ocrConfig.resolutionHeight)); using (var graphics = Graphics.FromImage(resized)) { graphics.CompositingMode = CompositingMode.SourceCopy; graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; using (var wrapMode = new ImageAttributes()) { wrapMode.SetWrapMode(WrapMode.TileFlipXY); graphics.DrawImage(screenshotbmp, new Rectangle(0, 0, 1920, 1080), 0, 0, screenshotbmp.Width, screenshotbmp.Height, GraphicsUnit.Pixel, wrapMode); } screenshotbmp?.Dispose(); screenshotbmp = resized; } } if (enableOutput) { AddBitmapToDebug(screenshotbmp); ocrControl.setScreenshot(screenshotbmp); } finalValues = new double[ocrConfig.labelRectangles.Count]; finalValues[8] = -1; // set imprinting to -1 to mark it as unknown and to set a difference to a creature with 0% imprinting. if (changeForegroundWindow) { Win32Stuff.SetForegroundWindow(Application.OpenForms[0].Handle); } bool wild = false; // todo: set to true and find out if the creature is wild in the first loop int stI = -1; for (int lbI = 0; lbI < ocrConfig.labelNames.Count; lbI++) { stI++; if (lbI == 8) { stI = 8; } string statName = ocrConfig.labelNames[stI]; Rectangle rec = ocrConfig.labelRectangles[lbI]; // wild creatures don't have the xp-bar, all stats are moved one row up if (wild && stI < 9) { rec.Offset(0, ocrConfig.labelRectangles[0].Top - ocrConfig.labelRectangles[1].Top); } Bitmap testbmp = SubImage(screenshotbmp, rec.X, rec.Y, rec.Width, rec.Height); //AddBitmapToDebug(testbmp); string statOCR = ""; if (statName == "NameSpecies") { statOCR = readImage(testbmp, true, false); } else if (statName == "Level") { statOCR = readImage(testbmp, true, true); } else if (statName == "Tribe" || statName == "Owner") { statOCR = readImage(testbmp, true, false); } else { statOCR = readImage(testbmp, true, true); // statvalues are only numbers } if (statOCR == "" && (statName == "Health" || statName == "Imprinting" || statName == "Tribe" || statName == "Owner")) { if (wild && statName == "Health") { stI--; wild = false; } continue; // these can be missing, it's fine } lastLetterPositions[statName] = new Point(rec.X + lastLetterPosition(removePixelsUnderThreshold(GetGreyScale(testbmp), whiteThreshold)), rec.Y); finishedText += (finishedText.Length == 0 ? "" : "\r\n") + statName + ":\t" + statOCR; // parse the OCR String Regex r; r = new Regex(@"^[_\/\\]*(.*?)[_\/\\]*$"); // trim. often the background is misinterpreted as underscores or slash/backslash statOCR = r.Replace(statOCR, "$1"); if (statName == "NameSpecies") { r = new Regex(@".*?([♂♀])?[_.,-\/\\]*([^♂♀]+?)(?:[\(\[]([^\[\(\]\)]+)[\)\]]$|$)"); } else if (statName == "Owner" || statName == "Tribe") { r = new Regex(@"(.*)"); } else if (statName == "Level") { r = new Regex(@".*\D(\d+)"); } else { r = new Regex(@"(?:[\d.,%\/]*\/)?(\d+[\.,']?\d?)(%)?"); // only the second numbers is interesting after the current weight is not shown anymore //if (onlyNumbers) //r = new Regex(@"((\d*[\.,']?\d?\d?)\/)?(\d*[\.,']?\d?\d?)"); //else // r = new Regex(@"([a-zA-Z]*)[:;]((\d*[\.,']?\d?\d?)\/)?(\d*[\.,']?\d?\d?)"); } MatchCollection mc = r.Matches(statOCR); if (mc.Count == 0) { if (statName == "NameSpecies" || statName == "Owner" || statName == "Tribe") { continue; } if (statName == "Torpor" && false) { // probably it's a wild creature // todo } else { finishedText += "error reading stat " + statName; finalValues[stI] = 0; continue; } } if (statName == "NameSpecies" || statName == "Owner" || statName == "Tribe") { if (statName == "NameSpecies" && mc[0].Groups.Count > 0) { if (mc[0].Groups[1].Value == "♀") { sex = Sex.Female; } else if (mc[0].Groups[1].Value == "♂") { sex = Sex.Male; } dinoName = mc[0].Groups[2].Value; species = mc[0].Groups[3].Value; if (species.Length == 0) { species = dinoName; } // remove non-letter chars r = new Regex("[^a-zA-Z]"); species = r.Replace(species, ""); // replace capital I with lower l (common misrecognition) r = new Regex("(?<=[a-z])I(?=[a-z])"); species = r.Replace(species, "l"); // readd spaces before capital letters r = new Regex("(?<=[a-z])(?=[A-Z])"); species = r.Replace(species, " "); finishedText += "\t→ " + sex.ToString() + ", " + species; } else if (statName == "Owner" && mc[0].Groups.Count > 0) { ownerName = mc[0].Groups[0].Value; finishedText += "\t→ " + ownerName; } else if (statName == "Tribe" && mc[0].Groups.Count > 0) { tribeName = mc[0].Groups[0].Value.Replace("Tobe", "Tribe").Replace("Tdbe", "Tribe").Replace("Tribeof", "Tribe of "); finishedText += "\t→ " + tribeName; } continue; } if (mc[0].Groups.Count > 2 && mc[0].Groups[2].Value == "%" && statName == "Weight") { // first stat with a '%' is damage, if oxygen is missing, shift all stats by one finalValues[4] = finalValues[3]; // shift food to weight finalValues[3] = finalValues[2]; // shift oxygen to food finalValues[2] = 0; // set oxygen (which wasn't there) to 0 stI++; } double.TryParse(mc[0].Groups[1].Value.Replace('\'', '.').Replace(',', '.').Replace('O', '0'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.GetCultureInfo("en-US"), out double v); // common substitutions: comma and apostrophe to dot, finishedText += $"\t→ {v}"; // TODO: test here that the read stat name corresponds to the stat supposed to be read finalValues[stI] = v; } OCRText = finishedText; // TODO reorder stats to match 12-stats-order return(finalValues); /* * Bitmap grab = Win32Stuff.GetSreenshotOfProcess(screenCaptureApplicationName); * AddBitmapToDebug(grab); * * //grab.Save("E:\\Temp\\Calibration8.png", ImageFormat.Png); * if (changeForegroundWindow) * Win32Stuff.SetForegroundWindow(Application.OpenForms[0].Handle); */ }
public bool setResolution() { return(setResolution(Win32Stuff.GetSreenshotOfProcess(screenCaptureApplicationName, waitBeforeScreenCapture))); }