toBlob – canvas als Bilddatei exportieren

canvas.toBlob erweitert die Techniken zum Umwandeln der Zeichnung im Canvas. Ein Blob kann als URL für ein a-Element oder als src-Attribut eines img-Tags eingesetzt werden und die Daten können dem Benutzer zum Download angeboten werden.

Inhalt eines Canvas als Bild laden

toBlob – Zeichnung im canvas zum Download anbieten

canvas.toBlob hält die Zeichnung auf einem HTML-Canvas-Element fest und bietet sie als PNG, JPG oder WebP zum Download an.

toBlob setzt als Argument eine Callback-Funktion, die den Blob erzeugt. Weitere Argumente sind der Mime-Type (PNG, JPG, WebP), und falls JPG/WebP erzeugt werden soll, die Qualitätsstufe.

canvas.toBlob((blob) => {
	// reserviert intern Speicher
	const url = URL.createObjectURL(blob);

	const a = document.createElement("a");
	a.href = url;
	a.download = "image.png";
	a.click();

	// räumt auf
	URL.revokeObjectURL(url);
}, "image/png");

URL.revokeObjectURL(url); gibt die zuvor erzeugte BLOB-URL wieder frei, sonst kommt es schnell zu Memory Leaks bei zu vielen Bildern / Downloads.

Per Vorgabe erzeugt toBlob ein PNG.

Der moderne Ansatz: toBlob() statt toDataURL()

  • speichereffizient (kein riesiger Base64-String)
  • async (blockiert UI nicht)
  • unterstützt: "image/png", "image/jpeg", "image/webp"
FormatEigenschaften
PNGverlustfrei, größer
JPEGverlustbehaftet, kleiner
WebPmodern, oft beste Wahl

canvas.toBlob funktioniert mit 2D-Canvas und auch mit WebGL-Canvas, aber dann sollte preserveDrawingBuffer: true nicht fehlen, sonst ist das Bild evtl. leer.

const gl = canvas.getContext("webgl", {
  preserveDrawingBuffer: true
});

Download SVG als PNG/WebP mit canvas.toBlob

Das ist eine typische Aufgabe für das canvas-Element und canvas.toBlob:
SVG → Image → Canvas → PNG/WebP/JPEG.

Die Transformation funktioniert im Browser, braucht keinen Server, ist flexibel, was Skalierung und Filter betrifft und ist schnell implementiert. Erst wenn viele Bilder transformiert werden sollen, die SVGs komplex sind, wenn z.B. auch die Druckqualität und eine bessere Schriftqualität eine Rolle spielt, werden eher Libraries wie librsvg und ImageMagick eingesetzt.

Upload + Vorschau

upload.addEventListener("change", async (e) => {
  const file = e.target.files[0];
  if (!file) return;

  currentSVGText = await file.text();

  // SVG anzeigen
  preview.innerHTML = currentSVGText;
});

SVG → Canvas → Download

async function downloadCurrentSVG(format = "png") {
	if (!currentSVGText) {
		alert("Bitte erst ein SVG hochladen");
		return;
	}

	const svgBlob = new Blob([currentSVGText], { type: "image/svg+xml" });
	const blobUrl = URL.createObjectURL(svgBlob);

	const img = new Image();
	img.src = blobUrl;

	await new Promise(resolve => img.onload = resolve);

	const inputWidth = Number(document.getElementById("svgwidth").value) || 500;

	const { width, height } = getSVGSize(currentSVGText, inputWidth);
	
	const canvas = document.createElement("canvas");
	canvas.width = width;
	canvas.height = height;
	
	const ctx = canvas.getContext("2d");
	
	// wichtig: skalieren!
	ctx.drawImage(img, 0, 0, width, height);

	const mime = format === "webp" ? "image/webp" : "image/png";

	canvas.toBlob(blob => {
    	const url = URL.createObjectURL(blob);

    	const a = document.createElement("a");
    	a.href = url;
    	a.download = `converted.${format}`;
    	a.click();

    	URL.revokeObjectURL(url);
	}, mime);
}

WebP-Qualität steuern

Im Grunde genommen ist es einfach, die Qualität des WebP zu steuern, nur ein paar Details sollten beachtet werden.

canvas.toBlob(callback, "image/webp", quality);

Mit dem Wert 0.8 für die Qualität verspricht toBlob eine gute Qualität bei einer deutlich kleineren Datei. So ab 0.6 können erste Folgen der Komprimierung sichtbar werden, bei 0.3 kommt es zu sichtbaren Artefakten.

canvas.toBlob(blob => {
  // use blob
}, "image/webp", 0.8);

oder 

const blob = await new Promise(resolve =>
  canvas.toBlob(resolve, "image/webp", 0.8)
);

WebP unterstützt auch Transparenz. Dabei Sollte die Qualität eher bei 0.8 bis 0.9 liegen.

canvas.toDataURL – der »alte Klassiker«

Für die Umwandlung der Bitmap des canvas-Elements ist heute canvas.toBlob() die bevorzugte Lösung. Der Klassiker war toDataURL.

Der Unterschied zwischen toBlob und toDataURL(): toDataURL ist synchron und blockiert die Benutzerschnittstelle, während canvas.toBlob die eigentliche Konvertierung in ein Bild asynchron durchführt.

  • großer Base64-String (≈ +33% Größe)
  • sehr langsam bei großen Bildern
  • blockiert den Hauptthread
Kriterium canvas.toDataURL() canvas.toBlob()
Ausgabeformat Base64-String (data:image/png;base64,...) Binäres Blob-Objekt
Größe der Daten Meist größer (wegen Base64-Overhead) Effizienter (kleiner)
Speichern / Upload Umständlicher (Base64 muss konvertiert werden) Direkt als Datei/Blob verwendbar
Kompatibilität Breite Unterstützung überall Ältere Browser (< Edge 18) brauchen Fallback
Performance Langsamer bei großen Bildern Schneller, asynchron
Synchron / Async Synchron (blockierend!) Asynchron (besser für große Datenmengen)
Suchen auf mediaevent.de