【PHP】画像データ文字列から画像の横幅と高さを取得する


APIなどで取得した画像のURLから、画像データを取得した際に画像の横幅と高さも取得する方法。

画像取得部分は既に実装済みだったのですが、新たに画像の横幅と高さが必要になったため、よい方法がないか調べた結果、GDライブラリの imagecreatefromstring、imagesx、imagesy を使用することにしました。

getimagesize を使えば、下記のように簡単にURLから横幅と高さを取得することができます。

list($width, $height) = getimagesize($url);

が、この場合「実データの取得」と「横幅、高さの取得」の2回 URL を叩く必要がでるため、速度が遅くなるのでこちらは却下。

実装済みのurlより画像を取得プログラムはこんな感じ。

// 初期化する
$curl = curl_init($url);

// タイムアウト
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);

// 返り値を文字列で取得
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);

// 実行する
$data = curl_exec($curl);

$error_number = curl_errno($curl);
$error_message = curl_error($curl);

// 閉じる
curl_close($curl);

// エラーが発生したら
if ($data === FALSE)
{
	// $error_number、$error_message、$urlなどをログに保存
}

画像ファイルの取得に、file_get_contents などではなく、cURL を使用しているのはこちらの方が動作が早いからです。
この辺は「file_get_contents cURL」などで検索すると色々と出てくるので、そちらに任せます。

今回追加した画像の横幅と高さを取得するプログラムがこちら。

$image = imagecreatefromstring($data);

// 幅
$width = imagesx($image);

// 高さ
$height = imagesy($image);

curl_exec で取得した $data を imagecreatefromstring関数に渡して、画像を新規作成し、その横幅と高さをそれぞれ imagesx と imagesy で取得しています。

折角なので、どの程度速度に差が出るのか調べてみました。
画像のURLを10個用意し、それぞれの取得にかかった時間と、その平均時間です。

◆ imagecreatefromstring
1 width:940 height:198 time:0.057245016098022
2 width:687 height:619 time:0.069268941879272
3 width:503 height:421 time:0.055033206939697
4 width:504 height:421 time:0.040925025939941
5 width:504 height:423 time:0.039738893508911
6 width:504 height:422 time:0.050230979919434
7 width:504 height:422 time:0.050395011901855
8 width:609 height:436 time:0.040589809417725
9 width:605 height:461 time:0.039741992950439
10 width:581 height:480 time:0.055176973342896
ave:0.049834585189819
◆ getimagesize
1 width:940 height:198 time:0.20524716377258
2 width:687 height:619 time:0.21880984306335
3 width:503 height:421 time:0.20294904708862
4 width:504 height:421 time:0.18598985671997
5 width:504 height:423 time:0.1845760345459
6 width:504 height:422 time:0.2015380859375
7 width:504 height:422 time:0.20126390457153
8 width:609 height:436 time:0.18370890617371
9 width:605 height:461 time:0.18281006813049
10 width:581 height:480 time:0.20241594314575
ave:0.19693088531494

10回では試行回数が少ないかと思いましたが、思ったよりも差が開きました。
「imagecreatefromstring」が平均で 0.05秒程度だったのに対し、「getimagesize」では 0.2秒程度かかりました。

getimagesize を使用して URL より直接画像サイズを取得するのは、GDライブラリが使えないなどの理由が無い限り、避けたほうが懸命ですね。

他にも、取得した画像データを一度ファイルに書き出して、getimagesizeを使用する方法が考えられます。(というか普通はこちらを先に試すよね)

・・・が、ちょっとプログラムが面倒なので試してません。
で終わろうかと思ったのですが、ここまできてそれは無いか・・・と思い試してみました。

画像データをファイルへ書き出す部分は、普通にこんな感じ。

// テンポラリファイルの作成
$temp_file = tempnam(sys_get_temp_dir(), 'Temp');

// テンポラリファイルに書き込み
$handle = fopen($temp_file, "w");
fwrite($handle, $data);
fclose($handle);

// テンポラリファイルから画像の幅と高さを取得
list($width, $height) = getimagesize($temp_file);

// テンポラリファイルの削除
unlink($temp_file);

計測結果がこちら。

◆ ファイル書き出し
1 width:940 height:198 time:0.047371864318848
2 width:687 height:619 time:0.055737018585205
3 width:503 height:421 time:0.046814918518066
4 width:504 height:421 time:0.0384681224823
5 width:504 height:423 time:0.036808013916016
6 width:504 height:422 time:0.047918081283569
7 width:504 height:422 time:0.049361944198608
8 width:609 height:436 time:0.037344932556152
9 width:605 height:461 time:0.037187814712524
10 width:581 height:480 time:0.046723127365112
ave:0.04437358379364

え~っと・・・。

うん、こっちの方が早かったです。。。

ファイルに書き出すのが面倒なので、画像データ文字列から直接、横幅と高さを取得出来る方法がないかな~と、探し始めたのが今回の事の発端だったのですが、最初から素直にファイルに書き出して取得していれば良かったですね。。。

「0.0498秒」と「0.0443秒」、一見すると大した差に見えないかもしれませんが、APIなどで複数回アクセスをすることを考えると早いに越したことはないですね。

テストに使用した画像のサイズが小さいこともあり、あまり差がないように見えるということもあるだろうと思い、大きいサイズで試してみました。
今度は、「cURL で画像データを取得」の部分を別個に分けて計測し、単純に「imagecreatefromstring」と「ファイル書き出し」での処理時間の差を比較できるようにしました。

まずは、cURL で画像取得にかかった時間がこちら。

◆ cURL
01 time:0.090460062026978
02 time:0.086920976638794
03 time:0.076326131820679
04 time:0.077839136123657
05 time:0.078439950942993
06 time:0.068161010742188
07 time:0.076191902160645
08 time:0.071757078170776
09 time:0.085734128952026
10 time:0.076704978942871
ave 0.078853535652161

画像サイズを大きくしたので、画像取得自体にかかる時間も増えています。

取得した画像データから imagecreatefromstring で画像を作成し、imagesx と imagesy で縦横を取得するのにかかった時間がこちら。

◆ imagecreatefromstring
01 width:1396 height:996 time:0.056331157684326
02 width:1920 height:1056 time:0.075820922851562
03 width:1680 height:940 time:0.050305128097534
04 width:1600 height:980 time:0.055998086929321
05 width:1840 height:980 time:0.062910079956055
06 width:1780 height:980 time:0.054359197616577
07 width:1830 height:960 time:0.064152002334595
08 width:1590 height:950 time:0.047601938247681
09 width:1920 height:1056 time:0.071624040603638
10 width:1650 height:1000 time:0.053611993789673
ave 0.059271454811096

取得した画像データをファイルに書き出し、getimagesize で縦横を取得するのにかかった時間がこちら。

◆ ファイル書き出し
01 width:1396 height:996 time:0.00076794624328613
02 width:1920 height:1056 time:0.00046300888061523
03 width:1680 height:940 time:0.00035810470581055
04 width:1600 height:980 time:0.00033402442932129
05 width:1840 height:980 time:0.00039386749267578
06 width:1780 height:980 time:0.0003209114074707
07 width:1830 height:960 time:0.00033903121948242
08 width:1590 height:950 time:0.00030994415283203
09 width:1920 height:1056 time:0.00043201446533203
10 width:1650 height:1000 time:0.00038290023803711
ave 0.00041017532348633

爆速ですね・・・。
画像サイズが大きくなるほど差が開くようです。

ということで、一度ファイルに書き出して縦横を取得する方法が一番早いということがわかりました。

面倒臭がらずに、一番単純な方法で実装するのが、一番動作が軽いという良い例になりました。

最終的な検証に使ったプログラムは下記です。
cURL で画像を取得する部分は、関数名「getFile」で関数化して「func_file.php」に保存してあります。

require_once 'func_file.php';

$img_array = array(
	1  => '画像のURL',
	2  => '画像のURL',
	3  => '画像のURL',
	4  => '画像のURL',
	5  => '画像のURL',
	6  => '画像のURL',
	7  => '画像のURL',
	8  => '画像のURL',
	9  => '画像のURL',
	10 => '画像のURL',
);

$time_total = 0;

echo '◆ cURL<br>';

foreach ($img_array as $img_key => $img_value)
{
	// 開始マイクロタイム
	list($msec, $sec) = explode(" ", microtime());
	$start = (float)$msec + (float)$sec;

	// 画像データを取得
	$data_image[$img_key] = getFile($img_value);

	// 終了マイクロタイム
	list($msec, $sec) = explode(" ", microtime());
	$end = (float)$msec + (float)$sec;

	$time = $end - $start;
	$time_total += $time;

	echo sprintf('%02d',$img_key),' time:',$time,'<br>';
}

$time_ave = $time_total / count($img_array);

echo 'ave ',$time_ave,'<br><br>';

$time_total = 0;

echo '◆ imagecreatefromstring<br>';

foreach ($img_array as $img_key => $img_value)
{
	// 開始マイクロタイム
	list($msec, $sec) = explode(" ", microtime());
	$start = (float)$msec + (float)$sec;

	// 画像データより新規イメージを作成
	$im = imagecreatefromstring($data_image[$img_key]);

	// 幅
	$width = imagesx($im);

	// 高さ
	$height = imagesy($im);

	// 終了マイクロタイム
	list($msec, $sec) = explode(" ", microtime());
	$end = (float)$msec + (float)$sec;

	$time = $end - $start;
	$time_total += $time;

	echo sprintf('%02d',$img_key),' width:',$width,' height:',$height,' time:',$time,'<br>';
}

$time_ave = $time_total / count($img_array);

echo 'ave ',$time_ave,'<br><br>';

$time_total = 0;

echo '◆ ファイル書き出し<br>';

foreach ($img_array as $img_key => $img_value)
{
	// 開始マイクロタイム
	list($msec, $sec) = explode(" ", microtime());
	$start = (float)$msec + (float)$sec;

	// テンポラリファイルの作成
	$temp_file = tempnam(sys_get_temp_dir(), 'Temp');

	// テンポラリファイルに書き込み
	$handle = fopen($temp_file, "w");
	fwrite($handle, $data_image[$img_key]);
	fclose($handle);

	// テンポラリファイルから画像の幅と高さを取得
	list($width, $height) = getimagesize($temp_file);

	unlink($temp_file);

	// 終了マイクロタイム
	list($msec, $sec) = explode(" ", microtime());
	$end = (float)$msec + (float)$sec;

	$time = $end - $start;
	$time_total += $time;

	echo sprintf('%02d',$img_key),' width:',$width,' height:',$height,' time:',$time,'<br>';
}

$time_ave = $time_total / count($img_array);

echo 'ave ',$time_ave,'<br><br>';

WindowsPCに「VMWare Player」を使用して仮想サーバを構築&CentOS6.5インストール


Windowsパソコンに、VMWare Player を使用して、Linuxサーバーのテスト環境を実装する。

目次
1.VMWare Player のインストール
2.CentOS6.5 のダウンロード
3.CentOS6.5 のインストール
4.TeraTerm から SSH 接続する
5.WinSCP を使用してファイル転送を行う

 

1.VMWare Player のインストール

ダウンロード VMware Player 6.0より、【VMware Player for Windows】をダウンロードして、インストールを行います。

 

2.CentOS6.5 のダウンロード

Download CentOSにアクセスして、画面中央下部の「Older Versions」より【then click here »】をクリックします。

ダウンロードしたいバージョンを選んでダウンロードする。
今回は、64bitのCentOS6.5を入れたいので、6.5の【x86_64】を選択します。
適当なミラーサイトを選んで【CentOS-6.5-x86_64-bin-DVD1.iso】をダウンロードします。

 

3.CentOS6.5 のインストール

1.VMware Player を起動し、【新規仮想マシンの作成】を選択

VMwareにCentOS6.5のインストール

 

2.【インストーラディスクイメージファイル】の【参照】で先ほどダウンロードした【CentOS-6.5-x86_64-bin-DVD1.iso】を選択

VMwareにCentOS6.5のインストール

 

3.アカウント設定

VMwareにCentOS6.5のインストール

ユーザー名とパスワードはログインで使用するので忘れないようにメモる。
今回はローカル環境なので、パスワードは簡単にしています。

 

4.仮想マシン名とディレクトリの設定

VMwareにCentOS6.5のインストール

 

5.ディスク容量の指定

VMwareにCentOS6.5のインストール

 

6.準備完了

VMwareにCentOS6.5のインストール

【完了】を押すとインストールが始まります。

 

7.CentOS起動

VMwareにCentOS6.5のインストール

インストールが終わると、起動するOSの選択画面が表示されるので【CentOS 6.5】を選んで起動。

VMwareにCentOS6.5のインストール

パスワードの入力を求められるので、「3.アカウント設定」で設定したパスワードを入力します。
これでインストールは終わりました。

 

8.仮想サーバのIPアドレスを確認

VMwareにCentOS6.5のインストール

メニューから、【Applications】>【System Tools】>【Terminal】と進み、ターミナルを起動し、下記のコマンドを打ちます。
 ※ 2014/09/17 「ifconfig」は非推奨コマンドのため「ip addr」に訂正

ip addr

VMwareにCentOS6.5のインストール

次に下記のコマンドで、SSH が稼働中か確認します。

/etc/rc.d/init.d/sshd status

VMwareにCentOS6.5のインストール

「running…」と表示されればOK。

次は接続環境を整えます。

 

4.TeraTerm から SSH 接続する

TeraTermを起動し、先ほど確認したIPアドレスを入力します。

VMwareにCentOS6.5のインストール

認証画面では、アカウント設定の際に入力した、ユーザー名とパスワードを入力します。

VMwareにCentOS6.5のインストール

ログインに成功すれば、コマンド入力画面が表示されます。

ただ、毎回パスワードを入力して接続するのは面倒なので、オートログインができるショートカットを作成しておきます。

下記の内容をテキストファイルに保存し、ファイル名は「VMware_CentOS.ttl」などとする。

USER_NAME = 'user'
PASSWD = 'pass'
HOST_NAME = '192.168.240.131'
PORT = '22'

sprintf '%s:%s /ssh /auth=password /user=%s /passwd=%s' HOST_NAME PORT USER_NAME PASSWD
COMMAND = inputstr

connect COMMAND

end

拡張子「ttl」のファイルが TeraTerm に関連付けされていれば、ダブルクリックするだけで、ログインできるようになります。

※関連付けの方法などは、以前書いた記事に載せているのでそちらをどうぞ。
Tera Termマクロ(SSH自動ログイン)

 

5.WinSCP を使用してファイル転送を行う

ソフトのダウンロードはWinSCP :: Downloadより、「Installation package」を選択。
インストールが完了したら、WinSCP を起動します。

VMwareにCentOS6.5のインストール

転送プロトコル:SFTP
ホスト名:IPアドレスを入力
ポート番号:22
ユーザ名:設定したユーザー名
パスワード:設定したパスワード

これらを入力したら【保存】を行い【ログイン】します。

これで作業環境が整いました。


誤って消した Google Chrome のブックマークの復活方法


ブックマークを消してしまった経緯

Chromeに会社で共有しているアカウントでログインをしてしまい、そちらを切断しようとしてユーザーデータまで消してしまいました。

 

Chrome にログインしたアカウントの切断

Chromeにログインしたアカウントを切断するには、【設定】>【ログイン】>【Googleアカウントを切断】だけでできます。

しかし、さらに【設定】>【ユーザー】>【このユーザーを削除】まで行ってしまったところ、ブックマークや保存されていたパスワードなど全て消えてしまいました。。。

 

ブックマークの復元

復旧方法を検索してみたところ、下記のサイトに詳しく書かれていました。
誤って削除したGoogle Chromeのブックマークを復元する方法 | OXY NOTES

大抵の人は上記のサイトに書かれている方法で解決できると思いますが、解決できなかった場合は、私の行った操作が参考になるかもしれません。

私が使っていたのは、Windows7 64bit だったので
C > Users > ユーザー名 > AppData > Local > Google > Chrome > User Data > Default
の中に、「Bookmarks」と「Bookmarks.bak」がありました。

テキストエディタで中身を確認してみたところ、幸いにも以前のブックマークのデータが残っていました。


1.そこで、まずはデスクトップに「Bookmarks.bak」をコピー

2.デスクトップにコピーした「Bookmarks.bak」を「Bookmarks」にリネーム

3.「Bookmarks」のコピーを、元の「Default」フォルダにアップ

4.Chromeの再起動

としましたが、ブックマークを復元できませんでした。

「User Data」フォルダを確認してみたところ、「Default」フォルダが削除されていました。

そこで「User Data」フォルダからエクスプローラーの検索機能で「Bookmarks」を検索してみたところ、「Profile 1」というフォルダに「Bookmarks」が新たに作られていることがわかりました。

詳しく調べたわけではないので推測になりますが、Chromeの設定で「ユーザーの削除」を行ってしまったので、再起動のタイミングで「Default」フォルダが削除され、新たに「Profile 1」というフォルダが作られたようです。

もし、「Default」が見つからずブックマークを復元できない場合は、「User Data」フォルダ内に別の名前でフォルダが作られている可能性がありますので、そちらを探してみると「Bookmarks」を見つけることができるかもしれません。

ただし、Chromeのユーザーを複数持っている場合は、別のユーザーのブックマークを上書きしないように注意してください。

上書き前に、そのフォルダの「Bookmarks」をテキストエディタで確認したり、「Bookmarks」のバックアップをとってから上書きすることをオススメします。