Signatur
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:
widthundheight(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
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);
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);
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');
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
ImageBitmapkann viel GPU- bzw. Arbeitsspeicher belegen. Rufeclose()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:widthundheightsind dann0. Wer das Objekt trotzdem zeichnet, bekommt einenInvalidStateError. - CORS: Stammt die Quelle aus einem fremden Ursprung ohne CORS-Freigabe, wird das Ziel-Canvas „tainted“ (verunreinigt).
getImageData()undtoDataURL()werfen dann einenSecurityError. Für fremde BildercrossOrigin="anonymous"setzen oderfetchmit CORS nutzen. - Kein Konstruktor:
new ImageBitmap()wirft einenTypeError. - Kompatibilität: Das Interface wird überall unterstützt. Safari kann
createImageBitmap()aber erst ab Version 15 vollständig, inklusive Optionen undBlob-Quellen. SVG-Bilder ohne feste Größe werden je nach Browser abgelehnt.imageOrientation: 'from-image'für EXIF undresizeQualitywerden nicht überall gleich umgesetzt. - Leistung: Mit
createImageBitmap()gleich auf die Zielgröße zu skalieren ist meist schneller, als bei jedemdrawImage()-Aufruf zu skalieren.