Chrome 50에서 Chrome이 createImageBitmap()을 지원합니다.

캔버스와 함께 사용하기 위해 이미지를 디코딩하는 것은 사용자가 아바타를 맞춤설정하거나, 이미지를 자르거나, 사진을 확대하는 것 등 다양한 용도로 사용할 수 있습니다. 이미지 디코딩의 문제는 CPU 집약적일 수 있고 때로는 버벅거림이나 체커보드를 의미할 수 있다는 점입니다. Chrome 50(및 Firefox 42 이상)부터 다른 옵션(createImageBitmap())이 제공됩니다. 이를 사용하면 백그라운드에서 이미지를 디코딩하고 새로운 ImageBitmap 프리미티브에 액세스할 수 있습니다. 이 프리미티브는 <img> 요소, 다른 캔버스, 동영상과 같은 방식으로 캔버스에 그릴 수 있습니다.

createImageBitmap()으로 blob 그리기

fetch() (또는 XHR)로 blob 이미지를 다운로드하여 캔버스에 그리려고 한다고 가정해 보겠습니다. createImageBitmap()가 없으면 이미지 요소와 Blob URL을 만들어 이미지를 사용할 수 있는 형식으로 가져와야 합니다. 이를 통해 페인팅으로 훨씬 더 직접적인 경로를 얻을 수 있습니다.

fetch(url)
    .then(response => response.blob())
    .then(blob => createImageBitmap(blob))
    .then(imageBitmap => ctx.drawImage(imageBitmap, 0, 0));

이 접근 방식은 IndexedDB에 blob으로 저장된 이미지에도 작동하므로 blob을 편리한 중간 형식으로 만들 수 있습니다. 이에 따라 Chrome 50에서는 캔버스 요소에서 .toBlob() 메서드도 지원합니다. 즉, 캔버스 요소에서 blob을 생성하는 등의 작업이 가능합니다.

웹 작업자에서 createImageBitmap() 사용

createImageBitmap()의 가장 좋은 기능 중 하나는 작업자에서도 사용할 수 있다는 것입니다. 즉, 이제 어디서나 이미지를 디코딩할 수 있습니다. 디코딩할 이미지가 많고 필수가 아니라고 여기는 경우, 이미지 URL을 Web Worker로 전달하며, Web Worker는 시간이 지나면서 다운로드하고 디코딩합니다. 그런 다음 캔버스에 그리도록 기본 스레드로 다시 전송합니다.

createImageBitmap 및 웹 작업자를 사용한 데이터 흐름

이를 위한 코드는 다음과 같습니다.

// In the worker.
fetch(imageURL)
    .then(response => response.blob())
    .then(blob => createImageBitmap(blob))
    .then(imageBitmap => {
    // Transfer the imageBitmap back to main thread.
    self.postMessage({ imageBitmap }, [imageBitmap]);
    }, err => {
    self.postMessage({ err });
    });

// In the main thread.
worker.onmessage = (evt) => {
    if (evt.data.err)
    throw new Error(evt.data.err);

    canvasContext.drawImage(evt.data.imageBitmap, 0, 0);
}

현재 기본 스레드에서 createImageBitmap()를 호출하면 정확히 이 스레드에서 디코딩이 실행됩니다. 하지만 Chrome이 다른 스레드에서 자동으로 디코딩을 실행하도록 하여 기본 스레드 워크로드를 줄이는 데 도움이 되도록 할 계획입니다. 하지만 기본 스레드에서 디코딩을 수행하는 것은 자바스크립트, 스타일 계산, 레이아웃, 페인팅 또는 합성 같은 다른 필수 작업을 차단할 수 있는 집약적인 작업이기 때문에 주의해야 합니다.

도우미 라이브러리

작업을 좀 더 간단하게 하기 위해 작업자의 디코딩을 처리하고 디코딩된 이미지를 기본 스레드로 다시 전송하여 캔버스에 그리는 도우미 라이브러리를 만들었습니다. 물론 자유롭게 모델을 리버스 엔지니어링하여 앱에 적용해야 합니다. 주요 이점은 더 세밀한 제어이지만, 평소와 같이 더 많은 코드와 디버그해야 하며 <img> 요소를 사용하는 것보다 더 많은 특이 사례를 고려할 수 있습니다.

이미지 디코딩을 좀 더 세부적으로 제어해야 하는 경우 createImageBitmap()를 사용하면 됩니다. Chrome 50에서 이 기능을 확인하고 사용해 보며 의견을 공유해 주세요.