本記事は、先日開催されたKyoto.js 19のために用意したLT資料に加筆したものです。
こんにちは、天城です。 最近はWebGLで動画編集アプリを開発しており、Webでの色の扱いについて日々苦しんでおります。 この記事では、僕が最近知った色関連の小ネタを共有します。
目次
話題1: mix-blend-modeにaddがない
- CSSのmix-blend-mode、ご存知ですか
- 最近まで単純な加算合成ができなかったの知ってましたか?
- 背景色と前景色のRGBAをそのまま加算する、という事ができなかった
- つまりクロスフェードが実装できなかった
- alpha 50%の要素を重ねると、出力は alpha 100% ではなく alpha 75% になる!
- Chrome100でplus-lighterが実装され、できるようになった
- JakeArchibaldによる解説 https://jakearchibald.com/2021/dom-cross-fade/
- 動画版 https://www.youtube.com/watch?v=PYSOnC2CrD8
そもそもBlendingって何?
- Webにおける色の合成は Compositing and Blending というSpecで定義されている
- BlendingとCompositingは別概念である
- Blending: 2つの色を混ぜること (multiply, darker… etc)
- Compositing: 前景色と背景色を合成すること (source-over, xor… etc)
Webでは基本的にsource-over compositingしか使われない
- source-over: 前景色が背景色の上に表示される
- DOM要素が、z-index順に塗り重ねられていくイメージ
- source-overにおけるBlendingとCompositingは、以下のように計算される:
- alpha 50%の要素を2つ重ねたとき、出力のalphaは
となり、0.75になる
Canvasではsource-over以外のCompositingが使える
- Canvasでは
globalCompositingOperation
で Compositing を指定できる- CanvasRenderingContext2D.globalCompositeOperation - Web API | MDN
- 背景色をマスクとして使う等のトリッキーな事もできる
- Canvasでは、globalCompositingOperationを
lighter
にすることで加算合成ができた- 全然 “lighter” では無いが……
- 実際Specにも「Porter-Duffにおける plus のことだよ」と書いてある
- つまり、
plus-lighter
というネーミングは、このlighter
とplus
を併記したもの……?
- 全然 “lighter” では無いが……
PDF Reference
- Adobe製品(Photoshop, AE etc)で使われてるBlending Functionは、PDF Referenceで定義されている
- 他社の画像/映像/デザイン系アプリも、基本的にAdobeのBlending Functionsを真似ているっぽい
- Adobe公式のPDFのドキュメントだが……
OK I found the PDF reference explaining blending functions used in Adobe apps, it wasn't even linked from the official AE doc... https://t.co/8eBnehXYnt pic.twitter.com/XckNEXV5mD
— 𝘼𝙈𝘼𝙂𝙄 (@amagitakayosi) 2022年12月9日
一方その頃WebGLは……
- WebGL (≒ OpenGL) では
gl_blendEquation()
とgl.blendFunc()
で色を合成する- ref. https://mrdoob.github.io/webgl-blendfunctions/blendfunc.html
- 定数をガチャガチャして処理を切り替える
- PDF Referenceで定義されてるようなBlendingをやりたいときは、自分でシェーダーを書くしか無い
- 僕は↑のライブラリをそのまま使うわけにもいかないので、頑張っています……………………………………………………………………………………………………………………………………………………………………………………
話題2: Display P3
CSS Color 4でDisplay P3が使えるようになった
なにそれ?
Display P3
つまり?
- 色域 (= 色空間 = Color Space) の一つ
- Appleが策定した
- 2015年のiMacからサポート https://support.apple.com/kb/SP731?locale=ja_JP
- 「数百万色以上」雑すぎる
- 2015年のiMacからサポート https://support.apple.com/kb/SP731?locale=ja_JP
- Display P3はDCI-P3という規格から派生した
- DCI-P3との違い
- white pointが D65 (≒ 6500K) (DCI-P3だと~6300 K)
- ガンマが2.2 (DCI-P3だと2.6)
つまり???????????????
- 表示できる色が増える
- Display P3での
rgb(1, 0, 0)
は、sRGBのrgb(1, 0, 0)
よりも赤い - 256色より1677万色(厳密には16777216色)のほうが良いよね、というのとは違う話
- Display P3での
CSS Color 4
https://www.w3.org/TR/css-color-4/
- Candidate Recommendation Draft 状態 (勧告準備?)
- Color 3が勧告されたのは2011年
- 昔だね
In particular, it allows specifying colors in other color spaces than sRGB; previously, the more saturated colors outside the sRGB gamut could not be used in CSS even if the display device supported them.
- sRGB 以外の色域も扱えるようにしようね、というのが主なテーマっぽい
CSS Color 4 で導入された記法
color()
関数
色空間を指定して色を定義できる
- Twitterで見つけたデモ: https://codepen.io/argyleink/pen/RwyOyeq
- 最近のブラウザではもう使える
linear-gradient(to right in hsl)
とか
詳しくはChromeの開発ブログとかtakanoripさんの記事に全部書いてある
余談: CSS Color 5ではICCプロファイルを読めるようになるらしい……?
media queryでディスプレイのカラープロファイルを判定する
デモ: https://codepen.io/fand/pen/poxYYrR
sRGBのディスプレイで表示:
MacBook Proのディスプレイで表示:
「sRGBの場合のみ表示する」ということはできない……?
(color-gamut: srgb) and (not(color-gamut))
だとダメだった- 誰か教えて!
CanvasでDisplay P3を使うには
getContext()
にオプションを渡すと、Display P3で出力できるようになる:
let canvas = document.getElementById("canvas"); let context = canvas.getContext("2d", { colorSpace: "display-p3" });
- 右の赤のほうが赤い
- ディスプレイの輝度を下げるとわかりやすいです
- ImageDataの色を取得するときも色域を指定できる
imageData = context.getImageData(0, 0, 1, 1, { colorSpace: "display-p3" });
WebGLでDisplay P3を使うには
const canvas = document.querySelector('#canvas'); const context = canvas.getContext("webgl"); context.drawingBufferColorSpace = "display-p3"; // これは動かないので注意 canvas.getContext("webgl", { colorSpace: "display-p3" });
demo: https://codesandbox.io/s/webgl-display-p3-test-xs8zcp
- ディスプレイがDisplay P3に対応しているとき、WebGLからDisplay P3空間の色を出力できる
- テクスチャとして使う画像のカラープロファイルは考慮されないので注意
スクリーンショット撮るときの注意
- macOSでスクリーンショットを撮ると、出力画像のカラープロファイルは撮影したディスプレイのカラープロファイルになる
- WebGLでsRGB出力した画面のスクショを他のアプリと比較して「おかしいな〜〜〜〜〜〜〜」と悩んでいた
I spent hours fixing a bug with a transparent PNG. It renders differently in different apps. I thought it must be a color encoding bug...
— 𝘼𝙈𝘼𝙂𝙄 (@amagitakayosi) 2023年4月18日
But finally, it turned out the problem was in macOS's screenshot app; I had to change the display's color profile before taking screenshot😭 pic.twitter.com/a5rZgm2ODC- 1行目のスクショと2行目のスクショで色味が違うのがわかりますか?
- ディスプレイのカラープロファイルをsRGBに変更すると正しい色味になった (3行目)
- なんかいい方法を教えてくれ……
- ColorSync Utilityで解決したりもできるらしい?????