对于我的应用程序,我需要动态创建网站的缩略图。到目前为止,我有来自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);
}
}
但正如你在这里看到的,我不知道我应该将哪一部分浏览器传递给我的捕获方法。任何提示?
答案 0 :(得分:10)
我没有看到,您提供的代码如何工作。 Shell
未打开,没有大小,Browser
没有时间实际加载任何内容,似乎没有运行事件循环来启用任何绘图,...
以下代码使用SWT浏览器显示页面的屏幕截图:
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();
}
}
但有一些严重的警告:
我会使用非Java解决方案,以便离开屏幕绘图。我相信相关问题可能会帮助您进一步发展。
答案 1 :(得分:4)
据我所知,当您使用Browser对象时,您加载的网页将直接呈现在您通过构造函数传递给它的Composite对象上。在您的情况下,它将在您的Shell项目上呈现,这是一个窗口样式的对象。没有方法直接在图像对象上呈现网页。
但是,您可以尝试在Canvas对象上实例化浏览器并直接从那里保存图像。
不幸的是我无法测试这是否有效,因为我既没有安装Eclipse也没有安装SWT;我很确定,如果你想做的事情是可行的,这是唯一的方法。
答案 2 :(得分:3)
我自己做了一些实验。我的直觉是尝试JEditorPane
就像提到的那样in the answer your code is based on.我不知道它会有多大的帮助,但它可能有所帮助。我给出了一些结果,但是由于显而易见的原因,JEditorPane
中的css支持等运气看起来很丑陋。
这是我的代码:
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);
}
}
我也对SWT
进行了一些挖掘,我发现有些人认为可能有用,但由于我现在运气好,所以无法测试。根据我的阅读,我必须同意@Emanuele Bezzi(+1),我们将不得不以某种方式使用Shell来获取网站的内容,我们实际上只对其感兴趣。
我发现Shell有print
方法,它可以将GC对象包含在Image中,包括对Image和其他有趣的东西,文档说:“Class GC是SWT支持的所有绘图功能所在的位置。实例用于在图像,控件或直接在人机界面上绘图。“。
然而在这个特殊的时刻,我不清楚如何让它完全按照我的意愿去做。无论如何,我提出这一点只是为了让你知道。我还需要进一步研究。
答案 3 :(得分:2)
也许你最好从一开始就在屏幕外渲染页面。对于这样的任务,您可以使用“飞碟”(仅限xhtml,因此您需要整理)。似乎还有一些工具可以直接从Java接口Webkit。