Internal of the image processing required on the developing of web applications

8cbb39dadafaf2287a83a13ee4981ec9?s=47 usa
March 23, 2019

Internal of the image processing required on the developing of web applications

Webアプリケーションの開発にあたっては、現代においては大量の画像を扱わないといけないことは明らかである。その際には、サイズ変換・フォーマット変換・転送量削減といったあたりは当然に必要となる。単純に見えて実は落とし穴がいっぱいなこうした画像変換の中身について、技術的側面から説明する(※デザインの話はしません)

8cbb39dadafaf2287a83a13ee4981ec9?s=128

usa

March 23, 2019
Tweet

Transcript

  1. アプリケーションの 開発運用で 当たり前に必要とされる 画像変換の中身 pixiv Inc. 2019.3.23 RailsDM2019

  2. 2 自己紹介 • CRubyのコミッタ (安定版リリースマネージャ ・Windows版担当) • www.ruby-lang.orgの記事をいっぱい書いてる人 (全体の1/4くらい) •

    配信技術部 = 画像とか動画とかそのものを取り 扱ってインターネットに流すための諸々をやるところ • 仕事では普段はだいたいGoで書いている • 仕事以外では普段はだいたいCで書いている 配信技術部エンジニア
  3. 福岡 3

  4. 4/12(金) 19:00~ ※RubyKaigiの前週末 参加申し込み:https://pixiv.connpass.com/event/124727/ 登壇申し込み:https://goo.gl/forms/V2rJnL47vad4XDSg2 4

  5. アプリケーションの 開発運用で 当たり前に必要とされる 画像変換の中身 pixiv Inc. 2019.3.23 RailsDM2019

  6. アプリで画像、使うよね? 6 • デザイン上必要な固定の画像はまあいい ◦ 枠とかの装飾っぽい奴とか ◦ 端の方に置くロゴとか • そうじゃなくて、コンテンツごとに貼りつけるやつが問題

    ◦ いっぱいある ◦ 縮小表示しておいてクリックしたらでっかくなるように、とか
  7. 7 「 アプリ」は だけじゃないよ 7 • 実質ブラウザっていうスマートフォン用アプリ ◦ 皆さん作ってますよね? •

    「実質ブラウザ」じゃないにしても、コンテンツを HTTP(S)で随時拾ってくる系のやつ ◦ ゲームとか ◦ ショッピングサービス(EC)
  8. で、その アプリで、 画像、 どうしてる? 8

  9. 9 :なにもしない 9 • <img src=”hoge.jpg” width=”160”> • クライアント側の負荷 •

    転送量膨大 • 速度低下 • UXの悪化
  10. 10 :手元で必要な加工をしてアップロード デプロイ 10 • 心温まる手作業…… • めんどくさい • だいたい定型作業なので頻度が増えてきたらスクリプトである程度自動化

    ◦ あれ、自動化してるのになんで人間が手で叩いてるんだっけ ……? • そもそも、画像をアップロードするのが自分 (開発・運用者)じゃない場合がある ◦ ユーザーがアップロードするやつとか
  11. 11 :アップロード時にサーバサイドで加工 11 • 楽ちん! • 配信サーバと共有すると運用上いろいろ不安がなくもない ◦ 負荷(特にメモリ)がアップロード時のみ高まる ▪

    金で解決してもいいけど、普段は完全にオーバースペックで無駄 ◦ き、脆弱性…… • 分離した画像変換サーバを用意すればいくらかマシにはなる
  12. • アップロードをトリガにして、所定の 加工を行う • 生成した画像を、クライアントがアクセスできるところに置く • おわり ◦ こういうのの作り方は、ぼくより皆さんの方が詳しい 12

    画像変換サーバの概要
  13. • 多種多様な画像フォーマットに対応 ◦ 画像どころかPDFとかまで対応しちゃう • 多彩な変換に対応 ◦ ぶっちゃけ、単純な図形の組み合わせ画像とかならこれだけで作れる • つまり、つよい!

    べんり!! 13
  14. • いいことばかりではない……(残念……) • 依存ライブラリが異様に多い(対応画像フォーマットの数が問題 ) ◦ バージョン管理とか脆弱性対応が大変 • 各種画像フォーマットに対応した上でありとあらゆる加工を実現するため、いったんメモリ 上で中間形式(RGB(+Alpha)、各要素float)に展開している

    ◦ 死ぬほどメモリ食う ◦ 速度イマイチ 14
  15. • ブラウザが対応してる程度の画像フォーマットだけでええねん ◦ JPEG, PNG, GIF, あとせいぜいWebPくらい • ぶっちゃけ、加工といっても、縮小だけできればええねん ◦

    だってサムネイル画像作りたかっただけだし 15 顧客 あなた が本当に欲しかったもの
  16. あれ? これくらいなら 自分で 作れるんじゃね? 16

  17. ほんとうに??? 17

  18. 実際に 画像変換エンジンを  作ってみよう! 18

  19. • Go ◦ Rubyだと思った? ごめんね • 単体で動くバイナリが生成されるのでデプロイが簡単で便利 • imageっていうパッケージがあって、JPEG, PNG,

    GIFとか読み書きできる ◦ 今回の用途にはぴったり! 19 用意するもの
  20. 20 画像ファイルの読み込み import( "image" "os" ) func LoadImage(path string) (image.Image,

    error) { file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() img, _, err := image.Decode(file) return img, err }
  21. 21 画像ファイルの書き出し func SaveImage(img image.Image, path string) error { file,

    err := os.Create(path) if err != nil { return err } defer file.Close() switch filepath.Ext(path) { case ".jpg", ".jpeg": return jpeg.Encode(file, img, &jpeg.Options{Quality: 100}) case ".png": return png.Encode(file, img) case ".gif": return gif.Encode(file, img, &gif.Options{}) } return fmt.Errorf("unsupported file: %s", path) }
  22. • bilinearなり、bicubicなり、Lanczosなり、お好みの方法で ◦ どんなアルゴリズムでやるとしても、結局、実際の画素データを触らないとリサイズで きない。それはそう • image.Image#At(x, y) で指定座標の画素データが得られる ◦

    color.Color 型 ◦ なにこれ? 22 リサイズ
  23. • 画素が示す色を抽象化した型 • その実態は様々 ◦ color.RGBA (color.RGBA64), color.NRGBA (color.NRGBA64) ◦

    color.Gray (color.Gray16) ◦ color.Palette ◦ color.YCbCr ◦ color.YMCK 23 型
  24. • AはAlpha channel(透過度、というか、透過してない度 ) • Nは何? • みんながぱっと想像する単純な R, G,

    B, Aの各値を持つのはNRGBA ◦ RGBAはR, G, BにAlphaの値を掛けたものが入っている(alpha-premultiplied) ◦ なので、NRGBAは “Non-alpha-premultiplied RGBA” のこと • どうせ表示する時は掛け算しないといけないので、最初から掛けておくという発想 (クライ アント側に優しい……のかなぁ……) 24 と
  25. • 0 (透過100%)をR, G, Bに掛けると、全部 0 になる ◦ つまり色情報が消える •

    リサイズ時に問題が起きる ◦ 隣のピクセルの色を見て色を混ぜたりする ◦ 透過ピクセルの色は常に「黒」 • color.Color 型の共通インターフェースは RGBA() ◦ 実際のデータがNRGBAであっても直接メンバを見ない限り RGBAになる 25 の落とし穴
  26. • 頑張るしかないので頑張る • PaletteはどうせRGB(+A)に変換するしかないのでそうする • Grayは、メモリ消費を抑えたいならそのまま ◦ 実装コストとのトレードオフ 26

  27. • 知ってる? ◦ Y:輝度 ◦ Cb:青色差 ◦ Cr:赤色差 • 人間の視覚は輝度の変化には敏感だがそれと比べれば色差には鈍感

    ◦ なので輝度情報と比べて色差の情報は間引ける • RGBとは簡単な計算式で相互変換可能 27
  28. • JPEGはだいたいYCbCr ◦ 内部的にRGBへの変換を経由しない方が、速度的にもメモリ的にもお得 ◦ いろんな規格で微妙に変換式中の定数が違うので RGB経由自体が危険 • ビット表現も1種類じゃない(Goのimage.YCbCr型は差異を吸収) ◦

    4:4:4 ◦ 4:2:2, 4:1:1 ◦ 4:2:0, 4:1:0 28
  29. • 印刷用 • Cyan, Magenta, Yellow, K...??? ◦ blacK? Kuro?

    Karbon? Key plate? • 入稿用データとかでは普通に存在する • これも加工時にはRGBを経由しない方が無難 29
  30. • いろんなメタ情報が入ってる ◦ 撮影場所のGPSの情報とかが入っていて問題になりがち • Go標準の image/jpeg パッケージはExifを取り扱わない ◦ ので読んで書いたら消える。ラッキー!?

    • Orientation情報:回転 ◦ 消したら「画像の向きが変わった!」とか言われる • Exif読み込んで解釈してGPS情報だけ消すとか地獄 30 問題
  31. • ICC:International Color Consotium • 追加の色情報(色空間の補正) • 最近のだいたいのブラウザはサポートしている • ブラウザと画像処理専門ソフト(Photoshopとか)以外はサポートしてない

    • Goの image パッケージも未サポート ◦ 読んで書いたら消える ◦ つまり、色が変わって見える 31 プロファイル問題 https://en.wikipedia.org/wiki/Color_space より
  32. 結論 32

  33. • ここまで挙げた以外にも落とし穴はいっぱいある ◦ 各種の画像フォーマット、その派生規格、画像処理、最適化、 etc… にそこそこ精通す る必要がある • 我々が本当に作りたかったのは Webアプリケーションであって画像変換エンジンじゃない

    ◦ なにかしらがないと顧客に価値(UX)を届けることはできないが、そのために画像変換 エンジンを自作するのはコストが高すぎる 33 生半可な覚悟で画像変換エンジンは作れない
  34. は偉大 がんばって うまく使いこなそう 34

  35. もうちょっとだけ 続くんぢゃ 35

  36. 36 :アップロード時にサーバサイドで加工 続き 36 • デザイナー < あ、デザイン変えたんでよろしく (^^) ◦

    全画像ファイル再生成 • Ap〇le < あ、新機種で解像度変えたんでよろしく (^^) ◦ 全画像ファイル再生成(※旧機種用も残す必要あり)
  37. 37 :オンデマンドでアクセスされたときに 加工後画像生成 37 • キャッシュヒット率が十分高ければ現実的選択肢 • 運用上の困難は増大 ◦ 脆弱性対応

    ◦ アクセススパイク時の対応 ◦ アラート、アラート、アラート……
  38. 注: ここからは宣伝です 38

  39. 39 :画像変換 にまかせる 39 • オンデマンド変換なので必要なときに必要な画像を生成 • 運用上の困難はSaaS側に押し付けられる • 最近はCDN屋さんがいろいろその手の付加サービスを提供し始めた

  40. 40

  41. • 世界最大級のイラスト共有SNS「pixiv」で培った画像変換のノウハウを投入 ◦ 同じものが今もpixivをはじめとするピクシブの各サービスで使われている • インフラはさくらインターネットが提供 ◦ アクセスポイントは国内にあるので高速 (太平洋往復したりしない) •

    URLに変換パラメータを含めるだけで画像を変換するプロクシとして機能 ◦ HTMLさえ書ければ、デザイナーが新デザイン案を試してみる、とかいう事も可能 41 の特徴
  42. 42 の使用例

  43. • image_flux.gemというものがあります ◦ 宇宙海賊さん作 ◦ https://github.com/space-pirates-llc/image_flux 43 コード絶無は悲しいので、ご紹介 require ”image_flux”

    origin = ImageFlux::Origin.new(domain: ”demo.imageflux.jp”) origin.image_url(”/bridge.jpg”, width: 600) #=> ”https://demo.imageflux.jp/c/w=600/bridge.jpg”
  44. それはそれとして 44

  45. 弊社と契約して 画像変換エンジニアに なってほしいんだ! 45

  46. • ぼくと一緒に画像変換サービスを作ろうよ! ◦ 罠と課題はまだまだ無限にある ◦ 最強の画像変換SaaSを実現しよう! • 最近は動画変換サービス ImageFlux Live

    Streaming も開始 ◦ こちらの技術者ももちろん募集中 • https://recruit.jobcan.jp/pixiv/show/b001/2969 46 画像変換サービス開発たのしす