Start · Sprachen · JavaScript · Referenz · ImageBitmap

ImageBitmap

Schnittstelle

Stellt ein bereits dekodiertes Bitmap-Bild dar, das sich ohne zusätzliche Verzögerung auf ein <code>&lt;canvas&gt;</code> oder in WebGL zeichnen lässt.

seit JavaScript Baseline: alle modernen Browser (seit ca. 2020 in Kategorie: webapi

Signatur

interface ImageBitmap

Beschreibung

ImageBitmap steht für ein fertig dekodiertes Bild im Speicher, meist auf der GPU. Anders als bei einem HTMLImageElement ist das Dekodieren beim Zeichnen schon erledigt. Deshalb laufen drawImage(), texImage2D() und ähnliche Aufrufe ohne Ruckler. Das hilft vor allem bei Spielen, Bildbearbeitung und Animationen, in denen dasselbe Bild oft gezeichnet wird.

Einen Konstruktor gibt es nicht. Man erzeugt ein ImageBitmap asynchron mit der globalen Funktion createImageBitmap(). Die gibt es in window und in Workern. Als Quelle eignen sich Blob, ImageData, HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, OffscreenCanvas, VideoFrame oder ein anderes ImageBitmap. Über Optionen kann man beim Erzeugen gleich einen Ausschnitt wählen, skalieren, spiegeln oder die Farbraum-Konvertierung steuern. Mit OffscreenCanvas.transferToImageBitmap() entsteht außerdem synchron ein ImageBitmap aus einer OffscreenCanvas.

ImageBitmap ist übertragbar (transferable). Man kann es also mit postMessage() ohne Kopie zwischen Hauptthread und Workern verschieben. So lassen sich Bilder in einem Worker dekodieren und aufbereiten, ohne die Oberfläche zu blockieren.

  • Eigenschaften: width und height (schreibgeschützt, in CSS-Pixeln des Bitmaps)
  • Methode: close() gibt die belegten Grafikressourcen frei

Parameter

Name Typ Default Beschreibung
$width number Schreibgeschützt. Breite des Bitmaps in Pixeln. Nach close() ist der Wert 0.
$height number Schreibgeschützt. Höhe des Bitmaps in Pixeln. Nach close() ist der Wert 0.
$close() () => void Gibt alle Grafikressourcen des Bitmaps frei. Danach ist das Objekt nicht mehr benutzbar: Ein Aufruf von drawImage() damit wirft einen InvalidStateError.

Rückgabewert

Typ
ImageBitmap
Beschreibung
Instanzen entstehen über createImageBitmap() (gibt Promise<ImageBitmap> zurück) oder über OffscreenCanvas.transferToImageBitmap().

Beispiele

Bild laden und ruckelfrei auf ein Canvas zeichnen

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

const ladeBitmap = async (url) => {
  const res = await fetch(url);
  const blob = await res.blob();
  return createImageBitmap(blob);
};

const sprite = await ladeBitmap('/img/sprite.png');
console.log(`Größe: ${sprite.width}x${sprite.height}`);

// Das Bild ist schon dekodiert, jeder Frame kann es sofort zeichnen
const loop = (t) => {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(sprite, 100 + Math.sin(t / 500) * 50, 50);
  requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
Größe: 256x256

Ausschnitt skalieren und spiegeln

const img = document.querySelector('#foto');
await img.decode();

// Nimmt den Bereich (0,0)–(400,300), skaliert auf 200x150 und spiegelt vertikal
const thumb = await createImageBitmap(img, 0, 0, 400, 300, {
  resizeWidth: 200,
  resizeHeight: 150,
  resizeQuality: 'high',
  imageOrientation: 'flipY'
});

const ctx = document.querySelector('#vorschau').getContext('2d');
ctx.drawImage(thumb, 0, 0);
console.log(thumb.width, thumb.height);
200 150

Im Worker dekodieren und ohne Kopie übertragen

// worker.js
self.onmessage = async ({ data: url }) => {
  const blob = await (await fetch(url)).blob();
  const bitmap = await createImageBitmap(blob);
  // Zweites Argument: Transfer-Liste, es wird nicht kopiert
  self.postMessage(bitmap, [bitmap]);
};

// main.js
const worker = new Worker('worker.js');
const ctx = document.querySelector('canvas').getContext('2d');

worker.onmessage = ({ data: bitmap }) => {
  ctx.drawImage(bitmap, 0, 0);
  bitmap.close(); // Speicher sofort freigeben
  console.log('Gezeichnet, Breite jetzt:', bitmap.width);
};
worker.postMessage('/img/gross.jpg');
Gezeichnet, Breite jetzt: 0

OffscreenCanvas als ImageBitmap weiterreichen

const off = new OffscreenCanvas(300, 150);
const octx = off.getContext('2d');
octx.fillStyle = 'teal';
octx.fillRect(0, 0, 300, 150);

// Synchron und ohne Kopie
const frame = off.transferToImageBitmap();

const bmCtx = document.querySelector('canvas').getContext('bitmaprenderer');
bmCtx.transferFromImageBitmap(frame);
console.log(frame.width);

// Wichtig · Fallstricke

  • Speicher freigeben: Ein ImageBitmap kann viel GPU- bzw. Arbeitsspeicher belegen. Rufe close() auf, sobald du es nicht mehr brauchst. Darauf zu warten, dass der Garbage Collector aufräumt, reicht gerade bei vielen oder großen Bildern oft nicht.
  • Nach Transfer oder close() unbrauchbar: width und height sind dann 0. Wer das Objekt trotzdem zeichnet, bekommt einen InvalidStateError.
  • CORS: Stammt die Quelle aus einem fremden Ursprung ohne CORS-Freigabe, wird das Ziel-Canvas „tainted“ (verunreinigt). getImageData() und toDataURL() werfen dann einen SecurityError. Für fremde Bilder crossOrigin="anonymous" setzen oder fetch mit CORS nutzen.
  • Kein Konstruktor: new ImageBitmap() wirft einen TypeError.
  • Kompatibilität: Das Interface wird überall unterstützt. Safari kann createImageBitmap() aber erst ab Version 15 vollständig, inklusive Optionen und Blob-Quellen. SVG-Bilder ohne feste Größe werden je nach Browser abgelehnt. imageOrientation: 'from-image' für EXIF und resizeQuality werden nicht überall gleich umgesetzt.
  • Leistung: Mit createImageBitmap() gleich auf die Zielgröße zu skalieren ist meist schneller, als bei jedem drawImage()-Aufruf zu skalieren.