Javascript Canvas: Bildpaket erzeugen

Mit Hilfe von Canvas kann JavaScript aus einem großen Bild ein Paket von kleineren Versionen erzeugen. Dafür wird das Bild in den Canvas geladen und dann in die verschiedenen Größen skaliert.

Canvas Pfad, Kurven und Kreisbögen oder Cancas Arc mit Javascript

Responsives Bild-Paket mit Canvas erzeugen

Das HTML ist das Eingabefeld für den File-Upload sowie ein canvas-Element mit ein div-Element mit der id="output", in dem die verkleinerten Bilder angezeigt werden.

 
<input type="file" id="uploadedFile" name="" accept="image/*">

<canvas id="canvas"></canvas>
<div id="output"></div>

Das Skript

Das Originalbild wird eingelesen und davon vier Bildgrößen erzeugt. Jedes der vier erzeugten Bilder wird in einem HTML-Canvas-Element angezeigt und ein Download-Link für das Bild erzeugt.

Im Anschluß wird ein Button für den Download des Bildpakets als ZIP-Datei angezeigt. Verantwortlich für das Erzeugen des ZIP-Pakets ist JSZip v3.7.1 - A JavaScript class for generating and reading zip files <http://stuartk.com/jszip>

const sizes = [1360, 920, 640, 420];

// Bildgröße des Pakets geändert? Abfangen mit event delegation
// und im array sizes ändern
const imgsizes = document.querySelector(".imgsizes");
imgsizes.addEventListener ("change", (evt) => {
	if (evt.target.className === "sizes") {
		sizes[parseInt(evt.target.getAttribute("data-s-id"))] = parseInt(evt.target.value);
	}
})

// Qualitätsfaktor für JPG-Komprimierung setzen
let qualityFactor = 0.6;
const quality = document.querySelector("#quality");
quality.addEventListener ("change", () => {
	qualityFactor = parseFloat(quality.value);
})

const imageSources = [];
// Hol das Datei-Input-Element
const fileInput = document.getElementById('fileInput');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

function downloadAllImages() {
	// Array mit Bildquellen (URLs oder Daten-URLs)
		
	var zip = new JSZip();
	const imgUrls = document.querySelectorAll("#output img");
	imgUrls.forEach (elem => {
		imageSources.push(elem.src)
	})
	console.log ("imageSources", imageSources);
		
	let count = 0;
	// Für jedes Bild einen Download-Prozess starten
	imageSources.forEach((src, index) => {
		// Erstellen eines unsichtbaren Link-Elements
		fetch (src) 
			.then(response => response.blob())
			.then(blob => {
				zip.file("image" + (index + 1) + ".jpg", blob);
				count++;
				if (count === imgUrls.length) {
					zip.generateAsync({ type: "blob"})
						.then (function (content) {
							var link = document.createElement("a");
							link.href = URL.createObjectURL(content);
							link.download = "images.zip";
							link.click();
						});
				}
			});
	});
}

// Überwache die Änderungen des Datei-Inputs
fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0];

  // Überprüfe, ob eine gültige Bilddatei hochgeladen wurde
  if (file && file.type.startsWith('image/')) {
	// Erzeuge eine temporäre URL für das Bild
	const imageURL = URL.createObjectURL(file);
	const fileName = file.name.split(".")[0];
	// Erstelle ein neues Bild-Element
	const img = new Image();
	img.src = imageURL;

	img.onload = () => {
	  // Originalgröße des Bildes
		const originalWidth = img.width;
		const originalHeight = img.height;
		
		const collection = [];
	  
		const ar =  originalHeight / originalWidth;

		sizes.forEach(size => {
			const newWidth = size  // neue Breite
			const newHeight = size * ar; // Höhe anhand Aspect Ratio
			console.log ("neue Größen", newWidth, newHeight);
			
			canvas.width = newWidth;
			canvas.height = newHeight;
			ctx.drawImage(img, 0, 0, newWidth, newHeight);
			URL.revokeObjectURL(imageURL);
			
			// Wenn die Breite des Bildes als Watermark ins Bild gesetzt werden soll
			if (document.querySelector("#sizing").checked) {
				const theString = size;
				ctx.fillStyle = 'cornflowerblue';
				
				const fontSize = size / 20;
				ctx.font = `italic ${fontSize}pt Arial`;
				ctx.fillText(theString, 50,100);
			}

			// Canvas zu Data URL (JPG) konvertieren und anzeigen
			const dataUrl = canvas.toDataURL("image/jpeg", qualityFactor); // "0.6" ist die Bildqualität (zB 0.6 für 60%)
			console.log ("dataUrl", dataUrl, qualityFactor)

			// Größe der Base64-Zeichenkette berechnen, um Bildgröße anzuzeigen
			const fileSizeInBytes = Math.round((dataUrl.length * (3/4)) - ((dataUrl.match(/==$/) || dataUrl.match(/=$/)) ? 2 : 0)); // Berechnung der Dateigröße
			const fileSizeInKB = (fileSizeInBytes / 1024).toFixed(2); // Größe in KB berechnen

			
			// Neues Image-Element erzeugen und die Quelle auf die JPG-Data URL setzen
			const div = document.createElement("div");
			const imgElement = document.createElement("img");
			imgElement.src = dataUrl;
			imgElement.alt = `Bild in Größe ${size}x${newHeight}`;
			imgElement.width = size;
			imgElement.height = parseInt(newHeight);
			
			// Neues Bild ins Output-Div setzen
			div.appendChild(imgElement);
			const br = document.createElement("br");
			div.appendChild(br);
			
			// Link für den Bilder-Download erzeugen
			// mit dem download-Attribut kann ein Dateiname für das Bild vergeben werden
			const downloadLink = document.createElement("a");
			downloadLink.href = dataUrl;
			downloadLink.download = `${fileName}-${parseInt(size)}x${parseInt(newHeight)}.jpg`; // Dateiname festlegen

			downloadLink.textContent = `${fileName}-${parseInt(size)}x${parseInt(newHeight)}.jpg herunterladen (${fileSizeInKB} KB)`;
			div.appendChild(downloadLink);
			document.getElementById("output").appendChild(div); // Zeilenumbruch
			
		});
		
		// Jetzt den Download-Link für ein zip-gepacktes Paket der Bilder einspielen
		document.querySelector(".download").style = "display:block";

		document.querySelector("#download").addEventListener ("click", downloadAllImages);
		
		//document.getElementById('download').addEventListener('click', downloadZip);
	};

	img.onerror = () => {
	  console.error('Bild konnte nicht geladen werden.');
	};
  } else {
	console.log('Bitte eine gültige Bilddatei auswählen.');
  }
});
Suchen auf mediaevent.de