Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ImageObserver in Graphics method drawImage()

The method I am trying to use is the: drawImage(image, int, int, int, int, ImageObserver) method so that i can scale my image, on all the examples i've seen the ImageObserver should be this, but this doesn't seem to work(i.e. the only methods i have seen is: drawImage(image, int, int, ImageObserver), don't know if this makes a difference).

Here is my main class that is the applet:

import java.applet.*;
import java.awt.*;

public class Main extends Applet implements Runnable{
    private Thread th;
    private Hitter hitter;

    //double buffering
    private Graphics dbg;
    private Image dbImage;

    public void init(){
        hitter = new Hitter(getImage(getCodeBase(), "Chitter.png"));
    }

    public void start(){
        th = new Thread(this);
        th.start();
    }

    public void stop(){
        th.stop();
    }

    public void update(Graphics g){
        if(dbImage == null){
            dbImage = createImage(this.getSize().width, this.getSize().width);
            dbg = dbImage.getGraphics();
        }

        dbg.setColor(getBackground());
        dbg.fillRect(0, 0, this.getSize().width, this.getSize().height);
        dbg.setColor(getForeground());
        paint(dbg);

        g.drawImage(dbImage, 0, 0, this);
    }

    public void paint(Graphics g){
        hitter.drawHitter(g);
    }

    public void run() {
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
        while(true){
            repaint();

            try{
                Thread.sleep(15);
            }catch(InterruptedException ex){}

            Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        }
    }

    public boolean mouseMove(Event e, int x, int y){
        hitter.move(x);

        return true;
    }

}

Here is the Hitter class:

import java.awt.*;
import java.awt.image.ImageObserver;

public class Hitter{
    private int x, y;
    private Image hitter;
    private int hitterWidth = 50, hitterHeight = 10;
    private int appletsizeX = 500, appletsizeY = 500;

    Hitter(Image i){
        hitter = i;
        start();
    }

    public void drawHitter(Graphics g){
        g.drawImage(hitter, x, y, hitterWidth, hitterHeight, this);
    }

    public void move(int a){
        x = a;
    }

    public void start(){
        x = appletsizeX/2 - hitterWidth/2;
        y = 0;
    }
}
like image 352
Matias Grioni Avatar asked Jul 10 '11 02:07

Matias Grioni


1 Answers

Unless the class in which you are calling Graphics.drawImage(Image, int, int, int, int, ImageObserver) is an ImageObserver, using this as the argument for the ImageObserver will not work:

class MyClass {
  public void resizeImage() {
    Graphics g = getGraphicsObjectFromSomewhere();

    // The following line will not compile, as `MyClass` 
    // does not implement `ImageObserver`.
    g.drawImage(img, 0, 0, 50, 50, this);
  }
}

If you're resizing an image which does not require an ImageObserver (such as a BufferedImage that already contains the image you want to resize), then you can just hand over a null:

// The image we want to resize
BufferedImage img = ImageIO.read("some-image.jpg");

// The Graphics object of the destination
// -- this will probably just be obtained from the destination image.
Graphics g = getGraphicsObjectFromSomewhere();

// Perform the resizing. Hand a `null` for the ImageObserver,
// as we don't need one.
g.drawImage(img, 0, 0, 50, 50, null);

That said, I'm going to throw in a little plug for my image resizing library Thumbnailator.

If all that is required is to resize an image, it can be accomplished as simple as the following code:

Thumbnails.of("path/to/image")
  .size(100, 100)
  .toFile("path/to/thumbnail");

Thumbnailator is flexible enough to accept BufferedImages, Files, and InputStreams as input.


Seeing your edit, I would suggest to change the Hitter class, so that it will perform the resizing of the image in the constructor.

Since you are calling the drawHitter method on each call from the Applet.drawImage, the resize operation using Graphics.drawImage is being called many times, even when the hitterWidth and hitterHeight are, for all intents and purposes, constants.

Resizing the Image ahead of time, and drawing that pre-resized image in the drawHitter method will be more efficient.

like image 191
coobird Avatar answered Oct 05 '22 22:10

coobird