Im making project for my uni, and I have a problem with one thing - everything works well, but there is bug with comparing colors of two pixels.
I have to count area of some figure, and I have to use MonteCarlo method. ( generate random points, count points in figure and out, calculete figure area )
And some points are counted well, some dont, I have no idea whats wrong, Im trying to solve that few hours...
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Runner extends JApplet{
private BufferedImage img;
public ArrayList<Point> w;
public ArrayList<Point> poza;
public BufferedImage output;
public void init(){
try{
img = ImageIO.read(new File("figura.gif"));
} catch (IOException e){
e.getStackTrace();
System.err.println("Nie ma obrazkaXD");
}
}
public void paint(Graphics g){
w = new ArrayList<Point>();
poza = new ArrayList<>();
super.paint(g);
Random random = new Random();
int wys = img.getHeight();
int szer = img.getWidth();
g.drawImage(img, 0, 0, wys, szer, null);
for (int i = 0; i < 1000; i++) {
int x = random.nextInt(wys);
int y = random.nextInt(szer);
Point p = new Point(x,y);
g.setColor(Color.GREEN);
g.drawOval(y, x, 1, 1);
Color c = new Color(img.getRGB(y, x));;
if(c.equals(Color.BLACK)){
w.add(p);
g.setColor(Color.RED);
g.drawOval(y, x, 1, 1);
}else{
poza.add(p);
}
}
float a = w.size();
float b = poza.size()+w.size();
float poleProstokata = wys*szer;
float pole = a/b*poleProstokata;
}
I would suggest you to switch the y and y Coordinate, because as described in the Oracle Documentation :
https://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html#getRGB(int,%20int)
The method getRGB takes the X first and the Y second, so you'll have to use
Color c = new Color(img.getRGB(x, y));
instead of
Color c = new Color(img.getRGB(y, x));;
and why dont use an int ? I mean, you always convert the returned int from getRGB to a color and compare it. But why dont create a int from the Color Black and compare it to the int returned from getRGB(x,y) ?
Heres what I suggest :
int black=Color.BLACK.getRGB();
at the beginning of your paint method
and in your loop :
int c=img.getRGB(y, x);
and compare them :
if (black==c) {
//Do your stuff...
}
Related
What I have here is a Buffer image called blackWhite which is completely either black or white. What I am trying to do here is that I take a 2d array of pixel coordinates (in this case, tog) and find out whether it is black or white, assign it to be 0 of black and 1 if not, then save it back to the 3rd column of the 2d array. While it does not through any error, it is not giving me the right colors and saying all of it is white when I know it is not. I have used DDA to pick the coordinates of each pixel between 2 click points for this case and that's what is in the array tog here. Even when I pick just black-to-black pixels, it still says all is white.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class W3_Img_Process_Class_Only extends JPanel {
//--------------variables
int[][] tog; int step;
String inTitle="L1";
int imageCount=0;
int[] x= new int[2], y= new int[2];
int[] black= new int[2]; //-------------if black is 0, then the pixel is black
int clr; int flag=0;
private BufferedImage master;
private BufferedImage blackWhite;
public W3_Img_Process_Class_Only() {
//----------------------try/catch for (pure black || pure white)
try {
master = ImageIO.read(new File(Image_Path));
blackWhite = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = blackWhite.createGraphics();
g2d.drawImage(master, 0, 0, this);
g2d.dispose();
}catch (IOException ex) {ex.printStackTrace();}
//--------------------------1st and 2nd click point data and color
this.addMouseListener(new MouseListener() {
int[] isFristEmpty;
#Override
public void mouseClicked(MouseEvent e1) {
int[] temp =new int[3]; //external container so i can get 1st and 2nd separately
temp[0] = (int) e1.getX();
temp[1] = (int) e1.getY();
clr = blackWhite.getRGB(temp[0], temp[1]);
temp[2] = (clr & 0x00ff0000) >> 16;//--------------------bit map to find if red is there or not.
//-------------------------------------------------------since its pure b/w, if red 0, its white.
if(isFristEmpty==null) {
isFristEmpty=temp;
x[0] = temp[0]; y[0] = temp[1]; black[0]=temp[2];//------1st click
}else {
x[1] = temp[0]; y[1] = temp[1]; black[1]=temp[2];//-----2nd click
isFristEmpty=null; //so the 3rd click is considered 1st click again
flag=1;
}
if (flag==1) {
System.out.print("X1: "+x[0]+" & "+"Y1: "+y[0]+" "+"(225 if white): "+black[0]+"\t");
System.out.println("X2: "+x[1]+" & "+"Y2: "+y[1]+" "+"(225 if white): "+black[1]);
counter();
}
}
#Override public void mousePressed(MouseEvent e) {}
#Override public void mouseReleased(MouseEvent e) {}
#Override public void mouseEntered(MouseEvent e) {}
#Override public void mouseExited(MouseEvent e) {}
});
}
//--------------------------------------------DDA block
private void counter() {
int dark;
if(flag!=1) return;//-------------------to only go to counter method after it takes that 2nd click
int dx = (x[1] - x[0]);
int dy = (y[1] - y[0]);//---------makes it applicable for both inclinations (we do not have math.abs implies-> -ve goes as -ve)
step = Math.abs(dx) > Math.abs(dy) ? Math.abs(dx) : Math.abs(dy);
System.out.println("Steps: "+step);
float Xinc = dx / (float) step;//----slope change with respect to x axis
float Yinc = dy / (float) step;//----slope change with respect to y axis
tog= new int[step][3];
tog[0][0]=x[0]; tog[0][1]=y[0];
tog[0][2]= (black[0]!=0) ? 1 : 0;//------------Tertiary operator where condition is true, then while is true
//---------------------------------------------------------------send value of x1 and y1 to listOfCoordinates
float xt=x[0],yt=y[0]; int i=0, j=1;
//-------------to get all the coordinates between the 2 points1111
System.out.println(tog[0][0]+" "+tog[0][1]+" "+tog[0][2]);
while (j<step){
if(i==2) i=0;
xt += Xinc;
yt += Yinc;
tog[j][i] = (int)xt;
tog[j][i+1] = (int)yt;
j++;
}
for (i = 0; i < step; i++) {
for (j = 0; j<= 1; j++) {
System.out.print(tog[i][j]+" ");
}//****************issue zone here till...
clr = blackWhite.getRGB(tog[i][j-1], tog[i][j]);
dark = clr & 0x000000ff;//----for blue but if it is 255, its white
System.out.print(dark);
tog[i][2]= (dark!=0) ? 1 : 0;
//System.out.print(tog[i][2]);
System.out.println();
}
//********issue zone till here..
}
//------------image size and such stuff. don't touch it
#Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
if (master != null) {
size = new Dimension(master.getWidth(), master.getHeight());
}
return size;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (master != null) {
int x = (getWidth() - (master.getWidth())) / 2;
int y = (getHeight() - master.getHeight()) / 2;
g.drawImage(blackWhite, x, y, this);
}
}
}
It's the well and fully functional code of it all. Hope it's good enough to be helpful.
The pixel is white if it gives 255 and 0 if black, if u r looking into already substituted to 1 and 0 part then it's 1 for white. it is supposed to give the value of pixel but it gives all white and that's the issue. the x1 y1 and x2 y2 are the coordinates of 1st and 2nd click. the list u get as output is the list of coordinates of pixels between those points and its color (1 of white adn 0 of black)
Apparently, the problem was with the loop where instead of:
for (i = 0; i < step; i++) {
for (j = 0; j<= 1; j++) {
System.out.print(tog[i][j]+" ");
}
}
I should have just used a single loop and reset the value of the y coordinate at the start of the loop again as follows:
for (i = 1; i < step; i++) {
j=0;
clr = blackWhite.getRGB(tog[i][j], tog[i][j+1]);
System.out.print(tog[i][j]+" "+tog[i][j+1]+" ");
}
works as intended.
A and C images are far away.
At this time, B image is created from the coordinate values of A
For each iteration, x, y must be moved to arrive at the C image coordinate value.
For example,
A (100,100), C (300,300)
Starting at B (100,100),
Each time it is repeated, x, y must be moved to reach
B (300,300).
This is the method for entering the current moving source.
Public void Attack () {
int x1 = a.getX ();
int y1 = a.getY ();
int x2 = c.getX ();
int y2 = c.getY ();
if(b.getX ()==c.getX&&b.getY () == c.getY())'
{
system.out.println ("ok");'
}else {
b.setbounds (help1,help2,100,50)
}
}
Here, I want to know the code to enter help1 help2.
Pythagorean formula
Between A and C images
I want to know how to make the B image move along a virtual straight line.
Like a tower defense game.
A image is a tower
B image is bullet
The C image is the enemy.
I want the bullets fired from the tower to move to enemy locations.
I am Korean.
I used a translator
The following code is an mre of using a straight line equation y = mx + c to draw a moving object along such line.
To test the code copy the entire code into MoveAlongStraightLine.java and run, or run it online:
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class MoveAlongStraightLine extends JFrame {
public MoveAlongStraightLine(){
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
ShootinBoard shootingBoard = new ShootinBoard();
JButton fire = new JButton("Fire");
fire.addActionListener(e->shootingBoard.fire());
add(shootingBoard);
add(fire, BorderLayout.SOUTH);
pack();
setVisible(true);
}
public static void main(String[]args){
SwingUtilities.invokeLater(()->new MoveAlongStraightLine());
}
}
class ShootinBoard extends JPanel{
//use constants for better readability
private static final double W = 600, H = 400;
private static final int DOT_SIZE = 10, SPEED = 2;
private final int dX = 1; //x increment
private final Timer timer;
private final Point2D.Double shooter, target;
private Point2D.Double bullet;
public ShootinBoard() {
setPreferredSize(new Dimension((int)W, (int)H));
shooter = new Point2D.Double(50,350);
bullet = shooter; //place bullet at start point
target = new Point2D.Double(550,50);
timer = new Timer(SPEED, e->moveBullet());
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setStroke(new BasicStroke(3));
//draw source
g2.setColor(Color.blue);
g2.draw(new Ellipse2D.Double(shooter.getX(), shooter.getY(),DOT_SIZE , DOT_SIZE));
//draw bullet
g2.setColor(Color.black);
g2.draw(new Ellipse2D.Double(bullet.getX(), bullet.getY(),DOT_SIZE , DOT_SIZE));
//draw target
g2.setColor(Color.red);
g2.draw(new Ellipse2D.Double(target.getX(), target.getY(),DOT_SIZE , DOT_SIZE));
}
void fire(){
timer.stop();
bullet = shooter; //place bullet at start point
timer.start();
}
void moveBullet() {
if(target.x == bullet.x && target.y == bullet.y) {
timer.stop();
}
//y = mx + c for more details see https://www.usingmaths.com/senior_secondary/java/straightline.php
double m = (target.y - bullet.y)/ (target.x - bullet.x);//slope
double c = (target.x * bullet.y - bullet.x * target.y)/(target.x - bullet.x);
double newBulletX = bullet.x+dX; //increment x
double newBulletY = m * newBulletX + c; //calculate new y
bullet = new Point2D.Double(newBulletX,newBulletY);
repaint();
}
}
So today I started with a new project. I want to make a simple heightmap generator in java, so I tried the following:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Heightmap {
public static int width = 200;
public static int height = 200;
public static void main(String[] args) {
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY );
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
bufferedImage.setRGB(x, y, (byte )(Math.random() * 256 + 128) ); // + 128 because byte goes from -128 to 127
}
}
File outputFile = new File("heightmap.png");
try {
ImageIO.write(bufferedImage, "png", outputFile);
}catch (IOException ioex){
ioex.printStackTrace();
}
}
}
The code is very simple, I plan to try perlin noise as the next step. But first I need to resolve this problem:
Generated Heightmap
The pixels in heightmap.png are either completely white, or completely black. There's no grays in the image, which of course is necessary in a heightmap. Does anyone know what I did wrong?
is it the BufferedImage.TYPE_BYTE_GRAY part? If so, what should I use instead?
After a friend set me on the right track, I found the solution.
Instead of BufferedImage.TYPE_BYTE_GRAY I used BufferdImage.TYPE_INT_RGB. So this is indeed where I went wrong. Also I added the object Color randomColor, wherein the RGB values all share the same integer with a value from 0 to 255. Then in BufferedImage.setRGB I use the color code of randomColor (so R,G,B = 255 gives #FFFFFF, which is white) as the value of pixel (x,y):
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Heightmap {
public static int width = 200;
public static int height = 200;
public static void main(String[] args) {
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB );
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
int randomValue = (int)(Math.random() * 256);
Color randomColor = new Color( randomValue, randomValue, randomValue);
bufferedImage.setRGB(x, y, randomColor.getRGB());
}
}
File outputFile = new File("heightmap.png");
try {
ImageIO.write(bufferedImage, "png", outputFile);
}catch (IOException ioex){
ioex.printStackTrace();
}
}
}
Now the heightmap.png gives what I expected: Heightmap.png
Hi guys I know this is a common one, but i've searched around quite a bit and can't seem to get my paint method to draw over the components in my JPanel.
My paint method is linked to a button press. It prints out about 1500 data points and their assigned cluster (kmeans)
package eye_pathscanner;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class ReplayData extends JPanel {
// replay type can be parsed as argument into draw() to change paints behaviour
private int ReplayType = 0;
public ArrayList<DataPoint> points;
//Initialise records
public ReplayData()
{
points = new ArrayList<DataPoint>();
}
public void ReplaceData() {
points = new ArrayList<DataPoint>();
}
public void PrintPoints()
{
}
public void addPoint(DataPoint point) {
points.add(point);
}
#Override
public void paintComponent(Graphics g) {
Color black = new Color(0, 0, 0);
Random random = new Random();
final float luminance = 0.9f;
if (ReplayType == 1)
{
super.paintComponent(g);
for (int x = 0; x < kMeans.NUM_CLUSTERS; x++)
{
// Saturation ideal between 0.1 and 0.3
float saturation = (random.nextInt(2000) + 1000) / 10000f;
float hue = random.nextFloat();
Color cluster_colour = Color.getHSBColor(hue, saturation, luminance);
// Randomise the border colour
saturation = (random.nextInt(2000) + 1000) / 10000f;
hue = random.nextFloat();
Color cluster_colour_border = Color.getHSBColor(hue, saturation, luminance);
double centroidx = kMeans.centroids.get(x).getmX();
double centroidy = kMeans.centroids.get(x).getmY();
for (int i = 0; i < kMeans.TOTAL_DATA; i++)
if(kMeans.dataSet.get(i).cluster() == x){
// Set each child data point to a colour so you can see which cluster it belongs too
g.setColor(cluster_colour);
g.fillRect((int)TrackerData.getRecordNumber(i).getEyeX(),(int)TrackerData.getRecordNumber(i).getEyeY(), 3, 3);
g.drawLine((int)kMeans.dataSet.get(i).X(),(int)kMeans.dataSet.get(i).Y(), (int)centroidx, (int)centroidy);
//g.setColor(Color.black);
g.setColor(cluster_colour_border);
g.drawRect((int)TrackerData.getRecordNumber(i).getEyeX(),(int)TrackerData.getRecordNumber(i).getEyeY(), 3, 3);
}
g.setColor(black);
g.fillOval((int)centroidx,(int)centroidy, 15, 15);
}
}
}
// 1 for K-means with different colour cluster groups
// 2 for slow replay
public void draw(int i) {
ReplayType = i;
repaint();
}
}
This code all works great for me, however I lose the image that was drawn beneath the paint after using it. I can maximize the page and the image shows up again but over the paint? (can anyone explain this behavior).
JLabel picture_panel = new JLabel();
picture_panel.setBounds(70, 130, 640, 797);
picture_panel.addMouseListener(this);
BufferedImage img = null;
try
{
img = ImageIO.read(new File("C:/Eyetracker_Images/Random.jpg")); // eventually C:\\ImageTest\\pic2.jpg
ImageIcon icon = new ImageIcon(img);
picture_panel.setIcon(icon);
}
catch (IOException e)
{
e.printStackTrace();
}
Heres where my image is created, and it's called as shown below on one my buttons
replayData.setBounds(0, 0, 802, 977);
frame.getContentPane().add(replayData);
replayData.draw(1);
Any help would be much appreciated, Thanks.
This maybe an artifact of using setBounds(). Moreover, you appear to be using the default layout manager without invoking pack() on the enclosing container.
As you already have a BufferedImage containing the rendered image, simply invoke drawImage() in your implementation of paintComponent(). Examples are seen here, here and here.
Also consider overriding the getPreferredSize() method of ReplayData, as suggested here and here, to establish its dimensions.
I am trying to get every single color of every single pixel of an image.
My idea was following:
int[] pixels;
BufferedImage image;
image = ImageIO.read(this.getClass.getResources("image.png");
int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
Is that right? I can't even check what the "pixels" array contains, because i get following error:
java.awt.image.DataBufferByte cannot be cast to java.awt.image.DataBufferInt
I just would like to receive the color of every pixel in an array, how do i achieve that?
import java.io.*;
import java.awt.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
public class GetPixelColor {
public static void main(String args[]) throws IOException {
File file = new File("your_file.jpg");
BufferedImage image = ImageIO.read(file);
// Getting pixel color by position x and y
int clr = image.getRGB(x, y);
int red = (clr & 0x00ff0000) >> 16;
int green = (clr & 0x0000ff00) >> 8;
int blue = clr & 0x000000ff;
System.out.println("Red Color value = " + red);
System.out.println("Green Color value = " + green);
System.out.println("Blue Color value = " + blue);
}
}
of course you have to add a for loop for all pixels
The problem (also with the answer that was linked from the first answer) is that you hardly ever know what exact type your buffered image will be after reading it with ImageIO. It could contain a DataBufferByte or a DataBufferInt. You may deduce it in some cases via BufferedImage#getType(), but in the worst case, it has type TYPE_CUSTOM, and then you can only fall back to some instanceof tests.
However, you can convert your image into a BufferedImage that is guaranteed to have a DataBufferInt with ARGB values - namely with something like
public static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
Otherwise, you can call image.getRGB(x,y), which may perform the required conversions on the fly.
BTW: Note that obtaining the data buffer of a BufferedImage may degrade painting performance, because the image can no longer be "managed" and kept in VRAM internally.
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedImage bufferedImage = ImageIO.read(new File("norris.jpg"));
int height = bufferedImage.getHeight(), width = bufferedImage.getWidth();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int RGBA = bufferedImage.getRGB(x, y);
int alpha = (RGBA >> 24) & 255;
int red = (RGBA >> 16) & 255;
int green = (RGBA >> 8) & 255;
int blue = RGBA & 255;
}
}
}
}
Assume the buffered image represents an image with 8-bit RGBA color components packed into integer pixels, I search for "RGBA color space" on wikipedia and found following:
In the byte-order scheme, "RGBA" is understood to mean a byte R,
followed by a byte G, followed by a byte B, and followed by a byte A.
This scheme is commonly used for describing file formats or network
protocols, which are both byte-oriented.
With simple Bitwise and Bitshift you can get the value of each color and the alpha value of the pixel.
Very interesting is also the other order scheme of RGBA:
In the word-order scheme, "RGBA" is understood to represent a complete
32-bit word, where R is more significant than G, which is more
significant than B, which is more significant than A. This scheme can
be used to describe the memory layout on a particular system. Its
meaning varies depending on the endianness of the system.
byte[] pixels
not
int[] pixels
try this : Java - get pixel array from image
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageUtil {
public static Color[][] loadPixelsFromImage(File file) throws IOException {
BufferedImage image = ImageIO.read(file);
Color[][] colors = new Color[image.getWidth()][image.getHeight()];
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
colors[x][y] = new Color(image.getRGB(x, y));
}
}
return colors;
}
public static void main(String[] args) throws IOException {
Color[][] colors = loadPixelsFromImage(new File("image.png"));
System.out.println("Color[0][0] = " + colors[0][0]);
}
}
I know this has already been answered, but the answers given are a bit convoluted and could use improvement.
The simple idea is to just loop through every (x,y) pixel in the image, and get the color of that pixel.
BufferedImage image = MyImageLoader.getSomeImage();
for ( int x = 0; x < image.getWidth(); x++ ) {
for( int y = 0; y < image.getHeight(); y++ ) {
Color pixel = new Color( image.getRGB( x, y ) );
// Do something with pixel color here :)
}
}
You could then perhaps wrap this method in a class, and implement Java's Iterable API.
class IterableImage implements Iterable<Color> {
private BufferedImage image;
public IterableImage( BufferedImage image ) {
this.image = image;
}
#Override
public Iterator<Color> iterator() {
return new Itr();
}
private final class Itr implements Iterator<Color> {
private int x = 0, y = 0;
#Override
public boolean hasNext() {
return x < image.getWidth && y < image.getHeight();
}
#Override
public Color next() {
x += 1;
if ( x >= image.getWidth() ) {
x = 0;
y += 1;
}
return new Color( image.getRGB( x, y ) );
}
}
}
The usage of which might look something like the following
BufferedImage image = MyImageLoader.getSomeImage();
for ( Color color : new IterableImage( image ) ) {
// Do something with color here :)
}