エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

スクリーンイメージをほかのPCと共有する

要は。今の仕事はメンバが複数箇所に分散してまして、全体の会議となると電話会議しかなくて、お互い喋ってることしかわからない。一カ所にいればプロジェクタで表示して、そこで議事録書いたりできるのだけれど。
で、最初、PCを共有するツールがないかと考えた。だけどそもそも操作は一人でいいわけで、ほかはその画面が見えればいいわけでそこまで機能は必要ない。
で、次に、スクリーンイメージを共有するツールがないかと考えた。それだったら、スクリーンイメージをキャプチャしてその画像を送りつけるだけでもいいんじゃね?と思いなおし。
で、最後に、キャプチャした画像がほかのPCから見えればいいんだから、webサーバを起動しておいて、数秒ごとにスクリーンイメージをキャプチャした画像をクライアント側から読み込んでもらえばいいじゃないか、という結論に到達。


そういや昔、スクリーンイメージをキャプチャするサンプルコード書いたなぁ、と思い出し、化石化している自分のWebサイトを捜索。

Delphi製だった…orz。

いやDelphiは好きなんだけれども、インストールしてあるPCはすでになく。Lazarusはインストールしてあったので、これでビルドできるかなぁとためしたものの、やっぱりダメだった。


もののついでに、字数稼ぎにスクリーンをキャプチャするDelphiのサンプルコードを上げときます。って、スーパーpre記法にDelphiないんだ…。

// ウィンドウ・イメージをキャプチャ

unit Captures;

interface

uses
  Windows, Graphics, SysUtils, Classes;

// ウィンドウ・イメージをキャプチャする
//
// 引数
//   Handle キャプチャするウィンドウのハンドル
//          (GetDesktopWindow を渡すとデスクトップをキャプチャ)
//   Bitmap キャプチャしたウィンドウのイメージを格納する TBitmap オブジェクト
procedure CaptureWindow(Handle: THandle; Bitmap: TBitmap);

implementation

procedure CaptureWindow(Handle: THandle; Bitmap: TBitmap);
var
  Canvas:  TCanvas;
  DC:      HDC;
  SrcRect: TRect;
  DstRect: TRect;
begin
  // ウィンドウ の DC を取得
  DC := GetDC(Handle);
  try
    // ウィンドウ 用の Canvas を作成
    Canvas := TCanvas.Create;
    try
      // Canvas に ウィンドウ の DC を割り当て
      Canvas.Handle := DC;

      // コピー元領域設定
      if not GetWindowRect(Handle, SrcRect) then
      begin
        raise Exception.Create('Window のサイズを取得できません');
      end;

      // コピー先の Bitmap の準備
      Bitmap.PixelFormat := pf24bit;
      Bitmap.Width       := SrcRect.Right - SrcRect.Left;
      Bitmap.Height      := SrcRect.Bottom - SrcRect.Top;

      // コピー先の範囲
      DstRect.Left       := 0;
      DstRect.Top        := 0;
      DstRect.Right      := SrcRect.Right - SrcRect.Left;
      DstRect.Bottom     := SrcRect.Bottom - SrcRect.Top;

      // ウィンドウ から Bitmap へ複写
      Bitmap.Canvas.CopyRect(DstRect, Canvas, SrcRect);
    finally
      // Canvas の破棄
      Canvas.Free;
    end;
  finally
    // ウィンドウ の DC の開放
    ReleaseDC(Handle, DC);
  end;
end;

end.
program Capture;

uses
  Windows, Graphics, Captures;

var
  Bitmap: TBitmap;
begin
  Bitmap := TBitmap.Create;
  try
    CaptureWindow(GetDesktopWindow, Bitmap);
    Bitmap.SaveToFile('capture.bmp');
  finally
    Bitmap.Free;
  end;
end.


検索の旅に出たところJavaで実装されている方をみつけたので、それをもとに書いてみました。


エラー処理も難にもしてないです。
Ctrl+Cで止めてください(ひでー)。

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class ScreenCapture
{
    public static void main(String[] args)
    {
        try
        {
            String    dirName  = "./";
            String    fileName = "screen.jpg";
            File      file     = new File(dirName, fileName);
            Robot     robot    = new Robot();
            Dimension dim      = Toolkit.getDefaultToolkit().getScreenSize();
            Rectangle bounds   = new Rectangle(0, 0, dim.width, dim.height);
            for(;;)
            {
                BufferedImage image = robot.createScreenCapture(bounds);
                ImageIO.write(image, "jpg", file);
                Thread.currentThread().sleep(10000);
            }
        }
        catch(AWTException e)
        {
            e.printStackTrace();
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
        catch(InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}


書くまでもない気がしますが、こういうHTMLファイルをクライアントで読み込んでもらえばいい…気がします(もしかしたらこれだとキャッシュとかの関係で画像が更新されないのかな?)。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="refresh" content="10" />
<title>すくり〜ん</title>
</head>
<body>
<img src="./screen.jpg" />
</body>
</html>