Programing

스케일링시 보간 비활성화

crosscheck 2020. 7. 14. 08:26
반응형

스케일링시 보간 비활성화


참고 :이 방법과 관련이있다 최대 크기를 조절할 때 기존의 캔버스 요소를 렌더링 , 하지 선이나 그래픽 렌더링 방법을 함께 할 캔버스 표면에 . 즉,이 함께 할 수있는 모든 것을 가지고 보간 확장 요소 와 함께 할 수있는 아무것도 앤티 앨리어싱 그래픽은 캔버스에 그려지의를. 브라우저가 선을 그리는 방법에 대해서는 신경 쓰지 않습니다. 나는 브라우저가 캔버스 요소를 렌더링하는 방법에 대해 신경 자체 가 최대의 크기를 조절할 때.


<canvas>요소를 스케일링 할 때 보간을 비활성화하기 위해 프로그래밍 방식으로 변경할 수있는 캔버스 속성 또는 브라우저 설정이 있습니까? 크로스 브라우저 솔루션은 이상적이지만 필수는 아닙니다. 웹킷 기반 브라우저가 나의 주요 대상입니다. 성능이 매우 중요합니다.

이 질문 은 가장 비슷하지만 문제를 충분히 설명하지 못합니다. 그만한 가치가 있기 때문에 image-rendering: -webkit-optimize-contrast아무 소용이 없었습니다.

이 응용 프로그램은 HTML5 + JS로 작성된 "레트로"8 비트 스타일 게임으로, 필요한 것을 명확하게합니다.


예를 들면 다음과 같습니다. ( 라이브 버전 )

21x21 캔버스가 있다고 가정합니다 ...

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

... 요소를 5 배 더 크게 만드는 CSS가 있습니다 (105x105).

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은 크기가 조정 된 캔버스 요소를 보간합니다. 보간되지 않은 버전


최종 업데이트 : 2014-09-12

요소를 스케일링 할 때 보간을 비활성화하기 위해 프로그래밍 방식으로 변경할 수있는 캔버스 속성 또는 브라우저 설정이 있습니까?

대답은 아마 언젠가입니다 . 지금은 원하는 것을 얻기 위해 해킹에 의존해야합니다.


image-rendering

CSS3의 초안은image-rendering 내가 원하는 것을 해야하는 새로운 속성을 간략하게 설명합니다 .

이미지 렌더링 속성은 사용자 에이전트에 적절한 크기 조정 알고리즘을 선택하는 데 도움이되도록 이미지의 크기가 조정될 때 보존해야하는 이미지의 측면이 가장 중요한지에 대한 힌트를 사용자 에이전트에 제공합니다.

사양은 세 가지 허용 값을 설명합니다 : auto, crisp-edges,와 pixelated.

픽셀 화 :

When scaling the image up, the "nearest neighbor" or similar algorithm must be used, so that the image appears to be simply composed of very large pixels. When scaling down, this is the same as auto.

Standard? Cross-browser?

Since this is merely a working draft, there's no guarantee that this will become standard. Browser support is currently spotty, at best.

The Mozilla Developer Network has a pretty thorough page dedicated to the current state of the art which I highly recommend reading.

The Webkit developers initially chose to tentatively implement this as -webkit-optimize-contrast, but Chromium/Chrome don't seem to be using a version of Webkit that implements this.

Update: 2014-09-12

Chrome 38 now supports image-rendering: pixelated!

Firefox has a bug report open to get image-rendering: pixelated implemented, but -moz-crisp-edges works for now.

Solution?

The most cross-platform, CSS-only solution so far is thus:

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                            */
}

Sadly this wont work on all major HTML5 platforms yet (Chrome, in particular).

Of course, one could manually scale up images using nearest-neighbor interpolation onto high-resolution canvas surfaces in javascript, or even pre-scale images server-side, but in my case this will be forbiddingly costly so it is not a viable option.

ImpactJS uses a texture pre-scaling technique to get around all this FUD. Impact's developer, Dominic Szablewski, wrote a very in-depth article about this (he even ended up citing this question in his research).

See Simon's answer for a canvas-based solution that relies on the imageSmoothingEnabled property (not available in older browsers, but simpler than pre-scaling and pretty widely-supported).

Live Demo

If you'd like to test the CSS properties discussed in the MDN article on canvas elements, I've made this fiddle which should display something like this, blurry or not, depending on your browser: 등각 픽셀 아트 스타일 TV의 4 : 1 (64x64 ~ 256x256) 이미지


New answer 7/31/2012

This is finally in the canvas spec!

The specification has recently added a property called imageSmoothingEnabled, which defaults to true and determines if images drawn on non-integer coordinates or drawn scaled will use a smoother algorithm. If it is set to false then nearest-neighbor is used, producing a less smooth image and instead just making larger looking pixels.

Image smoothing has only recently been added to the canvas specification and isn’t supported by all browsers, but some browsers have implemented vendor-prefixed versions of this property. On the context there exists mozImageSmoothingEnabled in Firefox and webkitImageSmoothingEnabled in Chrome and Safari, and setting these to false will stop anti-aliasing from occurring. Unfortunately, at the time of writing, IE9 and Opera have not implemented this property, vendor prefixed or otherwise.


Preview: JSFiddle

Result:

여기에 이미지 설명을 입력하십시오


Edit 7/31/2012 - This functionality is now in the canvas spec! See separate answer here:

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

Old answer is below for posterity.


Depending on your desired effect, you have this as one option:

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/

Which creates this:

여기에 이미지 설명을 입력하십시오

Probably not what you want. But if you were merely looking to have zero blur then that would be the ticket so I'll offer it just in case.

A more difficult option is to use pixel manipulation and write an algorithm yourself for the job. Each pixel of the first image becomes a 5x5 block of pixels on the new image. It wouldn't be too hard to do with imagedata.

But Canvas and CSS alone won't help you here for scaling one to the other with the exact effect you desire.


In google chrome, canvas image patterns aren't interpolated.

Here is a working example edited from the namuol answer http://jsfiddle.net/pGs4f/

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

Saviski's workaround explicated here is promising, because it works on:

  • Chrome 22.0.1229.79 Mac OS X 10.6.8
  • Chrome 22.0.1229.79 m Windows 7
  • Chromium 18.0.1025.168 (Developer Build 134367 Linux) Ubuntu 11.10
  • Firefox 3.6.25 Windows 7

But not works in the following, but the same effect can be achieved using CSS image-rendering:

  • Firefox 15.0.1 Mac OS X 10.6.8 (image-rendering:-moz-crisp-edges works in this )
  • Opera 12.02 Mac OS X 10.6.8 (image-rendering:-o-crisp-edges works in this )
  • Opera 12.02 Windows 7 (image-rendering:-o-crisp-edges works in this )

ctx.XXXImageSmoothingEnabled가 작동하지 않고 이미지 렌더링이 작동하지 않기 때문에 문제는 다음과 같습니다.

  • Safari 5.1.7 Mac OS X 10.6.8. (이미지 렌더링 : -webkit-optimize-contrast는 작동하지 않습니다)
  • Safari 5.1.7 Windows 7 (이미지 렌더링 : -webkit-optimize-contrast가 작동하지 않음)
  • IE 9 Windows 7 (-ms-interpolation-mode : nearest-neighbor가 작동하지 않음)

참고 URL : https://stackoverflow.com/questions/7615009/disable-interpolation-when-scaling-a-canvas

반응형