Signatur
Beschreibung
Der Konstruktor ImageDecoder() gehört zur WebCodecs API. Er erzeugt einen Dekoder für kodierte Bilddaten, die entweder vollständig als ArrayBuffer/TypedArray oder schrittweise als ReadableStream vorliegen. Anders als ein <img>-Element oder createImageBitmap() gibt er dir direkten Zugriff auf einzelne Frames, Spuren (Tracks) und Metadaten wie Frame-Anzahl und Wiederholungszahl animierter Bilder.
Typische Einsatzfälle sind das frameweise Verarbeiten animierter GIFs oder WebPs, das Dekodieren in einem Web Worker ohne DOM, progressives Rendern während des Downloads sowie das Weiterreichen der Frames an Canvas, WebGL/WebGPU oder einen VideoEncoder.
Der Konstruktor selbst dekodiert noch nichts. Nach der Erzeugung wartest du auf decoder.tracks.ready bzw. decoder.completed und rufst dann decoder.decode({ frameIndex }) auf. Das Ergebnis enthält ein VideoFrame, das du nach Gebrauch mit close() freigeben musst. Ob ein Format unterstützt wird, prüfst du vorab mit der statischen Methode ImageDecoder.isTypeSupported().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $init Pflicht | Object | Konfigurationsobjekt mit den folgenden Eigenschaften. | |
| $init.type Pflicht | string | MIME-Typ der Bilddaten, z. B. "image/png", "image/gif", "image/webp". Wird der Typ nicht unterstützt, schlägt tracks.ready fehl. |
|
| $init.data Pflicht | ArrayBuffer | TypedArray | DataView | ReadableStream | Die kodierten Bilddaten – als vollständiger Puffer oder als Byte-Stream (z. B. response.body). |
|
| $init.premultiplyAlpha | "default" | "none" | "premultiply" | "default" | Legt fest, ob Farbkanäle mit dem Alphakanal vormultipliziert werden. |
| $init.colorSpaceConversion | "default" | "none" | "default" | Bei "none" werden eingebettete Farbprofile ignoriert und keine Farbraumkonvertierung durchgeführt. |
| $init.desiredWidth | number | Gewünschte Ausgabebreite. Nur zusammen mit desiredHeight gültig; hilfreich bei Formaten mit mehreren Auflösungen (z. B. ICO). |
|
| $init.desiredHeight | number | Gewünschte Ausgabehöhe. Nur zusammen mit desiredWidth gültig. |
|
| $init.preferAnimation | boolean | Bei Formaten mit mehreren Spuren: true wählt bevorzugt die animierte Spur als Anfangsspur. |
|
| $init.transfer | ArrayBuffer[] | [] | Liste von ArrayBuffern, die ohne Kopie an den Dekoder übertragen (und dabei im Aufrufer detached) werden. |
Rückgabewert
ImageDecoder-Objekt mit den Eigenschaften type, complete, completed und tracks sowie den Methoden decode(), reset() und close().Beispiele
Erstes Frame eines PNG dekodieren und auf ein Canvas zeichnen
const response = await fetch('/bilder/logo.png');
const buffer = await response.arrayBuffer();
const decoder = new ImageDecoder({ type: 'image/png', data: buffer });
const { image } = await decoder.decode(); // frameIndex 0
const canvas = document.querySelector('canvas');
canvas.width = image.displayWidth;
canvas.height = image.displayHeight;
canvas.getContext('2d').drawImage(image, 0, 0);
console.log(`${image.displayWidth}×${image.displayHeight}`);
image.close(); // VideoFrame freigeben
decoder.close(); // Dekoder freigeben
Animiertes GIF per Stream laden und Frames abspielen
const type = 'image/gif';
if (!(await ImageDecoder.isTypeSupported(type))) {
throw new Error('GIF wird nicht unterstützt');
}
const response = await fetch('/animation.gif');
const decoder = new ImageDecoder({ type, data: response.body });
await decoder.tracks.ready;
const track = decoder.tracks.selectedTrack;
await decoder.completed; // warten, bis alle Daten geladen sind
console.log('Frames:', track.frameCount, 'Wiederholungen:', track.repetitionCount);
const ctx = document.querySelector('canvas').getContext('2d');
for (let i = 0; i < track.frameCount; i++) {
const { image } = await decoder.decode({ frameIndex: i });
ctx.drawImage(image, 0, 0);
// duration ist in Mikrosekunden angegeben
await new Promise((r) => setTimeout(r, (image.duration ?? 100000) / 1000));
image.close();
}
decoder.close();
Puffer ohne Kopie übertragen und Fehler abfangen
const buffer = await (await fetch('/foto.webp')).arrayBuffer();
try {
const decoder = new ImageDecoder({
type: 'image/webp',
data: buffer,
transfer: [buffer], // Zero-Copy-Übergabe
colorSpaceConversion: 'none'
});
console.log(buffer.byteLength); // Puffer ist jetzt detached
const { image } = await decoder.decode();
console.log(image.format, image.codedWidth);
image.close();
decoder.close();
} catch (err) {
console.error('Dekodierung fehlgeschlagen:', err.name, err.message);
}