sending Java 2d context to image file

i am currently creating a GUI that will allow me to open, draw on and save a image.

currently my implementation opens ,displays and writes on an jpeg image or simalar by using the graphics 2d method to overide the paint function of a jLabel. for example:

File file = new File (jFileChooser1.getSelectedFile().getAbsolutePath());

BufferedImage image = null;

try {

image = ImageIO.read(file);

} catch (IOException ex) {

ex.printStackTrace();

}

scaledHeight=500 ;

scaledWidth= 500;

int imageType = BufferedImage.TYPE_INT_RGB;

BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);

Graphics2D g = scaledBI.createGraphics();

g.setComposite(AlphaComposite.Src);

g.drawImage(image, 0, 0, scaledWidth, scaledHeight, null);

g.dispose();

Graphics2D g1 = (Graphics2D) jLabel1.getGraphics();

g1.drawImage(scaledBI, 0, 0, scaledWidth, scaledHeight, null);

g1.dispose();

however im stuck at how to take the context of the jLabel and use it to draw a image for saving purposes. what i have been attempting is:

BufferedImage image = new BufferedImage(scaledWidth, scaledHeight, imageType);

Graphics2D g1 = (Graphics2D) jLabel1.getGraphics();

Graphics2D g2 = (Graphics2D) image.creatGraphics();

g2.setComposite(AlphaComposite.Src);

g2=g1;

this method has been returning a result but when the file it apppears totally black.

is my thinking correct and what is needed to move the context of a component to an image?

[1599 byte] By [t_k_na] at [2007-11-26 13:23:21]
# 1
> is my thinking correct and what is needed to move the> context of a component to an image?Check out the preview method in my StandardPrint class http://forum.java.sun.com/thread.jspa?forumID=20&threadID=661036
tjacobs01a at 2007-7-7 17:55:39 > top of Java-index,Security,Cryptography...
# 2

Are you really using this code?

This is really not the right way to write in Java.

The first thing you have to do is write your own class that extends JLabel (or JPanel), add a BufferedImage as a member and set and get functions for this BufferedImage.

Then you have to implement paintComponent function of JLabel like this:

public void paintComponent(Graphics g) {

super.paintComponent(g);

g.drawImage(image, 0, 0, this);

}

This will draw the image on the JLabel every time it is being drawn.

Then you can use the getImage function you put in the class to get the BufferedImage and save it.

Rodney_McKaya at 2007-7-7 17:55:39 > top of Java-index,Security,Cryptography...
# 3

import java.awt.*;

import java.awt.font.*;

import java.awt.geom.*;

import java.awt.image.BufferedImage;

import java.io.*;

import javax.imageio.ImageIO;

import javax.swing.*;

public class YourImage extends JPanel {

BufferedImage image;

Rectangle locater;

public YourImage(BufferedImage src) {

image = getScaledImage(src, 200, 200);

locater = new Rectangle(200, 200);

}

protected void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D)g;

g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,

RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,

RenderingHints.VALUE_INTERPOLATION_BICUBIC);

int w = getWidth();

int h = getHeight();

int x = (w - image.getWidth())/2;

int y = (h - image.getHeight())/2;

locater.x = x;

locater.y = y;

g2.drawImage(image, x, y, this);

Font font = g2.getFont().deriveFont(24f);

g2.setFont(font);

FontRenderContext frc = g2.getFontRenderContext();

String s = "hello world";

float width = (float)font.getStringBounds(s, frc).getWidth();

LineMetrics lm = font.getLineMetrics(s, frc);

float sx = (w - width)/2;

float sy = (h + lm.getAscent())/2 - lm.getDescent();

g2.setPaint(Color.red);

g2.drawString(s, sx, sy);

}

private BufferedImage getScaledImage(BufferedImage src, int w, int h) {

BufferedImage image = new BufferedImage(w, h, src.getType());

double xScale = (double)w / src.getWidth();

double yScale = (double)h / src.getHeight();

// To avoid distortion: choose fit or fill scale option.

double scale = Math.min(xScale, yScale);// scale to fit

//Math.max(xScale, yScale);// scale to fill

// Center scaled image.

double x = (w - scale*src.getWidth())/2;

double y = (h - scale*src.getHeight())/2;

AffineTransform at = AffineTransform.getTranslateInstance(x, y);

at.scale(scale, scale);

Graphics2D g2 = image.createGraphics();

g2.setPaint(getBackground());

g2.fillRect(0,0,w,h);

g2.drawRenderedImage(src, at);

g2.dispose();

return image;

}

private void save() {

// Do this on a background thread.

Thread thread = new Thread(new Runnable() {

public void run() {

// Wait a bit so the ui can be rendered and settle down.

try {

Thread.sleep(3000);

} catch(InterruptedException e) {

System.out.println("interrupted");

}

// Make a BufferedImage of the ui that we can save.

int w = locater.width;

int h = locater.height;

BufferedImage save = new BufferedImage(w, h, image.getType());

Graphics2D g2 = save.createGraphics();

g2.translate(-locater.x, -locater.y);

// Have the ui draw itself into our new BufferedImage.

paint(g2);

g2.dispose();

// Save to file.

try {

ImageIO.write(save, "jpg", new File("yourImage.jpg"));

} catch(IOException e) {

System.out.println("write error: " + e.getMessage());

}

}

});

thread.setPriority(Thread.NORM_PRIORITY);

thread.start();

}

public static void main(String[] args) throws IOException {

BufferedImage image = ImageIO.read(new File("images/cougar.jpg"));

final YourImage yourImage = new YourImage(image);

JFrame f = new JFrame();

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.getContentPane().add(yourImage);

f.setSize(400,400);

f.setLocation(200,200);

f.setVisible(true);

// For the EDT after we leave main.

EventQueue.invokeLater(new Runnable() {

public void run() {

yourImage.save();

}

});

}

}

crwooda at 2007-7-7 17:55:39 > top of Java-index,Security,Cryptography...
# 4

crwood, that's a lot of boilerplate :-) Why not just use a JLabel for stuff like that? (With an icon and a label).

Furthermore, the save method has many deficiencies. It starts an ad-hoc thread without reason (the caller can do this, if he really wants). Sleeps for 3 seconds (without even providing a Future back to the caller - how is the caller supposed to know when the action he requested is actually done?) for obscure reasons (what's about UI settling down?). Finally, it's a bit funny to spend effort to make the save() call happen in the EDT, when save() just spawns a new thread anyway.

ounosa at 2007-7-7 17:55:39 > top of Java-index,Security,Cryptography...