package com.touchmain.controller;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import static java.lang.Thread.sleep;
/**
* Created by long.tang on 2019/4/25.
*/
public class FindRobot {
BufferedImage screenShotImage = this.getFullScreenShot(); //屏幕截圖
BufferedImage keyImage; //查找目標圖片
int scrShotImgWidth; //屏幕截圖寬度
int scrShotImgHeight; //屏幕截圖高度
int keyImgWidth; //查找目標圖片寬度
int keyImgHeight; //查找目標圖片高度
int[][] screenShotImageRGBData; //屏幕截圖RGB數據
int[][] keyImageRGBData; //查找目標圖片RGB數據
int findX; //查找結果,目標圖標位於屏幕截圖上的X座標數據
int findY; //查找結果,目標圖標位於屏幕截圖上的Y座標數據
private static Robot robot = getRobot();
private static Map map = new LinkedHashMap<>();
public FindRobot(){
}
/**
* 是否改變目標背景畫布再次查找
* @param keyImagePath
*/
public FindRobot(String keyImagePath,String screenshot,int x , int y) {
screenShotImage = (screenshot==null || screenshot.equals(""))?this.getFullScreenShot():this.getBfImageFromPath(screenshot);
keyImage = this.getBfImageFromPath(keyImagePath);
screenShotImageRGBData = this.getImageGRB(screenShotImage);
keyImageRGBData = this.getImageGRB(keyImage);
scrShotImgWidth = screenShotImage.getWidth();
scrShotImgHeight = screenShotImage.getHeight();
keyImgWidth = keyImage.getWidth();
keyImgHeight = keyImage.getHeight();
//開始查找
this.findImageXY(x,y);
}
/**
* 查找圖片
*/
public void findImageXY(int a ,int b) {
//遍歷屏幕截圖像素點數據
for (int y = b; y < scrShotImgHeight - keyImgHeight; y++) {
for (int x = 0; x < scrShotImgWidth - keyImgWidth; x++) {
//根據目標圖的尺寸,得到目標圖四個角映射到屏幕截圖上的四個點,
//判斷截圖上對應的四個點與圖B的四個角像素點的值是否相同,
//如果相同就將屏幕截圖上映射範圍內的所有的點與目標圖的所有的點進行比較。
if ((keyImageRGBData[0][0] ^ screenShotImageRGBData[y][x]) == 0
&& (keyImageRGBData[0][keyImgWidth - 1] ^ screenShotImageRGBData[y][x + keyImgWidth - 1]) == 0
&& (keyImageRGBData[keyImgHeight - 1][keyImgWidth - 1] ^ screenShotImageRGBData[y + keyImgHeight - 1][x + keyImgWidth - 1]) == 0
&& (keyImageRGBData[keyImgHeight - 1][0] ^ screenShotImageRGBData[y + keyImgHeight - 1][x]) == 0) {
boolean isFinded = isMatchAll(y, x);
//如果比較結果完全相同,則說明圖片找到,填充查找到的位置座標數據到查找結果數組。
if (isFinded) {
//0
int minY = y;
int maxY = y + keyImgHeight;
findY = ((minY + maxY) / 2);
//1
int minX = x;
int maxX = x + keyImgWidth;
findX = ((minX + maxX) / 2);
//System.out.println("找到第"+findX+"次");
map.put("point_"+findX+"_"+findY,findX+","+findY);
//return;
}
}
}
}
}
/**
* 獲取機器人
* @return
*/
private static Robot getRobot(){
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
return robot;
}
/**
* 全屏截圖
*
* @return 返回BufferedImage
*/
public BufferedImage getFullScreenShot() {
BufferedImage bfImage = null;
int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
try {
Robot robot = new Robot();
bfImage = robot.createScreenCapture(new Rectangle(0, 0, width, height));
} catch (AWTException e) {
e.printStackTrace();
}
return bfImage;
}
/**
* 輸出圖片文件
* @param bi
*/
public static String writeImageFile(BufferedImage bi) {
String path = "";
try {
path = "/files/screen_"+ System.currentTimeMillis()+".png";
File outputfile = new File(path);
ImageIO.write(bi, "png", outputfile);
} catch (IOException e) {
}
return path;
}
/**
* 從本地文件讀取目標圖片
*
* @param keyImagePath - 圖片絕對路徑
* @return 本地圖片的BufferedImage對象
*/
public BufferedImage getBfImageFromPath(String keyImagePath) {
BufferedImage bfImage = null;
try {
bfImage = ImageIO.read(new File(keyImagePath));
} catch (IOException e) {
e.printStackTrace();
}
return bfImage;
}
/**
* 根據BufferedImage獲取圖片RGB數組
*
* @param bfImage
* @return
*/
public int[][] getImageGRB(BufferedImage bfImage) {
int width = bfImage.getWidth();
int height = bfImage.getHeight();
int[][] result = new int[height][width];
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
//使用getRGB(w, h)獲取該點的顏色值是ARGB,而在實際應用中使用的是RGB,所以需要將ARGB轉化成RGB,即bufImg.getRGB(w, h) & 0xFFFFFF。
result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF;
}
}
return result;
}
/**
* 判斷屏幕截圖上目標圖映射範圍內的全部點是否全部和小圖的點一一對應。
*
* @param y - 與目標圖左上角像素點想匹配的屏幕截圖y座標
* @param x - 與目標圖左上角像素點想匹配的屏幕截圖x座標
* @return
*/
public boolean isMatchAll(int y, int x) {
int biggerY = 0;
int biggerX = 0;
int xor = 0;
for (int smallerY = 0; smallerY < keyImgHeight; smallerY++) {
biggerY = y + smallerY;
for (int smallerX = 0; smallerX < keyImgWidth; smallerX++) {
biggerX = x + smallerX;
if (biggerY >= scrShotImgHeight || biggerX >= scrShotImgWidth) {
return false;
}
xor = keyImageRGBData[smallerY][smallerX] ^ screenShotImageRGBData[biggerY][biggerX];
if (xor != 0) {
//hitMiss++;
return false;
}
}
//biggerX = x;
}
return true;
}
/*****
* //移動鼠標
* robot.mouseMove(500, 500);
* //點擊鼠標
* //鼠標左鍵
* System.out.println("單擊");
* robot.mousePress(InputEvent.BUTTON1_MASK);
* robot.mouseRelease(InputEvent.BUTTON1_MASK);
* //鼠標右鍵
* System.out.println("右擊");
* robot.mousePress(InputEvent.BUTTON3_MASK);
* robot.mouseRelease(InputEvent.BUTTON3_MASK);
* //按下ESC,退出右鍵狀態
* System.out.println("按下ESC");
* robot.keyPress(KeyEvent.VK_ESCAPE);
* robot.keyRelease(KeyEvent.VK_ESCAPE);
* //滾動鼠標滾軸
* System.out.println("滾軸");
* robot.mouseWheel(5);
* <p>
* <p>
* //按下Alt+TAB鍵(切換桌面窗口)
* robot.keyPress(KeyEvent.VK_ALT);
* for(int i=1;i<=2;i++)
* {
* robot.keyPress(KeyEvent.VK_TAB);
* robot.keyRelease(KeyEvent.VK_TAB);
* }
* robot.keyRelease(KeyEvent.VK_ALT);
* robot.mouseWheel 滾動鼠標
* @param path
*/
public static boolean touchPic(String path) {
//移動到定位
boolean res = findPoint(path);
System.out.println("移動到定位:"+res);
if(!res){
return false;
}
//1.click
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.setAutoDelay(100);
System.out.println("移動點擊完成...");
return true;
}
/**
* 找到定位並移動到定位點
* @param path
* @return
*/
public static boolean findPoint(String path){
return findPoint(path,true);
}
public static boolean findPoint(String path,boolean move){
map.clear();
FindRobot demo = new FindRobot(path,"",0,0);
if(map==null||map.size()==0){
return false;
} else {
System.out.println("找到:"+demo.findX+","+demo.findY);
if(move){
robot.mouseMove(demo.findX, demo.findY);
}
return true;
}
}
/**
* 查找是否唯一解
* @param path
* @return
*/
public static boolean findAllSamePoint(String path,String screen,int x ,int y){
FindRobot demo = new FindRobot(path,screen,x,y);
if(demo.findX==0 && demo.findY==0){
return false;
} else {
//System.out.println("找到:"+demo.findX+","+demo.findY);
findAllSamePoint(path,screen,demo.findX,demo.findY);
}
return true;
}
/**
* 輸入鍵盤對應值
* KeyEvent.VK_*
* @param keyPress
*/
public static boolean inputVaule(int keyPress){
downKeyPress(keyPress);
setAutoDelay(100);
upKeyPress(keyPress);
return true;
}
/**
* 設置休息時間,毫秒
* @param time
* @return
*/
public static void setAutoDelay(int time){
robot.setAutoDelay(time);
}
/**
* 按下鍵位
* @param keyPress
*/
public static void downKeyPress(int keyPress){
setAutoDelay(100);
robot.keyPress(keyPress);
}
/**
* 釋放按鍵
* @param keyPress
*/
public static void upKeyPress(int keyPress){
setAutoDelay(100);
robot.keyRelease(keyPress);
}
/**
* 左擊測試
*/
public static void leftClick(int time){
leftDown();
setAutoDelay(time==0?100:time);
leftUp();
}
/**
* 左擊按下
*/
public static void leftDown() {
robot.mousePress(InputEvent.BUTTON1_MASK);
}
/**
* 左擊釋放
*/
public static void leftUp() {
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}
/**
* 右擊測試
*/
public static void rightKey(int time){
robot.mousePress(InputEvent.BUTTON3_MASK);
setAutoDelay(time==0?100:time);
robot.mouseRelease(InputEvent.BUTTON3_MASK);
}
/**
* 移動鼠標
* @param x
* @param y
*/
public static void move(int x ,int y){
robot.mouseMove(x,y);
}
public static Map<String,Object> findComparePic(String touchPic,String screenPic){
findAllSamePoint(touchPic,screenPic,0,0);
Map<String,Object> result = new LinkedHashMap<>();
result.put("result",map.size()==0?0:1);
result.put("message",map.size()>0?"匹配到"+map.size()+"個座標":"沒有匹配到座標點");
result.put("points",map);
return result;
}
/**
* 截屏,遠程默認800*600
============BAT=============
@%windir%\System32\tscon.exe 0 /dest:console
@%windir%\System32\tscon.exe 1 /dest:console
@%windir%\System32\tscon.exe 2 /dest:console
==========================
for /f "skip=1 tokens=3 usebackq" %%s in (
`query user %username%`
) do (
%windir%\System32\tscon.exe %%s /dest:console
)
--------------------------
* @return
*/
public static String printScreen() {
FindRobot findRobot = new FindRobot();
BufferedImage bufferedImage=findRobot.getFullScreenShot();
return writeImageFile(bufferedImage);
}
public static void scroll(Integer x) {
robot.mouseWheel(x);
}
public static void main(String[] args) {
//Map<String,Object> map =findComparePic("E://files//test//new.png","E://files//test//screen.png");
//System.err.println("count map:"+map.size());
//map.forEach((k,v)->System.out.println("key : " + k + "; value : " + v));
while (true) {
touchPic("E://files//test//close.png");
try {
sleep(150);
} catch (InterruptedException e) {
}
touchPic("E://files//test//yes.png");
}
}
}