ctx.globalCompositeOperation =
あなたは複合方法を使用することができ、 "乗算" とダイナミックレンジが失われないよう、以下のようにRGBAフォーマットでfillRect()と色を定義する試しfrntのようにすると、0.6のアルファは元のマスクからのコントラストを大幅に減少させます。
多くのブレンドオプションがありますが、白い部分が見えず、暗い部分のみを追加したい画像の場合は、ブレンドモード "乗算"を使用します。この方法は、可能な限り最良のコントラストを提供します。
ctx.fillStyle = ??? // the background colour you want
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); // fill canvas with colour. This is now the destination
// Destination pixels get multiplied by source pixels
// nC = dC * (sC/255); (seperate for each channel RGB. no effect on alpha)
// where nC is the new colour, dC is destination colour and, sC is source colour;
// White pixels make no change, all others reduce the the colour
ctx.globalCompositeOperation = "multiply";
// draw the image over the top.
ctx.drawImage(img, 0, 0, canvas.width, cvtx.canvas.height);
ctx.globalCompositeOperation = "source-over"; // reset to default
最高品質
あり、より良い方法があるが、それはピクセルデータを取得し、乗算前に各ピクセルにフォトンカウントを行う必要。これにより、元のマスクに近い一致が得られます。式はnC =Math.sqrt(dC * dC * (sC * sC/(255*255)));
です。nC
は新しい色、dC
は宛先色、sC
は元の色です。アルファを無視して各チャンネルのRGBに適用します。アルファコンポジット経由
// r,g,b are the background colour
// img is a loaded image to convert
var r = ?, g = ?, b = ?;
// create canvas and context for image
var c = document.createElement("canvas");
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
// draw image onto the canvas
ctx.drawImage(img, 0,0);
// get the pixel data
var data = ctx.getImageData(0,0,c.width,c.height);
var d = data.data;
// Convert background colour to photon count and normalise
r = r * r/(255 * 255);
g = g * g/(255 * 255);
b = b * b/(255 * 255);
var i = 0, len = d.length;;
// for each pixel do the multiply using photon counts
while(i < len){
d[i] = Math.sqrt(d[i] * d[i++] * r);
d[i] = Math.sqrt(d[i] * d[i++] * g);
d[i] = Math.sqrt(d[i] * d[i++] * b);
i ++;
}
// put the image data back onto the canvas.
ctx.putImageData(data,0,0);
。
アルファコンポジットを使用することもできますが、乗算は効果ではない可能性があります。シンプルとフォトン数の2つの方法があります。 注:2つの方法は、背景色のアルファ値が255であると仮定し、その値に対してONLYを使用します。
ピクセルのアルファを簡単に取得します。アルファチャンネルが設定され、キャンバスのソースオーバー(デフォルト)ブレンディング機能を使用しただけの場合はどのように処理されますか。フォトンカウントカラーモデルを使用する理由(それは高品質のプロフェッショナルに混合するためにどのように行われるか)
// assume you have got the pixel data etc.. see above snipets
var amount = ?; // the mixing amount
var i = 0, len = d.length;;
// for each pixel do the alpha blend
while(i < len){
var rr = d[i]; // get source channels
var gg = d[i + 1];
var bb = d[i + 2];
var alpha = (rr + gg + bb)/(3 * 255); // calculate alpha by finding the mean
// alpha is inverted but also need to clamp alpha as floating point may give a value too high so clamp and invert
alpha = Math.min(1, 1 - alpha);
alpha *= amount; // set the mix amount
var aInv = 1 - alpha; // invert again
// each channel is the sum of background and image colour time their respective mix amounts
d[i++] = aInv * r + alpha * rr;
d[i++] = aInv * g + alpha * gg;
d[i++] = aInv * b + alpha * bb;
d[i++] = 255; // in this case alpha is always 255
}
// put the image data back onto the canvas.
ctx.putImageData(data,0,0);
そして正しい方法
// assume you have got the pixel data etc.. see above snipets
var amount = ?; // the mixing amount
// Convert background colour to photon count and normalise
r = r * r/(255 * 255);
g = g * g/(255 * 255);
b = b * b/(255 * 255);
var i = 0, len = d.length;;
// for each pixel do the alpha blend using photon counts
while(i < len){
var rr = d[i]; // get source channels
var gg = d[i + 1];
var bb = d[i + 2];
rr *= rr;
gg *= gg;
bb *= bb;
var alpha = (rr * + gg + bb)/(3 * 255 * 255); // calculate alpha by finding the mean in photon space
// alpha is inverted but also need to clamp alpha as floating point may give a value too high so clamp and invert
alpha = Math.min(1, 1 - alpha);
alpha *= amount; // set the mix amount
var aInv = 1 - alpha; // invert again
// each channel is the sum of background and image colour time their respective mix amounts
d[i++] = Math.sqrt(aInv * r + alpha * rr);
d[i++] = Math.sqrt(aInv * g + alpha * gg);
d[i++] = Math.sqrt(aInv * b + alpha * bb);
d[i++] = 255; // in this case alpha is always 255
}
// put the image data back onto the canvas.
ctx.putImageData(data,0,0);
。
私が使用するカラーモデルは、デバイスディスプレイから放出される光子の数に基づいています。各カラーチャネルは0〜255の値を保持しますが、これらの値はモニタの実際の出力と一致せず、カメラ(入力デバイス)でキャプチャされた光子の数も表しません。それらは光子束の平方根です。単純な線形平均で色を混ぜて、これを考慮しないと、結果として得られる色が暗くなります(画像の色合いが高い場合は特に顕著です)、コントラスト曲線が広がります。最良の結果を得るためにピクセルを直接操作するときは、常にr、g、bの値を四角形にして、混合、ブレンディングなどを行います。準備ができたら、結果の平方根を計算して値を対数表現に戻します。
このビデオでは、我々は色の不透明度を軽減することができるように、RGBAに進から変換された鮮やかな赤と背景を埋めるためにfillRectを使用している以上、ここでは詳細Computer Color is Broken
に説明します。 0.8から1に変更してみてください。また、画像を背景色とマージするには、透明にする必要があります。 – frnt
@Kaiido ctx.globalAlpha = 0.6;のようにコードにこれを加えます。 – frnt