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

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

関連記事

ガンダム占い

Yahoo!占いにガンダム占いってのがあったのでやってみました。 誕生日と血液型のデータを入力して導き出す宇宙世紀型の占い……それがガンダム占いです! 統計に基づいて全人類を48種類のガンダムキャラク …

パンダとペンギンとZenbackキーワーズ

さて、なかなか更新できない当ブログですがGoogle Analyticsでのアクセス解析は定期的に行なっています。記事を追加していないので仕方ないのですが、PV/UUともに下がりっぱなしの状態なのです …

ミニブログ(Twitter,Tumblr,Jaiku)をRSSアグリゲータとして使い倒す

※(追記:2007/10/17)twitter編のtwitterfeedの説明が間違っていたので直しました。sanbo-nさん、あざーす! マイクロブログ(とかミニブログ?)と呼ばれて大流行している …

no image

新型MacBook(Late 2008) は10月23日に到着予定

15日に発表されてソッコー注文した新型MacBookなんですが、まだ手元には届いていません>< BTOはUSキーボードだけなのですが、注文時点で「5〜7営業日で発送」となっていました。

AMN3周年記念パーティーに行ってきました #amn

今日、ブログクラブやイベントなどでお世話になっているアジャイルメディア・ネットワークさんの3周年記念パーティーがあるということで渋谷まで行ってきました。 アジャイルメディア・ネットワークは、2010年 …

スポンサードリンク

スポンサードリンク