【问题标题】:Generate thumbnail of website?生成网站缩略图?
【发布时间】:2012-05-06 00:40:05
【问题描述】:

对于我的应用程序,我需要动态创建网站缩略图。到目前为止,我从 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);
    }


}

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

【问题讨论】:

  • 除非您计算出缩略图的宽度和高度与网站图像的宽度和高度成正比,否则您会得到一个扭曲的缩略图。
  • @GilbertLeBlanc 现在如果我能得到任何缩略图我会很高兴
  • 我本来打算等着看有没有人有答案,但据我所知,Browser 类没有获取网页图像的方法。如果您使用的是 Swing,我建议您使用 Robot 类来获取图像。

标签: java swt


【解决方案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 解决方案,以便摆脱屏幕绘图。我相信链接的问题可能会帮助您走得更远。

【讨论】:

  • 人们不会将PaintListener 添加到Shall 对象,您将在其中对图像进行绘画,在这种情况下工作吗?类似于SWTzetcode.com/tutorials/javaswttutorial/painting 的绘画教程中的内容
  • 谢谢,这似乎正是我要找的。但是,我总是得到一个空图像(只是默认背景)。即使我没有在屏幕外渲染,也会发生这种情况。 IE。浏览器始终可见。
  • 奇怪,在 WinXP 上为我工作。但正如我已经写过的,google.com 实际上很棘手,因为它似乎是一个空页面 onLoad(我在这里谈论的是浏览器的 Javascript 事件)。页面本身稍后由 Javascript 呈现。添加 asyncExec 调用修复了该问题,但这可能是一个错误的修复,并且仅取决于时间。请尝试其他域,例如 stackoverflow.com。
  • @the.duckman 我尝试了很多其他域,但每次都遇到同样的问题:(
  • 该死的。您使用的是什么操作系统?我需要知道才能重现该行为。
【解决方案2】:

据我所知,当您使用 Browser 对象时,您加载的网页会直接呈现在您通过构造函数传递给它的 Composite 对象上。在您的情况下,它呈现在您的 Shell 项目上,这是一个窗口样式的对象。没有方法可以直接在 Image 对象上呈现网页。

不过,您可以尝试在 Canvas 对象上实例化您的浏览器并直接从那里保存图像。

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

【讨论】:

    【解决方案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 来获取我们实际上只感兴趣的网站内容。

    我发现Shellprint 方法,该方法采用GC 对象,该对象可以绘制包括图像和其他我们感兴趣的东西,文档说:“类 GC 是所有绘图的地方位于 SWT 支持的功能。实例用于在 Image、Control 或直接在 Display 上绘制。".

    然而,在这个特定的时刻,我不清楚如何让它完全按照我的意愿去做。无论如何,我提出这一点只是为了让你知道。我还需要进一步研究。

    【讨论】:

      【解决方案4】:

      也许您最好从一开始就将页面渲染到屏幕外。例如,对于这样的任务,您可以使用“飞碟”(仅限 xhtml,因此您需要整理)。似乎还有一些工具可以直接从 Java 接口 Webkit。

      【讨论】:

        猜你喜欢
        • 2011-12-06
        • 2011-06-02
        • 1970-01-01
        • 2015-12-13
        • 2017-05-01
        • 2010-10-15
        • 2013-11-23
        • 1970-01-01
        • 2016-09-29
        相关资源
        最近更新 更多