【スポンサーリンク】

【WordPress】https化で「保護された通信」にするための注意点

ある日、WordPressで作ったサイトにラビッドSSLで証明書を購入し、マニュアル(自分の場合さくらインターネットなのでさくらのマニュアル)に沿って設定したが、httpsでアクセスしても「保護された通信」にはなってくれなかった。

どうやらアップロードした画像なんかのsrcもhttps化しないといけないみたい。考えてみればそれもそうか。

幸いさくらには専用のプラグインがあったので、それを使って一括変換。無事「保護された通信」に・・・ならない。と、思ったが、タイトルロゴやスライドショーといったテーマオプションなどから設定する特定の画像URLは自分で変えないといけないっぽい。それらの設定をおこない無事httpsに移行完了。

【PageSpeed Insights】.htaccessを修正するだけで大幅にサイトの速度を向上【圧縮を有効にする+ブラウザのキャッシュを活用】

.htaccessに下記を足すとPageSpeed Insightsのスコアが20ほど増えた。
これに加えてPageSpeed Insightsに指摘された画像を適切なサイズに落とせば、ほぼ確実に緑スコアになるんじゃなかろうか。
(もちろん重たいJavascriptが動いてたり、サーバのスペックが足りてない場合などはダメだが…)

<ifModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 seconds"
ExpiresByType text/html "access plus 1 seconds"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType text/css "access plus 1 days"
ExpiresByType text/javascript "access plus 7 days"
ExpiresByType application/javascript "access plus 7 days"
ExpiresByType application/x-javascript "access plus 7 days"
</ifModule>

<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE font/opentype font/ttf font/eot font/otf
</IfModule>

ちなみに、これらはPageSpeed Insightsの「圧縮を有効にする」と「ブラウザのキャッシュを活用」の対策になっている。

参考文献
http://www.hirok-k.com/blog/2606.html
http://ittoybox.com/archives/253

【Unity 3D】クリック(タップ)先のゲームオブジェクトおよび座標の取得

Physics.Raycastでクリック先のオブジェクトと交点座標を取得できる。引数に必要なRayオブジェクトはメインカメラ一つの場合、
Camera.main.ScreenPointToRay(Input.mousePosition)
で取得できる。

なお、Physics.Raycastの返り値はbool値となっており、肝心のクリック先オブジェクトは参照渡しした変数に返すため、コードの見やすさを考慮すると用途に応じてラップしたほうが良いと思われる。

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour {
	void Update() {
		if(Input.GetKeyDown(KeyCode.Mouse0)) {
			Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
			Debug.Log(HitGameObject(ray) == null ? null : HitGameObject(ray).name);
			Debug.Log(HitPoint(ray));
		}
	}

	//クリック先のオブジェクトを取得する関数
	GameObject HitGameObject (Ray ray) {
		RaycastHit hit;
		return Physics.Raycast(ray, out hit) ? hit.transform.gameObject : null;
	}

	//クリック先とオブジェクトの交点座標を取得する関数
	Vector3? HitPoint (Ray ray) {
		RaycastHit hit;
		return Physics.Raycast(ray, out hit) ? hit.point : (Vector3?)null;
	}

}

【Unity, Android】AdMobテスト広告を出すためのデバイスIDを取得する

テスト用端末でAdMobの誤クリックを避けるためにデバイスIDが必要となったが、取得方法がわかるまで苦しんだのでメモ。

AdRequest request = new AdRequest.Builder ().AddTestDevice("ここに必要なデバイスIDの取得方法がなかなか分からなかった").Build ();

bannerView.LoadAd (request);

デバイスIDの取得方法

apkファイルを端末に入れる際に使うadbコマンドを使えばよいことがわかった。
まずAdMobを実装したアプリをテスト端末に入れる。

adb install -r /path/to/hoge.apk 

次にアプリを起動し、広告を出してみる。
そうしたら、下記のコマンドを叩く。

./adb logcat | grep "AdRequest"

すると、
Use AdRequest.Builder.addTestDevice("デバイスID") to get test ads on this device.
といった表示が出てくるので、出てきたデバイスIDを使えばOK。

【画像処理】HTML5+JavaScriptでリアルタイムに顔認識して顔を隠してみた

HTML5+JavaScriptでリアルタイム画像処理が割と簡単にできるっぽい。いろいろ調べてみるとclmtrackr.js を使えば顔認識も簡単にできるみたいなので、サンプルコード http://artak.hatenablog.com/entry/2014/08/11/195619を参考に、顔を追跡して隠してくれる(モザイク+黒目線)プログラムを作ってみた。

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <script src="clmtrackr.js"></script>
    <script src="models/model_pca_20_svm.js"></script>
    <title>Title</title>
    <style>
        #container {
            position: relative;
            width: 370px;
            /*margin : 0px auto;*/
        }
        #overlay {
            position: absolute;
            top: 0px;
            left: 0px;
            -o-transform: scaleX(-1);
            -webkit-transform: scaleX(-1);
            transform: scaleX(-1);
            -ms-filter: fliph;
            /*IE*/
            
            filter: fliph;
            /*IE*/
        }
        #videoel {
            -o-transform: scaleX(-1);
            -webkit-transform: scaleX(-1);
            transform: scaleX(-1);
            -ms-filter: fliph;
            /*IE*/
            
            filter: fliph;
            /*IE*/
        }
    </style>
</head>

<body>
    <div id="container">
        <video id="videoel" width="640" height="480" preload="auto" loop></video>
        <canvas id="overlay" width="640" height="480"></canvas>
    </div>
    <input class="btn" type="button" value="wait, loading video & images" disabled="disabled" onclick="startVideo()" id="startbutton"></input>
    <script>
        var vid = document.getElementById('videoel');
        var overlay = document.getElementById('overlay');
        var overlayCC = overlay.getContext('2d');

        var buffer = document.createElement('canvas');
        var bufferContext = buffer.getContext('2d');

        var ctrack = new clm.tracker({
            useWebGL: true
        });
        ctrack.init(pModel);

        function enablestart() {
            var startbutton = document.getElementById('startbutton');
            startbutton.value = "start";
            startbutton.disabled = null;
        }

        navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
        window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL;

        if (navigator.getUserMedia) {
            var videoSelector = {
                video: true
            };
            if (window.navigator.appVersion.match(/Chrome\/(.*?) /)) {
                var chromeVersion = parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10);
                if (chromeVersion < 20) {
                    videoSelector = "video";
                }
            };

            navigator.getUserMedia(videoSelector, function(stream) {
                if (vid.mozCaptureStream) {
                    vid.mozSrcObject = stream;
                } else {
                    vid.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
                }
                vid.play();
            }, function() {
                alert("There was some problem trying to fetch video from your webcam, using a fallback video instead.");
            });
        } else {
            alert("Your browser does not seem to support getUserMedia, using a fallback video instead.");
        }

        vid.addEventListener('canplay', enablestart, false);

        function startVideo() {
            vid.play(); //videoスタート
            ctrack.start(vid); //トラッキング開始
            drawLoop();
        }
        var flg = 0;

        function drawLoop() {
            requestAnimationFrame(drawLoop); //ずっと同様の処理をおこなう
            overlayCC.clearRect(0, 0, 400, 300);

            if (ctrack.getCurrentPosition()) {
                var data = ctrack.getCurrentPosition(); //顔の各パーツの座標を取得
                //顔領域の矩形座標を求める
                var max = [0, 0];
                var min = [100000, 100000];
                for (var i = 0; i < data.length; i++) {
                    max[0] = max[0] < data[i][0] ? data[i][0] : max[0];
                    max[1] = max[1] < data[i][1] ? data[i][1] : max[1];
                    min[0] = min[0] > data[i][0] ? data[i][0] : min[0];
                    min[1] = min[1] > data[i][1] ? data[i][1] : min[1];
                }
                var width = vid.videoWidth;
                var height = vid.videoHeight;
                if (width == 0 || height == 0) {
                    return;
                }

                buffer.width = overlay.width = width;
                buffer.height = overlay.height = height;
                bufferContext.drawImage(vid, 0, 0);

                var src = bufferContext.getImageData(0, 0, width, height); // カメラ画像
                var dest = bufferContext.createImageData(buffer.width, buffer.height); // 出力画像

                //ちょっとモザイク領域を広めにする処理
                min[1] = min[1] - (max[1] - min[1]) / 2;
                ex = (max[0] - min[0]) / 4;
                min[0] = min[0] - ex;
                max[0] = max[0] + ex;

                //モザイク化。シンプルに各領域の左上の色と同じ色に書き換える
                var size = 25;
                for (var y = Math.floor(min[1]); y < Math.floor(max[1]); y++) {
                    for (var x = Math.floor(min[0]); x < Math.floor(max[0]); x++) {
                        for (var c = 0; c < 3; c++) {
                            var i = ((y - y % size) * width + (x - x % size)) * 4 + c;
                            var j = (y * width + x) * 4 + c;
                            dest.data[j] = src.data[i];
                        }
                        dest.data[(y * width + x) * 4 + 3] = 255; // Alpha値の設定
                    }
                }

                //目周辺の座標で矩形を作る
                max = [0, 0];
                min = [100000, 100000];
                for (var i = 0; i < 2; i++) {
                    max[0] = max[0] < data[i][0] ? data[i][0] : max[0];
                    max[1] = max[1] < data[i][1] ? data[i][1] : max[1];
                    min[0] = min[0] > data[i][0] ? data[i][0] : min[0];
                    min[1] = min[1] > data[i][1] ? data[i][1] : min[1];
                }
                for (var i = 13; i < 32; i++) {
                    max[0] = max[0] < data[i][0] ? data[i][0] : max[0];
                    max[1] = max[1] < data[i][1] ? data[i][1] : max[1];
                    min[0] = min[0] > data[i][0] ? data[i][0] : min[0];
                    min[1] = min[1] > data[i][1] ? data[i][1] : min[1];
                }
                for (var y = Math.floor(min[1]); y < Math.floor(max[1]); y++) {
                    for (var x = Math.floor(min[0]); x < Math.floor(max[0]); x++) {
                        for (var c = 0; c < 3; c += 1) { //RGBを0に
                            var i = (y * width + x) * 4 + c;
                            dest.data[i] = 0;
                        }
                        dest.data[(y * width + x) * 4 + 3] = 255; // Alpha値の設定
                    }
                }

                overlayCC.putImageData(dest, 0, 0); //canvasに変換後の画像を書き出す
            }
        }
    </script>
</body>

</html>

なかなか楽しい

【スポンサーリンク】