web-dev-qa-db-ja.com

HTML5キャンバスを使用した高DPIグラフィック

HTML5キャンバスを使用して画像を作成するときにカスタムDPI/PPIを設定する方法はありますか?キャンバスに描画して画像としてエクスポートする方法は知っていますが、出力画像が特定のDPI/PPIであることを確認するにはどうすればよいですか。 SVG要素を使用してキャンバスに描画するのは方法だと思いますが、キャンバス全体を画像としてエクスポートすると、それは平坦化されませんか?または、デバイスのDPIを計算してから、DPI要件を満たすように画像をスケーリングしますが、それは正しい解決策ではないようです。

14
redGREENblue

どのブラウザでも、現在のWebページの表示のDPIにアクセスすることはできません。

JS/CSSからシステムDPI/PPIを検出しますか?

印刷の場合:ブラウザの標準機能を使用して、エクスポートされた<canvas>画像(PNG、JPEG)のDPIを設定できない可能性があります。ただし、純粋なJavascriptエンコーダーイメージエンコーダーを使用する場合は、任意の種類のバイナリファイルを自由に作成し、バイナリに埋め込まれたDPI値を手動で調整できます。

https://Gist.github.com/1245476

3
Mikko Ohtamaa

キャンバスには、DOMの幅/高さとCSSの幅/高さの2つの異なる「サイズ」があります。 CSSサイズを固定したままDOMサイズを増やしてから、.scale()メソッドを使用して、将来のすべての描画を新しい大きなサイズにスケーリングすることで、キャンバスの解像度を上げることができます。次に例を示します。

function changeResolution(canvas, scaleFactor) {
    // Set up CSS size.
    canvas.style.width = canvas.style.width || canvas.width + 'px';
    canvas.style.height = canvas.style.height || canvas.height + 'px';

    // Resize canvas and scale future draws.
    canvas.width = Math.ceil(canvas.width * scaleFactor);
    canvas.height = Math.ceil(canvas.height * scaleFactor);
    var ctx = canvas.getContext('2d');
    ctx.scale(scaleFactor, scaleFactor);
}

キャンバスのデフォルトの解像度は96dpi(CSSインチ、実際の画面に基づくものではありません)です。したがって、scaleFactorが2の場合は192dpi、3の場合は288dpiなどになります。実際、目的のDPIが得られるバージョンは次のとおりです。

function setDPI(canvas, dpi) {
    // Set up CSS size.
    canvas.style.width = canvas.style.width || canvas.width + 'px';
    canvas.style.height = canvas.style.height || canvas.height + 'px';

    // Resize canvas and scale future draws.
    var scaleFactor = dpi / 96;
    canvas.width = Math.ceil(canvas.width * scaleFactor);
    canvas.height = Math.ceil(canvas.height * scaleFactor);
    var ctx = canvas.getContext('2d');
    ctx.scale(scaleFactor, scaleFactor);
}

楽しんで!これらのコードサンプルは両方とも、キャンバスごとに1回しか使用できないことに注意してください。現在のDOMサイズが元のサイズであると想定しています(調整して変更できます)。また、キャンバス上で描画を行う前に再スケーリングを行う必要があります。方法と情報をありがとう この投稿

編集:これは、将来の描画をスケーリングし既存のキャンバスコンテンツを維持する、より堅牢な関数です。これは、複数回再スケーリングするために呼び出すことができます。

function setDPI(canvas, dpi) {
    // Set up CSS size.
    canvas.style.width = canvas.style.width || canvas.width + 'px';
    canvas.style.height = canvas.style.height || canvas.height + 'px';

    // Get size information.
    var scaleFactor = dpi / 96;
    var width = parseFloat(canvas.style.width);
    var height = parseFloat(canvas.style.height);

    // Backup the canvas contents.
    var oldScale = canvas.width / width;
    var backupScale = scaleFactor / oldScale;
    var backup = canvas.cloneNode(false);
    backup.getContext('2d').drawImage(canvas, 0, 0);

    // Resize the canvas.
    var ctx = canvas.getContext('2d');
    canvas.width = Math.ceil(width * scaleFactor);
    canvas.height = Math.ceil(height * scaleFactor);

    // Redraw the canvas image and scale future draws.
    ctx.setTransform(backupScale, 0, 0, backupScale, 0, 0);
    ctx.drawImage(backup, 0, 0);
    ctx.setTransform(scaleFactor, 0, 0, scaleFactor, 0, 0);
}
47
Erik Koopmans

PNGのdpiを設定したいだけの場合(つまり、ピクセル数を増やしたくない場合)、このライブラリを使用すると、pHYsチャンクを設定できます(とりわけ)物事):

https://github.com/imaya/CanvasTool.PngEncoder

HTML5キャンバスをbase64でエンコードされたPNGにエクスポートするための最小限の例:

        // convert dots per inch into dots per metre
        var pixelsPerM = dpi * 100 / 2.54;

        var param = {
            bitDepth : 8,
            colourType : 2,
            filterType : 0,
            height : canvas.height,
            interlaceMethod : 0,
            phys : {
                unit : 1,
                x : pixelsPerM,
                y : pixelsPerM
            },
            width : canvas.width
        };

        var array = canvas.getContext('2d').getImageData(0, 0, canvas.width,
                canvas.height).data;

        var png = new window.CanvasTool.PngEncoder(array, param).convert();

        var base64 = 'data:image/png;base64,' + btoa(png);
1
murkle