Java 生成网站的缩略图?

Java 生成网站的缩略图?,java,swt,Java,Swt,对于我的应用程序,我需要动态创建网站的缩略图。到目前为止,我有以下代码: public class CreateWebsiteThumbnail { private static final int WIDTH = 128; private static final int HEIGHT = 128; private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_IN

对于我的应用程序,我需要动态创建网站的缩略图。到目前为止,我有以下代码:

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);
    }


}

但正如您在这里看到的,我不知道应该将浏览器的哪一部分传递给我的捕获方法。有什么提示吗?

据我所知,在使用浏览器对象时,加载的网页会直接呈现在通过构造函数传递给它的复合对象上。在您的示例中,它在作为窗口样式对象的Shell项上渲染。没有直接在图像对象上呈现网页的方法

不过,您可以尝试在画布对象上实例化浏览器并直接从中保存图像


不幸的是,我无法测试这是否有效,因为我既没有安装Eclipse也没有安装SWT;我很确定,如果你想做的是可行的,这是唯一的办法。

我自己做了一些实验。我的直觉是尝试使用
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是SWT支持的所有绘图功能所在的位置。实例用于在图像、控件或直接在显示器上绘图。”


然而,在这个特殊的时刻,我不清楚如何让它做我想做的事情。不管怎样,我提出这一点只是想让你知道。我还需要进一步调查

也许您最好从一开始就将页面呈现在屏幕外。例如,对于这样的任务,您可以使用“飞碟”(这只是xhtml,所以您需要整理)。似乎还有一些工具可以直接从Java连接Webkit。

我不知道您提供的代码是如何工作的。
外壳
未打开,它没有大小,
浏览器
没有时间实际加载任何内容,似乎没有运行事件循环来启用任何图形

以下代码使用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的解决方案,以获得屏幕外的绘图。我相信链接的问题可能有助于你进一步了解。

除非你将缩略图的宽度和高度计算为与网站图像的宽度和高度成比例,否则你将得到一个扭曲的缩略图。@GilbertLeBlanc现在,如果我能得到任何缩略图,我将很高兴。我将等待,看看是否有人有答案,但据我所知,Browser类没有获取网页图像的方法。如果您使用的是Swing,我建议使用Robot类来获取图像。这里有一个裁剪实现:伙计们不会将
PaintListener
添加到
对象中,在该对象中您将对图像进行绘制,在这种情况下工作吗?类似于《代码》SWT的绘画教程,谢谢,这正是我想要的。但是,我总是得到一个空图像(只是默认背景)。即使我不在屏幕外渲染,也会发生这种情况。也就是说,浏览器一直可见。奇怪,在WinXP上对我有效。但正如我已经写过的,google.com实际上很棘手,因为它似乎是一个空页面onLoad(我在这里谈论的是浏览器的Javascript事件)。页面本身稍后由Javascript呈现。添加asyncExec调用修复了该问题,但这可能是一个错误的修复,并且只取决于时间。请尝试另一个域,例如stackoverflow.com.@the.duckman我尝试了很多其他域,但每次我都遇到相同的问题:(该死,你使用的是什么操作系统?我需要知道才能重现这种行为。