「NAVER まとめ」「NAVER Photo Album」サービスで画像を登録するプロセスの紹介

はじめまして!
検索サービス開発1チーム李政桓と申します。
イメージプラットフォームを担当しています。

ネイバージャパンでは画像を登録するサービスがたくさんあります。
大切な画像コンテンツをどうやって登録、管理しているかについて、検索サービス開発1チームで担当している、NAVER まとめ(以下まとめ)とNAVER Photo Album(以下PhotoAlbum)を中心に紹介しましょう。

まとめ、PhotoAlbumとは?

<まとめ>

matome.naver.jp
あらゆる情報を、自由に組み合わせ、ひとつのページにまとめて保存・紹介できるサービス。誰もが[情報をデザイン]できるようにすることで、今までにない人と情報との出会いを実現します。
まとめに登録できる情報のタイプには(リンク・画像・動画・引用・Twitter・テキスト・見出し)があります。

<PhotoAlbum>

photoalbum.naver.jp
iPhoneの中の眠っている膨大な写真をアルバム(フォルダ)毎に簡単に整理・保管・共有機能を提供します。

PhotoAlbumは文字通り、写真を扱うサービスなので画像を登録するプロセスがサービスの核です。
それと比べるとまとめでは、テキストや、動画、リンク、引用など様々な種類の情報を扱いますが、その中で、画像タイプはもちろんの事、リンク、引用にも画像を添付できます。
このためまとめでは現在、半分以上が画像コンテンツで占められています。
これらの大量な画像を登録・管理するプロセスはとても重要です。

それでは、どうやってサービスに画像を登録するのか見ていきましょう。

Chapter1.  サービスに画像を登録するプロセス

イメージ登録のプロセス

1.  画像を登録する方法

(ア)  直接画像をアップロード

①  ユーザーが保有している画像を直接アップロードしてサービスに登録

(イ)  画像のURLで登録

①  他のウェブページで画像のURLを取得して、サービスに登録

2.  各プロセスの説明

(ア)  原本イメージのチェック

①  イメージフォーマットのチェック:まとめとPhotoAlbumではjpeg(jpg), png, gifフォーマットだけ登録できるので、画像形式が登録できる形式かのチェックをしています。
②  ファイル容量のチェック:ネットワークを使うサービスなのでとても大きな画像ファイルは扱えません。まとめとPhotoAlbumの場合はサイズの制限は10MBに設定されてます。

(イ)  原本イメージの編集

①  PhotoAlbumでは画像を登録する前に、リサイズや回転やクロップなどの編集をしてから登録することもできます。

(ウ)  原本イメージアップロード

①  ユーザーがアップロードするイメージをストレージにストック
②  サービスの特性により、イメージのフォーマットが変わってアップロードされる場合があります。例えば携帯端末向けのサービスなら、pngをサポートしない端末のために、全てのイメージをjpegで管理する場合があります。

(エ)  サムネイル生成

①  まとめのように、多くの画像が一度に表示されるページではサイズの大きい原本画像の表示は、読み込み速度や見た目的に不利です。
②  ユーザーが登録した原本画像のサムネイルを使うことで、より速くページが表示されるようになります。

Chapter2.  サムネイルの生成プロセス

まとめサービスでは、画像の原本よりサムネイルがよく使われています。
そういうわけでサムネイルの生成がもっとも重要なプロセスです。
サムネイルの生成には、imagemagickを利用しています。

先ず、imagemagickのインストールから説明します。

imagemagick install

imagemagickはlinux/unix, windowsをサポートしていますが、ネイバージャパンではlinuxを使うため、linuxでimagemagickをインストールする方法について紹介します。

1. imagemagickのソースコードをダウンロードする

http://www.imagemagick.org/script/download.php

2. configure

(ア)  imagemagickがインストールされるpathの指定

①  --prefix=/path --exec-prefix=/pathのように設定します
②  何も指定しない場合はデフォルトで/usr/localが設定され、/usr/local/binにexecutable-binaryがインストールされます

(イ)  ./configureを実行して必要なパッケージがあるかチェック
(ウ)  libjpeg, libpng, libtiffなどの必要なライブラリはインストール
(エ)  --disable-openmpオプションは絶対入れたほうがいい

例)./configure --with-jpeg --with-png --with-tiff --with-zlib --with-bzlib --disable-openmp --prefix=/home/work
3. make & make install

※ openmpによる問題点
identify, convertなどのプロセスが並列で実行される場合、問題があります。

下記openmpの有効化によるconvertコマンドのベンチマーク結果を見ながら話します。
a) enable-openmp

1 thread running 200 times : Average call time : 65ms, Total completion time: 13076ms
2 threads running 200 times : Average call time : 326ms, Total completion time: 32681ms
4 threads running 200 times : Average call time: 806ms, Total completion time: 40374ms
8 threads running 200 times :Average call time: 1952ms, Total completion time: 49108ms

b) disable-openmp

1 thread running 200 times : Average call time : 73ms, Total completion time: 14638ms
2 threads running 200 times : Average call time : 85ms, Total completion time: 8643ms
4 threads running 200 times : Average call time: 94ms, Total completion time: 4780ms
8 threads running 200 times :Average call time: 98ms, Total completion time: 2500ms

1threadの場合、enable-openmpにしたほうが早いです。
実行時間がdisable-openmpの場合と比べて10%くらい短くなる効果が期待できます。
しかし、2thread以上の場合は、disable-openmpにしたほうが速いです。
enable-openmpにすると、実行時間が何倍も長くなることが分かります。

原本イメージのチェック

imagemagickをインストールすると、サムネイルが生成できるようになります。
サムネイルを生成するためにはまず、原本画像に問題があるかどうかをチェックして、問題なければサムネイルを生成しています。

1.imagemagickのidentifyコマンドを利用
2.イメージのMETAデータの中で必要な項目を取得

-format : METAデータの中で必要な項目を抽出

例)./identify -format “%m %n %[colorspace] %g %[EXIF:Orientation]n” sample.jpg

詳しい内容はhttp://www.imagemagick.org/script/escape.phpで確認できます
3.取得したMETAデータを利用してサービスで使えるイメージかチェック

(ア) チェックする重要な項目

① width, height
② フォーマット : jpeg, png, gif, tiffなど
③ sceneの数 : animated画像のチェック
③ colorspace : RGB、CMYKなどのチェック
④ EXIF : イメージのEXIF情報。Orientation情報などが入っている

サムネイル生成

原本画像のチェックが終わったら、サムネイルを生成します。

1.imagemagickのconvertコマンドを利用
2.jpegで生成 : pngは携帯端末によっては、見れない場合があるので、全てのサムネイルはjpegで生成します
3.convertコマンドのオプション

-resize : サムネイルのサイズ

例)-resize 300x600> : 300×600にリサイズ。横縦比は維持してリサイズするが、原本が300×600より小さい場合はリサイズしない

-delete : イメージsceneの削除。イメージ原本がAnimated gifの場合、特定のsceneを削除することができます

例)-delete 1--1 : 二番目からの全てのsceneを消す。1番目のsceneだけを使ってサムネイルを生成

-background : transparent -pngをjpgなど透過に対応していない画像へ変換する場合の背景色をセット

例)-background white

-flatten : transparent-pngをjpgに変換する場合、透明領域を削除する。削除される領域にはbackground-colorがセットされる

-colorspace : IEではCMYK colorspaceをサポートしないのでRGBに変換

例)-colorspace RGB

-auto-orient : デジタルカメラで撮影された画像の中には、回転されている場合があります。その画像を自動的に補正します。

-strip : image exif情報(付加情報)のクリア

-quality : jpeg画質

例)-quality 98

4.サムネイル生成の例

./convert apple.png –resize 300x600> -delete 1--1 –background white –colorspace RGB –autu-orient –strip –quality 98 apple_thumbnail.jpg

Chapter3.  デザインに合わせた画像サイズ

サービスで画像を使用するときには、デザインをよくするため多くのサイズの画像が必要です。
もし200×200サイズの画像を100×100サイズで表示しようと思えば、HTMLでは

<img src="//xxx.xxx.xx/200x200_image.jpg" alt="" width="100" height="100" />

と記述すると思います。
普通は、これで終わりです。

でも本当にこれでいいでしょうか?私は絶対NOとお答えします。

その理由は、

イメージの品質

左の画像が原本画像です。サイズは300×225
右のイメージはHTML documentに<img src="//xxx.xxx.xx/penguin.jpg" alt="" width="160" height="120" />を入れてInternet Explorer7.0で確認した結果です。
輪郭にジャギーのようなものが出て、画像の品質が悪くなったことがすぐ分かります。

かといって、Internet Explorerのバージョンが8.0以上なら全然問題がないのでは?
8.0以上でもまだ問題が残っています。

右の画像のようにimg tagでリサイズすると、クライアントサイドのメモリやCPUなどのリソースが必要です。
例えば、一つのウェブページで20個のimg tagがあり、それが全部リサイズされると仮定すれば、普通のパソコンではそのページを見る時、少し動作が遅く感じることになると思います。
画像のリサイズはかなりリソースが要求されるので、サービスが遅く感じられる恐れがあります。

イメージファイルの容量

異なるサイズの画像データを見てファイルの容量を確認します。

容量:28086バイト
ピクセル:300 x 225


容量:5909バイト
ピクセル:120×90ピクセル

ご覧の通りにサイズによって画像ファイルの容量が変わります。

UIにビッタリサイズのサムネイルを使わず、大きなサムネイルを利用してimg tagで小さく表示するとネットワークデータ量が増加するので、ユーザーの体感速度が遅くなります。
特に3Gネットワークを利用する携帯端末ではデータの量によって、ページをロードする時間の差が大きいです。

デザインに合わせる

結局、一つのサムネイルを利用してimg tagで多くのUIに対応することはサービスに悪影響を及ぼします。
結果、様々なサイズのサムネイルをサービスで用意して使うことになると思います。
でも、各サイズのサムネイルを全部生成してストレージに保存することは無理です。

では、ネイバージャパンではどうやってこの問題に対応しているでしょうか?

次の画像をご覧ください。


ユーザーが画像をアップロードする時、生成されたサムネイルが一番目のイメージで、2番目と3番目のイメージが一番目の画像をリサイズしたものです。
ネイバージャパンでは多くのUIに対応するために大きなサムネイルを生成し、リアルタイムでリサイズして利用しています。
勿論パフォーマンスの向上のためにキャッシュも使っています。

Chapter4.  JAVAでimagemagickの活用

まとめサービスはJAVAで実装されています。
JAVAにも様々なイメージライブラリはありますが、どちらもパフォーマンスがいいとは言えません。
なので、まとめサービスでもimagemagickを使っています。

JAVAでimagemagickを利用するためにはimagemagickのクライアントライブラリが必要です。
Imagemagickで紹介するライブラリはJMagickIm4javaがあります。
http://www.imagemagick.org/script/api.php

上記二つの中でまとめサービスが選んだのはIm4javaです。
Im4javaについて詳しく説明します。

Im4javaって何?

- imagemagickのJAVAクライアントライブラリ

- ホームページ : http://im4java.sourceforge.net/

- 全てのinterfaceがimagemagick コマンドに対応

- JNIを使わず、Runtime.exec()を利用してchild processでimagemagickのコマンドを実行

・JNIを使うと、imagemagickでcore dumpが発生した場合にJVMまで落ちる問題があるので、サービスの安全性のためRuntime.exec()を使うIm4javaを選びました。

- APIがimagemagickのコマンドに似ていて直感的に実装できる

Sample Code

サービスでサムネイルを生成するソースコード

public void createThumbnail(String sourceFile, String thumbnailFile, int width, int height, double quality) throws Exception {
ConvertCmd cmd = new ConvertCmd(); // convert

IMOperation op = new IMOperation();
op.addImage(sourceFile); // {sourceFile}
op.resize(width, height, '&gt;'); // -resize {width}x{height}&gt;
op.delete("1--1"); // -delete 1--1
op.background("white"); // -background white
op.flatten(); // -flatten
op.autoOrient(); // -auto-orient
op.colorspace("RGB"); // -colorspace RGB
op.strip(); // -strip
op.quality(quality); // -quality {quality}
op.addImage(thumbnailFile); // {thumbnailFile}

cmd.run(op);
}

このSample Codeは次のlinuxコマンドと同様

./convert {sourceFile} -resize {width}x{height}> -delete 1--1 -background white -flatten -auto-orient -quality {quality} {thumbnailFile}

まとめ

イメージチェック、サムネイル生成、UIデザインに合うようにサムネイルのリサイズ等について紹介させていただきました。まとめとPhotoAlbumサービスにとって画像の登録は重要な機能ですが、それほど複雑ではありません。
画像は、既に人と人のコミュニケーションの一部分になりました。友達に写メを送ったり、インターネットに写真をアップロードして共有したりしています。画像は全てのサービスに関わると言っても過言ではないかと思います。開発者になったからには画像の処理技術はもうデフォルトになったかも。でも、自分がイメージプラットフォームを担当することになって人から一番よく言われたのは、”画像処理は複雑で面倒くさそうだから関わりたくない”でした。実はシンプルだからみんなやればやれるはずなのに。。。
最近ずっと、イメージプラットフォームに様々な機能の追加やパフォーマンス向上に励んでいます。いつかもっと完成されたプラットフォームについてブログで紹介できたらなと思います。
それでは、最後までお読みいただきありがとうございました!


でもこんなの食べながら開発できるかな

Related Post