Creazy!

WEBエンジニア・ヤガーのテック・ガジェットブログ

技術情報

PHP + Mac + Bookmarklet でスクリーンキャプチャしてサムネイルとか

投稿日:


ターミナルを立ち上げて、おもむろに「screencapture test.png」と入力してreturnキーを押下すると画面全体のキャプチャ画像が「test.png」として保存されることになります(PNG形式)。

via: ウノウラボ Unoh Labs: Macでのスクリーンショットの撮り方まとめ

「Command+Shift+3」でスクリーンキャプチャが取れるのは知ってたんだけど、screencapture っていうマンマなコマンドが存在しているのは知りませんでした。
で、コマンドでキャプチャ取れるんならPHPからexecでコマンド実行してWEBページのサムネイル作ったりできるんじゃないか…とか思い付いてしまった。
PHP + Windowsとかなら結構簡単にできちゃうんだよなぁ。
PHP+Windowsでスクリーンショットやサムネイル作成 – Do You PHP はてな
秋元@サイボウズラボ・プログラマー・ブログ: PHP+Windowsでスクリーンショットやサムネイル作成
以下、だらだら続きます。

その1:シェルスクリプトからスクリーンキャプチャ

第1段階として、screencapture コマンドを使ってサイトのキャプチャを取れるようにしてみる。
こんなシェルスクリプト書いてみた。
mac_screencapture.sh

#!/bin/sh
export DYLD_LIBRARY_PATH=""
open -a Safari "$1"
sleep 5
/usr/sbin/screencapture /path/to/save/directory/capture_`date +%Y%m%d%H%M%S`.png

open コマンドで Safari を起動して、ページ読み込みを考えて5秒程スリープ。
で、screencapture コマンドでキャプチャを保存って手順です。
なぜか、DYLD_LIBRARY_PATHという環境変数がエラーになってしまったので無効化してます。
本当は、

unsetenv DYLD_LIBRARY_PATH

とかする気がするんだけどうまくいかなかった。
第1引数でURLを受けるので、

./mac_screencapture.sh http://creazy.net/

とかやると、こういうキャプチャがとれました。
シェルで撮ったキャプチャ
※クリックすると実際のサイズで表示されます。

その2:PHPからスクリーンキャプチャ

さて、その1で撮ったキャプチャはDocやメニューバーなど余計な部分が写ってしまっているので、なんとかブラウザの画面だけ抜き出したいです。
WindowsではCOM経由でウィンドウ情報を取得したりできるのでしょうが、Macではできなそう。
とりあえず、Safariウィンドウの座標XYと縦横幅を自分で調べて切り取るところまでやってくれるPHPスクリプトを書きました。

<?php
if ( $argv ) {             // コマンドモード
$url = $argv[1];
}
else if ( $_GET['url'] ) { // WEBモード
$url = $_GET['url'];
}
$file = '/path/to/save/directory/capture_'.date('Ymd_his').'.png';
$cmd  = 'export DYLD_LIBRARY_PATH="";';
$cmd .= 'open -a Safari "'.$url.'";';
$cmd .= 'sleep 5;';
$cmd .= '/usr/sbin/screencapture '.$file.';';
exec($cmd);
$im = imagecreatefrompng($file);
$safari_x = 39;   // SafariウィンドウのX座標
$safari_y = 98;   // SafariウィンドウのY座標
$safari_w = 1225; // Safariウィンドウのドキュメント幅
$safari_h = 685;  // Safariウィンドウのドキュメント高さ
$new_x = 400;     // サムネイルの横幅
$new_y = $safari_h * $new_x / $safari_w;
$newim = imagecreatetruecolor($new_x, $new_y);
imagecopyresampled($newim, $im, 0, 0, $safari_x, $safari_y, $new_x, $new_y, $safari_w, $safari_h);
imagepng($newim, $file);
?>

一応コマンドでも、WEB経由でも実行できるようにしてみました。
下記のように実行すると、

php -f mac_screencapture.php http://creazy.net/

こういうキャプチャがとれました。
PHPで撮ったキャプチャ
おー、ちゃんとサムネイルになってる!

その3:見ているページをスクリーンキャプチャするBookmarklet

その2までの仕組みで、PHPからサムネイルの出力に成功しました。
ということは、サムネイル生成のキューを貯めといて、cronでサムネイル生成スクリプトを実行とかすればSimpleAPIみたいなサムネイルサービスが作れるな。
でも、やっぱりPHP側でWindow情報を取得できていないのでサービスとしてはまだまだ課題が多過ぎるなぁ。
じゃあ、ローカルで動くサムネイラーとしてもっと有効活用できないかと思って考えついたのが見ているページをサムネイル化してくれるBookmarklet
まずは、サムネイル生成用のPHPを用意しますが基本的にはその2のスクリプトの下記部分がパラメータで渡されるという事だけ違うくらい。
・ウィンドウのX座標
・ウィンドウのY座標
・ウィンドウのドキュメント幅
・ウィンドウのドキュメント高さ
・サムネイルの横幅
ローカルでapache + PHPが起動している状態で下記URLにアクセスできるようにする。
http://localhost/mac_screencapture_bookmarklet.php
・mac_screencapture_bookmarklet.phpのソース

<?php
$file = '/path/to/save/directory/capture_'.date('Ymd_his').'.png';
$cmd  = 'export DYLD_LIBRARY_PATH="";';
$cmd .= '/usr/sbin/screencapture '.$file.';';
exec($cmd);
$im = imagecreatefrompng($file);
$x = $_GET['x']; // ウィンドウのX座標
$y = $_GET['y']; // ウィンドウのY座標
$w = $_GET['w']; // ウィンドウのドキュメント幅
$h = $_GET['h']; // ウィンドウのドキュメント高さ
$new_x = $_GET['size']; // サムネイルの横幅
$new_y = $safari_h * $new_x / $safari_w;
$newim = imagecreatetruecolor($new_x, $new_y);
imagecopyresampled($newim, $im, 0, 0, $x, $y, $new_x, $new_y, $w, $h);
imagepng($newim, $file);
?>

・登録するブックマークレット

javascript:(function(){var win=window,doc=document,ua=navigator.userAgent.toLowerCase(),isua=ua.indexOf('opera')+1||ua.indexOf('safari')+1;if(isua){w=win.innerWidth;h=win.innerHeight;}else{w=doc.documentElement.clientWidth||doc.body.clientWidth||doc.body.scrollWidth;h=doc.documentElement.clientHeight||doc.body.clientHeight||doc.body.scrollHeight;}off=140;x=win.screenX;y=win.screenY+off;size=400;s=doc.createElement('script');s.charset='UTF-8';s.src='http://localhost/mac_screencapture_bookmarklet.php?x='+x+'&y='+y+'&w='+w+'&h='+h+'&size='+size;doc.body.appendChild(s);})();

分かりやすい様に展開

javascript:(function(){
var win  = window;
var doc  = document;
var ua   = navigator.userAgent.toLowerCase();
var isua = ua.indexOf('opera')+1 || ua.indexOf('safari')+1;
// ドキュメントの縦横サイズを取得
if ( isua ) { // Safari or Opera
w = win.innerWidth;
h = win.innerHeight;
} else {
w = doc.documentElement.clientWidth || doc.body.clientWidth || doc.body.scrollWidth;
h = doc.documentElement.clientHeight || doc.body.clientHeight || doc.body.scrollHeight;
}
off = 140;             // ブラウザのメニューバーの縦幅(自分で調べる)
x   = win.screenX;     // ドキュメントのX座標
y   = win.screenY+off; // ドキュメントのY座標(ブラウザのY座標からメニューバーの高さを引く)
size = 400;            // サムネイルのサイズ(任意)
s = doc.createElement('script');
s.charset = 'UTF-8';
s.src = 'http://localhost/mac_screencapture_bookmarklet.php?x='+x+'&y='+y+'&w='+w+'&h='+h+'&size='+size;
doc.body.appendChild(s);
})();

ブクマークレットならJavaScriptでブラウザの情報が直接確認できるので、それをPHPスクリプトに渡してやれば良い。
唯一、ブラウザのメニューバーを除いたドキュメントの座標の取り方が分からなかったので自分で調べた。
ものさしで調べる
適当に見つけたものさしツールで簡単に計る事ができた。
Free Ruler for Mac OS X
で、オレのFirefoxは140pxだったのでそれをoff変数に代入してある。
さて、このブックマークレットを実行すると、
bookmarkletで撮ったキャプチャ
うん、成功。
Bookmarklet版はWindowサイズを動的に取得できるので、結構汎用的かも。
それに、PHPで画像保存するなら、GDなりImageMagickなりで自分好みに変形したものなんかも作れそう。

まとめ

思い付きからついカッとなってやってみたわけで、結果一応は成功したんだけども、どうにも変態的なコードを書いてしまったような気がする。
PHPでってところにこだわったせいか、なんかまわりくどいんだよなぁ。しかも、ローカルでApache + PHP動いてないといけないとか。
なんかスマートな方法あったら教えて下さい。>エラい人

ブラウザの見えていない部分もスクロールしてキャプチャーする方法色々(無料のみ)

-技術情報

執筆者:


  1. 藤棚 より:

    通りすがりにて。
    私は使ってませんが
    http://hmdt.jp/coral/
    がこの目的にはいかがでしょう。
    コマンドラインの簡単な画像処理ならOS X付属のsipsがあります。PHPを使わずとも,簡単な画像の変換,リサイズやトリムは一通りできます。
    screencaptureにこだわるなら, JavaScriptの代わりに,AppleScriptもありかな。osascriptでAppleScriptを呼び出せるので,簡単には以下で。
    osascript -e “bounds of window 1 of application \”Safari\””
    AppleScriptでウインドウのスクロールバーやツールバーの幅を知る方法は,ぱっと見た限りなさそうです。

  2. yager より:

    >藤棚さん
    > http://hmdt.jp/coral/
    おお、良さそうですね。今度ためしてみます。

comment

メールアドレスが公開されることはありません。

関連記事

CakePHP勉強会第4回@Tokyo:参加レポート

第4回CakePHP勉強会@Tokyoに参加してきました。 ・第4回CakePHP勉強会@Tokyo ・cakephpstudy on USTREAM: . Conference 今回、勉強会としては …

twitter とか tumblr. とか Vox とかを試してみた

最近ブロガーの間で twitter とか tumblr. が流行っているらしい。このクリフォトの更新も波にのってきているとはいえ、ちょっとマンネリ気味なのもあって刺激を求めてこいつらを試してみる事にし …

Google Chrome で CSS Animation して遊んでみた

今日はどこもかしこもGoogle Chromeの話題で持ち切りでしたね。 Chrome はあの Google が開発したブラウザーです。 早速使ってみましたが、噂に違わぬ爆速ぶりでデフォルトブラウザに …

A Letter From Google : Adsense PIN のメールが届いた

昨日、自宅のポストに見慣れた可愛いロゴの手紙が入っていた。 どうみてもGoogleのロゴですな。 そういえば、先日AdsenseのPINを送る旨のメールが来ていたなぁと思い開けてみると、やっぱりそうで …

300エントリー突破で考える「クチコミの技術」

7月のランキングをまとめていた時に偶然気がつきました。 いつのまにか累計エントリー数が300を超えていたのです。 (ちなみに300番目は「夜景がキレイ」という気の抜けたminiエントリーだった…)

スポンサードリンク

スポンサードリンク