Class 1
import java.awt.Canvas;
import java.awt.Color;
import java.awt.image.BufferStrategy;
import java.awt.Graphics;
import java.lang.Runnable;
import java.lang.Thread;
import javax.swing.JFrame;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.IOException;

public class Game extends JFrame implements Runnable{
    private Canvas canvas = new Canvas();
    private RenderHandler renderer;
    private BufferedImage testImage;
    private Rectangle testRectangle = new Rectangle(30, 90, 100, 100);

    public Game() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(0,0, 1000, 800);
        setLocationRelativeTo(null);
        add(canvas);
        setVisible(true);
        canvas.createBufferStrategy(3);
        renderer = new RenderHandler(getWidth(), getHeight());
        BufferedImage testImage = loadImage("Grass.jpg");
        testRectangle.generateGraphics(12234);
    }

    private BufferedImage loadImage(String path){
        try{
            BufferedImage loadedImage = ImageIO.read(Game.class.getResource(path));
            BufferedImage formattedImage = new BufferedImage(loadedImage.getWidth(), 
            loadedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
            formattedImage.getGraphics().drawImage(loadedImage, 0, 0, null);
            return formattedImage;
        } 
        catch(IOException exception){
            exception.printStackTrace();
            return null;
        }
    }

    public void render(){
        BufferStrategy bufferStrategy = canvas.getBufferStrategy();
        Graphics graphics = bufferStrategy.getDrawGraphics();
        super.paint(graphics);
        renderer.renderImage(testImage, 0, 0, 5, 5);
        renderer.renderRectangle(testRectangle, 1, 1);
        renderer.render(graphics);
        graphics.dispose();
        bufferStrategy.show();
    }

    public void run(){
        BufferStrategy bufferStrategy = canvas.getBufferStrategy();
        int i = 0;
        int x = 0;
        long lastTime = System.nanoTime(); //long 2^63
        double nanoSecondConversion = 1000000000.0 / 60; //60 frames per second
        double changeInSeconds = 0;

        while(true){
            long now = System.nanoTime();
            changeInSeconds += (now - lastTime) / nanoSecondConversion;
            while(changeInSeconds >= 1) {
                changeInSeconds--;
            }
            render();
            lastTime = now;
        }

    }

    public static void main(String[] args){
        Game game = new Game();
        Thread gameThread = new Thread(game);
        gameThread.start();
    }
}
Class 2

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

public class RenderHandler{
private BufferedImage view;
private Rectangle camera;
private int[] pixels;
public RenderHandler(int width, int height) {

    view = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

    camera = new Rectangle(0, 0, width, height);
    camera.x = -100;
    camera.y = -30;
    pixels = ((DataBufferInt) view.getRaster().getDataBuffer()).getData();
}

public void render(Graphics graphics){
    for(int index = 0; index < pixels.length; index++) {
        pixels[index] = (int)(Math.random() * 0xFFFFFF);
    }
    graphics.drawImage(view, 0, 0, view.getWidth(), view.getHeight(), null);
}

public void renderImage(BufferedImage image, int xPosition, int yPosition, int xZoom, int yZoom){
    int[] imagePixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
    renderArray(imagePixels, image.getWidth(), image.getHeight(),xPosition, yPosition, xZoom, yZoom);
}

public void renderRectangle(Rectangle rectangle, int xZoom, int yZoom){
    int[] rectanglePixels = rectangle.getPixels();
    if(rectanglePixels != null){
        renderArray(rectanglePixels, rectangle.w, rectangle.h, rectangle.x, rectangle.y, xZoom, yZoom);
    }
}

public void renderArray(int[] renderPixels,int renderWidth, int renderHeight,int xPosition, 
int yPosition, int xZoom, int yZoom){
    for(int y = 0; y < renderHeight; y++)
        for(int x = 0; x < renderWidth; x++)
            for(int yZoomPosition = 0; yZoomPosition <yZoom; yZoomPosition++)
                for(int xZoomPosition = 0; xZoomPosition < xZoom; xZoomPosition++)
                    setPixel(renderPixels[x + y * renderWidth], (x * xZoom) + xPosition + xZoomPosition, ((y * yZoom) + yPosition + yZoomPosition));

}

private void setPixel(int pixel, int x, int y){
    if(x >= camera.x && y >= camera.y && x <= camera.x + camera.w && y <= camera.y + camera.h){
    }

    int pixelIndex = (x - camera.x) + (y - camera.y) * view.getWidth();
    if(pixels.length > pixelIndex){
        pixels[pixelIndex] = pixel;
    }
}

}

Dani AI

Generated

Two high‑value fixes to try first (they’re the common gotchas here).

First: you shadowed the field testImage in the constructor, so the class field stays null and nothing gets rendered. Assign to the field and verify the resource is found:

this.testImage = loadImage("/Grass.jpg");
if (this.testImage == null) {
    System.err.println("Image not found: " + Game.class.getResource("/Grass.jpg"));
}

Second: your renderer currently replaces the entire view pixels each frame with random values, which will overwrite any image you just wrote into the pixel buffer. Either remove that random-fill from the draw path or perform the clear/fill step before calling renderImage and renderRectangle.

Other important checks and small fixes

  • Protect setPixel from out‑of‑bounds indexes. Compute the index only after confirming the coordinates are inside the camera and ensure 0 <= index < pixels.length. Example:
if (x < camera.x || y < camera.y || x >= camera.x + camera.w || y >= camera.y + camera.h) return;
int pixelIndex = (x - camera.x) + (y - camera.y) * view.getWidth();
if (pixelIndex >= 0 && pixelIndex < pixels.length) pixels[pixelIndex] = pixel;
  • Confirm the image type before casting to DataBufferInt. If ImageIO.read returns an image with a different raster type, convert it to TYPE_INT_RGB/TYPE_INT_ARGB first to avoid class‑cast errors.
  • As recommended, simplify while debugging: draw the loaded image in a plain JPanel’s paintComponent or a JLabel with an ImageIcon to prove the file is on the classpath before wiring it into the custom pixel renderer.
  • Avoid a busy while(true) render loop (it burns CPU). Use a scheduler or sleep the thread to cap frame rate. When using BufferStrategy, make the Canvas displayable before creating the strategy and consider canvas.setIgnoreRepaint(true).

Following those steps will narrow the problem quickly.

Recommended Answers

All 3 Replies

That looks like a lot of complex code to do something that should be simple. Why are you using an AWT Canvas in a Swing application? Why not just a simple JPanel and override paintComponent?

Your approach to animation isn't going to work. The loop on line 63 is just going to burn 100% of (one of) your CPU's time.
Use a java.util.Timer or a ScheduledThreadPoolExecutor (but not a javax.swing.Timer) to update your model at the required speed and call repaint on your graphics renderer each time.

Overall you are writing far too much code before you start testing.
Just about every part of that code contains errors, so it's never going to give a sensible output, and you will have no idea where to start fixing it.

Break it down into small steps and get each step working before moving on. eg;
load an image and display it
perform some trivial image transformation and display the result (yes, trivial!)
add a timer and display the updated image as you change one input to the transformation
implement the interesting transformations that I guess are the real point of this app

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.