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

사용자가 아바타를 맞춤설정하거나, 이미지를 자르거나, 사진을 확대할 수 있도록 캔버스에서 사용할 이미지를 디코딩하는 것은 매우 일반적입니다. 이미지 디코딩의 문제는 CPU를 많이 사용할 수 있으며 이로 인해 버벅거림이나 체커보딩이 발생할 수 있다는 점입니다. Chrome 50부터 (Firefox 42 이상에서도) createImageBitmap()라는 옵션이 추가되었습니다. 이를 통해 백그라운드에서 이미지를 디코딩하고 새 ImageBitmap 원시 요소에 액세스할 수 있습니다. 이 원시 요소는 <img> 요소, 다른 캔버스 또는 동영상과 동일한 방식으로 캔버스에 그릴 수 있습니다.

createImageBitmap()으로 블롭 그리기

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() 메서드도 지원합니다. 즉, 예를 들어 캔버스 요소에서 블롭을 생성할 수 있습니다.

웹 작업자에서 createImageBitmap() 사용

createImageBitmap()의 가장 좋은 기능 중 하나는 작업자에서도 사용할 수 있다는 점입니다. 즉, 이제 원하는 위치에서 이미지를 디코딩할 수 있습니다. 중요하지 않다고 생각되는 디코딩할 이미지가 많은 경우 URL을 웹 워커로 전송하면 웹 워커가 시간이 있을 때 다운로드하고 디코딩합니다. 그런 다음 캔버스에 그리기 위해 기본 스레드로 다시 전송합니다.

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이 다른 스레드에서 자동으로 디코딩하도록 계획되어 있어 기본 스레드 워크로드를 줄일 수 있습니다. 하지만 그때까지는 기본 스레드에서 디코딩을 실행할 때 주의해야 합니다. 디코딩은 JavaScript, 스타일 계산, 레이아웃, 페인팅, 합성 등 다른 필수 작업을 차단할 수 있는 집약적인 작업이기 때문입니다.

도우미 라이브러리

작업을 좀 더 간편하게 처리할 수 있도록, 작업자에서 디코딩을 처리하고 디코딩된 이미지를 기본 스레드로 다시 전송하고 캔버스에 그리는 도우미 라이브러리를 만들었습니다. 물론 자유롭게 리버스 엔지니어링하고 모델을 자체 앱에 적용할 수 있습니다. 주요 이점은 더 많은 제어 기능이지만, 이는 일반적으로 <img> 요소를 사용할 때보다 더 많은 코드, 더 많은 디버깅 작업, 더 많은 특이 사례가 고려되어야 한다는 것을 의미합니다.

이미지 디코딩을 더 세부적으로 제어해야 한다면 createImageBitmap()가 새로운 친구가 될 것입니다. Chrome 50에서 사용해 보고 의견을 알려주세요.