diff --git a/ReactionRecorder.cs b/ReactionRecorder.cs --- a/ReactionRecorder.cs +++ b/ReactionRecorder.cs @@ -31,8 +31,8 @@ namespace DesertPaintLab const int COLOR_TOLERANCE = 3; const int DEFAULT_SWATCH_HEIGHT = 24; // including top and bottom borders - const int DEFAULT_SWATCH_WIDTH = 260; - const int DEFAULT_COLOR_BAR_WIDTH = 306; + const int DEFAULT_SWATCH_WIDTH = 274; + const int DEFAULT_COLOR_BAR_WIDTH = 320; const int DEFAULT_RED_BAR_SPACING = 32; const int DEFAULT_GREEN_BAR_SPACING = 42; const int DEFAULT_BLUE_BAR_SPACING = 52; @@ -194,13 +194,13 @@ namespace DesertPaintLab unsafe private bool IsPossibleSwatchUpperLeft(byte* pixBytes, int x, int y, int stride) { - int testPixelStart = (y * stride) + (x * 3); - - if (testPixelStart < stride) - { - return false; - } - + int testPixelStart = (y * stride) + (x * 3); + + if (testPixelStart < stride) + { + return false; + } + bool result = true; // test the left edge for dark pixels int i = 0; @@ -209,11 +209,11 @@ namespace DesertPaintLab int otherPixelStart = testPixelStart + (stride * i); result &= IsDarkPixel(pixBytes[otherPixelStart], pixBytes[otherPixelStart+1], pixBytes[otherPixelStart+2]); } - if (!result) - { - // No dark border on the left side + if (!result) + { + // No dark border on the left side // WriteLog("Failed to find left border for swatch at {0}, {1}", x, y); - return false; + return false; } // test the dark top border and for papyrus above and below the swatch @@ -224,18 +224,18 @@ namespace DesertPaintLab int otherPixelStart = testPixelStart + (3 * i); bool isBorder = IsDarkPixel(pixBytes[otherPixelStart], pixBytes[otherPixelStart+1], pixBytes[otherPixelStart+2]); result &= isBorder; - if (!isBorder) - { - borderError = true; + if (!isBorder) + { + borderError = true; } - if (otherPixelStart >= stride) + if (otherPixelStart >= stride) { otherPixelStart = otherPixelStart - stride; - papyErrorCount += (IsPapyTexture(pixBytes[otherPixelStart], pixBytes[otherPixelStart + 1], pixBytes[otherPixelStart + 2]) ? 0 : 1); + papyErrorCount += (IsPapyTexture(pixBytes[otherPixelStart], pixBytes[otherPixelStart + 1], pixBytes[otherPixelStart + 2]) ? 0 : 1); } - else - { - papyErrorCount++; + else + { + papyErrorCount++; } // Checking along the bottom of the swatch - @@ -246,134 +246,137 @@ namespace DesertPaintLab result &= (papyErrorCount < (swatchWidth / 20)); // allow up to 5% error rate checking for papy texture, because this seems to be inconsistent if (!result && ((i > (swatchWidth*0.8)) || (papyErrorCount >= (swatchWidth/20)))) { - if (!borderError && (papyErrorCount < swatchWidth)) - { - WriteLog("Found a potential swatch candidate of width {0} at {1},{2} that had {3} failures matching papyrus texture", i, x, y, papyErrorCount); - } + if (!borderError && (papyErrorCount < swatchWidth)) + { + WriteLog("Found a potential swatch candidate of width {0} at {1},{2} that had {3} failures matching papyrus texture", i, x, y, papyErrorCount); + } } return result; } - unsafe private bool TestPosition(int x, int y, byte* pixBytes, int screenshotWidth, int screenshotHeight, int stride, ref PaintColor reactedColor, ref int redPixelStart) - { + unsafe private bool TestPosition(int x, int y, byte* pixBytes, int screenshotWidth, int screenshotHeight, int stride, ref PaintColor reactedColor, ref int redPixelStart) + { byte pixel_r, pixel_g, pixel_b; int pixelStart, otherPixelStart; - bool colorMatch = true; - - // Look for the color swatch. - pixelStart = (y * stride) + (x * 3); - pixel_r = pixBytes[pixelStart]; - pixel_g = pixBytes[pixelStart + 1]; - pixel_b = pixBytes[pixelStart + 2]; - - bool foundSwatch = IsPossibleSwatchUpperLeft(pixBytes, x, y, stride); // ((pixel_r < 0x46) && (pixel_g < 0x46) && (pixel_b < 0x46)); - if (foundSwatch) - { - int borderXOffset = 0; - for (borderXOffset = (2 * pixelMultiplier); foundSwatch && (borderXOffset < swatchTestWidth); ++borderXOffset) - { - foundSwatch &= IsPossibleSwatchSlice(pixBytes, x + borderXOffset, y, stride); - foundSwatch &= IsPossibleSwatchSlice(pixBytes, x + swatchWidth - borderXOffset, y, stride); - } - } - - if (foundSwatch) - { - // found a swatch with an appropriate dark top border with papyrus texture above it and papyrus a jump below it - // 4.) Scan the left border of the potential swatch - // location. - colorMatch = true; - for (int i = 2; i < swatchHeight - (2 * pixelMultiplier); ++i) - { - otherPixelStart = pixelStart + (stride * i); - if (!IsColorMatch(pixel_r, pixel_g, pixel_b, pixBytes[otherPixelStart], pixBytes[otherPixelStart + 1], pixBytes[otherPixelStart + 2])) - { - colorMatch = false; - break; - } - } - - if (colorMatch) - { - // WE FOUND THE SWATCH! - // Now we know where the color bars are. - redPixelStart = pixelStart + (redBarSpacing * stride); - int redPixelCount = 0; - while ((pixBytes[redPixelStart] > 0x9F) && - (pixBytes[redPixelStart + 1] < 0x62) && - (pixBytes[redPixelStart + 2] < 0x62)) - { - redPixelCount++; - // pixBytes[redPixelStart] = 0x00; - // pixBytes[redPixelStart + 1] = 0xFF; - // pixBytes[redPixelStart + 2] = 0xFF; - redPixelStart += 3; - } - - reactedColor.Red = (byte)Math.Round((float)redPixelCount * 255f / (float)colorBarWidth); - int greenPixelStart = pixelStart + (greenBarSpacing * stride); - - int greenPixelCount = 0; - while ((pixBytes[greenPixelStart] < 0x62) && - (pixBytes[greenPixelStart + 1] > 0x9F) && - (pixBytes[greenPixelStart + 2] < 0x62)) - { - greenPixelCount++; - // pixBytes[greenPixelStart] = 0x00; - // pixBytes[greenPixelStart + 1] = 0xFF; - // pixBytes[greenPixelStart + 2] = 0xFF; - greenPixelStart += 3; - } - - reactedColor.Green = (byte)Math.Round((float)greenPixelCount * 255f / (float)colorBarWidth); - int bluePixelStart = pixelStart + (blueBarSpacing * stride); - - int bluePixelCount = 0; - while ((pixBytes[bluePixelStart] < 0x62) && - (pixBytes[bluePixelStart + 1] < 0x62) && - (pixBytes[bluePixelStart + 2] > 0x9F)) - { - bluePixelCount++; - // pixBytes[bluePixelStart] = 0x00; - // pixBytes[bluePixelStart + 1] = 0xFF; - // pixBytes[bluePixelStart + 2] = 0xFF; - bluePixelStart += 3; - } - - reactedColor.Blue = (byte)Math.Round((float)bluePixelCount * 255f / (float)colorBarWidth); - WriteLog("Found the color swatch at {0}, {1}. Color={2}", x, y, reactedColor); - return true; - } - } - return false; + bool colorMatch = true; + + // Look for the color swatch. + pixelStart = (y * stride) + (x * 3); + pixel_r = pixBytes[pixelStart]; + pixel_g = pixBytes[pixelStart + 1]; + pixel_b = pixBytes[pixelStart + 2]; + + bool foundSwatch = IsPossibleSwatchUpperLeft(pixBytes, x, y, stride); // ((pixel_r < 0x46) && (pixel_g < 0x46) && (pixel_b < 0x46)); + if (foundSwatch) + { + int borderXOffset = 0; + for (borderXOffset = (2 * pixelMultiplier); foundSwatch && (borderXOffset < swatchTestWidth); ++borderXOffset) + { + foundSwatch &= IsPossibleSwatchSlice(pixBytes, x + borderXOffset, y, stride); + foundSwatch &= IsPossibleSwatchSlice(pixBytes, x + swatchWidth - borderXOffset, y, stride); + } + } + + if (foundSwatch) + { + // found a swatch with an appropriate dark top border with papyrus texture above it and papyrus a jump below it + // 4.) Scan the left border of the potential swatch + // location. + colorMatch = true; + for (int i = 2; i < swatchHeight - (2 * pixelMultiplier); ++i) + { + otherPixelStart = pixelStart + (stride * i); + if (!IsColorMatch(pixel_r, pixel_g, pixel_b, pixBytes[otherPixelStart], pixBytes[otherPixelStart + 1], pixBytes[otherPixelStart + 2])) + { + colorMatch = false; + break; + } + } + + if (colorMatch) + { + // WE FOUND THE SWATCH! + // Now we know where the color bars are. + redPixelStart = pixelStart + (redBarSpacing * stride); + int redPixelCount = 0; + while ((pixBytes[redPixelStart] > 0x9F) && + (pixBytes[redPixelStart + 1] < 0x62) && + (pixBytes[redPixelStart + 2] < 0x62)) + { + redPixelCount++; + // pixBytes[redPixelStart] = 0x00; + // pixBytes[redPixelStart + 1] = 0xFF; + // pixBytes[redPixelStart + 2] = 0xFF; + redPixelStart += 3; + } + WriteLog("Color {0}, {1}, {2} is no longer red at {3},{4}", pixBytes[redPixelStart], pixBytes[redPixelStart + 1], pixBytes[redPixelStart + 2], (redPixelStart % stride)/3, redPixelStart / stride); + + reactedColor.Red = (byte)Math.Round((float)redPixelCount * 255f / (float)colorBarWidth); + int greenPixelStart = pixelStart + (greenBarSpacing * stride); + + int greenPixelCount = 0; + while ((pixBytes[greenPixelStart] < 0x62) && + (pixBytes[greenPixelStart + 1] > 0x9F) && + (pixBytes[greenPixelStart + 2] < 0x62)) + { + greenPixelCount++; + // pixBytes[greenPixelStart] = 0x00; + // pixBytes[greenPixelStart + 1] = 0xFF; + // pixBytes[greenPixelStart + 2] = 0xFF; + greenPixelStart += 3; + } + WriteLog("Color {0}, {1}, {2} is no longer green at pixel offset {3},{4}", pixBytes[greenPixelStart], pixBytes[greenPixelStart + 1], pixBytes[greenPixelStart + 2], (greenPixelStart % stride)/3, redPixelStart / stride); + + reactedColor.Green = (byte)Math.Round((float)greenPixelCount * 255f / (float)colorBarWidth); + int bluePixelStart = pixelStart + (blueBarSpacing * stride); + + int bluePixelCount = 0; + while ((pixBytes[bluePixelStart] < 0x62) && + (pixBytes[bluePixelStart + 1] < 0x62) && + (pixBytes[bluePixelStart + 2] > 0x9F)) + { + bluePixelCount++; + // pixBytes[bluePixelStart] = 0x00; + // pixBytes[bluePixelStart + 1] = 0xFF; + // pixBytes[bluePixelStart + 2] = 0xFF; + bluePixelStart += 3; + } + WriteLog("Color {0}, {1}, {2} is no longer blue at pixel offset {3},{4}", pixBytes[bluePixelStart], pixBytes[bluePixelStart + 1], pixBytes[bluePixelStart + 2], (bluePixelStart % stride)/3, bluePixelStart / stride); + + reactedColor.Blue = (byte)Math.Round((float)bluePixelCount * 255f / (float)colorBarWidth); + WriteLog("Found the color swatch at {0}, {1}. Color={2} Red={3}px Green={4}px Blue={5}px", x, y, reactedColor, redPixelCount, greenPixelCount, bluePixelCount); + return true; + } + } + return false; } unsafe public bool CaptureReaction(byte* pixBytes, int screenshotWidth, int screenshotHeight, int stride, ref PaintColor reactedColor, ref int redPixelStart) { - if (!firstRun) - { - // If this is not the first run, let's check the last location, to see if the UI is still there. - if (TestPosition(lastSwatchX, lastSwatchY, pixBytes, screenshotWidth, screenshotHeight, stride, ref reactedColor, ref redPixelStart)) - { - return true; - } - else - { - firstRun = true; - } + if (!firstRun) + { + // If this is not the first run, let's check the last location, to see if the UI is still there. + if (TestPosition(lastSwatchX, lastSwatchY, pixBytes, screenshotWidth, screenshotHeight, stride, ref reactedColor, ref redPixelStart)) + { + return true; + } + else + { + firstRun = true; + } } for (int x = 0; x < screenshotWidth - colorBarWidth; ++x) { for (int y = 0; y < (screenshotHeight - (blueBarSpacing + 1) /*53*/); ++y) { - if (TestPosition(x, y, pixBytes, screenshotWidth, screenshotHeight, stride, ref reactedColor, ref redPixelStart)) - { - lastSwatchX = x; - lastSwatchY = y; - firstRun = false; - return true; + if (TestPosition(x, y, pixBytes, screenshotWidth, screenshotHeight, stride, ref reactedColor, ref redPixelStart)) + { + lastSwatchX = x; + lastSwatchY = y; + firstRun = false; + return true; } } }