takaaki.infotakaaki.infoソフトウエアデベロッパー兼技術系ライター水野貴明のサイト。開発・執筆関係のお仕事依頼お待ちしております。SQSのローカルテスト環境を作る以前DynamoDBをLocalで建てるようにしたことでDynamoDBを使ったサービスの開発やテストがローカルで完結できるようになって幸せをかみしめていたのですが、このたびSQSも使うことになり、さてどうしたものかと思っていたらElasticMQというSQS互換インターフェイスを持った実装が存在することを知って、使ってみました。自分はElasticってつくとなんでもAWSのサービスみたいに感じてますが、ElasticMQとElasticSearchはAWSのサービスではないですね。ElasticMQはJavaで実装されてるので、ダウンロードしてきて実行すればいいだけなので超簡単。0.7から対応しているようで素敵です。elasticmq-server-0.8.0.jarPythonでbotoを使ってキューを登録してみます。TEST'))アクセスキーとシークレットはダミーですので何を指定してもいいっぽいです。続いてキューを読み出します。msg.get_body()queue.delete_message(msg)読み出しのループを回しておいてキューにデータを入れると、読み出されているのがわかります。ロングポーリングが正しく動いていない気がするので、今後調査の方向で。Safari)にはReader機能というのがあって、ブログなどでコンテンツ部分だけを抜き出して表示してくれます。iOSにはあるのは知っていて、PC向けのページを読みやすくしてくれて便利なのでたまに活用していたのですが、PC版でもあるんですね。似た機能はPocketやReadabilityにもあります。このリーダー機能、ボタンが出る時と出ない時があります。コンテンツ抽出ができない時は出ないんだろうなっていう推測はできるのですが、どのようにコンテンツ抽出しているのかなと。PerlのモジュールでHTML::ExtractContentというのがあるのですが、似たようなことやっているんだろうなって思っていましたが、しらべるとh1~h6の含まれるブロック要素で文字数が多いものが取られているっぽいとかブロックのサイズが云々とか色々観測結果が書かれていました。調べていくと、新事実が。ReaderはJavaScriptで実装されており、以下の手順を踏めばコードが読める。Inspectorを開き、停止ボタンを一度だけ押すリーダーボタンを押すおお、よめた!ということで、JavaScriptで書かれたコードを読むことができます。中を読むと要素のIDやClassに”article”、”body”、”content”、”entry”とか入っていたら可能性が高く、”comment”とか”advertisement”、”breadcrumb”、”disqus”とか入っていたら可能性が低いとか、縦横の表示サイズやエリア面積などなど様々なチェックを行っているようです。ローカルで構築すると、ネットワークのない環境でも開発ができるので非常に便利です。昨年は飛行機に乗る機会がとても多く、僕の乗っていた便はまだ機内インターネット接続サービスの恩恵は受けられない便ばかりだったので、飛行機の中でも開発を続けるためには、開発環境とドキュメントをローカルに入れておくのはとても重要でした。VagrantとDashにはとてもお世話になりました。最近DynamoDBを使ってサービス作っています。AWSのサービスは非常に便利でよいですが、DynamoDBはElastiCacheやRDSみたいにローカルにMemcachedやRedis、MySQL、PostgreSQLなど入れておけば代用できるわけでもないので、どうすんだろ、と思いました。1点DynamoDBの問題として、DynamoDBの課金体系は保存容量以外に毎秒何回読み込みと書き込みができるかに対してお金を支払いますが、無料枠は、合計書き込み5回/秒、読み込み10回/秒までです。DynamoDBではグローバルセカンダリインデックスを用意すると、それぞれにつき少なくとも書き込み、読み込み1ずつ割り当てなければならないので、1つのテーブルが1回/秒で済まないケースもあって、本当にお試しでもない限り、無料枠をすぐ使い切っちゃいます。いっても、月数百円とかですむのですが、油断してて料金発生するのも怖い。Localなるものを公開していて、これを使ったらものすごく簡単にそれができてしまいました。紹介記事は2013年9月ですがリンクは最新版を指すようになっていてダウンロードされたのは2014年1月8日版でした。2013年12月に発表されたグローバルセカンダリインデックスにも対応。Javaで書かれているのでjarファイルを実行すればサービスが起動してしまう。ポート番号はデフォルトが8000ですが、8000なんてなにか他のものと容易に衝突しそうなんでそこはは変えました。8088それで、次はアクセスをしてみるのですが、開発はPythonを使うことが多いのでbotoを使いました。botoってconnectionの際にhostとportを指定できるようになってるんですね。res['time']実際のDynamoDBのようにコンソールが用意されていてテーブル作成できるわけではありませんが、そもそもきちんとテーブル定義はコードとして残しておいたほうがいいですね。AWSのブログ記事に以下の様なことが書かれています。スループットの指定は無視される。スループット以上にアクセスすることはできてしまう。アクセスキーとリージョンはDBファイル名を生成するときにだけ関係あるシークレットキーは無視されるテスト用なので、プロダクション作らないほうがいいよということで、これでとりあえずお金の心配も、ネットワークの心配もせずにDynamoDBで開発ができるようになりました。mizuno_takaaki.画像で最も使われている色を抽出するBBColorPickerの処理を読む自分はサイトやアプリを作る際に色を選択するのが非常にセンスがなくて下手っぴなので何とかせねばならないと思い、理屈から勉強するしか無いという思いに至っています。iOS7という記事がありまして、友達のウィッシュリストのヘッダ部分の背景色を画像で使われている色から計算するという処理を入れているとのことで、そのライブラリであるBBColorPickerが公開されているので、中身を読んでみました。このライブラリはBBColorSamplerManagerというシングルトンのクラスが提供されていて、その中では2つのメソッドが提供されていています。1つはcomputePrimaryColorForImageでもう一つはsortColorForImage。completionBlock:(color_sampler_sort_completion_block_t)completionBlock;名前からしてcomputePrimaryColorForImageは実際にアプリで使ってるヘッダ部分の背景色を計算するメソッド、2個めは使われている色をソートして抜き出すメソッドって感じに見えます。ブログ中での言及されているように非同期で動作するので、引数として完了時のコールバック関数を指定するようになっています。sortColorForImageのコールバック関数の引数はUIColorの配列かとおもいきや、UIImageだったのでちょっと動作がわかりません。*);それぞれのコードを読んでみると2つのメソッドは激しくコピペ臭がするのですが、とりあえず必要な処理はcomputePrimaryColorForImageっぽいのでこちらを読むことに。image.CGImage);ここでまずは画像サイズをちっこくしています。_sampleSizeはinitで32×32に指定されているので、それに合わせて縦横比をキープしながらサイズを小さくして、CGContextに描画してます。32);これで縦横最大32ピクセルの画像になりました。これを今度は1ピクセルずつループで回して分析しています。0;解析にあたってRGBの色をYUV色空間に変換しています。YUVは(Wikipediaによれば)”輝度信号Yと、2つの色差信号を使って表現される色空間”です。結果はy、u、vのそれぞれの変数に入ります。RGBの最大最小を取って差分を最大値で割ってますが、これはHSV色空間の彩度(Saturation)を計算しています。これらの結果から、その色を採用するかどうかを決めています。{これによると白黒に近い色を除くことで、より画像の特徴を表してそうな色を取り出すようにしているという感じでしょうか。この数値はすごくマジックナンバーな感じですが、どうやって決めたんでしょうね。試してチューニングしたのかな。彩度が低すぎ(0.3以下)の色もの特徴がなさすぎるので除外で、その情報からNSMutableDictionaryを作る。@(blue)}];なんかすごい。NSDictionaryやNSArrayが@{}や@[]で書けるようになったのは知ってましたが、@(y)とかって書くとNSNumberに変換できるって知りませんでした。1年位前から出来たっぽい。続いてはなんかすごい冗長な感じでもあるけどやってることはcolorBucketsっていう配列(NSMutableArray)に格納されている色情報と比較してYUVをピタゴラスの定理から2つの色の色差を計算して、それが近い(0.1未満)だった場合はほぼ同じ色と判断して、これまでチェックした色との平均をとって新しい色とします。違った色だった場合は新しく要素を配列に追加します。YES;break;}}}colorBucketsの各要素はまた配列(NSMutableArray)になっていて、類似色だった場合に要素が追加されて、結果としてその数が類似色の数になって、類似色が一番多かった際にその平均の色が画像の特徴色として取り出される仕組みです。colorBucketsの各要素の配列の先頭は類似色の平均(weightedAverageというメソッドで計算される)が入ります。bColorという変数の値として計算されています。一方で新しい要素を追加する際にも何やら取得した色とbColorの平均をとってnewColorを作っていますが、これ意味あるのかな。arrayWithObject:newColor]];}類似色がなかった場合はcolorBucketsに新しい色として追加します。要素数でソートします。NSOrderedDescending;}];そして最後にcolorBucketsをチェックしていますが何やらここにもマジックナンバーの香りが。色を出現数の多い順にチェックしますが、特定のUV領域の色が出現した場合は次の色を入れる的な処理が入っています。領域的にはUがマイナスでVが0から0.26の間。緑からオレンジ色的な領域にかけて?かと思いますが、これはUIに合わないから削った?のかまだ不明です。あとpopColとpopularColorとか変数名が微妙に気になります。floatValue]alpha:1];}で、最後に取り出した色をUIColorに変換して(もとのRGBを利用)、メインスレッドにてコールバック関数を呼び出しています。{completionBlock(popularColor);}});ということでここまで読んでわかったことは以下のとおりでした。画像を縮小して1ピクセルずつ調べることで特徴色を出しているRGBをYUVという色空間に変換することで、色の差を計算して類似色をまとめているコードはかなり改善の余地がある(コピペコードとかマジックナンバーとか...)ついでに調べていたんですけども、画像を特徴色を調べるを読んでいて、複数の色を出すならきちんとこちらのようなアルゴリズムを使ったほうがいいですし、上記アルゴリズムだと黄色の中に赤1点みたいなのは出ないなあと思いましたけど、1色だけ選ぶんならこれでいい...のかもですね。Timestampを入れるべきではないのかAPIを設計していてHTTPヘッダに情報を入れることがあるけれど、その際に時間を入れたい時があります。その際にどんな形式にすればいいのかなっていう話題です。時間というのはいろいろな形式で表現が可能です。Timestamp、いわゆるエポック秒かなと自分は思っています。数値だし、それにタイムゾーンの概念がないので世界に単一のタイムゾーンしか無いと思っているエンジニアが変な値を入れる危険性も少ないと思われるから。Timestampと自前の日時表現の変換の仕組みを提供しているし。他の形式だとフォーマットをこちらで指定しなくちゃいけなかったりして面倒な場合もあります。APIには一人のユーザーからのアクセス数(あるいは1アプリケーションなど)を制限する「レートリミット」という仕組みを導入しているものが多くてその際にはX-RateLimit-Limit(あるいはX-Rate-Limit-Limit)をはじめとするヘッダを使うのがデファクトスタンダードっぽいです。1.1で導入したのがはじめかな(調査中)と思うのですが、今は普通に使われています。GitHubもちょっと名前は違いますがほぼ全く同じです。Foursquareもほぼ同じ。その他たくさんあります。こんなまとめもありました。1372700873Rate-LimitとするかRateLimitとするかはどっちにするべきかよくわかりませんが、自分ならRate-Limitとするかなと思います。Timestampで値が入ってるケースが多いのです。TwitterもGitHubもそうです。Timestampは使うな、解除までの秒数(デルタ秒)を使え!と強く主張していました。Timestampは使えないんだから仕様に反してるんだよ!使うんだったらRFC1123形式を使うべきだ、と書かれています。1.1の仕様に立ち返ってみたところ、確かにHTTPでは時間を表すのに、以下の3つの形式か、デルタ秒を使わないといけないと書いてありました。1994定義で言うとrfc2616で以下のようになってます。asctime-dateそしてたしかに例えばきちんと定義されているHTTPヘッダを見てみると、例えばRetry-Afterは以下のようになっています。Timestampはハンディだし使いたいなあと思っているこの頃です。ちなみにHerokuも使っていますね。Timestampを選んだんでしょうか。Timestampを使い続けたいところ。スマフォアプリのサーバクライアント連携とか、半ばプライベートなAPIの場合は使ってしまっていい気もしますが、一般公開するAPIの場合はどうすべきか悩むところです。デルタ秒だといつを基準としたデルタ秒だよ、という気もするし...まあDateヘッダで示された時間からですね。Timestampも随分利用されてきているので、仕様があとから追いついていく可能性はあるような気がします。mizuno_takaaki.PNG画像のファイルサイズをなるべく小さくしたいPNGやJPEGなんかのファイルはいろいろなメタ情報が含まれているのでそれを削除したり、カラーパレットや圧縮の最適化でサイズを小さくでき、そのための色々なツールが存在しています。ウェブサイトで公開するにも、モバイルアプリ内で使うにも、同じ画像ならファイルサイズが小さいに越したことはないので、そのへん色々調べました。今回はPNGについてです。ウェブサービスだとKraken.ioとかTinyPNGとかがあります。これらはウェブ上で使うものなので手作業が発生してちょっと面倒。ビルドプロセスに組み込んだりできたほうがいいので、ローカルで使えるツールのほうがいいです。Kraken.ioはAPI用意してくれていますが、月額$10で1000画像までとちょっとお高いです。MacでPNGの最適化を行えるツールをいろいろ試して何をするのが一番いいんだということを調査したのでこれはその結果とメモです。調査したツールは5種類。以下のファイルを圧縮しました。これは自分のプロフィールアイコンとかに使ってる奴とほぼ同じもので、SPSTUDIOっていうサイトで作成したものです。76.3%最後のzopflipngはGoogleが2013年3月に公開したzopfliという新しいDeflate互換の圧縮アルゴリズムを使うもので、zopfliと一緒のリポジトリに入っているが、1.0.0のパッケージには入ってないのでリポジトリから直接持ってこないといけません。zopflipng結果を見ると、AdvanceCOMPとzopflipngが圧倒的に圧縮率が高いです。この画像だとzopflipngに軍配が上がってますけど、他に試したものではAdvanceCOMPが勝ったりもする。おお、と思って調べたら、AdvanceCOMPは今年の3月にzopfliを使えるようにアップデートがなされていた(2005年以来のアップデート)のでした。それ以前にインストールしている人はすぐにアップデートした方がいいです。今回の画像は24bitのPNGファイルですが、インデックスカラーにしたほうがサイズは減少するはずなので、pngquantというツールでインデックスカラー化しました。不可逆な圧縮ですが、今回の場合は見た目には変化はほぼわかりません。src.pngちなみにpngquantは最近2.0が公開され、アルゴリズムが見直されてクオリティが上がりました。サイト上にも「Ver.1はもう使わないように」って書いてあります。両方で圧縮してみたところ、やや差がでました。1.xを使っているようならアップグレードしたほうが良さげです。42.9%その後、pngrewriteというファイルで更にパレットを最適化しました。このツールの更新は2010年で止まっているのですが、とりあえず使ってみたところ、パレット数が256から253に減って25バイトだけ減りました。42.9%まあpngquantでカラーパレット最適化してるからあたり前なんだろうけど、じゃあなんで3個減らせたのか?とかまだ調べる余地はいろいろありそう。91.2%今度も若干zopflipngに軍配があがったです。ちなみにzopflipngが出力した結果はこちら。画像によっておそらくツールごとの差異は違ってくると思うのですが、とりあえずAdvanceCOMPとzopflipngのどちらかを使うのが良さげですね。ちなみにGUIでやるなら今回調べたツールはすべてImageOptimに統合されているみたいです。こちらためしてみると、24bitの場合はいまいちだったのですが、インデックスカラーの場合はzopflipngに迫るサイズになりました。42.9%あと最初に言及した、ウェブサービスとして公開されているツールを2つ調べました。43.3%TinyPNGはインデックスカラー化しかできませんが、KrakenはLossLessとLossyが選べるので両方を比較しました。今回の場合はどちらもコマンドラインツールのコンボにかなわなかった感じなので、AdvanceCOMPかzopflipng手元で処理してしまってもよい感じです。