/**
*
* This method returns all the Valid XY's from a color Array That are within
* the tolerances of the RGB. "deformed" accuracy 1.0 == 100% have to match
* (Exact) accuracy 0.1 == 10% have to match
*
* @author Eric
* @param colorMap
* the colors of the game screen sorted as short's in an array
* [x][y][0-2] where 0 is red, 1 is blue, 2 is green
* @param maxMatches
* The maximum number of matches to find.
* @param colorMapToFind
* the colors a image sorted as short's in an array [x][y][0-2]
* where 0 is red, 1 is blue, 2 is green
* @param bounds
* The Rectange to search, specifies which part of the
* colorArray2d to search
* @param ignore
* The Rectangles to ignore in the search, specifies which parts
* of the bounds to ignore, example searching game screen but
* ignoring your character
* @param accuracy
* range should be between 0.0-1.0
* @param redTolerance
* The maximum difference for the red color value
* @param greenTolerance
* The maximum difference for the green color value
* @param blueTolerance
* The maximum difference for the blue color value
* @param bitmaskOverRide
* The Color that all the bitmasks in the image should be matched
* against.
*
* @return An array of XY matches or null if none found
*/
public static final XY[] findXYs(short[][][] colorMap, int maxMatches,
short[][][] colorMapToFind, Rectangle bounds, Rectangle ignore[],
double accuracy, int redTolerance, int greenTolerance,
int blueTolerance, RGB bitmaskOverRide) {
// temp varibles
int x, y, ix, iy, redChange, greenChange, blueChange;
// image
int iW = colorMapToFind.length;
int iL = colorMapToFind[0].length;
// deformed bitmap
double temp = (1 - accuracy) * (iW * iL);
int maxWrong = (int) temp;
int wrong;
// search zone
int minX = bounds.x;
int maxX = minX + bounds.width - iW + 1;
int minY = bounds.y;
int maxY = minY + bounds.height - iL + 1;
// results
ArrayList<XY> list = null;
if (maxMatches < 10) {
list = new ArrayList<XY>(10);
} else {
list = new ArrayList<XY>(maxMatches);
}
// masks, bitmask definition
;
int BITMASK_MATCH = BitMapInfo.BITMASK_MATCH;
int BITMASK_NOMATCH = BitMapInfo.BITMASK_NOMATCH;
boolean bitmaskOverRideENULL = bitmaskOverRide == null;
int bitMaskR = 0, bitMaskG = 0, bitMaskB = 0;
int firstBitMaskXOffSet = -1, firstBitMaskYOffSet = -1;
if (bitmaskOverRideENULL) {
boolean found = false;
for (x = 0; !found && x < iW; x++)
for (y = 0; !found && y < iL; y++)
if (colorMapToFind[x][y][0] == BITMASK_MATCH) {
firstBitMaskXOffSet = x;
firstBitMaskYOffSet = y;
found = true;
}
} else {
bitMaskR = bitmaskOverRide.r;
bitMaskG = bitmaskOverRide.g;
bitMaskB = bitmaskOverRide.b;
}
// Ignore Rectangles
boolean ignoreENULL = ignore != null;
boolean ignoreSpot;
boolean valid = false;
boolean firstMask = false;
int relX, relY;
for (x = minX; x < maxX; x++) {
for (y = minY; y < maxY; y++) {
wrong = 0;
valid = true;
if (bitmaskOverRideENULL)
firstMask = true;
for (ix = 0; valid && ix < iW; ix++) {
for (iy = 0; iy < iL; iy++) {
if (wrong > maxWrong) {
valid = false;
break;
}
relX = x + ix;
relY = y + iy;
if (ignoreENULL) {
ignoreSpot = false;
for (int i = 0; i < ignore.length; i++) {
if (ignore[i].contains(relX, relY)) {
ignoreSpot = true;
break;
}
}
if (ignoreSpot) {
valid = false;
break;
}
}
if (colorMapToFind[ix][iy][0] < 0) {
if (firstMask) {
if (firstBitMaskXOffSet != -1
&& firstBitMaskYOffSet != -1) {
bitMaskR = colorMap[relX
+ firstBitMaskXOffSet][relY
+ firstBitMaskYOffSet][0];
bitMaskG = colorMap[relX
+ firstBitMaskXOffSet][relY
+ firstBitMaskYOffSet][1];
bitMaskB = colorMap[relX
+ firstBitMaskXOffSet][relY
+ firstBitMaskYOffSet][2];
firstMask = false;
}
}
if (colorMapToFind[ix][iy][0] == BITMASK_MATCH) {
redChange = bitMaskR - colorMap[relX][relY][0];
if ((redChange >= 0 ? redChange : -redChange) > redTolerance) {
wrong++;
continue;
}
greenChange = bitMaskG
- colorMap[relX][relY][1];
if ((greenChange >= 0 ? greenChange
: -greenChange) > greenTolerance) {
wrong++;
continue;
}
blueChange = bitMaskB - colorMap[relX][relY][2];
if ((blueChange >= 0 ? blueChange : -blueChange) > blueTolerance) {
wrong++;
continue;
}
} else if (colorMapToFind[ix][iy][0] == BITMASK_NOMATCH
&& !firstMask) {
redChange = bitMaskR - colorMap[relX][relY][0];
greenChange = bitMaskG
- colorMap[relX][relY][1];
blueChange = bitMaskB - colorMap[relX][relY][2];
if ((greenChange >= 0 ? greenChange
: -greenChange) < greenTolerance
&& (redChange >= 0 ? redChange
: -redChange) < redTolerance
&& (blueChange >= 0 ? blueChange
: -blueChange) < blueTolerance) {
wrong++;
continue;
}
}
continue;
}
redChange = colorMapToFind[ix][iy][0]
- colorMap[relX][relY][0];
if ((redChange >= 0 ? redChange : -redChange) > redTolerance) {
wrong++;
continue;
}
greenChange = colorMapToFind[ix][iy][1]
- colorMap[relX][relY][1];
if ((greenChange >= 0 ? greenChange : -greenChange) > greenTolerance) {
wrong++;
continue;
}
blueChange = colorMapToFind[ix][iy][2]
- colorMap[relX][relY][2];
if ((blueChange >= 0 ? blueChange : -blueChange) > blueTolerance) {
wrong++;
continue;
}
}
}
if (valid) {
list.add(new XY(x, y));
if (list.size() >= maxMatches) {
XY resultXY[] = new XY[list.size()];
for (int i = 0; i < resultXY.length; i++) {
resultXY[i] = list.get(i);
}
return resultXY;
}
}
}
}
XY resultXY[] = new XY[list.size()];
for (int i = 0; i < resultXY.length; i++) {
resultXY[i] = list.get(i);
}
list = null;
return resultXY;
}