I've got a method that's supposed to add some text to screenshots. The screenshot is fed into this method as a File object like this:
private void modifyScreenshot(File file) throws Exception {
String textToAdd = "Something something";
BufferedImage image = ImageIO.read(file);
Graphics g = image.getGraphics();
At this point, adding the text via g.drawString is easy to do. However, I want the text to not cover any of the actual screenshot, but be in a white area "above" the screenshot.
What I mean is, at this point, this is what the Graphics object looks like when it gets saved to file:
However, I want it to look like this instead, with the "Some text some text" being the string I specify in the code.
So, how would I be able to add white rectangle above the image where the text can be written?
EDIT: Note, this is not simply adding a string to an image. This involves "enlarging" the canvas to have white space for the string, so that the string is not over the actual image.
Here's the rough idea:
BufferedImage image = ImageIO.read(file);
int whiteSpaceHeight = 20;
BufferedImage result = new BufferedImage(image.getWidth(),
image.getHeight()+whiteSpaceHeight, image.getType());
Graphics graphics = result.getGraphics();
graphics.drawImage(image, 0, whiteSpaceHeight, null);
graphics.drawString(textToAdd, 0, whiteSpaceHeight/2);
(Edit: Answer was rewritten - see history for details)
The task that is indicated in the example image may in fact be a bit tricky: Namely, having multi-line text. But one simple solution here is to use a JLabel and a CellRendererPane for rendering the text, because it also supports HTML. So for a title like
String title =
"<html><font size=4>This <font color=#FF0000><b>Text</b></font><br>" +
"with line breaks<br>" +
"will be the title</font></html>");
with line breaks and colors and a dedicated font size, one can obtain the appropriate image:
Here is an example showing how this may be achieved:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.swing.CellRendererPane;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TitleAdder
{
public static void main(String[] args)
{
addTitle("yS2aQ.png", "output.png",
"<html><font size=4>This <font color=#FF0000><b>Text</b></font><br>" +
"with line breaks<br>" +
"will be the title</font></html>");
}
private static void addTitle(
String inputFileName, String outputFileName, String title)
{
try (InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFileName))
{
BufferedImage sourceImage = ImageIO.read(in);
BufferedImage targetImage =
addTitle(sourceImage, title);
ImageIO.write(targetImage, "png", out);
// Show the image, for testing
show(targetImage);
}
catch (IOException e)
{
e.printStackTrace();
}
}
private static BufferedImage addTitle(
BufferedImage sourceImage, String title)
{
JLabel label = new JLabel(title);
label.setBackground(Color.WHITE);
label.setForeground(Color.BLACK);
label.setOpaque(true);
int titleHeight = label.getPreferredSize().height;
int height = sourceImage.getHeight() + titleHeight;
BufferedImage targetImage = new BufferedImage(
sourceImage.getWidth(), height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = targetImage.createGraphics();
SwingUtilities.paintComponent(g, label, new CellRendererPane(),
0, 0, sourceImage.getWidth(), titleHeight);
g.drawImage(sourceImage, 0, titleHeight, null);
g.dispose();
return targetImage;
}
private static void show(final BufferedImage image)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
JFrame f = new JFrame();
f.getContentPane().add(new JLabel(new ImageIcon(image)));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
Related
I am making a 2d game and I need to draw an image on top of another. After I draw the first image(the larger one, jpg), the second image(the smaller one,png) erases from where the second image is to the lower right hand corner. Like this:
I have looked into this a bit, and it was suggested that I use buffered images, so I did that with both images and the problem remains. Here is one post I looked at: How to draw an image over another image?. I have also seen some people suggesting graphics2d, though I did not really understand the reason to use them or how to use them. I am new to java graphics and images, so it is probably a silly mistake.
Here is my code. Thank you.
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import javax.swing.*;
import java.util.ArrayList;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.IOException;
public class DisplayExample extends JComponent
{
private BufferedImage backgroundImage;
private String backgroundName;
private BufferedImage image; //image to draw
private int imageX; //position of left edge of image
private int imageY; //position of top edge of image
private JFrame frame;
public static void main(String[] args)
{
DisplayExample example = new DisplayExample();
example.run();
}
public DisplayExample()
{
imageX = 200;
imageY = 200;
backgroundName = "backgroundShip.jpg";
URL backgroundURL = getClass().getResource(backgroundName);
if (backgroundURL == null)
throw new RuntimeException("Unable to load: " + backgroundName);
try{backgroundImage = ImageIO.read(backgroundURL);}catch(IOException ioe){}
//load image
String fileName = "explosion.png";
URL url = getClass().getResource(fileName);
if (url == null)
throw new RuntimeException("Unable to load: " + fileName);
//image = new ImageIcon(url).getImage();
try{image = ImageIO.read(url);}catch(IOException ioe){}
System.out.println(image instanceof BufferedImage);
setPreferredSize(new Dimension(1040,500)); //set size of drawing region
//need for keyboard input
setFocusable(true); //indicates that WorldDisp can process key presses
frame = new JFrame();
frame.getContentPane().add(this);
frame.pack();
frame.setVisible(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(backgroundImage != null)
g.drawImage(backgroundImage,0,0,getWidth(), getHeight(), null);
g.drawImage(image, imageX, imageY, this);
}
public void run()
{
while(true)
{
imageY+=1;
repaint();
try{Thread.sleep(100);}catch(Exception e){}
}
}
}
So I took your code, added my own images and it runs fine for me.
Having said that, there are some areas you can improve:
You're running the risk of either blocking the Event Dispatching Thread or introducing a thread race condition into your code with your run method. You should consider using a Swing Timer instead. See How to use Swing Timers for more details. This allows you to schedule regular callbacks which are called within the context of the EDT, making it safer to update the context of the UI
You should only ever create or modify the state of the UI from within the context of the EDT, Swing is not thread safe. See Initial Threads for more details. Swing has been known to have "issues" when the UI is not initialised within the EDT
Scaling an image is expensive, you should avoid doing so from within the paint methods, instead, scale the image and keep a reference to the result and use it when you need to paint it.
You should consider using the key bindings API over KeyListener, it will solve many of the issues associated with using KeyListener. See How to Use Key Bindings for more details.
For example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DisplayExample extends JComponent {
private BufferedImage backgroundImage;
private String backgroundName;
private BufferedImage image; //image to draw
private int imageX; //position of left edge of image
private int imageY; //position of top edge of image
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DisplayExample example = new DisplayExample();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(example);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public DisplayExample() {
imageX = 200;
imageY = 200;
try {
backgroundImage = ImageIO.read(new File("..."));
} catch (IOException ioe) {
ioe.printStackTrace();
}
//load image
try {
image = ImageIO.read(new File("..."));
} catch (IOException ioe) {
ioe.printStackTrace();
}
//need for keyboard input
//setFocusable(true); //indicates that WorldDisp can process key presses
// Use the key bindings API instead, causes less issues
Timer timer = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
imageY += 1;
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return backgroundImage == null ? new Dimension(200, 200) : new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (backgroundImage != null) {
// Scaling is expensive, don't do it here
int x = (getWidth() - backgroundImage.getWidth()) / 2;
int y = (getHeight() - backgroundImage.getHeight()) / 2;
g2d.drawImage(backgroundImage, x, y, this);
}
g2d.drawImage(image, imageX, imageY, this);
g2d.dispose();
}
}
I am working on a project related to colored image manipulation using JAVA.
I got to know the conversion of the colored image into a matrix using a getSample method of Raster class,
pixels[x][y]=raster.getSample(x,y,0);
I got the matrix in pixels[][] (only the values in red band).
Then i converted the matrix back to image using WritableRaster as,
raster.setSample(i,j,0,pixels[i][j]);
I converted it to image using,
*BufferedImage image=new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
image.setData(raster);*
But the problem is,
1) I want the colored image to be displayed as it is whereas i am getting only a particular band(like only red, only blue . . ) because I have to specify a band as per the prototype of the method setSample and getenter code hereSample.
2) How can i get a 2d matrix representing a colored image(of all 3 bands represented in 3 different matrices)
Here is the code that i wrote with the help of snippets of code online...
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
class TestImage {
ImageIcon icon;
SampleModel sampleModel;
public static void main(String args[]){
TestImage mamu = new TestImage();
File file = new File("photo.jpg");
mamu.compute(file);
}
public void compute(File file){
try{
BufferedImage img= ImageIO.read(file);
Raster raster=img.getData();
sampleModel = raster.getSampleModel();
int w=raster.getWidth(),h=raster.getHeight();
int pixels[][]=new int[w][h];
for (int x=0;x<w;x++){
for(int y=0;y<h;y++){
pixels[x][y]=raster.getSample(x,y,0);
}
}
Image image = getImage(pixels);
JFrame frame = new JFrame("uff");
ImageIcon icon = new ImageIcon(image);
JLabel label = new JLabel(icon);
frame.setContentPane(label);
frame.setVisible(true);
frame.setSize(200,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}catch (Exception e){
e.printStackTrace();
}
}
public java.awt.Image getImage(int pixels[][]){
int w=pixels.length;
int h=pixels[0].length;
WritableRaster raster= Raster.createWritableRaster(sampleModel, new Point(0,0));
for(int i=0;i<w;i++){
for(int j=0;j<h;j++){
raster.setSample(i,j,0,pixels[i][j]);
}
}
BufferedImage image=new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
image.setData(raster);
File output=new File("check.jpg");
try {
ImageIO.write(image,"jpg",output);
}catch (Exception e){
e.printStackTrace();
}
return image;
}
}
You may be looking or java.awt.image.LookupOp, which uses a java.awt.image.LookupTable to modify bands en bloc. Several examples are cited here. The image below illustrates inversion:
short[] invert = new short[256];
for (int i = 0; i < 256; i++) {
invert[i] = (short) (255 - i);
}
BufferedImageOp invertOp = new LookupOp(new ShortLookupTable(0, invert), null));
invertOp.filter(src, dst);
I want to display an image but don't know what to do. Whether I have to install some library files or simply it can be done I don't know. Actually I want to do image processing, but first I have to take the image input and display image then I can get the effect of image processing as the output and decide whether it(algorithm) is correct or not. I have installed the eclipse only. I have searched in Google also but whatever they suggest is not working well. Either I have to install something or not.
I have tried the following code:
public class ImageTest {
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
public void run(){
ImageFrame frame = new ImageFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
);
}
}
class ImageFrame extends JFrame{
public ImageFrame(){
setTitle("ImageTest");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
ImageComponent component = new ImageComponent();
add(component);
getContentPane().validate();
getContentPane().repaint();
}
public static final int DEFAULT_WIDTH = 300;
public static final int DEFAULT_HEIGHT = 200;
}
class ImageComponent extends JComponent{
private static final long serialVersionUID = 1L;
private Image image;
public ImageComponent(){
try{
File image2 = new File("bishnu.jpg");
image = ImageIO.read(image2);
} catch (IOException e){
e.printStackTrace();
}
}
public void paintComponent (Graphics g){
if(image == null) return;
int imageWidth = image.getWidth(this);
int imageHeight = image.getHeight(this);
g.drawImage(image, 50, 50, this);
for (int i = 0; i*imageWidth <= getWidth(); i++)
for(int j = 0; j*imageHeight <= getHeight();j++)
if(i+j>0) g.copyArea(0, 0, imageWidth, imageHeight, i*imageWidth, j*imageHeight);
}
}
It simply shows a graphical window but can't show the image "bishnu.jpg"
Should I install anything in eclipse? But I think nothing needs to install.
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
public class DisplayImage {
public static void main(String avg[]) throws IOException
{
DisplayImage abc=new DisplayImage();
}
public DisplayImage() throws IOException
{
BufferedImage img=ImageIO.read(new File("f://images.jpg"));
ImageIcon icon=new ImageIcon(img);
JFrame frame=new JFrame();
frame.setLayout(new FlowLayout());
frame.setSize(200,300);
JLabel lbl=new JLabel();
lbl.setIcon(icon);
frame.add(lbl);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Running your code shows an image for me, after adjusting the path. Can you verify that your image path is correct, try absolute path for instance?
If you want to load/process/display images I suggest you use an image processing framework. Using Marvin, for instance, you can do that easily with just a few lines of source code.
Source code:
public class Example extends JFrame{
MarvinImagePlugin prewitt = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.edge.prewitt");
MarvinImagePlugin errorDiffusion = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.halftone.errorDiffusion");
MarvinImagePlugin emboss = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.color.emboss");
public Example(){
super("Example");
// Layout
setLayout(new GridLayout(2,2));
// Load images
MarvinImage img1 = MarvinImageIO.loadImage("./res/car.jpg");
MarvinImage img2 = new MarvinImage(img1.getWidth(), img1.getHeight());
MarvinImage img3 = new MarvinImage(img1.getWidth(), img1.getHeight());
MarvinImage img4 = new MarvinImage(img1.getWidth(), img1.getHeight());
// Image Processing plug-ins
errorDiffusion.process(img1, img2);
prewitt.process(img1, img3);
emboss.process(img1, img4);
// Set panels
addPanel(img1);
addPanel(img2);
addPanel(img3);
addPanel(img4);
setSize(560,380);
setVisible(true);
}
public void addPanel(MarvinImage image){
MarvinImagePanel imagePanel = new MarvinImagePanel();
imagePanel.setImage(image);
add(imagePanel);
}
public static void main(String[] args) {
new Example().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Output:
As a beginer, I found that is easy to see the picture you draw:
Source code
public class CheckCodeTest {
private int width = 100, height = 50;
private BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
#Test
public void drawGraphicsTest() throws IOException {
Graphics graphics = image.createGraphics();
// draw an orange rectangle
graphics.setColor(Color.orange);
graphics.fillRect(0,0,width,height);
// layout the picture right now!
graphics.drawImage(image,0,0,null);
ImageIO.write(image, "png", new File("checkcode.png"));
}
}
Output
It produce a picture file under your projects content.
output-picture
Then you can see what change after adding draw code in small window, it is more convenient than closing an jump-out Frame / Label window:
output-picture-in-editor
Hope it helps.
For my application I need to dynamically create thumbnails of websites. So far I have this code from SO:
public class CreateWebsiteThumbnail {
private static final int WIDTH = 128;
private static final int HEIGHT = 128;
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
public void capture(Component component) {
component.setSize(image.getWidth(), image.getHeight());
Graphics2D g = image.createGraphics();
try {
component.paint(g);
} finally {
g.dispose();
}
}
private BufferedImage getScaledImage(int width, int height) {
BufferedImage buffer = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffer.createGraphics();
try {
g.drawImage(image, 0, 0, width, height, null);
} finally {
g.dispose();
}
return buffer;
}
public void save(File png, int width, int height) throws IOException {
ImageIO.write(getScaledImage(width, height), "png", png);
}
public static void main(String[] args) throws IOException {
Shell shell = new Shell();
Browser browser = new Browser(shell, SWT.EMBEDDED);
browser.setUrl("http://www.google.com");
CreateWebsiteThumbnail cap = new CreateWebsiteThumbnail();
cap.capture(What her?);
cap.save(new File("foo.png"), 64, 64);
}
}
But as you can see here, I don't know which part of the browser I should pass to my capture method. Any hints?
I don't see, how the code you provided could work. The Shell is not opened, it has no size, the Browser didn't get time to actually load anything, no event loop seems to be running to enable any drawing, ...
The following code does a screenshot of a page using SWT browser:
import java.io.IOException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class CreateWebsiteThumbnail {
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
public static void main( String[] args ) throws IOException {
final Display display = new Display();
final Shell shell = new Shell();
shell.setLayout(new FillLayout());
final Browser browser = new Browser(shell, SWT.EMBEDDED);
browser.addProgressListener(new ProgressListener() {
#Override
public void changed( ProgressEvent event ) {}
#Override
public void completed( ProgressEvent event ) {
shell.forceActive();
display.asyncExec(new Runnable() {
#Override
public void run() {
grab(display, shell, browser);
}
});
}
});
browser.setUrl("http://www.google.com");
shell.setSize(WIDTH, HEIGHT);
shell.open();
while ( !shell.isDisposed() ) {
if ( !display.readAndDispatch() ) display.sleep();
}
display.dispose();
}
private static void grab( final Display display, final Shell shell, final Browser browser ) {
final Image image = new Image(display, browser.getBounds());
GC gc = new GC(browser);
gc.copyArea(image, 0, 0);
gc.dispose();
ImageLoader loader = new ImageLoader();
loader.data = new ImageData[] { image.getImageData() };
loader.save("foo.png", SWT.IMAGE_PNG);
image.dispose();
shell.dispose();
}
}
But there are some serious caveats:
You cannot do this off-screen. SWT screenshots are just a copy of the current Display.
The window containing your browser must be on top, when taking the screenshot.
The page should be visible after onLoad (which is actually not the case with google.com, but works for me because of the asyncExec call anyway - if you get a white image, try another URL)
The result is dependant on your OS and its installed browsers
I'd go with a non Java-solution, in order to get off screen drawing. I believe the linked question might help you to get further.
As far as I know, when you use a Browser object, the webpage you load is rendered directly on the Composite object you pass to it through the constructor. In your case, it is rendered on your Shell item which is a window-style object. There is no method to render the webpage directly on, say, an Image object.
You can try, though, to instantiate your Browser on a Canvas object and save the image directly from there.
Unfortunately I am unable to test whether this works or not because I have neither Eclipse nor SWT installed; I am pretty sure though that, if what you want to do is doable, this is the only way.
I did some experimenting myself. My intuition was to try on JEditorPane just like mentioned in the answer your code is based on. I do not know of how much help it is going to be but it might help. I gives some results, but from obvious reasons, luck of css support etc in JEditorPane it all looks ugly.
This is my code:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.text.html.HTMLEditorKit;
public class WebPageToImageThumbnail {
public static void main(String[] a) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JEditorPane editorPane = new JEditorPane();
editorPane.setEditorKit(new HTMLEditorKit());
try {
editorPane.setPage(new URL("http://weblogs.java.net/blog/alex2d/archive/2008/12/jwebpane_projec.html"));
} catch (IOException ex) {
}
final JPanel panel = new JPanel(new BorderLayout());
panel.add(new JScrollPane(editorPane), BorderLayout.CENTER);
panel.add(new JButton(new AbstractAction("SAVE") {
#Override
public void actionPerformed(ActionEvent e) {
BufferedImage image = capture(editorPane);
try {
save(image, new File("foo.png"), 64, 64);
} catch (IOException ex) {
}
}
}), BorderLayout.SOUTH);
frame.setContentPane(panel);
frame.setSize(600, 400);
frame.setVisible(true);
}
});
}
public static BufferedImage capture(Component component) {
BufferedImage image = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB);//component.setSize(image.getWidth(), image.getHeight());
Graphics2D g = image.createGraphics();
try {
component.paint(g);
} finally {
g.dispose();
}
return image;
}
private static BufferedImage getScaledImage(BufferedImage image, int width, int height) {
BufferedImage buffer = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffer.createGraphics();
try {
g.drawImage(image, 0, 0, width, height, null);
} finally {
g.dispose();
}
return buffer;
}
public static void save(BufferedImage image, File png, int width, int height) throws IOException {
ImageIO.write(getScaledImage(image, width, height), "png", png);
}
}
I also did some digging about the SWT I found some thinks that might be of use, but since I currently luck time, I cannot test. From what I read I have to agree with #Emanuele Bezzi (+1) that we are going to have to use the Shell somehow to get the content of the site, in which we are effectively only interested.
I found out that Shell has print method which takes GC object which can paint including to Image and other interesting to us stuff, the documentation says: "Class GC is where all of the drawing capabilities that are supported by SWT are located. Instances are used to draw on either an Image, a Control, or directly on a Display.".
Yet at this particular moment it is not clear to me how to exactly get it to do what I want. Anyway I am raising this point just to make you aware. I still need to look into it further.
Maybe you're better off rendering the page offscreen right from the start. For such a task you may for example use "flying saucer" (which is xhtml only, so you need to tidy up). There seem to be also some tools to interface Webkit directly from Java.
I have checked similarly named questions, but they don't answer this use case.
Basically, I was to overlay some text (text) at a given coordinate (x,y) I have the below function in a package;
protected BufferedImage Process2(BufferedImage image){
Graphics2D gO = image.createGraphics();
gO.setColor(Color.red);
gO.setFont(new Font( "SansSerif", Font.BOLD, 12 ));
gO.drawString(this.text, this.x, this.y);
System.err.println(this.text+this.x+this.y);
return image;
}
I feel like im missing something patently obvious; every reference to Graphics2D I can find is dealing with either games or writing directly to a file but I just want a BufferedImage returned. with the overlay 'rendered'
In the current code, the image appears out the end unchanged.
Thanks!
The method drawString() uses x and y for the leftmost character's baseline. Numbers typically have no descenders; if the same is true of text, a string drawn at position (0,0) will be rendered entirely outside the image. See this example.
Addendum: You may be having trouble with an incompatible color model in your image. One simple expedient is to render the image and then modify it in situ.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/questions/2658663
*/
public class TextOverlay extends JPanel {
private BufferedImage image;
public TextOverlay() {
try {
image = ImageIO.read(new URL(
"http://cdn.sstatic.net/stackexchange/img/logos/so/so-logo.png"));
} catch (IOException e) {
e.printStackTrace();
}
image = process(image);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(image.getWidth(), image.getHeight());
}
private BufferedImage process(BufferedImage old) {
int w = old.getWidth() / 3;
int h = old.getHeight() / 3;
BufferedImage img = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(old, 0, 0, w, h, this);
g2d.setPaint(Color.red);
g2d.setFont(new Font("Serif", Font.BOLD, 20));
String s = "Hello, world!";
FontMetrics fm = g2d.getFontMetrics();
int x = img.getWidth() - fm.stringWidth(s) - 5;
int y = fm.getHeight();
g2d.drawString(s, x, y);
g2d.dispose();
return img;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
private static void create() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new TextOverlay());
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
create();
}
});
}
}