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에서 사용해 보고 의견을 알려주세요.