1

crossOrigin を許可しない s3 サーバーから取得した画像の色を変換する必要があります。

これは私が必要とする機能です:

  const img = new Image();
  img.src = src;
  ctx.drawImage(img, 0, 0);
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const colors = [25,50,100,255];
  const data = imageData.data;
  for (let i = 0; i < data.length; i += 4) {
    if(data[i] == 1){data[i] = colors[1]}
    if(data[i] == 2){data[i] = colors[2]}
    if(data[i] == 3){data[i] = colors[3]}
  }

しかし、crossOrigin エラーによって汚染されました:

ここに画像の説明を入力

getImageDataこの場合使えないことはわかっています。画像データを読みたくない。

しかし、他の webGL / キャンバス操作でタスクを完了することができますか?

サーバーまたはプロキシでのレンダリングはできません。

4

1 に答える 1

2

WebGL は、クロスオリジン テクスチャではまったく機能しません。ドラフトには拡張機能がありますが、まだ標準化されておらず、限られたシナリオでのみ許可されているため、そのようなテクスチャを使用するサンプラーは条件式で使用できません。

クラシック キャンバスでは、ブレンド モードを巧みに使用して多数のカラー効果を実現できます。それらのリストはMDNにあり、より技術的な説明はW3にあります。

特に、非常に便利なトリックには、color-dodge操作の使用が含まれます。ソースとして非常に明るい一定の色を使用することで、背景画像に大きな値を効果的に乗算し、しきい値操作を実行できるようにします。

あなたの場合、次のコードを使用して、特定の色のすべてのピクセルを「選択」できます。

// 1. Use 'difference' to make all matching pixels black
ctx.globalCompositeOperation = "difference";
ctx.fillStyle = srcColor;
ctx.fillRect(0, 0, w, h);
// 2. Use 'color-dodge' trick to turn all non-black pixels into white
ctx.globalCompositeOperation = "color-dodge";
ctx.fillStyle = "#fefefe";
ctx.fillRect(0, 0, w, h);

// Steps 3 and 4 are only necessary if full RGB matching is required
// Without these steps, matching will be done on per-channel basis 
// 3*. Desaturate the image, ensuring all three channels have the same value
ctx.globalCompositeOperation = "saturation";
ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, w, h);
// 4*. Use color-dodge again, to mask pixels where all 3 components matched
ctx.globalCompositeOperation = "color-dodge";
ctx.fillStyle = "#fefefe";
ctx.fillRect(0, 0, w, h);

// 5. Invert the image to make matching pixels white and the rest black
ctx.globalCompositeOperation = "difference";
ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, w, h);
// 6. Multiply by desired color
ctx.globalCompositeOperation = "multiply";
ctx.fillStyle = dstColor;
ctx.fillRect(0, 0, w, h);

コードを実装した実際の例を次に示します (出力イメージの左半分は黒に見えます。これは、 のような暗い色が見えないためですrgb(1,0,0))。

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

function makeImage(w, h) {
  const c = document.createElement("canvas");
  c.width = w;
  c.height = h;
  return c;
}

function paintSource(c) {
  const ctx = c.getContext("2d");
  const data = ctx.getImageData(0, 0, c.width, c.height);
  for (let x = 0; x < c.width; ++x) {
    for (let y = 0; y < c.height; ++y) {
      const i = (y * c.width + x) * 4;
      const v = Math.round((x + y) / 2);
      // 1, 2 or 3
      data.data[i] = Math.floor(x * 3 / c.width) + 1;
      data.data[i + 3] = 255;
    }
  }
  ctx.putImageData(data, 0, 0);
}

function selectColor(srcCanvas, dstCanvas, srcColor, dstColor) {
  const ctx = dstCanvas.getContext("2d");
  ctx.drawImage(srcCanvas, 0, 0);
  const w = srcCanvas.width, h = srcCanvas.height;
  
  ctx.globalCompositeOperation = "difference";
  ctx.fillStyle = srcColor;
  ctx.fillRect(0, 0, w, h);
  ctx.globalCompositeOperation = "color-dodge";
  ctx.fillStyle = "#fefefe";
  ctx.fillRect(0, 0, w, h);
  ctx.globalCompositeOperation = "difference";
  ctx.fillStyle = "#ffffff";
  ctx.fillRect(0, 0, w, h);
  ctx.globalCompositeOperation = "multiply";
  ctx.fillStyle = dstColor;
  ctx.fillRect(0, 0, w, h);
}

const source = makeImage(256, 256);
paintSource(source);

const c1 = makeImage(256, 256);
selectColor(source, c1, "rgb(1,0,0)", "rgb(50,0,0)");
const c2 = makeImage(256, 256);
selectColor(source, c2, "rgb(2,0,0)", "rgb(100,0,0)");
const c3 = makeImage(256, 256);
selectColor(source, c3, "rgb(3,0,0)", "rgb(255,0,0)");

ctx.drawImage(source, 0, 0);
ctx.globalCompositeOperation = "lighter";
ctx.drawImage(c1, 256, 0);
ctx.drawImage(c2, 256, 0);
ctx.drawImage(c3, 256, 0);
<canvas id="canvas" width="512" height="256"></canvas>

しきい値処理を示すもう少し複雑な例を次に示します: https://jsfiddle.net/Rivvy/kq2ga90z/35/

于 2018-08-01T16:32:41.490 に答える