web-dev-qa-db-ja.com

<canvas>のスケーリング時に補間を無効にします

NOTE:これは、既存のキャンバス要素がスケールアップ時にレンダリングされる方法と関係しています。 、notは、線またはグラフィックスのレンダリング方法に関係しますキャンバス表面上。つまり、これはinterpolation of scaled elementsと関係があり、キャンバスに描画されるグラフィックスのantialiasingとは関係ありません。ブラウザがどのように線を引くかは気にしません。ブラウザがキャンバス要素をどのようにレンダリングするかを気にしていますitself拡大されたとき。


<canvas>要素のスケーリング時に補間を無効にするためにプログラムで変更できるキャンバスプロパティまたはブラウザ設定はありますか?クロスブラウザソリューションは理想的ですが、必須ではありません。 Webkitベースのブラウザーが私の主なターゲットです。パフォーマンスは非常に重要です。

この質問 は最も似ていますが、問題を十分に説明していません。それが価値があるものとして、私はimage-rendering: -webkit-optimize-contrastを試してみましたが無駄になりました。

アプリケーションは、必要なものを明確にするために、HTML5 + JSで記述された「レトロな」8ビットスタイルのゲームになります。


説明のために、ここに例を示します。 ( ライブバージョン

21x21のキャンバスがあるとします...

<canvas id='b' width='21' height='21'></canvas>

...要素を5倍(105x105)にするCSSがあります:

canvas { border: 5px solid #ddd; }
canvas#b { width: 105px; height: 105px; } /* 5 * 21 = 105 */

次のように、キャンバスに単純な「X」を描画します。

$('canvas').each(function () {
    var ctx = this.getContext("2d");
    ctx.moveTo(0,0);
    ctx.lineTo(21,21);
    ctx.moveTo(0,21);
    ctx.lineTo(21,0);
    ctx.stroke();
});

左側の画像は、Chromium(14.0)がレンダリングするものです。右側の画像は、私が望むものです(説明のために手描き)。

Chrome interpolates scaled canvas elementsA non-interpolated version

120
namuol

最終更新日:2014-09-12

要素をスケーリングするときに補間を無効にするためにプログラムで変更できるキャンバスプロパティまたはブラウザ設定はありますか?

答えは多分いつかです。今のところ、あなたが望むものを手に入れるには、ハックアラウンドに頼らなければなりません。


image-rendering

CSS3のワーキングドラフトでは、新しいプロパティの概要を説明していますimage-rendering

Image-renderingプロパティは、ユーザーエージェントが適切なスケーリングアルゴリズムを選択するのを支援するために、画像のスケーリング時に画像のどの側面が最も重要であるかについてユーザーエージェントにヒントを提供します。

仕様では、autocrisp-edges、およびpixelatedの3つの許容値の概要を説明しています。

pixelated:

画像を拡大する場合、「最近傍」または同様のアルゴリズムを使用する必要があります。そのため、画像は単純に非常に大きなピクセルで構成されているように見えます。縮小する場合、これは自動と同じです。

標準?クロスブラウザ?

これは単なる作業ドラフトであるため、これが標準になるという保証はありません。現在のところ、ブラウザのサポートは最高の状態でしかありません。

Mozilla Developer Networkには、 最新の技術に特化した非常に詳細なページ があります。これを読むことを強くお勧めします。

Webkit開発者は当初 (暫定的に-webkit-optimize-contrastとしてこれを実装する を選択しましたが、Chromium/Chromeはこれを実装するWebkitのバージョンを使用していないようです。

更新:2014-09-12

Chrome 38はimage-rendering: pixelatedをサポートするようになりました

Firefoxにはimage-rendering: pixelatedを実装するための バグレポート がありますが、現在は-moz-crisp-edgesが機能しています。

解決?

したがって、これまでで最もクロスプラットフォームなCSSのみのソリューションは次のとおりです。

canvas {
  image-rendering: optimizeSpeed;             /* Older versions of FF          */
  image-rendering: -moz-crisp-edges;          /* FF 6.0+                       */
  image-rendering: -webkit-optimize-contrast; /* Safari                        */
  image-rendering: -o-crisp-edges;            /* OS X & Windows Opera (12.02+) */
  image-rendering: pixelated;                 /* Awesome future-browsers       */
  -ms-interpolation-mode: nearest-neighbor;   /* IE                            */
}

残念ながら、これはまだすべての主要なHTML5プラットフォーム(特にChrome)で動作しません。

もちろん、JavaScriptで高解像度のキャンバスサーフェスに最近傍内挿を使用して画像を手動で拡大することも、画像をサーバー側で事前に拡大することもできますが、私の場合、これは非常にコストがかかるため、実行可能なオプションではありません。

ImpactJS は、テクスチャの事前スケーリング手法を使用して、このFUDをすべて回避します。 Impactの開発者であるDominic Szablewskiは、 これについて非常に詳細な記事を書いた (彼は研究でこの質問を引用することさえしました)。

imageSmoothingEnabledプロパティに依存するキャンバスベースのソリューションについては、 Simonの答え を参照してください(古いブラウザーでは使用できませんが、事前スケーリングよりも単純で、広くサポートされています)。

ライブデモ

canvas要素に関するMDNの記事で説明されているCSSプロパティをテストしたい場合、ブラウザーに応じて、ぼやけているかどうかにかかわらず、このような表示をする this fiddle を作成しました: a 4:1 (64x64 to 256x256) image of an isometric pixel-art style TV

119
namuol

新しい回答7/31/2012

これがついにキャンバス仕様になりました!

仕様では最近imageSmoothingEnabledと呼ばれるプロパティを追加しました。このプロパティはデフォルトでtrueに設定され、非整数座標で描画されたイメージまたは描画されたスケーリングがより滑らかなアルゴリズムを使用するかどうかを決定します。 falseに設定されている場合、最近傍が使用され、画像の滑らかさが低下し、代わりにピクセルが大きくなります。

画像の平滑化はごく最近キャンバス仕様に追加され、すべてのブラウザでサポートされているわけではありませんが、一部のブラウザはこのプロパティのベンダー接頭辞バージョンを実装しています。コンテキストには、FirefoxのmozImageSmoothingEnabledとChromeおよびSafariのwebkitImageSmoothingEnabledが存在し、これらをfalseに設定すると、アンチエイリアスの発生が停止します。残念ながら、この記事の執筆時点では、IE9およびOperaは、このプロパティ(ベンダープレフィックスなど)を実装していません。


プレビュー:JSFiddle

結果:

enter image description here

58
Simon Sarris

2012年7月31日編集-この機能は、現在キャンバス仕様にあります!こちらの別の回答をご覧ください:

https://stackoverflow.com/a/11751817/154112

古い答えは後世のためです。


希望する効果に応じて、これを1つのオプションとして選択できます。

var can = document.getElementById('b');
var ctx = can.getContext('2d');
ctx.scale(5,5);
$('canvas').each(function () {
    var ctx = this.getContext("2d");
    ctx.moveTo(0,0);
    ctx.lineTo(21,21);
    ctx.moveTo(0,21);
    ctx.lineTo(21,0);
    ctx.stroke();
});

http://jsfiddle.net/wa95p/

これはこれを作成します:

enter image description here

おそらくあなたが望むものではありません。しかし、単にブラーをゼロにしたい場合は、それがチケットになるので、念のために提供します。

より難しいオプションは、ピクセル操作を使用して、ジョブのためにアルゴリズムを自分で記述することです。最初の画像の各ピクセルは、新しい画像の5x5ピクセルのブロックになります。画像データを扱うのはそれほど難しくありません。

ただし、CanvasとCSSだけでは、希望する正確な効果で一方を他方にスケーリングすることはできません。

11
Simon Sarris

Google Chromeでは、キャンバスの画像パターンは補間されません。

Namuolの回答 http://jsfiddle.net/pGs4f/ から編集した実際の例を次に示します。

ctx.scale(4, 4);
ctx.fillStyle = ctx.createPattern(image, 'repeat');
ctx.fillRect(0, 0, 64, 64);
4
saviski

Saviskiの回避策 説明 ここ は、以下で動作するため、有望です。

  • Chrome 22.0.1229.79 Mac OS X 10.6.8
  • Chrome 22.0.1229.79 m Windows 7
  • Chromium 18.0.1025.168(開発者ビルド134367 Linux)Ubuntu 11.10
  • Firefox 3.6.25 Windows 7

ただし、以下では機能しませんが、CSS画像レンダリングを使用して同じ効果を実現できます。

  • Firefox 15.0.1 Mac OS X 10.6.8(image-rendering:-moz-crisp-edgesは this で動作します)
  • Opera 12.02 Mac OS X 10.6.8(image-rendering:-o-crisp-edgesは this で動作します)
  • Opera 12.02 Windows 7(image-rendering:-o-crisp-edgesは this で動作します)

問題は、ctx.XXXImageSmoothingEnabledが機能せず、画像レンダリングが機能しないためです。

  • Safari 5.1.7 Mac OS X 10.6.8。 (image-rendering:-webkit-optimize-contrastは機能しません)
  • Safari 5.1.7 Windows 7(image-rendering:-webkit-optimize-contrastは機能しません)
  • IE 9 Windows 7(-ms-interpolation-mode:nearest-neighborは機能しません)
1
Timo Kähkönen