10

私のアプリケーションでは、Webサイトのサムネイルを動的に作成する必要があります。これまでのところ、私は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);
    }


}

しかし、ここでわかるように、ブラウザのどの部分をキャプチャメソッドに渡す必要があるのか​​わかりません。ヒントはありますか?

4

4 に答える 4

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

}

ただし、いくつかの重大な注意事項があります。

  • これを画面外で行うことはできません。SWT のスクリーンショットは、現在のディスプレイの単なるコピーです。
  • スクリーンショットを撮るときは、ブラウザを含むウィンドウが一番上にある必要があります。
  • ページは onLoad 後に表示されるはずです (これは実際には google.com には当てはまりませんが、とにかく asyncExec 呼び出しのために機能します。白い画像が表示された場合は、別の URL を試してください)。
  • 結果は、OS とインストールされているブラウザによって異なります。

画面描画から抜け出すために、Java以外のソリューションを使用します。リンクされた質問は、さらに先に進むのに役立つと思います。

于 2012-05-05T16:40:05.570 に答える
4

私の知る限り、Browser オブジェクトを使用すると、ロードした Web ページは、コンストラクターを介して渡す Composite オブジェクトに直接レンダリングされます。あなたの場合、ウィンドウ スタイルのオブジェクトであるシェル アイテムでレンダリングされます。たとえば、Image オブジェクトに Web ページを直接レンダリングする方法はありません。

ただし、Canvas オブジェクトで Browser をインスタンス化し、そこから直接画像を保存することはできます。

残念ながら、Eclipse も SWT もインストールしていないため、これが機能するかどうかをテストできません。ただし、やりたいことが実行可能であれば、これが唯一の方法だと確信しています。

于 2012-05-01T19:15:38.177 に答える
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)に同意する必要があります。これは、サイトのコンテンツを取得するために何らかの方法でシェルを使用する必要があるということです。

シェルには、画像やその他の興味深いものを含めてペイントできるGCprintオブジェクトを取るメソッドがあることがわかりました。ドキュメントには次のように書かれています: 「クラスGCは、SWTでサポートされているすべての描画機能が配置されている場所です。インスタンスは画像、コントロール、またはディスプレイに直接描画します。」.

しかし、現時点では、私がやりたいことを正確に実行する方法は明確ではありません。とにかく、私はあなたに気づいてもらうためにこの点を提起しています。私はまだそれをさらに調べる必要があります。

于 2012-05-04T15:32:43.193 に答える
2

おそらく、最初からオフスクリーンでページをレンダリングするほうがよいでしょう。このようなタスクには、たとえば「空飛ぶ円盤」を使用できます (これは xhtml のみであるため、整理する必要があります)。Java から Webkit を直接インターフェースするためのツールもいくつかあるようです。

于 2012-05-04T15:33:10.823 に答える