SRL Archive - General

How to search for and click a color in Java?


rj

2013-04-20 10:05:50

I am trying to create my own AutoAlcher, I will make it for a RSPS then transfer it to RS07 with anti-ban, but how do I make Java click a color? Google isn't helping me out, this is what I have so far:


Color.java:

public class Colors {

}

Main.java:
import java.awt.AWTException;



public class Main extends Methods {
static int n;
boolean InvFull = false;


public static void main(String []args) {
while (n<10) {
n+=1;
System.out.println("n:" + n);
StartRobot( );
}

}

}

Methods.java:
import java.awt.AWTException;
import java.awt.event.InputEvent;
import java.awt.Robot;
import java.awt.Color;
import java.util.Arrays;



public class Methods extends Colors {


int SpellBook = (new Color(150, 114, 56)).getRGB();
int Spell = (new Color(195, 161, 16)).getRGB();
int Inerface_book = (new Color(66, 31, 94)).getRGB();
int Inerface_inv = (new Color(163, 151, 151)).getRGB();
static int x,y;



public void AntiBan( ){
System.out.println("AntiBan");


}

public static void Right_Click( ) {
try {
Robot click = new Robot();
click.mousePress(InputEvent.BUTTON3_MASK);
click.mouseRelease(InputEvent.BUTTON3_MASK);
} catch (AWTException j) {
System.out.println("Could not click");
j.printStackTrace();
}
}
public static void Left_Click( ) {
try {
Robot click = new Robot();
click.mousePress(InputEvent.BUTTON1_MASK);
click.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (AWTException j) {
System.out.println("Could not click");
j.printStackTrace();
}

}
public static void ToSpellBook( ) {
try {
Robot Miner = new Robot();

Miner.getPixelColor(x, y);
//Miner.mouseMove(40,40);
Left_Click( );
} catch (AWTException j) {
System.out.println("Could not start J-Robot");
j.printStackTrace();
}

}
public static void main(String []args){
// Methods MyBot = new Methods( );



}

}

Brandon

2013-04-20 12:47:50

Ok here goes.. If you're writing a bot, avoid using Robot. What you want to do is create a canvas yourself and replace the RS canvas with that one. For private servers, how do you plan on getting a DC or handle to the window to obtain colours/Images? Or are you loading the private server using an Applet and classloader? Take a look at how smart Clicks colours.


For just simple colour finding like Simba does, you need some of the following algorithms ported to Java.. These algorithms let you convert to different colour spaces. Each has its own advantages for colour finding. MasterBB has a tutorial on how each colour space works and their advantages. As well as how the CTS stuff works. You can also look at Simba's source and just write Java-code based off that I guess.. Anyway, here is what you need:

LAB <-> XYZ
HSL <-> RGBA
XYZ <-> RGBA

And all the conversions that can be derived from those..


You can port the following to Java for colour finding:


typedef union RGBA //Java doesn't have unions so just make this a class or something.
{
std::uint32_t Colour; //std::uint32_t is a long in java.
struct //ignore this in java.
{
std::uint8_t B, G, R, A; //std::uint8_t is the same as char.
};
} *PRGB; //ignore this in Java.


bool CTSN(RGBA FirstCol, RGBA SecondCol, int Tol)
{
return (FirstCol.Colour == SecondCol.Colour); //Comparing the two colours must be exactly the same!
}

bool CTS0(RGBA FirstCol, RGBA SecondCol, int Tol)
{
return abs(FirstCol.R - SecondCol.R) <= Tol && abs(FirstCol.G - SecondCol.G) <= Tol && abs(FirstCol.B - SecondCol.B) <= Tol;
}

bool CTS1(RGBA FirstCol, RGBA SecondCol, int Tol) //Compares using Pythagorean theorem..
{
return ((FirstCol.R - SecondCol.R)*(FirstCol.R - SecondCol.R) + (FirstCol.G - SecondCol.G)*(FirstCol.G - SecondCol.G) + (FirstCol.B - SecondCol.B)*(FirstCol.B - SecondCol.B)) <= (Tol * Tol);
}

bool SimilarColours(int FirstColour, int SecondColour, int Tolerance) //Calls a function that takes two colours, a tolerance, and a CTS and compares using CTS0, CTS1, etc..
{
return CTS(Rgba(FirstColour), Rgba(SecondColour), Tolerance, this->cts);
}

//Finds a bitmap. Uhh Image class I wrote myself. Java has one but you might need to create your own getpixel and put the image into a ByteBuffer.

bool FindBitmapToleranceIn(Image ImageToFind, int &X, int &Y, int X1, int Y1, int X2, int Y2, int Tolerance)
{
ValidateRange(X1, Y1, X2, Y2);

int dX = (X2 - X1) - (ImageToFind.Width() - 1);
int dY = (Y2 - Y1) - (ImageToFind.Height() - 1);

for (int I = 0; I < dY; ++I)
{
for (int J = 0; J < dX; ++J)
{
for (int YY = 0; YY < ImageToFind.Height(); ++YY)
{
for (int XX = 0; XX < ImageToFind.Width(); ++XX)
{
if (ImageToFind.GetPixel(XX, YY).Colour != 0)
{
if (!SimilarColours(ImageToFind.GetPixel(XX, YY), TargetImage.GetPixel(XX + J, YY + I), Tolerance))
{
goto Skip;
}
}
}
}

X = J + X1; Y = I + Y1;
return true;
Skip: continue;
}
}

X = -1; Y = -1;
return false;
}


The following code I wrote in Java when I first started learning it. I never really got a chance to test it or anything at all since I got bored. In hopes that it helps or works, I'm posting it. It should get you started:

I believe this class works.. I remember using it within Smart once but I made it a lot cleaner in Smart 8.1. However, the one for Smart is special and requires no copying and uses JNI, so this is the right one for you:

package std;

import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.nio.ByteBuffer;

public final class ImageHandler {
private int ByteSize;

private BufferedImage ImageFromBytes(byte[] Bytes, int Width, int Height) {
BufferedImage Image = new BufferedImage(Width, Height, BufferedImage.TYPE_INT_BGR);
WritableRaster raster = (WritableRaster) Image.getData();
raster.setPixels(0, 0, Width, Height, ByteBufferToIntBuffer(Bytes));
Image.setData(raster);
return Image;
}

private BufferedImage ImageFromByteBuffer(ByteBuffer ByteBuffer, int Width, int Height) {
byte Bytes[] = new byte[ByteSize];
ByteBuffer.get(Bytes);
return ImageFromBytes(Bytes, Width, Height);
}

private int[] ByteBufferToIntBuffer(byte[] Data) {
int IntBuffer[] = new int[Data.length];

for (int I = 0; I < Data.length; I++) {
IntBuffer[I] = (int)Data[I] & 0xFF;
}
return IntBuffer;
}
}

This class I never tested.. My Java standards with lowercase first character is a bit off I know.. I'm not a big fan of that style. Anyway, this class is a bit incomplete. I believe I only did the first constructor for testing. If that one works, the others would be fairly simple to do..

package std;

import java.io.IOException;

public final class Imaging {

private RGBA Pixels[];
private int Width, Height, BitsPerPixel;

public Imaging(String FilePath) throws java.io.FileNotFoundException, IOException, Exception {
java.io.DataInputStream IOStream = new java.io.DataInputStream(new java.io.FileInputStream(FilePath));

byte Header[] = new byte[IOStream.available()];
if (IOStream.read(Header, 0, 54) <= 0) {
IOStream.close();
throw new IOException("Un-able to read file header.");
}

if (Header[0] != 'B' && Header[1] != 'M') {
IOStream.close();
throw new IOException("Invalid File Format!");
}

if (Header[28] != 24 && Header[28] != 32) {
IOStream.close();
throw new IOException("Invalid Bits Per Pixel. 24 or 32 Bit Image Required.");
}

BitsPerPixel = Header[28];
Width = Header[18] + (Header[19] << 8);
Height = Header[22] + (Header[23] << 8);
int PixelsOffset = Header[10] + (Header[11] << 8);
int Size = ((Width * BitsPerPixel + 31) / 32) * 4 * Height;

IOStream.read(Header, PixelsOffset, Size);
IOStream.close();

int K = 0;
Pixels = new RGBA[Width * Height];

for (int I = 0; I < Height; ++I) {
for (int J = 0; J < Width; ++J) {
Pixels[(Height - 1 - I) * Width + J] = new RGBA();
Pixels[(Height - 1 - I) * Width + J].B = Header[K++];
Pixels[(Height - 1 - I) * Width + J].G = Header[K++];
Pixels[(Height - 1 - I) * Width + J].R = Header[K++];
Pixels[(Height - 1 - I) * Width + J].A = (byte)(BitsPerPixel > 24 ? Header[K++] : 0xFF);
}

if (BitsPerPixel == 24) {
K += (-Width * 3) & 3;
}
}
}

public Imaging(Imaging Img) {
}

public Imaging(byte Pixels[], int Width, int Height, int BitsPerPixel) {
}

public Imaging(RGBA Pixels[]) {
}

public RGBA[] Pixels() {
return this.Pixels;
}

private boolean BytesEqual(byte[] One, byte[] Two) {
for (int I = 0; I < One.length; ++I)
{
if (One[I] != Two[I]) {
return false;
}
}
return true;
}

private int ValidImage(byte[] ImageBytes) {
byte[] GIFBytesOne = {0x47, 0x49, 0x46, 0x38, 0x37, 0x61};
byte[] GIFBytesTwo = {0x47, 0x49, 0x46, 0x38, 0x39, 0x61};
//byte[] PNGBytes = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
byte[] BMPBytes = {0x42, 0x4D};
//byte[] JPGBytes = {0xFF, 0xD8, 0xFF};
byte[] JPEGBytes = {0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20};
//byte[] TIFFMonoChrome = {0x0C, 0xED};
byte[] TIFFOne = {0x49, 0x20, 0x49};
byte[] TIFFTwo = {0x49, 0x49, 0x2A, 0x00};
byte[] TIFFThree = {0x4D, 0x4D, 0x00, 0x2A};
byte[] TIFFFour = {0x4D, 0x4D, 0x00, 0x2B};

byte[][] All = {GIFBytesOne, GIFBytesTwo, BMPBytes, JPEGBytes, TIFFOne, TIFFTwo, TIFFThree, TIFFFour};

int I = 0;
for (byte[] Bytes : All) {
if (BytesEqual(Bytes, ImageBytes)) {
return I;
}
++I;
}
return -1;
}
}

rj

2013-04-20 12:55:25

From: Brandon
Ok here goes.. If you're writing a bot, avoid using Robot. What you want to do is create a canvas yourself and replace the RS canvas with that one. For private servers, how do you plan on getting a DC or handle to the window to obtain colours/Images? Or are you loading the private server using an Applet and classloader?


For just simple colour finding like Simba does, you need some of the following algorithms ported to Java.. These algorithms let you convert to different colour spaces. Each has its own advantages for colour finding. MasterBB has a tutorial on how each colour space works and their advantages. As well as how the CTS stuff works. You can also look at Simba's source and just write Java-code based off that I guess.. Anyway, here is what you need:

LAB <-> XYZ
HSL <-> RGBA
XYZ <-> RGBA

And all the conversions that can be derived from those..


You can port the following to Java for colour finding:


typedef union RGBA //Java doesn't have unions so just make this a class or something.
{
std::uint32_t Colour; //std::uint32_t is a long in java.
struct //ignore this in java.
{
std::uint8_t B, G, R, A; //std::uint8_t is the same as char.
};
} *PRGB; //ignore this in Java.


bool CTSN(RGBA FirstCol, RGBA SecondCol, int Tol)
{
return (FirstCol.Colour == SecondCol.Colour); //Comparing the two colours must be exactly the same!
}

bool CTS0(RGBA FirstCol, RGBA SecondCol, int Tol)
{
return abs(FirstCol.R - SecondCol.R) <= Tol && abs(FirstCol.G - SecondCol.G) <= Tol && abs(FirstCol.B - SecondCol.B) <= Tol;
}

bool CTS1(RGBA FirstCol, RGBA SecondCol, int Tol) //Compares using Pythagorean theorem..
{
return ((FirstCol.R - SecondCol.R)*(FirstCol.R - SecondCol.R) + (FirstCol.G - SecondCol.G)*(FirstCol.G - SecondCol.G) + (FirstCol.B - SecondCol.B)*(FirstCol.B - SecondCol.B)) <= (Tol * Tol);
}

bool SimilarColours(int FirstColour, int SecondColour, int Tolerance) //Calls a function that takes two colours, a tolerance, and a CTS and compares using CTS0, CTS1, etc..
{
return CTS(Rgba(FirstColour), Rgba(SecondColour), Tolerance, this->cts);
}

//Finds a bitmap. Uhh Image class I wrote myself. Java has one but you might need to create your own getpixel and put the image into a ByteBuffer.

bool FindBitmapToleranceIn(Image ImageToFind, int &X, int &Y, int X1, int Y1, int X2, int Y2, int Tolerance)
{
ValidateRange(X1, Y1, X2, Y2);

int dX = (X2 - X1) - (ImageToFind.Width() - 1);
int dY = (Y2 - Y1) - (ImageToFind.Height() - 1);

for (int I = 0; I < dY; ++I)
{
for (int J = 0; J < dX; ++J)
{
for (int YY = 0; YY < ImageToFind.Height(); ++YY)
{
for (int XX = 0; XX < ImageToFind.Width(); ++XX)
{
if (ImageToFind.GetPixel(XX, YY).Colour != 0)
{
if (!SimilarColours(ImageToFind.GetPixel(XX, YY), TargetImage.GetPixel(XX + J, YY + I), Tolerance))
{
goto Skip;
}
}
}
}

X = J + X1; Y = I + Y1;
return true;
Skip: continue;
}
}

X = -1; Y = -1;
return false;
}


The following code I wrote in Java when I first started learning it. I never really got a chance to test it or anything at all since I got bored. In hopes that it helps or works, I'm posting it. It should get you started:

I believe this class works.. I remember using it within Smart once but I made it a lot cleaner in Smart 8.1. However, the one for Smart is special and requires no copying and uses JNI, so this is the right one for you:

package std;

import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.nio.ByteBuffer;

public final class ImageHandler {
private int ByteSize;

private BufferedImage ImageFromBytes(byte[] Bytes, int Width, int Height) {
BufferedImage Image = new BufferedImage(Width, Height, BufferedImage.TYPE_INT_BGR);
WritableRaster raster = (WritableRaster) Image.getData();
raster.setPixels(0, 0, Width, Height, ByteBufferToIntBuffer(Bytes));
Image.setData(raster);
return Image;
}

private BufferedImage ImageFromByteBuffer(ByteBuffer ByteBuffer, int Width, int Height) {
byte Bytes[] = new byte[ByteSize];
ByteBuffer.get(Bytes);
return ImageFromBytes(Bytes, Width, Height);
}

private int[] ByteBufferToIntBuffer(byte[] Data) {
int IntBuffer[] = new int[Data.length];

for (int I = 0; I < Data.length; I++) {
IntBuffer[I] = (int)Data[I] & 0xFF;
}
return IntBuffer;
}
}

This class I never tested.. My Java standards with lowercase first character is a bit off I know.. I'm not a big fan of that style. Anyway, this class is a bit incomplete. I believe I only did the first constructor for testing. If that one works, the others would be fairly simple to do..

package std;

import java.io.IOException;

public final class Imaging {

private RGBA Pixels[];
private int Width, Height, BitsPerPixel;

public Imaging(String FilePath) throws java.io.FileNotFoundException, IOException, Exception {
java.io.DataInputStream IOStream = new java.io.DataInputStream(new java.io.FileInputStream(FilePath));

byte Header[] = new byte[IOStream.available()];
if (IOStream.read(Header, 0, 54) <= 0) {
IOStream.close();
throw new IOException("Un-able to read file header.");
}

if (Header[0] != 'B' && Header[1] != 'M') {
IOStream.close();
throw new IOException("Invalid File Format!");
}

if (Header[28] != 24 && Header[28] != 32) {
IOStream.close();
throw new IOException("Invalid Bits Per Pixel. 24 or 32 Bit Image Required.");
}

BitsPerPixel = Header[28];
Width = Header[18] + (Header[19] << 8);
Height = Header[22] + (Header[23] << 8);
int PixelsOffset = Header[10] + (Header[11] << 8);
int Size = ((Width * BitsPerPixel + 31) / 32) * 4 * Height;

IOStream.read(Header, PixelsOffset, Size);
IOStream.close();

int K = 0;
Pixels = new RGBA[Width * Height];

for (int I = 0; I < Height; ++I) {
for (int J = 0; J < Width; ++J) {
Pixels[(Height - 1 - I) * Width + J] = new RGBA();
Pixels[(Height - 1 - I) * Width + J].B = Header[K++];
Pixels[(Height - 1 - I) * Width + J].G = Header[K++];
Pixels[(Height - 1 - I) * Width + J].R = Header[K++];
Pixels[(Height - 1 - I) * Width + J].A = (byte)(BitsPerPixel > 24 ? Header[K++] : 0xFF);
}

if (BitsPerPixel == 24) {
K += (-Width * 3) & 3;
}
}
}

public Imaging(Imaging Img) {
}

public Imaging(byte Pixels[], int Width, int Height, int BitsPerPixel) {
}

public Imaging(RGBA Pixels[]) {
}

public RGBA[] Pixels() {
return this.Pixels;
}

private boolean BytesEqual(byte[] One, byte[] Two) {
for (int I = 0; I < One.length; ++I)
{
if (One[I] != Two[I]) {
return false;
}
}
return true;
}

private int ValidImage(byte[] ImageBytes) {
byte[] GIFBytesOne = {0x47, 0x49, 0x46, 0x38, 0x37, 0x61};
byte[] GIFBytesTwo = {0x47, 0x49, 0x46, 0x38, 0x39, 0x61};
//byte[] PNGBytes = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
byte[] BMPBytes = {0x42, 0x4D};
//byte[] JPGBytes = {0xFF, 0xD8, 0xFF};
byte[] JPEGBytes = {0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20};
//byte[] TIFFMonoChrome = {0x0C, 0xED};
byte[] TIFFOne = {0x49, 0x20, 0x49};
byte[] TIFFTwo = {0x49, 0x49, 0x2A, 0x00};
byte[] TIFFThree = {0x4D, 0x4D, 0x00, 0x2A};
byte[] TIFFFour = {0x4D, 0x4D, 0x00, 0x2B};

byte[][] All = {GIFBytesOne, GIFBytesTwo, BMPBytes, JPEGBytes, TIFFOne, TIFFTwo, TIFFThree, TIFFFour};

int I = 0;
for (byte[] Bytes : All) {
if (BytesEqual(Bytes, ImageBytes)) {
return I;
}
++I;
}
return -1;
}
}


So how do I use that? And I want to test it on a RSPS first because I don't have mems ATM so I don't want to load a client or anything

Brandon

2013-04-20 13:01:49

From: Officer Barbrady
So how do I use that? And I want to test it on a RSPS first because I don't have mems ATM so I don't want to load a client or anything



What do you mean how do you use it? You want to obtain an Image of the RSPS on screen. Perhaps look up Java screenshot. http://stackoverflow.com/questions/58305/is-there-a-way-to-take-a-screenshot-using-java-and-save-it-to-some-sort-of-image

Once you get an Image, convert it to a ByteBuffer, byte[], or BufferedImage.

Using either of those, you can pass those to the functions to do the finding/matching for you.

rj

2013-04-20 13:04:01

From: Brandon
What do you mean how do you use it? You want to obtain an Image of the RSPS on screen. Perhaps look up Java screenshot. http://stackoverflow.com/questions/58305/is-there-a-way-to-take-a-screenshot-using-java-and-save-it-to-some-sort-of-image

Once you get an Image, convert it to a ByteBuffer, byte[], or BufferedImage.

Using either of those, you can pass those to the functions to do the finding/matching for you.



Well I have it included but the 2nd one gives me tons of errors:



"RGBA cannot be resolved to a type" on abunch of lines


Can you give me a quick example of the parameters used just to click a color?

Brandon

2013-04-20 14:38:46

From: Officer Barbrady
Well I have it included but the 2nd one gives me tons of errors:



"RGBA cannot be resolved to a type" on abunch of lines


Can you give me a quick example of the parameters used just to click a color?



Here goes.. just finished writing this.. Nothing has been tested. Its a direct port from Cpp.. The boxed types such as "Integer" and "Double" is my way of saying, these values should be pass by reference.. I think you'd actually have to make a class to pass them by value reference via Get/Set. Extra stupid but sure..

Use the ImageFinding to get a screenshot of your RSPS window.. Use the ImageFinder to find whatever it is you're looking for. Use ImageIO to read an image from file to a BufferedImage so you can search for it.. Use FindColour functions to find colours on the screen. Use Robot to click it I guess..

Again, I never tested these yet as I just finished writing them. I'll leave that up to you or someone else for now. They work in Cpp though.

Here is everything:


package imagefinding;

public class HSL {

public double Hue, Sat, Lum;
}


package imagefinding;

public class LAB {

public double L, A, B;
}


package imagefinding;

public class XYZ {
public double X, Y, Z;
}


package imagefinding;

import java.awt.Color;

public class ColourSpace {

public XYZ XYZ(Color C) {
XYZ Result = new XYZ();
double Red = (C.getRed() / 255.0);
double Green = (C.getGreen() / 255.0);
double Blue = (C.getBlue() / 255.0);

Red = (Red > 0.04045) ? Math.pow(((Red + 0.055) / 1.055), 2.4) * 100 : Red / 12.92;
Green = (Green > 0.04045) ? Math.pow(((Green + 0.055) / 1.055), 2.4) * 100.0 : Green / 12.92;
Blue = (Blue > 0.04045) ? Math.pow(((Blue + 0.055) / 1.055), 2.4) * 100.0 : Blue / 12.92;
Result.X = Red * 0.4124 + Green * 0.3576 + Blue * 0.1805;
Result.Y = Red * 0.2126 + Green * 0.7152 + Blue * 0.0722;
Result.Z = Red * 0.0193 + Green * 0.1192 + Blue * 0.9505;
return Result;
}

public Color Rgba(XYZ Xyz) {
double X = Xyz.X / 100.0;
double Y = Xyz.Y / 100.0;
double Z = Xyz.Z / 100.0;

double Red = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
double Green = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
double Blue = X * 0.0557 + Y * -0.2040 + Z * 1.0570;

Red = (Red > 0.0031308) ? (1.055 * Math.pow(Red, (1 / 2.4)) - 0.055) : 12.92 * Red;
Green = (Green > 0.0031308) ? (1.055 * Math.pow(Green, (1 / 2.4)) - 0.055) : 12.92 * Green;
Blue = (Blue > 0.0031308) ? (1.055 * Math.pow(Blue, (1 / 2.4)) - 0.055) : 12.92 * Blue;

long R = Math.round(Red * 255.0);
long G = Math.round(Green * 255.0);
long B = Math.round(Blue * 255.0);

return new Color(R, G, B);
}

public HSL Hsl(Color Rgba) {
HSL Result = new HSL();
double Red, Green, Blue;
Red = Rgba.getRed() / 255.0;
Green = Rgba.getGreen() / 255.0;
Blue = Rgba.getBlue() / 255.0;
double Max = Red > Blue ? Red > Green ? Red : Green : Blue > Green ? Blue : Green;
double Min = Red < Blue ? Red < Green ? Red : Green : Blue < Green ? Blue : Green;
Result.Lum = (Max + Min) / 2.0;

if (Max == Min) {
Result.Hue = Result.Sat = 0.0;
} else {
double Delta = Max - Min;
Result.Sat = Result.Lum > 0.5 ? Delta / (2.0 - Max - Min) : Delta / (Max + Min);
if (Max == Red) {
Result.Hue = (Green - Blue) / Delta + (Green < Blue ? 6.0 : 0.0);
} else if (Max == Green) {
Result.Hue = (Blue - Red) / Delta + 2.0;
} else {
Result.Hue = (Red - Green) / Delta + 4.0;
}

Result.Hue /= 6.0;
}

Result.Hue *= 100.0;
Result.Sat *= 100.0;
Result.Lum *= 100.0;
return Result;
}

private static double HSLToRGBHelper(double I, double J, double Hue) {
if (Hue < 0.0) {
Hue += 1.0;
}
if (Hue > 1.0) {
Hue -= 1.0;
}
if (Hue < (1.0 / 6.0)) {
return Math.round((I + (J - I) * 6.0 * Hue) * 255.0);
} else if (Hue < (1.0 / 2.0)) {
return Math.round(J * 255.0);
} else if (Hue < (2.0 / 3.0)) {
return Math.round((I + (J - I) * 6.0 * ((2.0 / 3.0) - Hue)) * 255.0);
} else {
return Math.round(I * 255.0);
}
}

public Color Rgba(HSL Hsl) {
double H = Hsl.Hue / 100.0;
double S = Hsl.Sat / 100.0;
double L = Hsl.Lum / 100.0;
Color Result = null;

if (S == 0.0) {
double Value = L * 255.0;
Result = new Color((int) Value, (int) Value, (int) Value);
} else {
double J = (L < 0.5) ? (L * (1.0 + S)) : ((L + S) - (S * L));
double I = 2.0 * L - J;

double R = HSLToRGBHelper(I, J, H + (1.0 / 3.0));
double G = HSLToRGBHelper(I, J, H);
double B = HSLToRGBHelper(I, J, H - (1.0 / 3.0));
Result = new Color((int) R, (int) G, (int) B);
}
return Result;
}

public LAB Lab(XYZ Xyz) {
double X = Xyz.X / 95.047;
double Y = Xyz.Y / 100.000;
double Z = Xyz.Z / 108.883;

X = (X > 0.008856) ? Math.pow(X, (1.0 / 3.0)) : (X * 7.787) + (16.0 / 116.0);
Y = (Y > 0.008856) ? Math.pow(Y, (1.0 / 3.0)) : (Y * 7.787) + (16.0 / 116.0);
Z = (Z > 0.008856) ? Math.pow(Z, (1.0 / 3.0)) : (Z * 7.787) + (16.0 / 116.0);

LAB Result = new LAB();
Result.L = ((Y * 116.0) - 16.0);
Result.A = ((X - Y) * 500);
Result.B = ((Y - Z) * 200);
return Result;
}

public XYZ Xyz(LAB Lab) {
double Y = (Lab.L + 16.0) / 116.0;
double X = ((Lab.A / 500.0) + Y);
double Z = (Y - (Lab.B / 200.0));

Y = (Math.pow(Y, 3) > 0.008856) ? Math.pow(Y, 3) : ((Y - (16.0 / 116.0)) / 7.787);
X = (Math.pow(X, 3) > 0.008856) ? Math.pow(X, 3) : ((X - (16.0 / 116.0)) / 7.787);
Z = (Math.pow(Z, 3) > 0.008856) ? Math.pow(Z, 3) : ((Z - (16.0 / 116.0)) / 7.787);

XYZ Result = new XYZ();
Result.X = (X * 95.047);
Result.Y = (Y * 100.000);
Result.Z = (Z * 108.883);
return Result;
}

public static ColourSpace Instance = new ColourSpace();

private ColourSpace() {
}

public static ColourSpace getInstance() {
return Instance;
}
}


package imagefinding;

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.nio.ByteBuffer;

public final class ImageHandler {
private int ByteSize;

public BufferedImage Screenshot(int X, int Y, int Width, int Height) throws AWTException {
Rectangle Rect = new Rectangle(X, Y, Width, Height);
return new Robot().createScreenCapture(Rect);
}

public BufferedImage ImageFromBytes(byte[] Bytes, int Width, int Height) {
BufferedImage Image = new BufferedImage(Width, Height, BufferedImage.TYPE_INT_BGR);
WritableRaster raster = (WritableRaster) Image.getData();
raster.setPixels(0, 0, Width, Height, ByteBufferToIntBuffer(Bytes));
Image.setData(raster);
return Image;
}

public BufferedImage ImageFromByteBuffer(ByteBuffer ByteBuffer, int Width, int Height) {
byte Bytes[] = new byte[ByteSize];
ByteBuffer.get(Bytes);
return ImageFromBytes(Bytes, Width, Height);
}

public int[] ByteBufferToIntBuffer(byte[] Data) {
int IntBuffer[] = new int[Data.length];

for (int I = 0; I < Data.length; I++) {
IntBuffer[I] = (int)Data[I] & 0xFF;
}
return IntBuffer;
}
}


package imagefinding;

import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class ImageFinder {

private int CTSValue;
private double TMod, HueMod, SatMod;
private BufferedImage TargetImage;

public void SetTargetImage(BufferedImage IMG) {
this.TargetImage = null;
this.TargetImage = IMG;
}

public void Reset() {
CTSValue = 1;
TMod = 4.0;
HueMod = 0.2;
SatMod = 0.2;
}

public int GetColourToleranceSpeed() {
return this.CTSValue;
}

void SetColourToleranceSpeed(int Value) {
this.CTSValue = Value;
if (Value < -1 || Value > 3) {
this.CTSValue = 1;
}
}

void GetSpeed2Modifiers(Double HueMod, Double SatMod) {
HueMod = this.HueMod;
SatMod = this.SatMod;
}

void SetSpeed2Modifiers(double HueMod, double SatMod) {
this.HueMod = HueMod;
this.SatMod = SatMod;
}

double GetSpeed3Modifier() {
return TMod;
}

void SetSpeed3Modifier(double TMod) {
this.TMod = TMod;
}

boolean SimilarColours(Color FirstColour, Color SecondColour, int Tolerance) {
switch (CTSValue) {
case -1:
return CTSN(FirstColour, SecondColour, Tolerance);
case 0:
return CTS0(FirstColour, SecondColour, Tolerance);
case 1:
return CTS1(FirstColour, SecondColour, Tolerance);
case 2:
return CTS2(FirstColour, SecondColour, Tolerance);
case 3:
return CTS3(FirstColour, SecondColour, Tolerance);
default:
return CTS1(FirstColour, SecondColour, Tolerance);
}
}

private boolean CTSN(Color FirstCol, Color SecondCol, int Tol) {
return (FirstCol.getRGB() == SecondCol.getRGB());
}

private boolean CTS0(Color FirstCol, Color SecondCol, int Tol) {
return Math.abs(FirstCol.getRed() - SecondCol.getRed()) <= Tol && Math.abs(FirstCol.getGreen() - SecondCol.getGreen()) <= Tol && Math.abs(FirstCol.getBlue() - SecondCol.getBlue()) <= Tol;
}

private boolean CTS1(Color FirstCol, Color SecondCol, int Tol) {
return ((FirstCol.getRed() - SecondCol.getRed()) * (FirstCol.getRed() - SecondCol.getRed()) + (FirstCol.getGreen() - SecondCol.getGreen()) * (FirstCol.getGreen() - SecondCol.getGreen()) + (FirstCol.getBlue() - SecondCol.getBlue()) * (FirstCol.getBlue() - SecondCol.getBlue())) <= (Tol * Tol);
}

private boolean CTS2(Color FirstCol, Color SecondCol, int Tol) {
HSL HFirstCol = new HSL();
HSL HSecondCol = new HSL();

if (FirstCol.getRGB() != 0) {
HFirstCol = ColourSpace.getInstance().Hsl(FirstCol);
}

if (SecondCol.getRGB() != 0) {
HSecondCol = ColourSpace.getInstance().Hsl(SecondCol);
}

return (Math.abs(HSecondCol.Hue - HFirstCol.Hue) <= (Tol * HueMod)) && (Math.abs(HSecondCol.Sat - HFirstCol.Sat) <= (Tol * SatMod));
}

private boolean CTS3(Color FirstCol, Color SecondCol, int Tol) {
LAB LabFirstCol = new LAB(), LabSecondCol = new LAB();
if (FirstCol.getRGB() != 0) {
LabFirstCol = ColourSpace.getInstance().Lab(ColourSpace.getInstance().XYZ(FirstCol));
}

if (SecondCol.getRGB() != 0) {
LabSecondCol = ColourSpace.getInstance().Lab(ColourSpace.getInstance().XYZ(SecondCol));
}

double L = (LabSecondCol.L - LabFirstCol.L);
double A = (LabSecondCol.A - LabFirstCol.A);
double B = (LabSecondCol.B - LabFirstCol.B);

return ((L * L) + (A * A) + (B * B)) <= Math.ceil(Math.sqrt(Tol * TMod));
}

public int CountColour(Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = this.CTSValue;
SetColourToleranceSpeed(-1);
int Result = CountColourTolerance(Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public int CountColourTolerance(Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
int Result = 0;

for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(Colour, new Color(TargetImage.getRGB(J, I)), Tolerance)) {
++Result;
}
}
}

return Result;
}

public boolean FindColour(Integer X, Integer Y, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColourTolerance(X, Y, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColours(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColoursTolerance(Points, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColourTolerance(Integer X, Integer Y, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), Colour, Tolerance)) {
X = J;
Y = I;
return true;
}
}
}
return false;
}

public boolean FindColoursTolerance(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), Colour, Tolerance)) {
Points.add(new Point(J, I));
}
}
}
return (!Points.isEmpty());
}

public boolean FindImage(BufferedImage ImageToFind, Integer X, Integer Y) {
return FindImageIn(ImageToFind, X, Y, 0, 0, TargetImage.getWidth(), TargetImage.getHeight());
}

public boolean FindImageIn(BufferedImage ImageToFind, Integer X, Integer Y, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
boolean Result = FindImageToleranceIn(ImageToFind, X, Y, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindImageToleranceIn(BufferedImage ImageToFind, Integer X, Integer Y, int X1, int Y1, int X2, int Y2, int Tolerance) {
int dX = (X2 - X1) - (ImageToFind.getWidth() - 1);
int dY = (Y2 - Y1) - (ImageToFind.getHeight() - 1);

for (int I = 0; I < dY; ++I) {
for (int J = 0; J < dX; ++J) {
Skip:
for (int YY = 0; YY < ImageToFind.getHeight(); ++YY) {
for (int XX = 0; XX < ImageToFind.getWidth(); ++XX) {
if (ImageToFind.getRGB(XX, YY) != 0) {
if (!SimilarColours(new Color(ImageToFind.getRGB(XX, YY)), new Color(TargetImage.getRGB(XX + J, YY + I)), Tolerance)) {
++J;
break Skip; //Java doesn't have goto :S
}
}
}
}

X = J + X1;
Y = I + Y1;
return true;
}
}

X = -1;
Y = -1;
return false;
}
}

rj

2013-04-20 14:50:53

@Brandon Damn thanks! but which one of these do I not need?



I get an error in imagefinder.java"L cannot be resolved to a variable or is not a field"
And in Colourspace.java I get the same error except for "A,L,B,Y,Z"


EDIT: ERROR WENT AWAY when I deleted the other package, all I have to do now is figure out the parameters for these lol, thanks

Brandon

2013-04-20 14:54:12

Delete everything in the std Package and delete the std package itself. Drag and drop all the code I gave you into your "default" package or drag drop all your code into the imagefinding package and refactor.

The code compiles just fine. You need to decide on what packages you're using. All the classes I posted in my most recent post is what you need. They all depend on each other so yeah.

rj

2013-04-20 15:03:14

From: Brandon
Delete everything in the std Package and delete the std package itself. Drag and drop all the code I gave you into your "default" package or drag drop all your code into the imagefinding package and refactor.

The code compiles just fine. You need to decide on what packages you're using. All the classes I posted in my most recent post is what you need. They all depend on each other so yeah.


How do I use findColortol in the main.java? Do I have to make all of the procedures global in the other files?

package main;
import java.awt.AWTException;
import java.awt.Color;




public class Main extends Methods {
static int n;
static int x,y;
boolean InvFull = false;


public static void main(String []args) {

FindColourTolerance(x,y, 0, 0, 0, 500, 500, 5);
}

}

"the method FindColourTolerance is undefined for the type main"

Brandon

2013-04-20 15:27:40

From: Officer Barbrady
How do I use findColortol in the main.java? Do I have to make all of the procedures global in the other files?

"the method FindColourTolerance is undefined for the type main"


Usage:

ImageHandler Handler = new ImageHandler();
BufferedImage TargetImage = Handler.Screenshot(0, 0, 765, 553);

int X = -1;
int Y = -1;
ImageFinder Finder = new ImageFinder();
Finder.SetTargetImage(TargetImage);
if (Finder.FindColourTolerance(X, Y, Color.blue, 0, 0, 765, 553, 10)) {
//Do some colour clicking here..
}


If you change the ImageFinder class functions to the following(which I recommend in order to get rid of the pass by reference problem):


public boolean FindColour(Point P, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColourTolerance(P, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColours(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColoursTolerance(Points, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColourTolerance(Point P, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), Colour, Tolerance)) {
P.setLocation(J, I);
return true;
}
}
}
return false;
}

public boolean FindColoursTolerance(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), Colour, Tolerance)) {
Points.add(new Point(J, I));
}
}
}
return (!Points.isEmpty());
}

public boolean FindImage(BufferedImage ImageToFind, Point P) {
return FindImageIn(ImageToFind, P, 0, 0, TargetImage.getWidth(), TargetImage.getHeight());
}

public boolean FindImageIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
boolean Result = FindImageToleranceIn(ImageToFind, P, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

boolean FindImageToleranceIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2, int Tolerance) {
int dX = (X2 - X1) - (ImageToFind.getWidth() - 1);
int dY = (Y2 - Y1) - (ImageToFind.getHeight() - 1);

for (int I = 0; I < dY; ++I) {
for (int J = 0; J < dX; ++J) {
Skip:
for (int YY = 0; YY < ImageToFind.getHeight(); ++YY) {
for (int XX = 0; XX < ImageToFind.getWidth(); ++XX) {
if (ImageToFind.getRGB(XX, YY) != 0) {
if (!SimilarColours(new Color(ImageToFind.getRGB(XX, YY)), new Color(TargetImage.getRGB(XX + J, YY + I)), Tolerance)) {
++J;
break Skip; //Java doesn't have goto :S
}
}
}
}

P.setLocation(J + X1, I + Y1);
return true;
}
}

P.setLocation(-1, -1);
return false;
}


Then the usage would be:


ImageHandler Handler = new ImageHandler();
BufferedImage TargetImage = Handler.Screenshot(0, 0, 765, 553);

Point P = new Point(-1, -1);
ImageFinder Finder = new ImageFinder();
Finder.SetTargetImage(TargetImage);
if (Finder.FindColourTolerance(P, Color.blue, 0, 0, 765, 553, 10)) {
//Do some colour clicking at P.
//MoveMouse(P);
//ClickMouse(P);
}

rj

2013-04-20 15:31:56

From: Brandon
Usage:

ImageHandler Handler = new ImageHandler();
BufferedImage TargetImage = Handler.Screenshot(0, 0, 765, 553);

int X = -1;
int Y = -1;
ImageFinder Finder = new ImageFinder();
Finder.SetTargetImage(TargetImage);
if (Finder.FindColourTolerance(X, Y, Color.blue, 0, 0, 765, 553, 10)) {
//Do some colour clicking here..
}


If you change the ImageFinder class functions to the following(which I recommend in order to get rid of the pass by reference problem):


public boolean FindColour(Point P, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColourTolerance(P, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColours(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColoursTolerance(Points, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColourTolerance(Point P, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), Colour, Tolerance)) {
P.setLocation(J, I);
return true;
}
}
}
return false;
}

public boolean FindColoursTolerance(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), Colour, Tolerance)) {
Points.add(new Point(J, I));
}
}
}
return (!Points.isEmpty());
}

public boolean FindImage(BufferedImage ImageToFind, Point P) {
return FindImageIn(ImageToFind, P, 0, 0, TargetImage.getWidth(), TargetImage.getHeight());
}

public boolean FindImageIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
boolean Result = FindImageToleranceIn(ImageToFind, P, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

boolean FindImageToleranceIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2, int Tolerance) {
int dX = (X2 - X1) - (ImageToFind.getWidth() - 1);
int dY = (Y2 - Y1) - (ImageToFind.getHeight() - 1);

for (int I = 0; I < dY; ++I) {
for (int J = 0; J < dX; ++J) {
Skip:
for (int YY = 0; YY < ImageToFind.getHeight(); ++YY) {
for (int XX = 0; XX < ImageToFind.getWidth(); ++XX) {
if (ImageToFind.getRGB(XX, YY) != 0) {
if (!SimilarColours(new Color(ImageToFind.getRGB(XX, YY)), new Color(TargetImage.getRGB(XX + J, YY + I)), Tolerance)) {
++J;
break Skip; //Java doesn't have goto :S
}
}
}
}

P.setLocation(J + X1, I + Y1);
return true;
}
}

P.setLocation(-1, -1);
return false;
}


Then the usage would be:


ImageHandler Handler = new ImageHandler();
BufferedImage TargetImage = Handler.Screenshot(0, 0, 765, 553);

Point P = new Point(-1, -1);
ImageFinder Finder = new ImageFinder();
Finder.SetTargetImage(TargetImage);
if (Finder.FindColourTolerance(P, Color.blue, 0, 0, 765, 553, 10)) {
//Do some colour clicking at P.
//MoveMouse(P);
//ClickMouse(P);
}


Ok thanks, 2 more questons, do I have to use RGB? I get an error when I use 2911372, figured that part out, just had to make new Color.



also I am getting the error "buffered image cannot be resolved to a type" - I used quick fix to solve this but IDK if it worked.

I get anothe error when I try to run:

Exception in thread "main" java.lang.NullPointerException
at main.ImageFinder.FindColourTolerance(ImageFinder.java:175)
at main.Main.main(Main.java:31)
package main;
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Robot;
import java.awt.image.BufferedImage;




public class Main extends Methods {
static int n;
static int x,y;
boolean InvFull = false;
static Color j = new Color(150, 114, 56);



public static void main(String []args) {

ImageHandler Handler = new ImageHandler();
try {
BufferedImage TargetImage = Handler.Screenshot(0, 0, 765, 553);
} catch (AWTException e) {
System.out.println("Error when taking screenshot");
e.printStackTrace();
}

int X = -1;
int Y = -1;
ImageFinder Finder = new ImageFinder();
if (Finder.FindColourTolerance(X, Y, j, 0, 0, 765, 553, 10)) {
try {
Robot Miner = new Robot();
Miner.mouseMove(X,Y);
Left_Click( );
} catch (AWTException j) {
System.out.println("Could not start J-Robot");
j.printStackTrace();
}
}


}

}

Brandon

2013-04-20 15:55:01

From: Officer Barbrady
Ok thanks, 2 more questons, do I have to use RGB? I get an error when I use 2911372, figured that part out, just had to make new Color.



also I am getting the error "buffered image cannot be resolved to a type" - I used quick fix to solve this but IDK if it worked.

I get anothe error when I try to run:

Exception in thread "main" java.lang.NullPointerException
at main.ImageFinder.FindColourTolerance(ImageFinder.java:175)
at main.Main.main(Main.java:31)


Look at my example again.. You're missing a line.. "Finder.SetTargetImage(TargetImage);".. I would really really recommend you make the changes I mentioned above.. instead of X, Y, it should be a Point.

rj

2013-04-20 15:57:18

From: Brandon
Look at my example again.. You're missing a line.. "Finder.SetTargetImage(TargetImage);".. I would really really recommend you make the changes I mentioned above.. instead of X, Y, it should be a Point.


Oh, but I still get this error "The local variable TargetImage may not have been initialized"

Brandon

2013-04-20 17:12:28

From: Officer Barbrady
Oh, but I still get this error "The local variable TargetImage may not have been initialized"
@Kasi; I think you might be interested in this topic ;)


:S Iunno what you're doing wrong but anyway.. I got some free time just now and tested it.. I made some changes which are necessary due to the RGBA being swapped to BGRA on Windows..

Anyway, these classes are now 100% use-able and working.. Just play around with whatever code you have and use the classes provided.

ImageFinding.java:


package imagefinding;

import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class ImageFinder {

private int CTSValue;
private double TMod, HueMod, SatMod;
private BufferedImage TargetImage;

public void SetTargetImage(BufferedImage IMG) {
this.TargetImage = null;
this.TargetImage = IMG;
}

public void Reset() {
CTSValue = 1;
TMod = 4.0;
HueMod = 0.2;
SatMod = 0.2;
}

public int Colorref(int R, int G, int B) {
return (R | (G << 8) | (B << 16));
}

public Color Colorref(int Colour) {
int R = (Colour & 0x00ff0000) >> 16;
int G = (Colour & 0x0000ff00) >> 8;
int B = (Colour & 0x000000ff);
return new Color(R, G, B);
}

public int ColourSwap(int Colour) {
return ((Colour & 0xFF000000)|((Colour & 0xFF0000) >> 16)|(Colour & 0x00FF00)|((Colour & 0x0000FF) << 16));
}

public Color ColourSwap(Color Colour) {
return new Color(ColourSwap(Colour.getRGB()));
}

public int GetColourToleranceSpeed() {
return this.CTSValue;
}

void SetColourToleranceSpeed(int Value) {
CTSValue = Value >= -1 && Value <= 3 ? Value : 1;
}

void GetSpeed2Modifiers(Double HueMod, Double SatMod) {
HueMod = this.HueMod;
SatMod = this.SatMod;
}

void SetSpeed2Modifiers(double HueMod, double SatMod) {
this.HueMod = HueMod;
this.SatMod = SatMod;
}

double GetSpeed3Modifier() {
return TMod;
}

void SetSpeed3Modifier(double TMod) {
this.TMod = TMod;
}

boolean SimilarColours(Color FirstColour, Color SecondColour, int Tolerance) {
switch (CTSValue) {
case -1:
return CTSN(FirstColour, SecondColour);
case 0:
return CTS0(FirstColour, SecondColour, Tolerance);
case 1:
return CTS1(FirstColour, SecondColour, Tolerance);
case 2:
return CTS2(FirstColour, SecondColour, Tolerance);
case 3:
return CTS3(FirstColour, SecondColour, Tolerance);
default:
return CTS1(FirstColour, SecondColour, Tolerance);
}
}

private boolean CTSN(Color FirstCol, Color SecondCol) {
return (FirstCol.getRed() == SecondCol.getRed() && FirstCol.getGreen() == SecondCol.getGreen() && FirstCol.getBlue() == SecondCol.getBlue());
}

private boolean CTS0(Color FirstCol, Color SecondCol, int Tol) {
return Math.abs(FirstCol.getRed() - SecondCol.getRed()) <= Tol && Math.abs(FirstCol.getGreen() - SecondCol.getGreen()) <= Tol && Math.abs(FirstCol.getBlue() - SecondCol.getBlue()) <= Tol;
}

private boolean CTS1(Color FirstCol, Color SecondCol, int Tol) {
return ((FirstCol.getRed() - SecondCol.getRed())*(FirstCol.getRed() - SecondCol.getRed()) + (FirstCol.getGreen() - SecondCol.getGreen())*(FirstCol.getGreen() - SecondCol.getGreen()) + (FirstCol.getBlue() - SecondCol.getBlue())*(FirstCol.getBlue() - SecondCol.getBlue())) <= (Tol * Tol);
}

private boolean CTS2(Color FirstCol, Color SecondCol, int Tol) {
HSL HFirstCol = new HSL();
HSL HSecondCol = new HSL();

if (FirstCol.getRGB() != 0) {
HFirstCol = ColourSpace.getInstance().Hsl(FirstCol);
}

if (SecondCol.getRGB() != 0) {
HSecondCol = ColourSpace.getInstance().Hsl(SecondCol);
}

return (Math.abs(HSecondCol.Hue - HFirstCol.Hue) <= (Tol * HueMod)) && (Math.abs(HSecondCol.Sat - HFirstCol.Sat) <= (Tol * SatMod));
}

private boolean CTS3(Color FirstCol, Color SecondCol, int Tol) {
LAB LabFirstCol = new LAB(), LabSecondCol = new LAB();
if (FirstCol.getRGB() != 0) {
LabFirstCol = ColourSpace.getInstance().Lab(ColourSpace.getInstance().XYZ(FirstCol));
}

if (SecondCol.getRGB() != 0) {
LabSecondCol = ColourSpace.getInstance().Lab(ColourSpace.getInstance().XYZ(SecondCol));
}

double L = (LabSecondCol.L - LabFirstCol.L);
double A = (LabSecondCol.A - LabFirstCol.A);
double B = (LabSecondCol.B - LabFirstCol.B);

return ((L * L) + (A * A) + (B * B)) <= Math.ceil(Math.sqrt(Tol * TMod));
}

public int CountColour(Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = this.CTSValue;
SetColourToleranceSpeed(-1);
int Result = CountColourTolerance(Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public int CountColourTolerance(Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
int Result = 0;

for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(ColourSwap(Colour), new Color(TargetImage.getRGB(J, I)), Tolerance)) {
++Result;
}
}
}

return Result;
}

public boolean FindColour(Point P, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColourTolerance(P, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColours(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColoursTolerance(Points, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColourTolerance(Point P, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {

for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), ColourSwap(Colour), Tolerance)) {
P.setLocation(J, I);
return true;
}
}
}
return false;
}

public boolean FindColoursTolerance(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), ColourSwap(Colour), Tolerance)) {
Points.add(new Point(J, I));
}
}
}
return (!Points.isEmpty());
}

public boolean FindImage(BufferedImage ImageToFind, Point P) {
return FindImageIn(ImageToFind, P, 0, 0, TargetImage.getWidth(), TargetImage.getHeight());
}

public boolean FindImageIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
boolean Result = FindImageToleranceIn(ImageToFind, P, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

boolean FindImageToleranceIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2, int Tolerance) {
int dX = (X2 - X1) - (ImageToFind.getWidth() - 1);
int dY = (Y2 - Y1) - (ImageToFind.getHeight() - 1);

for (int I = 0; I < dY; ++I) {
for (int J = 0; J < dX; ++J) {
Skip:
for (int YY = 0; YY < ImageToFind.getHeight(); ++YY) {
for (int XX = 0; XX < ImageToFind.getWidth(); ++XX) {
if (ImageToFind.getRGB(XX, YY) != 0) {
if (!SimilarColours(new Color(ImageToFind.getRGB(XX, YY)), new Color(TargetImage.getRGB(XX + J, YY + I)), Tolerance)) {
++J;
break Skip; //Java doesn't have goto :S
}
}
}
}

P.setLocation(J + X1, I + Y1);
return true;
}
}

P.setLocation(-1, -1);
return false;
}
}



The result of testing it:

package imagefinding;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Main {

public static void main(String[] args) throws AWTException, IOException {
ImageHandler Handler = new ImageHandler();
BufferedImage TargetImage = Handler.Screenshot(0, 0, 765, 553);

Point P = new Point(-1, -1);
ImageFinder Finder = new ImageFinder();
Finder.SetTargetImage(TargetImage);
Finder.SetColourToleranceSpeed(1);

if (Finder.FindColourTolerance(P, new Color(7912686), 0, 0, TargetImage.getWidth(), TargetImage.getHeight(), 10)) {
System.out.println(P);
Robot Miner = new Robot();
Miner.mouseMove(P.x, P.y);
}

ImageIO.write(TargetImage, "bmp", new File("C:/Users/Brandon/Desktop/Meh.bmp"));
}
}

Which gives the exact same result as:


Procedure PrintRGB(Color: Integer);
var
R, G, B: Integer;
begin
ColorToRGB(Color, R, G, B);
Writeln('R: ' + ToStr(R) + ', G: ' + ToStr(G) + ', B: ' + ToStr(B));
end;


var
BMP, X, Y, W, H: Integer;

begin
//BMP := LoadBitmap('C:/Users/Brandon/Desktop/Meh.bmp');
//SetTargetBitmap(BMP);
GetClientDimensions(W, H);
FindColorTolerance(X, Y, 7912686, 0, 0, W - 1, H - 1, 10);
Writeln('Found at: ' + ToStr(Point(X, Y)));
PrintRGB(7912686);

MoveMouse(X, Y);
end.

I've tested it with many different colours.. Both scripts move the mouse to the exact same position for CTSN, CTS0, CTS1. I did not Test CTS2 or CTS3.

Good luck on your endeavors. I really hope you get it working. I'm not sure why you got that error because I don't get it. It's probably because of your Try-Catch. Should be:


BufferedImage TargetImage = null; //Initialize it to null.

try {
TargetImage = .......;
} catch(Exception E) {
}

rj

2013-04-20 17:31:08

From: Brandon
@Kasi; I think you might be interested in this topic ;)


:S Iunno what you're doing wrong but anyway.. I got some free time just now and tested it.. I made some changes which are necessary due to the RGBA being swapped to BGRA on Windows..

Anyway, these classes are now 100% use-able and working.. Just play around with whatever code you have and use the classes provided.

ImageFinding.java:


package imagefinding;

import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class ImageFinder {

private int CTSValue;
private double TMod, HueMod, SatMod;
private BufferedImage TargetImage;

public void SetTargetImage(BufferedImage IMG) {
this.TargetImage = null;
this.TargetImage = IMG;
}

public void Reset() {
CTSValue = 1;
TMod = 4.0;
HueMod = 0.2;
SatMod = 0.2;
}

public int Colorref(int R, int G, int B) {
return (R | (G << 8) | (B << 16));
}

public Color Colorref(int Colour) {
int R = (Colour & 0x00ff0000) >> 16;
int G = (Colour & 0x0000ff00) >> 8;
int B = (Colour & 0x000000ff);
return new Color(R, G, B);
}

public int ColourSwap(int Colour) {
return ((Colour & 0xFF000000)|((Colour & 0xFF0000) >> 16)|(Colour & 0x00FF00)|((Colour & 0x0000FF) << 16));
}

public Color ColourSwap(Color Colour) {
return new Color(ColourSwap(Colour.getRGB()));
}

public int GetColourToleranceSpeed() {
return this.CTSValue;
}

void SetColourToleranceSpeed(int Value) {
CTSValue = Value >= -1 && Value <= 3 ? Value : 1;
}

void GetSpeed2Modifiers(Double HueMod, Double SatMod) {
HueMod = this.HueMod;
SatMod = this.SatMod;
}

void SetSpeed2Modifiers(double HueMod, double SatMod) {
this.HueMod = HueMod;
this.SatMod = SatMod;
}

double GetSpeed3Modifier() {
return TMod;
}

void SetSpeed3Modifier(double TMod) {
this.TMod = TMod;
}

boolean SimilarColours(Color FirstColour, Color SecondColour, int Tolerance) {
switch (CTSValue) {
case -1:
return CTSN(FirstColour, SecondColour);
case 0:
return CTS0(FirstColour, SecondColour, Tolerance);
case 1:
return CTS1(FirstColour, SecondColour, Tolerance);
case 2:
return CTS2(FirstColour, SecondColour, Tolerance);
case 3:
return CTS3(FirstColour, SecondColour, Tolerance);
default:
return CTS1(FirstColour, SecondColour, Tolerance);
}
}

private boolean CTSN(Color FirstCol, Color SecondCol) {
return (FirstCol.getRed() == SecondCol.getRed() && FirstCol.getGreen() == SecondCol.getGreen() && FirstCol.getBlue() == SecondCol.getBlue());
}

private boolean CTS0(Color FirstCol, Color SecondCol, int Tol) {
return Math.abs(FirstCol.getRed() - SecondCol.getRed()) <= Tol && Math.abs(FirstCol.getGreen() - SecondCol.getGreen()) <= Tol && Math.abs(FirstCol.getBlue() - SecondCol.getBlue()) <= Tol;
}

private boolean CTS1(Color FirstCol, Color SecondCol, int Tol) {
return ((FirstCol.getRed() - SecondCol.getRed())*(FirstCol.getRed() - SecondCol.getRed()) + (FirstCol.getGreen() - SecondCol.getGreen())*(FirstCol.getGreen() - SecondCol.getGreen()) + (FirstCol.getBlue() - SecondCol.getBlue())*(FirstCol.getBlue() - SecondCol.getBlue())) <= (Tol * Tol);
}

private boolean CTS2(Color FirstCol, Color SecondCol, int Tol) {
HSL HFirstCol = new HSL();
HSL HSecondCol = new HSL();

if (FirstCol.getRGB() != 0) {
HFirstCol = ColourSpace.getInstance().Hsl(FirstCol);
}

if (SecondCol.getRGB() != 0) {
HSecondCol = ColourSpace.getInstance().Hsl(SecondCol);
}

return (Math.abs(HSecondCol.Hue - HFirstCol.Hue) <= (Tol * HueMod)) && (Math.abs(HSecondCol.Sat - HFirstCol.Sat) <= (Tol * SatMod));
}

private boolean CTS3(Color FirstCol, Color SecondCol, int Tol) {
LAB LabFirstCol = new LAB(), LabSecondCol = new LAB();
if (FirstCol.getRGB() != 0) {
LabFirstCol = ColourSpace.getInstance().Lab(ColourSpace.getInstance().XYZ(FirstCol));
}

if (SecondCol.getRGB() != 0) {
LabSecondCol = ColourSpace.getInstance().Lab(ColourSpace.getInstance().XYZ(SecondCol));
}

double L = (LabSecondCol.L - LabFirstCol.L);
double A = (LabSecondCol.A - LabFirstCol.A);
double B = (LabSecondCol.B - LabFirstCol.B);

return ((L * L) + (A * A) + (B * B)) <= Math.ceil(Math.sqrt(Tol * TMod));
}

public int CountColour(Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = this.CTSValue;
SetColourToleranceSpeed(-1);
int Result = CountColourTolerance(Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public int CountColourTolerance(Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
int Result = 0;

for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(ColourSwap(Colour), new Color(TargetImage.getRGB(J, I)), Tolerance)) {
++Result;
}
}
}

return Result;
}

public boolean FindColour(Point P, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColourTolerance(P, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColours(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
SetColourToleranceSpeed(-1);
boolean Result = FindColoursTolerance(Points, Colour, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

public boolean FindColourTolerance(Point P, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {

for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), ColourSwap(Colour), Tolerance)) {
P.setLocation(J, I);
return true;
}
}
}
return false;
}

public boolean FindColoursTolerance(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
for (int I = Y1; I < Y2; ++I) {
for (int J = X1; J < X2; ++J) {
if (SimilarColours(new Color(TargetImage.getRGB(J, I)), ColourSwap(Colour), Tolerance)) {
Points.add(new Point(J, I));
}
}
}
return (!Points.isEmpty());
}

public boolean FindImage(BufferedImage ImageToFind, Point P) {
return FindImageIn(ImageToFind, P, 0, 0, TargetImage.getWidth(), TargetImage.getHeight());
}

public boolean FindImageIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2) {
int TemporaryCTS = CTSValue;
boolean Result = FindImageToleranceIn(ImageToFind, P, X1, Y1, X2, Y2, 0);
SetColourToleranceSpeed(TemporaryCTS);
return Result;
}

boolean FindImageToleranceIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2, int Tolerance) {
int dX = (X2 - X1) - (ImageToFind.getWidth() - 1);
int dY = (Y2 - Y1) - (ImageToFind.getHeight() - 1);

for (int I = 0; I < dY; ++I) {
for (int J = 0; J < dX; ++J) {
Skip:
for (int YY = 0; YY < ImageToFind.getHeight(); ++YY) {
for (int XX = 0; XX < ImageToFind.getWidth(); ++XX) {
if (ImageToFind.getRGB(XX, YY) != 0) {
if (!SimilarColours(new Color(ImageToFind.getRGB(XX, YY)), new Color(TargetImage.getRGB(XX + J, YY + I)), Tolerance)) {
++J;
break Skip; //Java doesn't have goto :S
}
}
}
}

P.setLocation(J + X1, I + Y1);
return true;
}
}

P.setLocation(-1, -1);
return false;
}
}



The result of testing it:

package imagefinding;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Main {

public static void main(String[] args) throws AWTException, IOException {
ImageHandler Handler = new ImageHandler();
BufferedImage TargetImage = Handler.Screenshot(0, 0, 765, 553);

Point P = new Point(-1, -1);
ImageFinder Finder = new ImageFinder();
Finder.SetTargetImage(TargetImage);
Finder.SetColourToleranceSpeed(1);

if (Finder.FindColourTolerance(P, new Color(7912686), 0, 0, TargetImage.getWidth(), TargetImage.getHeight(), 10)) {
System.out.println(P);
Robot Miner = new Robot();
Miner.mouseMove(P.x, P.y);
}

ImageIO.write(TargetImage, "bmp", new File("C:/Users/Brandon/Desktop/Meh.bmp"));
}
}

Which gives the exact same result as:


Procedure PrintRGB(Color: Integer);
var
R, G, B: Integer;
begin
ColorToRGB(Color, R, G, B);
Writeln('R: ' + ToStr(R) + ', G: ' + ToStr(G) + ', B: ' + ToStr(B));
end;


var
BMP, X, Y, W, H: Integer;

begin
//BMP := LoadBitmap('C:/Users/Brandon/Desktop/Meh.bmp');
//SetTargetBitmap(BMP);
GetClientDimensions(W, H);
FindColorTolerance(X, Y, 7912686, 0, 0, W - 1, H - 1, 10);
Writeln('Found at: ' + ToStr(Point(X, Y)));
PrintRGB(7912686);

MoveMouse(X, Y);
end.

I've tested it with many different colours.. Both scripts move the mouse to the exact same position for CTSN, CTS0, CTS1. I did not Test CTS2 or CTS3.

Good luck on your endeavors. I really hope you get it working. I'm not sure why you got that error because I don't get it. It's probably because of your Try-Catch. Should be:


BufferedImage TargetImage = null; //Initialize it to null.

try {
TargetImage = .......;
} catch(Exception E) {
}


Thanks! Worked great, but one problem, how do I use it with more then one file? When I try to extend it to Methods it gives me the error:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
Exception IOException is not compatible with throws clause in Methods.main(String[])
Exception AWTException is not compatible with throws clause in Methods.main(String[])

at main.Main.main(Main.java:59)

Brandon

2013-04-20 17:34:52

What in the world? Don't do that. You do not want to "Override/Overload" main..

That'll lead you down the wrong road. Here's the rules to any programming language.

There can only be ONE entry point. Usually called Main. In ASM, you can choose the entry point (or rename it) but again, it must only have ONE!

You are trying to extend a class that already contains a main and have the child class also contain main. This is not allowed.

Solutions:

Copy whatever was in my main to yours.
Copy whatever was in your main to mine.

Moral of the story, TWO mains is a very bad idea. I don't know what you mean by using more than one file. If you mean the ImageIO, that line is redundant. I only have that line so I can see what Java is taking a screenshot of. That line isn't needed at all but it gives you a nice idea of what your computer is seeing and what image it is searching.

rj

2013-04-20 17:40:13

From: Brandon
What in the world? Don't do that. You do not want to "Override/Overload" main..

That'll lead you down the wrong road. Here's the rules to any programming language.

There can only be ONE entry point. Usually called Main. In ASM, you can choose the entry point (or rename it) but again, it must only have ONE!

You are trying to extend a class that already contains a main and have the child class also contain main. This is not allowed.

Solutions:

Copy whatever was in my main to yours.
Copy whatever was in your main to mine.

Moral of the story, TWO mains is a very bad idea. I don't know what you mean by using more than one file. If you mean the ImageIO, that line is redundant. I only have that line so I can see what Java is taking a screenshot of. That line isn't needed at all but it gives you a nice idea of what your computer is seeing and what image it is searching.


I want to include the file that will have all my methods like inv full on spell book on inv


Brandon

2013-04-20 17:57:51

From: Officer Barbrady
I want to include the file that will have all my methods like inv full on spell book on inv




I know that. And according to your OP, your "Methods.java" contains "main". Remove main from "Methods.java" or else you cannot inherit from it.

Secondly, Inheritance specifies an "Is-A" relationship. Not a "Has-A".

Example:


public class Car extends Vehicle { //A car "Is a" vehicle.
}

public class Car extends Vehicle { //A car "Is a" vehicle.
private Door D = new Door(); //A car "Has a" door.
}

That is the difference between having vs. is Typeof. A car is a type of vehicle. At the same time, a car has a door. A car will not extend door because a car is not a door.

Use inheritance wisely. Rather than extending methods, you use a "Has-a" relationship and do something like:


main() {
Methods M = new Methods(); //Creates a new Instance. Aka Has-A relationship. Main has an instance of methods.
M.OpenSpellBook();
M.OpenInventory();
}


Anyway, like I said before that, if you want to extend Methods then remove main from Methods if you plan to use the main I gave you. Else, copy my main into your Methods main and delete my main.

I'm really not sure if I'm the right person to explain it to you as I usually explain things in a very difficult way and if so, I'm sorry. But I hope you get the idea.

rj

2013-04-20 18:05:05

From: Brandon
I know that. And according to your OP, your "Methods.java" contains "main". Remove main from "Methods.java" or else you cannot inherit from it.

Secondly, Inheritance specifies an "Is-A" relationship. Not a "Has-A".

Example:


public class Car extends Vehicle { //A car "Is a" vehicle.
}

public class Car extends Vehicle { //A car "Is a" vehicle.
private Door D = new Door(); //A car "Has a" door.
}

That is the difference between having vs. is Typeof. A car is a type of vehicle. At the same time, a car has a door. A car will not extend door because a car is not a door.

Use inheritance wisely. Rather than extending methods, you use a "Has-a" relationship and do something like:


main() {
Methods M = new Methods(); //Creates a new Instance. Aka Has-A relationship. Main has an instance of methods.
M.OpenSpellBook();
M.OpenInventory();
}


Anyway, like I said before that, if you want to extend Methods then remove main from Methods if you plan to use the main I gave you. Else, copy my main into your Methods main and delete my main.

Ok thanks, and how do I make public booleans return values for stuff like OnMagic:

public boolean OnMagic( ) {

return true;
}

I want it to count the colors in the area of the spellbook, how do I get these coords since I can't "select" a client
When I try to use the code above it wants me to do this stuff:

throws AWTException, IOException,

But I don't know how, and I don't want to do this number:

ImageHandler Handler = new ImageHandler();
BufferedImage TargetImage = Handler.Screenshot(0, 0, 765, 553);

Point P = new Point(-1, -1);
ImageFinder Finder = new ImageFinder();
Finder.SetTargetImage(TargetImage);
Finder.SetColourToleranceSpeed(1);
Random Sleep = new Random();
int randomInt = Sleep.nextInt(250);
Methods M = new Methods();

if (Finder.FindColourTolerance(P, new Color(2911372), 250, 250, TargetImage.getWidth(), TargetImage.getHeight(), 10)) {
System.out.println(P);
return true;

}

everytime I want to do a public boolean, is there a way I can like declare it globally? Also is there any other wait I can use besides thread.sleep? It is annoying to use InterruptedException and I don't know how to add that to a public void for my left click procedure:

public static void Left_Click( ) {
try {
Robot click = new Robot();
click.mousePress(InputEvent.BUTTON1_MASK);
click.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (AWTException j) {
System.out.println("Could not click");
j.printStackTrace();
}

}

(I want to add a delay between to make it more human like)

Sin

2013-04-20 18:08:23

As far as I know, thread.sleep in a try catch is the most effective.

rj

2013-04-20 18:10:11

From: Sin
As far as I know, thread.sleep in a try catch is the most effective.


Should I make a seperate procedure to Sleep instead of having java play ball every time because I'm going to be using it alot

public static void SleepLittle ( )throws InterruptedException {		
Random sleep = new Random();
int randomInt = sleep.nextInt(250);
Thread.sleep((100)+randomInt);
}

Nebula

2013-04-20 18:30:10

Why was I mentioned here?

Sin

2013-04-20 18:48:13

From: Officer Barbrady
Should I make a seperate procedure to Sleep instead of having java play ball every time because I'm going to be using it alot

public static void SleepLittle ( )throws InterruptedException {		
Random sleep = new Random();
int randomInt = sleep.nextInt(250);
Thread.sleep((100)+randomInt);
}


public void sleepEx(int n)
{
try
{
thread.sleep(n);
}
catch (Exception ex)
{
}
}

Brandon

2013-04-20 18:54:18

From: Officer Barbrady
Should I make a seperate procedure to Sleep instead of having java play ball every time because I'm going to be using it alot



There is a pattern in Object-Oriented languages called the singleton pattern. With this pattern, only one instance of a class is allowed to exist ever! Since there are no such things as global variables in java, you can create a singleton class that holds a global variable such that any class can access that variable and change it. Other classes will see that change as well. It can also make things easier for example:

This singleton class cannot be instantiated. It's a wrapper around the other classes you wrote as well as the functions you have. See the usage below..

Globals.java:

package imagefinding;

import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class Globals {
private static int X, Y, Width, Height;
private static Robot robot = null;
private static Globals instance = new Globals();
private static ImageHandler Handler = new ImageHandler();
private static ImageFinder Finder = new ImageFinder();
private static BufferedImage TargetImage = null;

private Globals() {
try {
robot = new Robot();
} catch (Exception Ex) {
}
}

public static Globals getInstance() {
return instance;
}

public static void MoveMouse(int X, int Y) {
robot.mouseMove(X, Y);
}

public static void ClickMouse(int X, int Y, boolean LeftClick) {
MoveMouse(X, Y);
robot.mousePress(LeftClick ? InputEvent.BUTTON1_MASK : InputEvent.BUTTON3_MASK);
robot.mouseRelease(LeftClick ? InputEvent.BUTTON1_MASK : InputEvent.BUTTON3_MASK);
}

public static void DragMouse(int FromX, int FromY, int ToX, int ToY) {
MoveMouse(FromX, FromY);
robot.mousePress(InputEvent.BUTTON1_MASK);
MoveMouse(ToX, ToY);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}

public static void Sleep(int HowLong) {
try {
Thread.sleep(HowLong);
} catch (Exception Ex) {
}
}

public static void SleepRandomRange(int Min, int Max) {
Sleep(Min + (int)(Math.random() * ((Max - Min) + 1)));
}

public static BufferedImage GetTarget() {
return TargetImage;
}

public static void Target(int X, int Y, int Width, int Height) {
try {
TargetImage = null;
TargetImage = Handler.Screenshot(X, Y, Width, Height);
Globals.X = X;
Globals.Y = Y;
Globals.Width = Width;
Globals.Height = Height;
Finder.SetTargetImage(TargetImage);
} catch (Exception Ex) {
}
}

public static void SetToleranceSpeed(int Value) {
Finder.SetColourToleranceSpeed(Value);
}

public static void ResetToleranceSpeed() {
Finder.Reset();
}

public static int GetColourToleranceSpeed() {
return Finder.GetColourToleranceSpeed();
}

public static boolean SimilarColours(Color FirstColour, Color SecondColour, int Tolerance) {
Target(X, Y, Width, Height);
return Finder.SimilarColours(FirstColour, SecondColour, Tolerance);
}

public static int CountColour(Color Colour, int X1, int Y1, int X2, int Y2) {
Target(X, Y, Width, Height);
return Finder.CountColour(Colour, X1, Y1, X2, Y2);
}

public static int CountColourTolerance(Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
return Finder.CountColourTolerance(Colour, X1, Y1, X2, Y2, Tolerance);
}

public static boolean FindColour(Point P, Color Colour, int X1, int Y1, int X2, int Y2) {
Target(X, Y, Width, Height);
return Finder.FindColour(P, Colour, X1, Y1, X2, Y2);
}

public static boolean FindColours(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2) {
Target(X, Y, Width, Height);
return Finder.FindColours(Points, Colour, X1, Y1, X2, Y2);
}

public static boolean FindColourTolerance(Point P, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
Target(X, Y, Width, Height);
return Finder.FindColourTolerance(P, Colour, X1, Y1, X2, Y2, Tolerance);
}

public static boolean FindColoursTolerance(ArrayList<Point> Points, Color Colour, int X1, int Y1, int X2, int Y2, int Tolerance) {
Target(X, Y, Width, Height);
return Finder.FindColoursTolerance(Points, Colour, X1, Y1, X2, Y2, Tolerance);
}

public static boolean FindImage(BufferedImage ImageToFind, Point P) {
Target(X, Y, Width, Height);
return Finder.FindImage(ImageToFind, P);
}

public static boolean FindImageIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2) {
Target(X, Y, Width, Height);
return Finder.FindImageIn(ImageToFind, P, X1, Y1, X2, Y2);
}

public static boolean FindImageToleranceIn(BufferedImage ImageToFind, Point P, int X1, int Y1, int X2, int Y2, int Tolerance) {
Target(X, Y, Width, Height);
return Finder.FindImageToleranceIn(ImageToFind, P, X1, Y1, X2, Y2, Tolerance);
}
}

Notice that everything is static in this class.. That's because it is a singleton. Also note that the constructor is private. These features are how you recognize a singleton.

Anyway, the usage would then be:


package imagefinding;

import java.awt.*;

public class ImageFinding {
public static void main(String[] args) {

Point P = new Point();
Globals.Target(0, 0, 765, 553);

if (Globals.FindColour(P, Color.blue, 0, 0, 700, 500)) {
Globals.MoveMouse(P.x, P.y);
}

if (Globals.FindColourTolerance(P, Color.blue, 0, 0, 765, 553, 10)) {
Globals.ClickMouse(P.x, P.y, true);
}

/*if (Globals.FindSpellBook()) {
Globals.MoveMouse(P.x, P.y);
}*/

Globals.Sleep(5000);
Globals.MoveMouse(500, 500);
Globals.SleepRandomRange(500, 1000);

//etc..
}
}


In the above, you should notice that I never did:


Globals G = new Globals(); //The reason is because it is a singleton and singletons instantiate themselves. Thus you cannot do this!

To access variables of a singleton or functions, you do: ClassName.Whatever_You_Want_To_Access.

In the above, we did Globals.Whatever_You_Want_To_Access. You should always remember that since it is a singleton, every class only uses that one instance. So no matter what, you can't have multiple instances of a singleton class. If a class wants its own instance, it must not use a singleton. You can easily change the singleton above to an instanced class by removing the private from the constructor and removing static from everything.

I believe the singleton is good here because you'll only be using one mouse for now, you seem to want global variables and you only have one client. We only need one Robot as well. I don't see anyway possible that you can use two Robots moving the mouse at the same time for one client. After all, one screen = one client = one instance = singleton. If you made something like RSBot where it can have multiple tabs, a singleton is NOT what you want.


Sorry Nebula. I thought you would be able to explain it easier than I, but Sin did the job :)

rj

2013-04-20 19:32:06

@Brandon Thanks! Can't rep twice in 24 hours haha this will defiantly get me started but unfortunately for you there will be no end to my questions for a long time(how to make GUI remember a number, how to load any .jar, how to muiltithread, how to use g.drawstring on GUI, how to make my own imports so I don't have to keep using the same files, how to use JCombo, how to make the mousemove instead of jump, how to add randomness to mouse, + additional errors I will be getting from these questions)

Only ones I have on top of my head :d

NKN

2013-04-20 19:40:28

Sorry to derail, but Brandon.


If I have an applet(Runescape), and I add it to a JPane, and added a JMenuBar to the frame.

When I open the menu, the choices go behind the applet. I thought lightweight components and heavyweight were like, fixed. D:




/offtopic


RJJ, just shoot me a PM over Skype if you need something tho. ;)

Brandon

2013-04-20 20:01:26

From: NKN
Sorry to derail, but Brandon.


If I have an applet(Runescape), and I add it to a JPane, and added a JMenuBar to the frame.

When I open the menu, the choices go behind the applet. I thought lightweight components and heavyweight were like, fixed. D:




/offtopic


RJJ, just shoot me a PM over Skype if you need something tho. ;)



Ahh mixing of heavy and light components used to be frowned upon before JDK 7: http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html

I believe that is the same problem you're having. Either you use a glass-pane or you do like that article does. Smart 8.1 also had this problem with the combobox appearing behind the applet until the applet is finished loading. Why not add the Menu to the frame itself?

I also had that problem once. I'll play around with it when I get home and see if I can add a Menu to my applet. When I do, I'll let you know how to fix it if that article doesn't help.

rj

2013-04-20 20:03:18

From: Brandon
Ahh mixing of heavy and light components used to be frowned upon before JDK 7: http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html

I believe that is the same problem you're having. Either you use a glass pane or you do like that article does. Smart 8.1 also had this problem with the combobox appearing behind the applet until the applet is finished loading.


On a scale of 1-10 how hard would it be to load a .jar in a applet?

Brandon

2013-04-20 20:18:49

Depends on the programmer's skill level. On average, I'd say its about a 3 if 10 is the hardest, 1 the easiest. Also depends on what you're loading. Not any jar can be loaded into an applet.

RS uses gamepack.jar. Using a classloader and passing the correct parameters, it can be done in two-three functions. To retrieve colours or draw on the canvas, you need to force the RS canvas to inherit from yours or replace it with yours. This can be done using xbootclasspath or injection.

rj

2013-04-20 20:19:59

From: Brandon
Depends on the programmer's skill level. On average, I'd say its about a 3 if 10 is the hardest, 1 the easiest. Also depends on what you're loading. Not any jar can be loaded into an applet.

RS uses gamepack.jar. Using a classloader and passing the correct parameters, it can be done in two-three functions. To retrieve colours or draw on the canvas, you need to force the RS canvas to inherit from yours or replace it with yours. This can be done using xbootclasspath or injection.


BTW how do I add that Globals.java? I get a ton of errors, abunch of stuff can't be resolved to a type

NKN

2013-04-20 20:21:58

From: Officer Barbrady
BTW how do I add that Globals.java? I get a ton of errors, abunch of stuff can't be resolved to a type


Add an applet?
I wrote a guide on making a loader, you can use that.

Brandon

2013-04-20 21:01:25

From: Officer Barbrady
BTW how do I add that Globals.java? I get a ton of errors, abunch of stuff can't be resolved to a type


Shouldn't have any errors unless your packages are messed again.

rj

2013-04-20 21:09:59

From: Brandon
Shouldn't have any errors unless your packages are messed again.


I don't think so:


Brandon

2013-04-20 21:30:15

From: Officer Barbrady
I don't think so..





import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

Add those to the Globals.java right after the package main;

I'm not sure why you're missing those :S. I was sure I had them in the code I posted? Anyway, add those and your problems will disappear. Hopefully.

rj

2013-04-20 21:31:52

From: Brandon

import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

Add those to the Globals.java right after the package main;

I'm not sure why you're missing those :S. I was sure I had them in the code I posted? Anyway, add those and your problems will disappear. Hopefully.


OOO I forgot the includes lol

Were are the include files located?

Brandon

2013-04-20 21:33:42

From: Officer Barbrady
OOO I forgot the includes lol

Were are the include files located?




Umm don't worry about the location of them. All you need to know is what to include (unless you're using JNI). In case you are curious, wherever your java jdk is installed, that's where the include files are. And yeah you forgot the includes lol. Usually the compiler should resolve missing includes for you. I know in netbeans, the shortcut to do this is Alt+Enter. I cannot remember for eclipse. I code in notepad++ most of the time and cmd to compile. If you can, find out how to resolve imports. Perhaps right-clicking on an underlined segment of code will give you options to add imports/fix imports.

Either way, add those imports and you'll be golden.

I gotta redownload eclipse :l

rj

2013-04-20 21:38:13

From: Brandon
Umm don't worry about the location of them. All you need to know is what to include (unless you're using JNI). In case you are curious, wherever your java jdk is installed, that's where the include files are. And yeah you forgot the includes lol. Usually the compiler should resolve missing includes for you. I know in netbeans, the shortcut to do this is Alt+Enter. I cannot remember for eclipse. I code in notepad++ most of the time and cmd to compile.

I gotta redownload eclipse :l


eclipse lets you know if your missing a import most of the time this time it didn't

Fox

2013-05-08 21:51:26

From: Officer Barbrady
On a scale of 1-10 how hard would it be to load a .jar in a applet?


Loading a .jar in a applet is easy. It's just a simple rsLoader.

rj

2013-05-08 22:03:34

From: Frostie
Loading a .jar in a applet is easy. It's just a simple rsLoader.


Yea, considering I have almost 0 Java knowledge loading a .jar into a applet and letting my scripts communicate with that applet would be easy.

Fox

2013-05-08 22:03:58

From: Officer Barbrady
Yea, considering I have almost 0 Java knowledge loading a .jar into a applet and letting my scripts communicate with that applet would be easy.


I'll post a code for you.

This isn't my work.
07.
import java.applet.Applet;
import java.applet.AppletContext;
import java.applet.AppletStub;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.swing.*;

/**
* @author Parnassian, Nissan Nut
*/
public class OldSchoolLoader extends JFrame implements AppletStub {

private static final long serialVersionUID = 0001;

private static final HashMap<String, String> params = new HashMap<String, String>();
final String baseLink = "http://oldschool70.runescape.com/";
private Applet loader;

public OldSchoolLoader() {
setTitle("Nissan Nut's Old School (2007) Runescape loader");
setSize(768, 530);
setVisible(true);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
try {
downloadFile(getUrl());
ClassLoader clientClassLoader = new URLClassLoader(
new URL[] { new File("Loader.jar").toURL() });
Class<?> clientClass = clientClassLoader.loadClass("client");
loader = (Applet) clientClass.newInstance();
loader.setStub(this);
loader.init();
loader.start();
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
add(loader);
} catch (Exception e) {
e.printStackTrace();
}
setVisible(true);
}

public void appletResize(int width, int height) {
}

public final URL getCodeBase() {
try {
return new URL(baseLink);
} catch (Exception e) {
return null;
}
}

public final URL getDocumentBase() {
try {
return new URL(baseLink);
} catch (Exception e) {
return null;
}
}

public final String getParameter(String name) {
return params.get(name);
}

public final AppletContext getAppletContext() {
return null;
}

public static void main(String[] args) {
try {
new OldSchoolLoader();
} catch (Exception e) {
throw new RuntimeException(e);
}
}



void addParam(final String str1) {
addParam(str1, "");
}

void addParam(final String str1, final String str2) {
params.put(str1, str2);
}

String getUrl() throws Exception {
return baseLink + params.get("archive");
}

void downloadFile(final String url) {
try {
BufferedInputStream in = new java.io.BufferedInputStream(new URL(
url).openStream());
FileOutputStream fos = new java.io.FileOutputStream("Loader.jar");
BufferedOutputStream bout = new BufferedOutputStream(fos, 1024);
byte[] data = new byte[1024];
int x = 0;
while ((x = in.read(data, 0, 1024)) >= 0) {
bout.write(data, 0, x);
}
bout.close();
in.close();
} catch (Exception e) {
return;
}
}

}

But some quick tips
Use the final modifier.
I'll highlight where you should use them.

public class Main extends Methods {
[COLOR="#FFFF00"] public static final[/COLOR] int n;
[COLOR="#FFFF00"] public static final int[/COLOR] x,y;
[COLOR="#FFFF00"]public final [/COLOR]boolean InvFull = false;
[COLOR="#FFFF00"] public static final [/COLOR]Color j = new Color(150, 114, 56);



public static void main(String []args) {

[COLOR="#FFFF00"]final [/COLOR]ImageHandler Handler = new ImageHandler();
try {
[COLOR="#FFFF00"] final[/COLOR] BufferedImage TargetImage = Handler.Screenshot(0, 0, 765, 553);
} catch (AWTException e) {
System.out.println("Error when taking screenshot");
e.printStackTrace();
}

int X = -1;
int Y = -1;
[COLOR="#FFFF00"]final [/COLOR]ImageFinder Finder = new ImageFinder();
if (Finder.FindColourTolerance(X, Y, j, 0, 0, 765, 553, 10)) {
try {
[COLOR="#FFFF00"]final[/COLOR] Robot Miner = new Robot();
Miner.mouseMove(X,Y);
Left_Click( );
} catch (AWTException j) {
System.out.println("Could not start J-Robot");
j.printStackTrace();
}
}


}

}

If you need help with anything with java just shoot me a pm.