andreask
andreask

Reputation: 109

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)
        );
    }
}

Upvotes: 0

Views: 63

Answers (1)

Paulo
Paulo

Reputation: 3008

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

Upvotes: 1

Related Questions