FuelPHPでEXIF情報を読み画像を回転させる
iPhoneで撮った画像をサーバーにあげて表示すると、全て横向きで表示されます。
これはEXIFの情報で縦にしてるからなんですね。知らなかったです。
ということでEXIF情報を読み込んでFuelPHPで角度にあった回転をさせます。
public static function exif_rotate($filepath) { try { $exif = exif_read_data($filepath); } catch(Exception $e) { return 0; } if (isset($exif['Orientation']) && is_numeric($exif['Orientation'])) { $rotate = 0; switch ($exif['Orientation']) { case 1: case 4: break; case 2: case 3: $rotate = 180; break; case 5: case 8: $rotate = 270; break; case 6: case 7: $rotate = 90; break; } return $rotate; } return 0; }
こんな感じの関数を用意しました。
これにファイルパスを投げると画像に必要な回転の角度が返ってきます。
使い方はこんな感じ
$filepath = 'image.jpg'; Image::forge()->load($filepath)->rotate(self::exif_rotate($filepath))->output($filepath);
exif_read_dataでEXIF情報を読み込みます。
Orientationキーが回転を表す数値です。
詳しいことは下のURLを参考にさせてもらいました。
JPEGのExifタグ情報のOrientaionの定義の早見表 - DQNEO起業日記
EXIF情報はjpegかTIFFとかいう画像にしか存在しないので、それ以外のファイルが指定された時は0を返すようになっています。
本当は左右反転、上下反転ていうのが定義されてるのですが、GDには反転するメソッドは用意されていないし、わざわざ反転する人も殆ど居ないので無視しちゃってます。
Imageクラスのでrotateメソッドを使って回転させます。
Image - クラス - FuelPHP ドキュメント
これでiPhoneで撮った画像も正しい角度で表示されます
料理を美味しく見せるためのCSSフィルター
CSSフィルターって名前だけは聞いたことあったんですが、こんなに色々出来るんですね。。
・グレースケール
・セピア
・色相
・明度
・彩度
・透明度
・階調の反転
・コントラスト
・ドロップシャドウ
・ぼかし
CSSさんナメてましたごめんなさい。
CSS3のフィルター効果をまとめた | おぼめも
上記URLでとっても素晴らしい効果の数々を確認出来ます。綺麗なサイトですなぁ。
料理を美味しく見せるには
暖色系を使う
図る〜色と食欲の関係
人間には暖色系の色(赤とかオレンジ)を使うと食べ物がより美味しく見えるようです。
入った瞬間に売れなそうな店だなー、とか美味しくないのでは・・・と思う店ってあるんですが、そういうとこって大体青白系の蛍光灯を使ってるんですね。
よく中華料理屋とかラーメン屋とかで見かけます。
記憶色に近づける
用語解説辞典 | NTTPCコミュニケーションズ
人間は目で見たものを記憶するとき、より鮮やかな色として記憶するそうです。
つまり実際の色と同じ色の写真を見せるより、鮮やかな色にすることで記憶色に近い写真になるといえます。
CSSフィルター
元の写真。僕がどこかのラーメン屋でiPhone5Sで撮りました。
これだけでもラーメン好きの僕としてはかなり来るんですが、もっと美味しそうに見せられます。
明るさを足す
店内は大抵暗くて明るさも足りないので、明るくします。
img { -webkit-filter: brightness(1.2); -moz-filter: brightness(1.2); -o-filter: brightness(1.2); -ms-filter: brightness(1.2); filter: brightness(1.2); }
彩度を足す
記憶色に近づけるため鮮やかな色合いにします
img { -webkit-filter: brightness(1.2) saturate(150%); -moz-filter: brightness(1.2) saturate(150%); -o-filter: brightness(1.2) saturate(150%); -ms-filter: brightness(1.2) saturate(150%); filter: brightness(1.2) saturate(150%); }
ぐっと美味しそうになりましたね
暖色系にする
色相を弄って暖色系にします。
img { -webkit-filter: brightness(1.2) saturate(150%) hue-rotate(-10deg); -moz-filter: brightness(1.2) saturate(150%) hue-rotate(-10deg); -o-filter: brightness(1.2) saturate(150%) hue-rotate(-10deg); -ms-filter: brightness(1.2) saturate(150%) hue-rotate(-10deg); filter: brightness(1.2) saturate(150%) hue-rotate(-10deg); }
このhue-rotateってパラメータをどんどん弄ってくと、逆に青系とかの色にも出来るのでまずそうな写真にも出来ます。
元画像と比較
全然印象が違いますね!
個人差はあると思いますが僕は圧倒的に右の方が美味しそうに見えます。
てかラーメン食いたくなった!クソ!
各パラメータは画像によって調整が必要ですが、今あげた3つのフィルターをかけるだけでも結構効果が見込めますね。
InstagramAPIのタグ検索で次のページを表示する方法
instagramのAPIを使って写真を取得する方法 : matsudam blog
このページを参考にアプリケーションを登録します。
この情報だとちょっと古くてアクセストークンが取得できないので別のやり方で取得します。
Instagramにログインした状態で以下のページにアクセスします
https://instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token
「CLIENT-ID」と「REDIRECT-URI」を自分のアプリケーションに置き換えてアクセスしてください。
画面が表示されたら「Authorize」ボタンをクリック。
するとリダイレクト先に「access_token」というパラメータ付きでリダイレクトされます。
APIにアクセス
アクセストークンがGET出来たので早速InstagramのタグAPIにアクセスします。
Tag Endpoints • Instagram Developer Documentation
上記のリファレンスを参考にアクセスします
https://api.instagram.com/v1/tags/snow/media/recent?access_token=ACCESS-TOKEN
JSONが返ってきますね。
上記URLの「snow」ってなってる部分を変更することで好きなタグにアクセス出来ます。
で、表題の次のページに行く方法なのですがレファレンスにはこう書いてあります
Get a list of recently tagged media. Note that this media is ordered by when the media was tagged with this tag, rather than the order it was posted. Use the max_tag_id and min_tag_id parameters in the pagination response to paginate through these objects. Can return a mix of image and video types.
Google翻訳さんの力を借りると、ページ毎にアクセスするにはmax_tag_idとmin_tag_idを付けてくださいってことらしい。
APIの中身を見るとpaginationキーの中にそれっぽいものがあります
"pagination": { "deprecation_warning": "next_max_id and min_id are deprecated for this endpoint; use min_tag_id and max_tag_id instead", "min_tag_id": "1401794306803592", "next_max_id": "1401794079657725", "next_max_tag_id": "1401794079657725", "next_min_id": "1401794306803592", "next_url": "https://api.instagram.com/v1/tags/snow/media/recent?access_token=ACCESS-TOKEN&_=1401767576393&max_tag_id=1401794079657725" }
この「next_max_id」と「next_min_id」を指定すれば次のページ取れるんだなーと思ってjQueryでこんな感じで書きました。
var minTagId = undefind; var maxTagId = undefind; var tagName = 'snow'; function getInstagram() { $.ajax({ type: 'get', url: 'https://api.instagram.com/v1/tags/' + tagName + '/media/recent', dataType: 'jsonp', data: { access_token:ACCESS-TOKEN, max_tag_id:maxTagId, min_tag_id:minTagId }, jsonpCallback: 'instagram', }) .done(function(data) { maxTagId = data.pagination.next_max_id; minTagId = data.pagination.next_min_id; Console.log(data); }); }
1回目の時はundefindで2回目以降はレスポンスのnext_max_idとnext_min_idを指定するようにしたんですが、これではダメでした。何回やっても同じデータが取得されます。
で、色々ググったんですが見つからなくて途方にくれていたんですが、答えはレスポンスに書いてありました。
_人人人人人人_
> next_url <
 ̄Y^Y^Y^Y^Y ̄
先ほどのJSONにも書いてますがpagination.next_urlというキーで帰って来てるURLにアクセスすれば次のページが取得できます。
next_urlと自分が書いたリクエストurlを比べるとmin_tag_idが無いのでmin_tag_idなしでリクエストしてもダメでした。
レファレンスに書いてあるとおりにやってるのにー!
何か釈然としないのですが、next_urlには&_=********みたいな形で知らないパラメータが追加されてるので、なんかこの辺でゴニョゴニョしてるのかなーとか思うんですがInstagram側のことなので分かりません。
git commit前にGruntでCSSとJSをminifyしてaddしてcommit
GoogleのPageSpeed Insightsとか使うと必ずJavaScript を縮小するとCSS を縮小するって怒られませんか?
僕はよく怒られます。
なのでGruntとかいう凄いツールを使って怒られないよう頑張って見ようと思います。
したいこと
・CSSとJSのminify(圧縮)して*.min.css / *.min.jsという名前でそれぞれ保存する
・git hooksを使ってcommit前にGruntを実行し、出来上がったファイルをaddする
Node.jsのインストール
Grunt cliのインストール
$ npm install -g grunt-cli
プロジェクトの設定
Gruntはプロジェクトごとにインストールする必要があります
$ cd project_directry
$ npm init
ターミナル上で色々質問されるので入力していくとpackage.jsonとGruntfile.jsが出来上がります。
Gruntのインストール
$ npm install grunt --save-dev
Gruntfileの設定
$ vim Gruntfile.js
Gruntfile.js
module.exports = function(grunt) { grunt.initConfig({ pkg : grunt.file.readJSON('package.json'), cssmin : { css1 : { src : 'public/assets/css/1.css', dest : 'public/assets/css/1.min.css' }, css2 : { src : 'public/assets/css/2.css', dest : 'public/assets/css/2.min.css' } }, uglify : { min : { files: { "public/assets/js/1.min.js" : ["public/assets/js/1.js"], "public/assets/js/2.min.js" : ["public/assets/js/2.js"] } } } }); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.registerTask("default", ["uglify", "cssmin"]); };
この設定で、1.cssは1.min.cssという名前で圧縮したものが保存されます。
同じ用にjsも1.jsが1.min.jsという名前で圧縮されてます。
cssはまとめることも出来てそのほうがリクエスト数も減るしいいのですが、ページごとに読み込ませるcssを変えてるので今回このようにしました。
Gruntの実行
$ grunt
これでGruntfile.jsに設定されている通りに圧縮などの作業が行われます。
git hooksを使い自動化
gitには特定のタイミングでシェルなどを実行出来る機能があります。
今回はcommit直前なのでpre-commitを使用します
$ cd .git/hooks/
$ vim pre-commit
pre-commit
#!/bin/sh
grunt
git add public/assets/js/*.min.js
git add public/assets/css/*.min.css
pre-commitファイルに実行権限を与えます
$ chmod 775 pre-commit
これでgit commitを実行するとgruntが実行されminファイルがaddされてからcommitされます。
このpre-commitとかにJSHintとか噛ませるのがナウいみたいですね。
ネットワーク素人が、さくらクラウドで負荷分散構築した時のメモ4【Fileサーバー編】
前回のネットワーク素人が、さくらクラウドで負荷分散構築した時のメモ3【DBサーバー編】 - なりせなるてずからひき続きです。
今回で最終回です。
前回までの構成で以下のようになりました。
今回はファイルサーバを構築します。
NFSとは
NFSとはWindowsで言うところの共有フォルダです。
Sambaとか、あとはデフォルトのグループ機能とかみたいなもんですね。
元々1台のサーバで運営してた頃はwebもDBもファイルも全部1台だったので気にしなくてよかったのですが、Webサーバーを複数にしたので例えば画像をアップロードするとロードバランサで振り分けられた方のWebサーバのみにしか画像は存在しない事になります。
それでは画像がある方のWebサーバに接続された時しか画像が表示されてないのでNFSの出番です。
NFSサーバに複数のwebサーバからアクセスすれば問題ありません。
rsyncで同期すればいいんじゃね?とか思ってたんですが、お互いがMasterになるのでちゃんと同期出来ないみたいです。
Nix::WebLab : lsyncd の双方向同期はヤメておけ!
実はNFSを導入前に試そうと思ったんですが、上記の記事見てガクブルしたので辞めました。
Fileサーバーの設定
接続先の変更
もうyumを使わないので、ローカルネットワークに接続先を変更します。
当該サーバの電源操作からシャットダウンし、NICの接続先をローカル用のスイッチに変更します。
前回同様なのではしょります。
共有するディレクトリを作る
# mkdir -p /export/kyoyu
/exportディレクトリはNFSの共有用のディレクトリらしいです。
Windowsユーザーに教えるLinuxの常識(2):各ディレクトリの役割を知ろう(ルートディレクトリ編) (1/2) - @IT
「kyoyu」の部分は好きな名前にしてください
オーナーとグループの変更
# chown -R nfsnobody:nfsnobody /export
クライアント側の設定
今回はWebからのみFileサーバーにアクセスするので以下の設定をwebサーバに行います
rpcbindのインストール
# yum install rpcbind
iptablesの設定
# vim /etc/sysconfig/iptables
以下を貼り付け
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 32765:32768 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 2049 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 111 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 747 -j ACCEPT
rpcbindの起動
# /etc/init.d/rpcbind start
rpcbindの自動起動設定
# chkconfig rpcbind on
マウント用ディレクトリの作成
# mkdir /home/mount
ディレクトリの場所は任意です
マウントする
# mount -t nfs 192.168.0.10:/export/kyoyu /home/mount
IPアドレスはFileサーバーのIPアドレスにしてください。
確認
$ df -h Filesystem Size Used Avail Use% Mounted on /dev/vda3 97G 20G 72G 22% / tmpfs 1.9G 0 1.9G 0% /dev/shm /dev/vda1 98M 52M 41M 57% /boot 192.168.0.10:/export/kyoyu 97G 4.5G 88G 5% /home/mount
マウントされた!(∩´∀`)∩ワーイ
あとは画像とかWebサーバー間で共有が必要なファイルのパスをマウント先にしてやることで読み書きが出来ます!
参考にしたサイト
はじめての自宅サーバ構築 - Fedora/CentOS - ファイルサーバの構築(nfs)
[CentOS6] NFSサーバ構築 - OSSでLinuxサーバ構築