Compare two screenshots doesn't work correctly-java - java

i am trying to make two screenshots with 6 seconds difference, to see if there is some changes on the website.
But my code says me that the screenshots are always different, even if i test it without any changing on the screen.
what am i doing wrong?
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension screensize = toolkit.getScreenSize();
Rectangle rectangle = new Rectangle(0,0,screensize.width,screensize.height);
Robot robot = new Robot();
BufferedImage image1 = robot.createScreenCapture(rectangle);
System.out.println("screenshot "+i+"");
Thread.sleep(6000);
BufferedImage image2 = robot.createScreenCapture(rectangle);
System.out.println("screenshot "+(i+10)+"");
int x1 = image1.getWidth();
int x2 = image2.getWidth();
if ( x1 != x2 ) {
System.out.println( "Widths are different: " + x1 + " != " + x2 );
return;
}
int y1 = image1.getHeight();
int y2 = image2.getHeight();
if ( y1 != y2 ) {
System.out.println( "Heights are different: " + y1 + " != " + y2 );
return;
}
for ( int x = 0; x < x1; x++ ) {
for ( int y = 0; y < y1; y++ ){
int p1 = image1.getRGB( x, y );
int p2 = image2.getRGB( x, y );
if ( p1 != p2 ) {
System.out.println("Pixel is different at x/y " + x + "/" + y + ": " + p1 + " != " + p2 );
return;
}
}
}
System.out.println( "Images are identical" );

I tried your code and my pixel is different because of a blinking cursor in Eclipse Console.
Then I had a problem with an animated icon (process explorer in task bar)
Finally it said Image identical.
Note : Mouse isn't part of the thing :
Creates an image containing pixels read from the screen. This image does not include the mouse cursor.

Related

Attempting to return a float[] from a method in Java

I'm writing a game and working on collisions. Currently, I'm trying to use the tileCollision function to return a 1-dimensional array containing 2 numbers; the coordinates of the corner. (represented in the program by cX and cY)
I expected this to run smoothly: that is, to return {-999, -999} if it wasn't colliding, and to return a valid set of coordinates otherwise. Unfortunately, IntelliJ tells me that the goodCX and goodCY variables "might not have been initialised" which I do not know how to solve. Running the program gives me the same error.
The Tile class can be treated as a class containing an X value, a Y value, and a texture. The t.texture.width & t.texture.height should be set to 50 to make it simpler to understand. Entity can be assumed as a class containing variables named x, y, vx, vy, and a "texture" whose dimensions should be 20x20. I use Java with the Processing 3 library to render my code and am happy to provide extra info if needed.
The main problem is less with those rather than the "might not have been initialised" problem, though.
Please, go easy on me, and if possible, don't use anything wildly outside the realm of what is demonstrated in my code. I am an amateur programmer, and while I have been programming for a while, am not exactly professional.
Here's my code:
public float[] tileCollision(Tile t)
{
boolean isCollide = false;
float tX = t.eX;
float tX2 = t.eX + t.texture.width;
float tY = t.eY;
float tY2 = t.eY + t.texture.height;
float[] cX = new float[]{this.x + this.vx, this.x + this.texture.width + this.vx};
float[] cY = new float[]{this.y + this.vy, this.y + this.texture.height + this.vy};
float[] bad = new float[]{-999, -999};
float goodCX, goodCY;
System.out.println("\nCollisions Testing Names:");
System.out.println(this);
System.out.println(t);
for(int i = 0; i < 2; i ++)
{
for(int i_ = 0; i_ < 2; i_ ++)
{
System.out.println("\nCollisions Testing:");
System.out.println("Entity X: " + cX[i]);
System.out.println("Entity Y: " + cY[i_]);
System.out.println("Tile Xs: " + tX + ", " + tX2);
System.out.println("Tile Ys: " + tY + ", " + tY2);
if( ( (tX <= cX[i]) && (cX[i] <= tX2) ) && ( (tY <= cY[i_]) && (cY[i_] <= tY2) ) )
{
isCollide = true;
goodCX = cX[i];
goodCY = cY[i_];
}
}
}
System.out.println("Am I colliding?\n>>> " + isCollide);
if(isCollide)
{
return new float[]{goodCX, goodCY};
}
else { return(bad); }
}
The problem resides in the fact that you only assign (and first-assign, and hence, initialize) your goodCX and goodCY variables inside a complex if nested inside your for loops. Then, if(isCollide), you will attempt to return them, but there is no way the compiler can infer any kind of connection between the complex if condition you have, and the isCollide condition, so you may be returning unassigned references.
To resolve this, simply make a default initialization of your float references at the top, as follows:
float goodCX = 0.0;
float goodCY = 0.0;
If the collision check do not evaluate true GoodCX and GoodCY will never be initialized. You will have problems trying to return "new float[]{goodCX, goodCY}". Try initializing your GoodCX and GoodCY with -999. You will also be able to simplify your code with that:
public float[] tileCollision(Tile t)
{
boolean isCollide = false;
float tX = t.eX;
float tX2 = t.eX + t.texture.width;
float tY = t.eY;
float tY2 = t.eY + t.texture.height;
float[] cX = new float[]{this.x + this.vx, this.x + this.texture.width + this.vx};
float[] cY = new float[]{this.y + this.vy, this.y + this.texture.height + this.vy};
float goodCX = -999;
float goodCY = -999;
System.out.println("\nCollisions Testing Names:");
System.out.println(this);
System.out.println(t);
for(int i = 0; i < 2; i ++)
{
for(int i_ = 0; i_ < 2; i_ ++)
{
System.out.println("\nCollisions Testing:");
System.out.println("Entity X: " + cX[i]);
System.out.println("Entity Y: " + cY[i_]);
System.out.println("Tile Xs: " + tX + ", " + tX2);
System.out.println("Tile Ys: " + tY + ", " + tY2);
if( ( (tX <= cX[i]) && (cX[i] <= tX2) ) && ( (tY <= cY[i_]) && (cY[i_] <= tY2) ) )
{
goodCX = cX[i];
goodCY = cY[i_];
}
}
}
return new float[]{goodCX, goodCY};
}
Intellij is giving you that response because the variables are declared but not initialized. You need to define them with some default state or modify the code that follows to ensure they're initialized.

Converting monochrome image to minimum number of 2d shapes

Basically, what I need to do is take a 2d array of bitflags and produce a list of 2d rectangles to fill the entire area with the minimum number of total shapes required to perfectly fill the space. I am doing this to convert a 2d top-down monochrome of a map into 2d rectangle shapes which perfectly represent the passed in image which will be used to generate a platform in a 3d world. I need to minimize the total number of shapes used, because each shape will represent a separate object, and flooding it with 1 unit sized squares for each pixel would be highly inefficient for that engine.
So far I have read in the image, processed it, and filled a two dimensional array of booleans which tells me if the pixel should be filled or unfilled, but I am unsure of the most efficient approach of continuing.
Here is what I have so far, as reference, if you aren't following:
public static void main(String[] args) {
File file = new File(args[0]);
BufferedImage bi = null;
try {
bi = ImageIO.read(file);
} catch (IOException ex) {
Logger.global.log(Level.SEVERE, null, ex);
}
if (bi != null) {
int[] rgb = bi.getRGB(0, 0, bi.getWidth(), bi.getHeight(), new int[bi.getWidth() * bi.getHeight()], 0, bi.getWidth());
Origin origin = new Origin(bi.getWidth() / 2, bi.getHeight() / 2);
boolean[][] flags = new boolean[bi.getWidth()][bi.getHeight()];
for (int y = 0; y < bi.getHeight(); y++) {
for (int x = 0; x < bi.getWidth(); x++) {
int index = y * bi.getWidth() + x;
int color = rgb[index];
int type = color == Color.WHITE.getRGB() ? 1 : (color == Color.RED.getRGB() ? 2 : 0);
if (type == 2) {
origin = new Origin(x, y);
}
flags[x][y] = type != 1;
}
}
List<Rectangle> list = new ArrayList();
//Fill list with rectangles
}
}
White represents no land. Black or Red represents land. The check for the red pixel marks the origin position of map, which was just for convenience and the rectangles will be offset by the origin position if it is found.
Edit: The processing script does not need to be fast, the produced list of rectangles will be dumped and that will be what will be imported and used later, so the processing of the image does not need to be particularly optimized, it doesn't make a difference.
I also just realized that expecting a 'perfect' solution is expecting too much, since this would qualify as a 'knapsack problem' of the multidimensionally constrained variety, if I am expecting exactly the fewest number of rectangles, so simply an algorithm that produces a minimal number of rectangles will suffice.
Here is a reference image for completion:
Edit 2: It doesn't look like this is such an easy thing to answer given no feedback yet, but I have started making progress, but I am sure I am missing something that would vastly reduce the number of rectangles. Here is the updated progress:
static int mapWidth;
static int mapHeight;
public static void main(String[] args) {
File file = new File(args[0]);
BufferedImage bi = null;
System.out.println("Reading image...");
try {
bi = ImageIO.read(file);
} catch (IOException ex) {
Logger.global.log(Level.SEVERE, null, ex);
}
if (bi != null) {
System.out.println("Complete!");
System.out.println("Interpreting image...");
mapWidth = bi.getWidth();
mapHeight = bi.getHeight();;
int[] rgb = bi.getRGB(0, 0, mapWidth, mapHeight, new int[mapWidth * mapHeight], 0, mapWidth);
Origin origin = new Origin(mapWidth / 2, mapHeight / 2);
boolean[][] flags = new boolean[mapWidth][mapHeight];
for (int y = 0; y < mapHeight; y++) {
for (int x = 0; x < mapWidth; x++) {
int index = y * mapWidth + x;
int color = rgb[index];
int type = color == Color.WHITE.getRGB() ? 1 : (color == Color.RED.getRGB() ? 2 : 0);
if (type == 2) {
origin = new Origin(x, y);
}
flags[x][y] = type != 1;
}
}
System.out.println("Complete!");
System.out.println("Processing...");
//Get Rectangles to fill space...
List<Rectangle> rectangles = getRectangles(flags, origin);
System.out.println("Complete!");
float rectangleCount = rectangles.size();
float totalCount = mapHeight * mapWidth;
System.out.println("Total units: " + (int)totalCount);
System.out.println("Total rectangles: " + (int)rectangleCount);
System.out.println("Rectangle reduction factor: " + ((1 - rectangleCount / totalCount) * 100.0) + "%");
System.out.println("Dumping data...");
try {
file = new File(file.getParentFile(), file.getName() + "_Rectangle_Data.txt");
if(file.exists()){
file.delete();
}
file.createNewFile();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
for(Rectangle rect: rectangles){
bw.write(rect.x + "," + rect.y + "," + rect.width + ","+ rect.height + "\n");
}
bw.flush();
bw.close();
} catch (Exception ex) {
Logger.global.log(Level.SEVERE, null, ex);
}
System.out.println("Complete!");
}else{
System.out.println("Error!");
}
}
public static void clearRange(boolean[][] flags, int xOff, int yOff, int width, int height) {
for (int y = yOff; y < yOff + height; y++) {
for (int x = xOff; x < xOff + width; x++) {
flags[x][y] = false;
}
}
}
public static boolean checkIfFilled(boolean[][] flags, int xOff, int yOff, int width, int height) {
for (int y = yOff; y < yOff + height; y++) {
for (int x = xOff; x < xOff + width; x++) {
if (!flags[x][y]) {
return false;
}
}
}
return true;
}
public static List<Rectangle> getRectangles(boolean[][] flags, Origin origin) {
List<Rectangle> rectangles = new ArrayList();
for (int y = 0; y < mapHeight; y++) {
for (int x = 0; x < mapWidth; x++) {
if (flags[x][y]) {
int maxWidth = 1;
int maxHeight = 1;
Loop:
//The search size limited to 400x400 so it will complete some time this century.
for (int w = Math.min(400, mapWidth - x); w > 1; w--) {
for (int h = Math.min(400, mapHeight - y); h > 1; h--) {
if (w * h > maxWidth * maxHeight) {
if (checkIfFilled(flags, x, y, w, h)) {
maxWidth = w;
maxHeight = h;
break Loop;
}
}
}
}
//Search also in the opposite direction
Loop:
for (int h = Math.min(400, mapHeight - y); h > 1; h--) {
for (int w = Math.min(400, mapWidth - x); w > 1; w--) {
if (w * h > maxWidth * maxHeight) {
if (checkIfFilled(flags, x, y, w, h)) {
maxWidth = w;
maxHeight = h;
break Loop;
}
}
}
}
rectangles.add(new Rectangle(x - origin.x, y - origin.y, maxWidth, maxHeight));
clearRange(flags, x, y, maxWidth, maxHeight);
}
}
}
return rectangles;
}
My current code's search for larger rectangles is limited to 400x400 to speed up testing, and outputs 17,979 rectangles, which is a 99.9058% total reduction of rectangles if I treated each pixel as a 1x1 square(19,095,720 pixels). So far so good.

Error in plotting graphs with discontinuities in Java?

I am trying to create a graphing calculator applet using Java. I am having trouble plotting graphs that contain discontinuities such as holes and asymptotes. Here is the code I have for graphs with asymptotes so far:
for (int i = 1; i < size; i++) {
x1 = round((startX + ((graphdata.get(i - 1)).getX()) * scale));
y1 = round((startY - ((graphdata.get(i - 1)).getY()) * scale));
x2 = round((startX + ((graphdata.get(i)).getX()) * scale));
y2 = round((startY - ((graphdata.get(i)).getY()) * scale));
for (int j = 0; j < VertAsympArray.size(); j++)
{
if(Math.abs((round(graphdata.get(i).getX(),3)) - (VertAsympArray.get(j))) > epsilon && Math.abs((round(graphdata.get(i-1).getX(),3)) - (VertAsympArray.get(j))) > epsilon ){
System.out.println("Drawing points : x1 : " + round(graphdata.get(i-1).getX(),3) + ", y1 :" + round(graphdata.get(i-1).getY(),3) + "; x2 : " + round(graphdata.get(i).getX(),3) + ", y2 : " + round(graphdata.get(i).getY(),3) );
g.drawLine(x1, y1, x2, y2);
}
else
System.out.println("VertAsympArray : " + VertAsympArray.get(j) + "; Function x value : " + round(graphdata.get(i).getX(),3));
}
}
Even though I removed the values that make the function the user inputs undefined, for some reason a straight line is drawn connecting the last lowest point on the graph to the next highest point. Here is how a graph looks like for ((x-1)(x+3))/((x+1)(x-6)) around the x = 6 asymptote:
The straight red line is not any asymptote I drew in, it is showing up as part of the function, which is wrong. How do I get rid of it/is there a better way to graph asymptotes?

Creating a for loop with inputs in Java

Here is my code:
public static Picture modifyPicture (Picture p, int value)
{
// get width and height of the picture
int width = p.getWidth();
int height = p.getHeight();
System.out.println ("Picture has width of " + width +
" and height of " + height);
Picture p2 = new Picture (width, height*value);
int x = -1;
int y = -1;
for ( x = 0 ; x < width ; ++x )
{
for ( y = 0 ; y < height ; ++y )
{
Pixel pixel1 = p.getPixel (x,y);
Color c1 = pixel1.getColor();
Pixel pixel4 = p2.getPixel (x, y);
pixel4.setColor( c1 );
Pixel pixel5 = p2.getPixel (x, y + 1 * height);
pixel5.setColor( c1 );
Pixel pixel6 = p2.getPixel (x, y + 2 * height);
pixel6.setColor( c1 );
}
}
return p2;
} // end of method
Hey guys, this seems like a simple problem but I cannot figure out how I could do this. I want to somehow loop the items inside of the for loop. What the code does is places pictures vertically on top of each other. This code works for 3 pictures (value = 3), but if I wanted less or more pictures, I have to keep adding/removing a new line i.e. Pixel pixel7 etc.
I need a way to loop this according to the number in value. I'm not looking for you to write my code for me, just give me some idea how I could do this. Thank you for your time and help!
You have to modify your method to loop value times for each pixel:
public static Picture modifyPicture (Picture p, int value)
{
// get width and height of the picture
int width = p.getWidth();
int height = p.getHeight();
System.out.println ("Picture has width of " + width +
" and height of " + height);
Picture p2 = new Picture (width, height*value);
for (int x = 0 ; x < width ; ++x )
{
for (int y = 0 ; y < height ; ++y )
{
Pixel pixel1 = p.getPixel (x,y);
Color c1 = pixel1.getColor();
for (int j=1; j < value; j++) {
Pixel pixel = p2.getPixel (x, y + j * height);
pixel.setColor( c1 );
}
}
}
return p2;
} // end of method

I try to set some values to an array of integers but the values won't stick

Here is my code:
int[][] coordX = new int[10000][10000];
int[][] coordY = new int[10000][10000];
int cX = 0;
int cY = 0;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int width = (int) (screenSize.getWidth());
int height = (int) (screenSize.getHeight());
BufferedImage dirt = null;
{
try {
dirt = ImageIO.read(new File("res/dirt.png"));
} catch (IOException e) {
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
for (int y = 0; y <= height; y = y + 50) {
for (int x = 0; x <= width; x = x + 50) {
g.drawImage(dirt, x, y, 50, 50, Color.BLACK, this);
coordX[cX][cY] = cX;
coordY[cX][cY] = cY;
cX = cX + 1;
System.out.println("X=" + coordX[cX][cY]);
}
cY = cY + 1;
cX = 0;
System.out.println("Y=" + coordY[cX][cY]);
}
}
The console outputs all the "X=" values as zero, and same for the "Y=", however, when I print the "cX" and "cY" values on their own, they are counting as intended. The problem only seems to arise when I try to store the "cX" and "cY" values in an array.
You're incrementing cX prior to printing
cX = cX + 1;
System.out.println("X=" + coordX[cX][cY]);
i.e. you're not printing the element you've just populated. You'll always get the default (uninitialised) int element value (0).
You're incrementing cX and cY before printing. Try this:
coordX[cX][cY] = cX;
coordY[cX][cY] = cY;
System.out.println("X=" + coordX[cX][cY]);
System.out.println("Y=" + coordY[cX][cY]);
cX = cX + 1;

Categories

Resources