andreask andreask - 1 month ago 19
Java Question

Only the last circle is shown in saved BufferedImage

I want to render n circles in a

BufferedImage
but my problem is that only the last one is visible. Can you help me to find my failure? Perhaps it has something to do with the loops I'm using. Thanks in advance.

Scene.java

public class Scene {
private final int width;
private final int height;
private BufferedImage imageOfScene;
private ArrayList<Geometry> geometries;
private final String folderToSaveIn = "doc/";
private final String fileName = "a02.png";

public Scene(int width,int height){
this.geometries = new ArrayList<Geometry>();
this.width = width;
this.height = height;
this.imageOfScene = new BufferedImage(
this.width, this.height, BufferedImage.TYPE_INT_RGB
);
System.out.println("The scene has a size of:"+width+"X"+height);
}

public void renderScene(){
for (int x = 0; x != width; x++) {
for (int y = 0; y != this.height; y++) {
for (Geometry geometry: this.geometries){
if(geometry.isHit(x,y)){
this.imageOfScene.setRGB(x, y, geometry.getColor().getRGB());
}
else
this.imageOfScene.setRGB(x,y,giveColorForThisPixel(y));
}
}
}
}

public int giveColorForThisPixel(int y){
double y2 = (double) y;
double t = y2/this.height;
int value = (int) (t* 255);
return new Color(0, 0, value).getRGB();
}

public void saveScene(){

try {
File outputfile = new File(this.folderToSaveIn +fileName);
ImageIO.write(this.imageOfScene, "png", outputfile);
System.out.println("Wrote image: " + fileName);
} catch (IOException e) {
e.printStackTrace();
}

}

public void addGeometry(Geometry geometry){
geometries.add(geometry);
}


public int getWidth() {
return width;
}

public int getHeight() {
return height;
}

public ArrayList<Geometry> getGeometries() {
return geometries;
}
}


Circle.java

public class Circle extends Geometry {

private final int radius;
private final int centerX;

private final int centerY;

public Circle(int centerX, int centerY, int radius, Color color){
super(color);
this.radius = radius;
this.centerX = centerX;
this.centerY = centerY;
}

@Override
public boolean isHit(int x,int y) {
if( Math.pow( (x - this.centerX),2) + Math.pow((y - this.centerY),2) < Math.pow(this.radius,2))
return true;
else
return false;
}

@Override
public String toString() {
return "Circle{" +
"radius=" + radius +
", centerX=" + centerX +
", centerY=" + centerY +
", color=" + getColor() +
'}';
}
}


Main.java

public class Main {

static String name = "doc/a02.png";
static int width = 480;
static int height = 270;
static int widthRatio = 16;
static int heightRatio = 9;

public static void main(String[] args) {


int numberOfCircles = 2;
Random random = new Random();
int ratioMultiplier = ThreadLocalRandom.current().nextInt(30,121);
System.out.println(ratioMultiplier);
//Scene scene = new Scene(width,height);
Scene scene = new Scene(widthRatio*ratioMultiplier,heightRatio*ratioMultiplier);
//ThreadLocalRandom.current().nextInt(min, max + 1);

for (int counter = 1; counter <= 5; counter++){
int centerX = ThreadLocalRandom.current().nextInt(0,height+1);
int centerY = ThreadLocalRandom.current().nextInt(0,width+1);
int radius = ThreadLocalRandom.current().nextInt(20,80);
scene.addGeometry(new Circle(centerX,centerY,radius,getRandomColor()));
System.out.println(scene.getGeometries());
}

scene.renderScene();
scene.saveScene();
}
static Color getRandomColor(){
return new Color(
ThreadLocalRandom.current().nextInt(0,256),
ThreadLocalRandom.current().nextInt(0,256),
ThreadLocalRandom.current().nextInt(0,256)
);
}
}

Answer

The problem is in renderScene() method. Change to it:

   public void renderScene(){
        for (int x = 0; x != width; x++) {
            for (int y = 0; y != this.height; y++) {
                this.imageOfScene.setRGB(x, y, giveColorForThisPixel(y));
                for (Geometry geometry: this.geometries) {
                    if (geometry.isHit(x, y)) {
                        this.imageOfScene.setRGB(x, y, geometry.getColor().getRGB());
                    }
                }
            }
        }
    }

When your code execute else this.imageOfScene.setRGB(x,y,giveColorForThisPixel(y)); inside renderScene() method, the last circle "erase" the previous circle.

The result:

enter image description here

Comments