HTMLの<canvas>要素でアンチエイリアスをオフにできますか?


88

<canvas>要素をいじったり、線を引いたりしています。

対角線がアンチエイリアス処理されていることに気づきました。私がしていることにはギザギザの外観が好きです-この機能をオフにする方法はありますか?


それはむしろブラウザ関連だと思います。使用しているソフトウェアに関する追加情報が役立つかもしれません。
Tomalak 2008年

私はクロスブラウザの方法が、任意の単一のブラウザ上の作品はまだ私には興味深いものになるだろうという方法を好む
Blorgbeardが出ている

このトピックにまだ変更があったかどうかを確認したかっただけですか?
vternal3 2011


これに関する更新はありますか?
ローランド

回答:


64

画像については、現在あります。context.imageSmoothingEnabled= false

ただし、線画を明示的に制御するものはありません。とを使用して独自の線を引く必要がある場合があります(難しい方法)。getImageDataputImageData


1
javascript行アルゴリズムのパフォーマンスについて疑問に思います。ある時点でブレゼンハムのアルゴリズムを試してみるかもしれません。
Blorgbeardは出て

ブラウザベンダーは最近、新しい超高速JSエンジンを売り込んでいるので、最終的にはそれをうまく利用できるでしょう。
kornel

1
これは本当に機能しますか?を使用して線を描画してputImageData いますが、それでも近くのピクセルのエイリアシングが発生します。
Pacerier 2018年

小さいキャンバス(キャッシュ)に描画してから、その設定をオフにして別のキャンバスにdrawImageを描画すると、意図したとおりに機能しますか?
SPARK

69

1-pixelような座標に線を引きますctx.lineTo(10.5, 10.5)。ポイント上に1ピクセルの線を引くという(10, 10)ことは、1その位置にあるこのピクセルがそこから到達し9.510.5そこから2本の線がキャンバスに描かれることを意味します。

0.51ピクセルの線がたくさんある場合に、描画する実際の座標に常にを追加する必要がないという優れたトリックctx.translate(0.5, 0.5)は、最初にキャンバス全体に追加することです。


うーん、この手法を使用してアンチエイリアシングを取り除くのに問題があります。たぶん、私は何かを理解するのが恋しいですか?どこかに例を投稿していただけませんか?
Xavi 2010年

7
これはアンチエイリアスを取り除くことはありませんが、アンチエイリアスされた線の見栄えを大幅に改善します。たとえば、実際に1ピクセルが必要なときに、2ピクセルの太さの恥ずかしい水平線または垂直線を取り除くなどです。
デビッドギブン

1
@porneL:いいえ、ピクセルの角の間に線が引かれます。ラインの幅が1ピクセルの場合、どちらの方向にも0.5ピクセル伸びます
Eric

+0.5を追加するとうまくいきますが、ctx.translate(0.5,0.5)うまくいきませんでした。FF39.0
Paulo Bueno

どうもありがとうございました!変更のために実際の1pxの線があるなんて信じられません!
チャンキーチャンク2017

24

これはMozillaFirefoxで実行できます。これをコードに追加します。

contextXYZ.mozImageSmoothingEnabled = false;

Operaでは現在機能リクエストですが、間もなく追加されることを願っています。


涼しい。あなたの貢献のために+1。AAを無効にすると、線画が速くなるのではないかと思います
marcusklaas 2011

7
OPはアンチエイリアスを解除したいのですが、これは画像でのみ機能します。パースペック、それが決定"whether pattern fills and the drawImage() method will attempt to smooth images if their pixels don't line up exactly with the display, when scaling images up"
rvighne

13

それはアンチエイリアスベクトルグラフィックスでなければなりません

アンチエイリアスは、整数以外の座標(0.4、0.4)を含むベクターグラフィックを正しくプロットするために必要です。これは、ごく一部のクライアントを除いてすべて実行されます。

整数以外の座標が指定されている場合、キャンバスには2つのオプションがあります。

  • アンチエイリアス-整数座標が非整数座標からどれだけ離れているかに基づいて、座標の周りのピクセルをペイントします(つまり、丸め誤差)。
  • ラウンド- (1.4は、例えば、1となるであろうように)座標非整数にいくつかの丸め関数を適用します。

後者の戦略は静的グラフィックスで機能しますが、小さなグラフィックス(半径2の円)の場合、曲線は滑らかな曲線ではなく明確なステップを示します。

本当の問題は、グラフィックが変換(移動)されるときです-1つのピクセルと別のピクセルの間のジャンプ(1.6 => 2、1.4 => 1)は、形状の原点が親コンテナに対してジャンプする可能性があることを意味します(常にシフトします) 1ピクセル上下および左/右)。

いくつかのヒント

ヒント1:キャンバスをスケーリングして(たとえばxで)アンチエイリアスを柔らかく(または固く)してから、(キャンバスを使用せずに)自分でジオメトリに逆数スケール(1 / x)を適用できます。

比較(スケーリングなし):

いくつかの長方形

と(キャンバススケール:0.75;手動スケール:1.33):

エッジが柔らかい同じ長方形

および(キャンバススケール:1.33;手動スケール:0.75):

エッジが暗い同じ長方形

ヒント2:ギザギザの外観が本当に必要な場合は、各形状を数回(消去せずに)描画してみてください。描画するたびに、アンチエイリアスピクセルは暗くなります。

比較してください。一度描いた後:

いくつかのパス

3回描いた後:

同じパスですが、暗く、目に見えるアンチエイリアスはありません。


@vanowmは、自由にクローンを作成して遊んでください:github.com/Izhaki/gefri。すべての画像は/ demoフォルダーのスクリーンショットです(ヒント#2用にコードが少し変更されています)。描かれた図形に整数の丸めを導入して(4分かかりました)、ドラッグするだけで効果を確認するのは簡単だと思います。
Izhaki 2017年

それは信じられないように見えるかもしれないが、そこにあるあなたはアンチエイリアスをオフにしたいまれな状況で。実際のところ、私は人々がキャンバス上の領域をペイントしなければならないゲームをプログラムしたばかりで、4色だけで十分であり、アンチエイリアスのために立ち往生しています。パターンを3回繰り返しても問題は解決せず(200まで上がった)、間違った色のピクセルがまだ残っています。
アルノー

9

ブレゼンハムの線アルゴリズムなどのカスタム線アルゴリズムを使用してすべてを描画します。このjavascriptの実装を確認してくださいhttp//members.chello.at/easyfilter/canvas.html

これで間違いなくあなたの問題は解決すると思います。


2
まさに私が必要としていたことですが、私が追加するのは、実装する必要があるということだけですsetPixel(x, y)。私はここで受け入れられた答えを使用しました:stackoverflow.com/questions/4899799/…–
Tina Vall

8

画像を縮小してキャンバスに描画するときに問題が発生したことを付け加えたいと思います。拡大時に使用していなかったにもかかわらず、スムージングを使用していました。

私はこれを使用して解決しました:

function setpixelated(context){
    context['imageSmoothingEnabled'] = false;       /* standard */
    context['mozImageSmoothingEnabled'] = false;    /* Firefox */
    context['oImageSmoothingEnabled'] = false;      /* Opera */
    context['webkitImageSmoothingEnabled'] = false; /* Safari */
    context['msImageSmoothingEnabled'] = false;     /* IE */
}

この関数は次のように使用できます。

var canvas = document.getElementById('mycanvas')
setpixelated(canvas.getContext('2d'))

多分これは誰かに役立つでしょう。


なぜcontext.imageSmoothingEnabled = falseではないのですか?
Martijn Scheffer 2018

私が答えを書いたとき、これはうまくいきませんでした。今は動作しますか?
eri0o

1
それは、まったく同じことです。javascriptの記述では、obj ['name']またはobj.nameは常に同じであり、今後も同じになります。オブジェクトは、名前付きの値(タプル)のコレクションであり、ハッシュテーブル、両方の表記は同じように扱われます。コードが以前に機能しなかった理由はまったくありません。最悪の場合、効果のない値が割り当てられます(別のブラウザーを対象としているためです。簡単な例:write obj = {a:123}; console.log(obj ['a'] === obj.a? "yes its true": "no it's not")
MartijnScheffer18年

私はあなたがなぜ他のすべてのものを持っているのかを意味していると思いました、私のコメントで私が意味したのは、当時ブラウザは異なるプロパティを必要としたということです。
eri0o

もちろんそうです:)私はコード自体の有効性ではなく構文について話していました(それは機能します)
MartijnScheffer18年

6
ctx.translate(0.5, 0.5);
ctx.lineWidth = .5;

このコンボで、1pxの細い線を描くことができます。


6
lineWidthを.5に設定する必要はありません...それは半分の不透明度にするだけです(またはそうすべきです)。
aaaidan 2015年

4

非常に限られたトリックに注意してください。2色の画像を作成する場合は、色#000000の背景に色#010101で任意の形状を描画できます。これが完了したら、imageData.data []の各ピクセルをテストし、0x00以外の値を0xFFに設定できます。

imageData = context2d.getImageData (0, 0, g.width, g.height);
for (i = 0; i != imageData.data.length; i ++) {
    if (imageData.data[i] != 0x00)
        imageData.data[i] = 0xFF;
}
context2d.putImageData (imageData, 0, 0);

結果は、アンチエイリアス処理されていない白黒画像になります。いくつかのアンチエイリアシングが行われるため、これは完全ではありませんが、このアンチエイリアシングは非常に制限され、形状の色は背景の色と非常によく似ています。


1

まだ答えを探している人のために。これが私の解決策です。

画像が1チャンネルグレーであると仮定します。ctx.stroke()の後にしきい値を設定しました。

ctx.beginPath();
ctx.moveTo(some_x, some_y);
ctx.lineTo(some_x, some_y);
...
ctx.closePath();
ctx.fill();
ctx.stroke();

let image = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height)
for(let x=0; x < ctx.canvas.width; x++) {
  for(let y=0; y < ctx.canvas.height; y++) {
    if(image.data[x*image.height + y] < 128) {
      image.data[x*image.height + y] = 0;
    } else {
      image.data[x*image.height + y] = 255;
    }
  }
}

画像チャンネルが3または4の場合、次のように配列インデックスを変更する必要があります。

x*image.height*number_channel + y*number_channel + channel

0

StashOfCodeの答えに関する2つのメモ:

  1. グレースケールの不透明なキャンバスでのみ機能します(fillRectを白で、次に黒で描画、またはその逆)
  2. 線が細い場合(〜1pxの線幅)失敗する可能性があります

代わりにこれを行うことをお勧めします。

ストロークして塗りつぶし#FFFFFF、次にこれを行います。

imageData.data[i] = (imageData.data[i] >> 7) * 0xFF

これにより、幅が1pxの行で解決されます。

それ以外は、StashOfCodeのソリューションは、独自のラスタライズ関数を作成する必要がないため完璧です(線だけでなく、ベジエ、円弧、穴のある塗りつぶされたポリゴンなどを考えてください)。


0

これは、JavaScriptでのブレゼンハムのアルゴリズムの基本的な実装です。これは、このウィキペディアの記事で説明されている整数演算バージョンに基づいています:https//en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

    function range(f=0, l) {
        var list = [];
        const lower = Math.min(f, l);
        const higher = Math.max(f, l);
        for (var i = lower; i <= higher; i++) {
            list.push(i);
        }
        return list;
    }

    //Don't ask me.
    //https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
    function bresenhamLinePoints(start, end) {

        let points = [];

        if(start.x === end.x) {
            return range(f=start.y, l=end.y)
                        .map(yIdx => {
                            return {x: start.x, y: yIdx};
                        });
        } else if (start.y === end.y) {
            return range(f=start.x, l=end.x)
                        .map(xIdx => {
                            return {x: xIdx, y: start.y};
                        });
        }

        let dx = Math.abs(end.x - start.x);
        let sx = start.x < end.x ? 1 : -1;
        let dy = -1*Math.abs(end.y - start.y);
        let sy = start.y < end.y ? 1 : - 1;
        let err = dx + dy;

        let currX = start.x;
        let currY = start.y;

        while(true) {
            points.push({x: currX, y: currY});
            if(currX === end.x && currY === end.y) break;
            let e2 = 2*err;
            if (e2 >= dy) {
                err += dy;
                currX += sx;
            }
            if(e2 <= dx) {
                err += dx;
                currY += sy;
            }
        }

        return points;

    }

0

のようなものを試してくださいcanvas { image-rendering: pixelated; }

アンチエイリアス処理されていない1行だけを作成しようとしている場合、これは機能しない可能性があります。

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

ctx.fillRect(4, 4, 2, 2);
canvas {
  image-rendering: pixelated;
  width: 100px;
  height: 100px; /* Scale 10x */
}
<html>
  <head></head>
  <body>
    <canvas width="10" height="10">Canvas unsupported</canvas>
  </body>
</html>

ただし、これは多くのブラウザでテストしていません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.