Created
January 27, 2015 16:55
-
-
Save Darker/f08b2fbf1795af9ebbe2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* License: | |
* Open source ftw. I doubt anybody would actually like to use this file. | |
* But if you want, use it, change it or share it under any license you like. | |
*/ | |
package autoclick; | |
//Comment this out if you don't have the library | |
import com.sun.jna.platform.win32.WinDef; | |
//Used for exporting rect class as normal rectangle | |
import java.awt.Rectangle; | |
/** | |
* | |
* @author Jakub Mareda | |
*/ | |
public class Rect { | |
public final int width; | |
public final int height; | |
public final int top; | |
public final int bottom; | |
public final int left; | |
public final int right; | |
/** The parameters go clockwise - top, right, bottom, left | |
* @param t top | |
* @param r right | |
* @param b bottom | |
* @param l left**/ | |
public Rect(int t, int r, int b, int l) { | |
top = t; | |
bottom = b; | |
right = r; | |
left = l; | |
width = r-l; | |
height = b-t; | |
} | |
/** Can be used to define a point. In this case, width and height will be zero. | |
* @param x x offset of the point | |
* @param y y offset of the point**/ | |
public Rect(int x, int y) { | |
top = bottom = y; | |
left = right = x; | |
width = height = 0; | |
} | |
/** Using WinDef.RECT from com.sun.jna.platform.win32.WinDef. Comment this out for | |
* if this library is not present. Java doesn't provide smarter approach. | |
* @param rect WinDef rect. Can be obtained for example by sirius.core.user32Ext.GetClientRect | |
**/ | |
public Rect(WinDef.RECT rect) { | |
top = rect.top; | |
bottom = rect.bottom; | |
right = rect.right; | |
left = rect.left; | |
width = right-left; | |
height = bottom-top; | |
} | |
/** Define by starting offset (top, left) and width and height. | |
* | |
* @param t top offset (y axis) | |
* @param l left offset (x axis) | |
* @param w width (x axis) | |
* @param h height (y axis) | |
* @return | |
*/ | |
public static Rect byWidthHeight(int t, int l, int w, int h) { | |
return new Rect(t, l+w, t+h, l); | |
} | |
/** Get the middle point of the rectangle. | |
* @return Rect of zero size that is in the middle of this rect. | |
*/ | |
public Rect middle() { | |
return new Rect(width/2+left, height/2+top); | |
} | |
@Override | |
public String toString() { | |
return "autoclick.Rect["+top+", "+right+", "+bottom+", "+left+"] ("+width+" x "+height+")"; | |
} | |
/** Get java.awt.Rectangle equal to this rectangle. Intelligent language | |
* would allow me to override (Rectangle). But Java really sucks. | |
* @return java.awt.Rectangle of the same size and position as this rectangle. | |
*/ | |
public Rectangle toStdRectangle() { | |
return new Rectangle(top, left, width, height); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* To change this license header, choose License Headers in Project Properties. | |
* To change this template file, choose Tools | Templates | |
* and open the template in the editor. | |
*/ | |
package autoclick; | |
import java.awt.Color; | |
import java.awt.Image; | |
import java.awt.geom.AffineTransform; | |
import java.awt.image.AffineTransformOp; | |
import java.awt.image.BufferedImage; | |
/** | |
* | |
* @author Jakub | |
*/ | |
/**All static. Set of methods to allow you finding locations on screen **/ | |
public class ScreenWatcher { | |
public static Rect findByAvgColor(BufferedImage image, BufferedImage bigImage, float tolerance) { | |
return null; | |
} | |
public static Rect findByExactMatch(BufferedImage image, BufferedImage bigImage, float tolerance) { | |
image = (BufferedImage)image.getScaledInstance((int)(tolerance*image.getWidth()), (int)(tolerance*image.getHeight()), Image.SCALE_SMOOTH); | |
bigImage = (BufferedImage)bigImage.getScaledInstance((int)(tolerance*bigImage.getWidth()), (int)(tolerance*bigImage.getHeight()), Image.SCALE_SMOOTH); | |
return findByExactMatch(image, bigImage); | |
} | |
/** Finds image in bigImage by exact pixel match (all pixels must be exactly the same color). | |
* | |
* @param image the smaller image you want to find | |
* @param bigImage the big image you're searching in | |
* @return Rect object describing the location where the small image was found. Returns null if nothing was found. | |
*/ | |
public static Rect findByExactMatch(BufferedImage image, BufferedImage bigImage) { | |
//I marked these final so that I don't accidentally change them later | |
final int iw = image.getWidth(); | |
final int ih = image.getHeight(); | |
final int bw = bigImage.getWidth(); | |
final int bh = bigImage.getHeight(); | |
//Loop from 0 to big image width/height MINUS the small image width/height | |
//The MINUS there is, because once you are at the end, the small image overlaps to undefined area | |
for(int rect_x=0, mrx=bw-iw; rect_x<mrx; rect_x++) { | |
for(int rect_y=0, mry=bh-ih; rect_y<mry; rect_y++) { | |
//This is where pixel looping begins | |
int x = 0; | |
int y = 0; | |
for (; x < iw; x++) { | |
for (; y < ih; y++) { | |
//Get RGB returns 0x00rrggbb | |
if(image.getRGB(x, y)!= | |
bigImage.getRGB(x+rect_x, y+rect_y)) { | |
//If the color does not match, break back to the rectangular search | |
//WITHOUT -1 THE VALUE OVERFLOWS ON NEXT ITERATION (damnit, debuged this like an idiot!!!) | |
y = x = Integer.MAX_VALUE-1; | |
break; | |
} | |
} | |
} | |
//This statement asks if the loop ended normally | |
// - otherwise, the x and y are MAX_INT and greater than iw | |
if(x==iw) { | |
return Rect.byWidthHeight(rect_x, rect_y, iw, ih); | |
} | |
} | |
} | |
//Nothing found - return null | |
return null; | |
} | |
/*int clr = image.getRGB(x, y); | |
int red = (clr & 0x00ff0000) >> 16; | |
int green = (clr & 0x0000ff00) >> 8; | |
int blue = clr & 0x000000ff; | |
image.setRGB(x, y, clr);*/ | |
/** Utility methods **/ | |
public static BufferedImage resampleImage(BufferedImage original, double xscale, double yscale) { | |
int w = original.getWidth(); | |
int h = original.getHeight(); | |
BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); | |
AffineTransform at = new AffineTransform(); | |
at.scale(xscale, yscale); | |
AffineTransformOp scaleOp = | |
new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); | |
after = scaleOp.filter(original, after); | |
return after; | |
} | |
/* | |
* Where bi is your image, (x0,y0) is your upper left coordinate, and (w,h) | |
* are your width and height respectively | |
*/ | |
public static Color averageColor(BufferedImage bi, int x0, int y0, int w, int h) { | |
int x1 = x0 + w; | |
int y1 = y0 + h; | |
long sumr = 0, sumg = 0, sumb = 0; | |
for (int x = x0; x < x1; x++) { | |
for (int y = y0; y < y1; y++) { | |
Color pixel = new Color(bi.getRGB(x, y)); | |
sumr += pixel.getRed(); | |
sumg += pixel.getGreen(); | |
sumb += pixel.getBlue(); | |
} | |
} | |
int num = w * h; | |
return new Color(sumr / num, sumg / num, sumb / num); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* To change this license header, choose License Headers in Project Properties. | |
* To change this template file, choose Tools | Templates | |
* and open the template in the editor. | |
*/ | |
package autoclick; | |
import java.awt.Color; | |
import java.awt.Graphics2D; | |
import java.awt.image.BufferedImage; | |
import java.io.File; | |
import java.io.IOException; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
import javax.imageio.ImageIO; | |
/** | |
* | |
* @author Jakub | |
*/ | |
public class ScreenWatcherMain { | |
public static void main(String[] args) | |
{ | |
//The small image to search for | |
BufferedImage thing = loadFromPath("thing.png"); | |
//The big image to search in | |
BufferedImage screenshot = loadFromPath("screenshot.png"); | |
if(thing!=null && screenshot!=null) { | |
Rect pos = autoclick.ScreenWatcher.findByExactMatch(thing, screenshot); | |
if(pos!=null) { | |
System.out.println("Found object: "+pos); | |
//Draw rectangle on discovered position | |
Graphics2D graph = screenshot.createGraphics(); | |
graph.setColor(Color.RED); | |
graph.drawRect(pos.top, pos.left, pos.width, pos.height); | |
graph.dispose(); | |
//Save the file for review | |
try { | |
ImageIO.write(screenshot, "png", new File("output.png")); | |
} catch (IOException ex) { | |
Logger.getLogger("wtf goes here?").log(Level.SEVERE, null, ex); | |
} | |
} | |
} | |
} | |
public static BufferedImage loadFromPath(String path) { | |
File img = new File(path); | |
BufferedImage thing = null; | |
try { | |
thing = ImageIO.read(img); | |
} | |
catch(IOException e) { | |
System.err.println("Can't read '"+path+"': "+e); | |
} | |
return thing; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment