Создать эскиз веб-сайта?
Для моего приложения мне нужно динамически создавать эскизы веб-сайтов. Пока у меня этот код из 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);
}
}
Но, как вы можете видеть здесь, я не знаю, какую часть браузера я должен передать методу захвата. Любые подсказки?
Ответы
Ответ 1
Я не вижу, как код, который вы предоставили, может работать. 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();
}
}
Но есть некоторые серьезные оговорки:
- Вы не можете сделать это за кадром. Скриншоты SWT - это всего лишь копия текущего дисплея.
- Окно, содержащее ваш браузер, должно быть сверху, при съемке экрана.
- Страница должна быть видимой после onLoad (что на самом деле не относится к google.com, но работает для меня из-за вызова asyncExec в любом случае - если вы получаете белое изображение, попробуйте другой URL-адрес)
- Результат зависит от вашей ОС и установленных браузеров.
Я бы пошел с не-Java-решением, чтобы выйти из экрана. Я считаю, что связанный вопрос может помочь вам в дальнейшем.
Ответ 2
Насколько я знаю, когда вы используете объект Browser, загружаемая вами веб-страница отображается непосредственно на объект Composite, который вы передаете ему через конструктор. В вашем случае он отображается в элементе Shell, который является объектом в стиле окна. Не существует способа отображения веб-страницы непосредственно, скажем, объекта изображения.
Однако вы можете попробовать создать экземпляр вашего браузера на объекте Canvas и сохранить изображение прямо оттуда.
К сожалению, я не могу проверить, работает ли это или нет, потому что у меня нет Eclipse или SWT; Я уверен, однако, что, если то, что вы хотите сделать, выполнимо, это единственный способ.
Ответ 3
Я немного экспериментировал. Моя интуиция заключалась в том, чтобы попробовать JEditorPane
точно так же, как упомянутый в ответе, на котором основан ваш код. Я не знаю, как много поможет, но это может помочь. Я даю некоторые результаты, но по очевидным причинам, удача css-поддержки и т.д. В JEditorPane
все выглядит уродливо.
Это мой код:
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 имеет метод print
, который принимает GC, который может рисовать, включая изображение и другие интересные нам материалы, в документации говорится: "Класс GC - это место, где расположены все возможности рисования, которые поддерживаются SWT. нарисуйте либо изображение, либо элемент управления, либо непосредственно на дисплее.".
Однако в этот конкретный момент мне непонятно, как точно заставить его делать то, что я хочу. В любом случае я поднимаю этот момент, чтобы вы знали. Мне все еще нужно заглядывать в нее дальше.
Ответ 4
Может быть, вам лучше сделать страницу за кадром с самого начала. Для такой задачи вы можете, например, использовать "летающую тарелку" (которая является только xhtml, поэтому вам нужно привести в порядок). Похоже, что есть некоторые инструменты для интерфейса Webkit непосредственно с Java.