Podczas tworzenia nowoczesnych aplikacji webowych, takich jak Look Scanned, optymalizacja wydajności stanowi kluczowy priorytet. Jest to szczególnie istotne w kontekście przetwarzania obrazów. Interfejs ImageBitmap, choć nie jest jeszcze powszechnie stosowany, stanowi potężne narzędzie umożliwiające znaczącą poprawę wydajności. W tym artykule omawiamy główne funkcje ImageBitmap, jego zalety oraz nasze doświadczenia z wdrożenia w Look Scanned.

Czym jest ImageBitmap?

ImageBitmap to interfejs HTML5 stworzony z myślą o wydajnym przetwarzaniu obrazów. Jego kluczową zaletą jest możliwość wykonywania dekodowania i przetwarzania obrazów poza głównym wątkiem, co znacząco redukuje obciążenie podczas renderowania i poprawia ogólną responsywność aplikacji. Utworzony obiekt ImageBitmap może być bezpośrednio wykorzystywany w kontekstach renderowania, takich jak Canvas 2D czy WebGL, co sprawia, że jest idealnym rozwiązaniem dla aplikacji operujących na dużej liczbie obrazów.

Dlaczego zdecydowaliśmy się na ImageBitmap?

Początkowo w Look Scanned wykorzystywaliśmy Blob do przekazywania danych obrazów między funkcjami przetwarzającymi. Niestety, Blob wymaga kodowania i dekodowania przy każdym użyciu, co negatywnie wpływa na wydajność. Z kolei ImageBitmap zapewnia bezpośredni dostęp do danych obrazu, eliminując te dodatkowe operacje i znacząco poprawiając wydajność renderowania.

Szczegóły wdrożenia

Ze względu na konieczność zachowania kompatybilności ze starszymi przeglądarkami, całkowite przejście na ImageBitmap nie wchodziło w grę. Dlatego opracowaliśmy hybrydowe podejście zapewniające szeroką kompatybilność. Szczegółowe informacje o wsparciu można znaleźć na caniuse.com. Dodatkowo, z powodu ograniczeń Safari w obsłudze Canvas, wykorzystujemy WebAssembly (WASM) do przetwarzania obrazów, co wymaga użycia Blob jako formatu wejściowego.

Uwzględniając te uwarunkowania, stworzyliśmy stopniowe rozwiązanie hybrydowe obsługujące zarówno Blob, jak i ImageBitmap. Oto kluczowe elementy implementacji:

Ładowanie i dekodowanie obrazów

async function loadImage(url): Promise<ImageBitmap | Blob> {
  const response = await fetch(url);
  const blob = await response.blob();
  if (window.createImageBitmap) {
    return createImageBitmap(blob);
  }
  // Fallback do Blob
  return blob;
}

Integracja z WebAssembly

W przypadku zaawansowanego przetwarzania, przekazujemy Blob do modułu WASM, co zapewnia funkcjonalność w przeglądarkach bez obsługi ImageBitmap. W tym procesie najpierw renderujemy obraz na Canvas, a następnie wykorzystujemy canvas.toBlob do utworzenia wymaganego obiektu Blob.

Alternatywny system renderowania

async function renderImage(canvas, imageUrl) {
  const ctx = canvas.getContext("2d");
  const image = await loadImage(imageUrl);
  if (image instanceof ImageBitmap) {
    ctx.drawImage(image, 0, 0);
  } else {
    const img = new Image();
    img.src = URL.createObjectURL(image);
    img.onload = () => ctx.drawImage(img, 0, 0);
  }
}

Uzyskane rezultaty

Wdrożenie ImageBitmap pozwoliło skrócić czas przetwarzania obrazów w Look Scanned z 50 ms do 20 ms na obraz. Poprawa jest szczególnie widoczna przy przetwarzaniu skanowanych dokumentów, zapewniając znacznie płynniejsze i szybsze działanie aplikacji.

Ciekawe spostrzeżenia

Podczas wdrożenia dokonaliśmy interesującego odkrycia: utworzenie nowej kopii ImageBitmap przed przekazaniem jej do Web Workera zapewnia lepszą wydajność niż bezpośrednie przekazanie oryginalnego obiektu. Najprawdopodobniej wynika to z wewnętrznych optymalizacji przeglądarki dla obiektów przenośnych.

Wsparcie w przeglądarkach

Obecnie ImageBitmap jest szeroko wspierany we wszystkich głównych nowoczesnych przeglądarkach, włączając najnowsze wersje Chrome, Firefox, Edge i Safari. Szczegółowe informacje o kompatybilności znajdują się w dokumentacji createImageBitmap na caniuse.com.

Podsumowanie i perspektywy

Wdrożenie ImageBitmap w Look Scanned nie tylko przyniosło znaczącą poprawę wydajności, ale również umożliwiło asynchroniczne dekodowanie, efektywne renderowanie i lepszą integrację z Web Workers. Choć wsparcie dla Blob pozostaje niezbędne dla starszych przeglądarek, stopniowe przechodzenie na ImageBitmap będzie przynosić coraz większe korzyści w dłuższej perspektywie.

Wypróbuj ulepszenia wydajności na własną rękę na Look Scanned!