Link to home
Start Free TrialLog in
Avatar of profesoralex2
profesoralex2

asked on

Copy image from a canvas, zoom it and put it into the same canvas (JAVA graphics 2D)

Hi!
I would like to get a code tha copies an image from a canvas (to a buffer), zoom it (in or out) and put it once again on the same canvas. The reason is I have problems using the AffineTransformation in Java and preffer to use that this method. Anyone can help me?
Thanks in advance!
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

>>The reason is I have problems using the AffineTransformation in Java

What problems?
This way of copying sounds inefficient. What is use for advanced graphics is the simple methods in Graphics2D. If i want to scale everything i draw by 2. I use g.scale(2,2) , and then call the drawImage or drawLine commands.
Here is a sample program showing transforms
import javax.swing.*;
import java.awt.*;
 
class SampleGraphics extends JFrame
{
	double time = 0;
 
	SampleGraphics()
	{
		setSize(640,480);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
 
		while(true)
		{
			time++;
			paint();
 
			try
			{
				Thread.sleep(30);
			}
			catch(Exception e){e.printStackTrace();}
		}
	}
 
	public void paint()
	{
		if(getBufferStrategy() == null)
			createBufferStrategy(2);   //Set double buffering
 
		Graphics2D g = (Graphics2D)getBufferStrategy().getDrawGraphics();  //Get double buffered graphics
 
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
 
		g.setColor(Color.WHITE);
		g.fillRect(0,0,getWidth(),getHeight());
 
		//ORDER IS VERY SIGNIFICANT WITH TRANSFORMATIONS
 
		g.translate(350,250); //Shifts left 350 pixels and down 250 pixels
		g.scale(time%100/200,time%100/200);
		g.rotate(time/100,150,150);
 
		g.setColor(Color.BLUE);
		g.drawLine(100,100,200,100);
		g.drawLine(100,100,100,200);
		g.drawLine(200,200,200,100);
		g.drawLine(200,200,100,200);
		g.drawLine(100,100,200,200);
		g.drawLine(100,200,200,100);
 
		getBufferStrategy().show();
	}
 
	public static void main(String args[])
	{
		new SampleGraphics();
	}
}

Open in new window

Avatar of profesoralex2
profesoralex2

ASKER

Ok, Thanks to all! My problem is not to make a zoom, but make a zoom and paint! Could someone give me a code to zoom in a canvas image and paint on it(by hand)? I observe that the zooming doenst work properly (not centered when I use the scrollbar) and doesn't paint fine (the cursor is moved when I try to paint something). So it's a reason to use a buffered image, copying it, zooming it and putting it on the canvas. Also I observe when I use the affine transform zooming out, the canvas area is also reduced. I realize that I need to do something with the affine transform parameters but I'am new in it. Could anyone help me?
Thanks!!!!

Alex
Could you post your problematic code?
Ok! See my code related to affineTransform: Basically I have a canvas I paint into. I have a zoom in button. When I want to zoom I use  tx.translate(WhiteboardContext.WIDTH/2, WhiteboardContext.HEIGHT/2);
scale it and paint it. The problem is when I zoom it the zoom is not centered and also when I zoom out I get then image I attached. So bascically what I want is:
1) get the image from my canvas
2) zoom it (in or out)
3) put it into my canvas
With this method the canvas size still the same.
Thank you!!!!

Alex
public class Whiteboard extends Canvas implements MouseListener,
						  MouseMotionListener,
						  KeyListener,
						  ActionListener,
						  WhiteboardContext{
......................
private AffineTransform tx = new AffineTransform();
 
......................
 
 
public void paintContents(Graphics g) {
     ((Graphics2D) g).setTransform(tx);
     //((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
	    currentShape.paint(this, g);
    }
 
    else if (buttonin == zoom_in){
        System.out.println("zoom_in");
    tx.translate(WhiteboardContext.WIDTH/2, WhiteboardContext.HEIGHT/2);
 
    tx.scale(1.5,1.5);
 
    }
 else if (buttonin == zoom_out){
        System.out.println("zoom_out");
    tx.translate((WhiteboardContext.WIDTH-20)*(1-1/1.5)/4, WhiteboardContext.HEIGHT*(1-1/1.5)/4);
    tx.scale(1/1.5,1/1.5);
    }

Open in new window

Imagen-2.png
Imagen-3.png
This was a tricky problem. The reason why I really dont want to do your canvas resizing way is that it kind of ruins to point of zooming. The quality wouldn't be any better and the antialiasing would be mostly lost. Also scaling images takes processing time for it to be inconvient to do it every frame.

I took your code and changed a little so i could run it, then i added three variables, centerX, centerY, zoom. Everytime the canvas paints, it zooms the graphics object and translates it so that centerX and centerY are at the center of your screen.

Hope this helps.
import java.awt.*;
import java.awt.geom.*;
 
public class Whiteboard extends Canvas
{
	public static final int WIDTH = 640;
	public static final int HEIGHT = 480;
 
	int centerX = 150;
	int centerY = 150;
	double zoom = 1;
 
	public void paint(Graphics g)
	{
		paintContents(g);
	}
 
	public void paintContents(Graphics g1)
	{
		Graphics2D g = (Graphics2D)g1;
 
		g.translate(WIDTH/2 - centerX * zoom,HEIGHT/2 - centerY * zoom);
		g.scale(zoom,zoom);
 
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
 
		g.setColor(Color.RED);
		g.fillOval(150 - 50,150 - 50,100,100);
 
		g.setColor(Color.BLUE);
		g.fillOval(250 - 25,250 - 25,50,50);
	}
 
	public void zoomIn()
	{
		zoom += 1;
		System.out.println("zoom_in");
	}
 
	public void zoomOut()
	{
		zoom -= 1;
		System.out.println("zoom_out");
	}
}

Open in new window

Heres some code is used to test this Whiteboard, so you can try it. I basically automates zooming in and then changing the center and then zooming out for testing purposes.
import javax.swing.*;
import java.awt.*;
 
class Sample extends JFrame
{
	Whiteboard w = new Whiteboard();
 
	Sample()
	{
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(640,480);
		setUndecorated(true);
 
		add(w);
 
		setVisible(true);
 
		pause(1000);
 
		w.zoomIn();
		w.repaint();
 
		pause(1000);
 
		w.zoomIn();
		w.repaint();
 
		pause(1000);
 
		w.zoomIn();
		w.repaint();
 
		pause(1000);
 
		w.centerX = 250;
		w.centerY = 250;
		w.repaint();
 
		pause(1000);
 
		w.zoomOut();
		w.repaint();
 
		pause(1000);
 
		w.zoomOut();
		w.repaint();
 
		pause(1000);
 
		w.zoomOut();
		w.repaint();
	}
 
	public static void pause(int i)
	{
		try
		{
			Thread.sleep(i);
		}
		catch(Exception e){}
	}
 
	public static void main(String args[])
	{
		new Sample();
	}
}

Open in new window

Hello, Thomas4019!
Look, your solution seems to be OK, but the problem I find is the cursor "not pointed" when I paint. Please, see the attached pictures (picture 3, after to make a zoom, when I try to paint the cursor's position is not matched with the line).
Thank you!!!

Alex
import java.awt.*;
import java.awt.geom.*;
 
public class Whiteboard extends Canvas
{
	public static final int WIDTH = 640;
	public static final int HEIGHT = 480;
 
	int centerX = 150;
	int centerY = 150;
	double zoom = 1;
 
	public void paint(Graphics g)
	{
		paintContents(g);
	}
 
	public void paintContents(Graphics g1)
	{
		Graphics2D g = (Graphics2D)g1;
 
		g.translate(WIDTH/2 - centerX * zoom,HEIGHT/2 - centerY * zoom);
		g.scale(zoom,zoom);
 
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
 
		g.setColor(Color.RED);
		g.fillOval(150 - 50,150 - 50,100,100);
 
		g.setColor(Color.BLUE);
		g.fillOval(250 - 25,250 - 25,50,50);
	}
 
	public void zoomIn()
	{
		zoom += 1;
		System.out.println("zoom_in");
	}
 
	public void zoomOut()
	{
		zoom -= 1;
		System.out.println("zoom_out");
	}
}

Open in new window

ex1.bmp
ex2.bmp
ex3.bmp
ASKER CERTIFIED SOLUTION
Avatar of Thomas4019
Thomas4019
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thomas4019, your solution is exactly what I need. Thank you!