TL; DR;
Gibt es eine Möglichkeit, ein Bild (meistens JPEG, PNG und GIF) direkt im Browser zu komprimieren, bevor es hochgeladen wird? Ich bin mir ziemlich sicher, dass JavaScript dies kann, aber ich kann keinen Weg finden, dies zu erreichen.
Hier ist das vollständige Szenario, das ich implementieren möchte:
- Der Benutzer besucht meine Website und wählt ein Bild über ein
input type="file"
Element aus. - Dieses Bild wird über JavaScript abgerufen. Wir führen einige Überprüfungen durch, z. B. das korrekte Dateiformat, die maximale Dateigröße usw.
- Wenn alles in Ordnung ist, wird auf der Seite eine Vorschau des Bildes angezeigt.
- Der Benutzer kann einige grundlegende Vorgänge ausführen, z. B. das Bild um 90 ° / -90 ° drehen, es nach einem vordefinierten Verhältnis zuschneiden usw. oder der Benutzer kann ein anderes Bild hochladen und zu Schritt 1 zurückkehren.
- Wenn der Benutzer zufrieden ist, wird das bearbeitete Bild komprimiert und lokal "gespeichert" (nicht in einer Datei gespeichert, sondern im Speicher / auf der Seite des Browsers).
- Der Benutzer füllt ein Formular mit Daten wie Name, Alter usw. aus.
- Wenn der Benutzer auf die Schaltfläche "Fertig stellen" klickt, wird das Formular mit Daten + komprimiertem Bild an den Server gesendet (ohne AJAX).
Der gesamte Prozess bis zum letzten Schritt sollte clientseitig erfolgen und mit den neuesten Versionen von Chrome und Firefox, Safari 5+ und IE 8+ kompatibel sein . Wenn möglich, sollte nur JavaScript verwendet werden (aber ich bin mir ziemlich sicher, dass dies nicht möglich ist).
Ich habe momentan nichts codiert, aber ich habe bereits darüber nachgedacht. Das lokale Lesen von Dateien ist über die Datei-API möglich. Die Bildvorschau und -bearbeitung kann mit dem Canvas- Element erfolgen, aber ich kann keine Möglichkeit finden, den Teil der Bildkomprimierung durchzuführen .
Laut html5please.com und caniuse.com ist die Unterstützung dieses Browsers (dank IE) ziemlich schwierig, könnte aber mit Polyfill wie FlashCanvas und FileReader erfolgen .
Eigentlich ist das Ziel, die Dateigröße zu reduzieren, daher sehe ich die Bildkomprimierung als Lösung. Ich weiß jedoch, dass hochgeladene Bilder jedes Mal am selben Ort auf meiner Website angezeigt werden, und ich kenne die Größe dieses Anzeigebereichs (z. B. 200 x 400). So konnte ich die Größe des Bilds an diese Abmessungen anpassen und so die Dateigröße reduzieren. Ich habe keine Ahnung, wie hoch das Kompressionsverhältnis für diese Technik sein würde.
Was denken Sie ? Hast du einen Rat, den du mir sagen kannst? Kennen Sie eine Möglichkeit, eine Bildbrowserseite in JavaScript zu komprimieren? Vielen Dank für Ihre Antworten.
canvas.toDataURL("image/jpeg",0.7)
effektiv komprimiert, es speichert JPEG mit der Qualität 70 (im Gegensatz zur Standardqualität 100).URL.createObjectUrl()
ohne dass die Datei in einen Blob umgewandelt wird. Die Datei zählt als Blob.In den anderen Antworten fehlen zwei Dinge:
canvas.toBlob
(falls verfügbar) ist performanter alscanvas.toDataURL
und auch asynchron.Das folgende Skript behandelt beide Punkte:
Anwendungsbeispiel:
quelle
Die Antwort von @PsychoWoods ist gut. Ich möchte meine eigene Lösung anbieten. Diese Javascript-Funktion verwendet eine Bilddaten-URL und eine Breite, skaliert sie auf die neue Breite und gibt eine neue Daten-URL zurück.
Dieser Code kann überall dort verwendet werden, wo Sie eine Daten-URL haben und eine Daten-URL für ein verkleinertes Bild wünschen.
quelle
Sie können einen Blick auf die Bildkonvertierung werfen. Probieren Sie es hier aus -> Demoseite
quelle
Ich hatte ein Problem mit der
downscaleImage()
oben von @ daniel-allen-langdon geposteten Funktion, da die Eigenschaftenimage.width
undimage.height
nicht sofort verfügbar sind, da das Laden des Bildes asynchron ist .Das aktualisierte TypeScript-Beispiel unten berücksichtigt dies, verwendet
async
Funktionen und ändert die Größe des Bilds basierend auf der längsten Dimension und nicht nur auf der Breitequelle
quality
,resolution
undimageType
(Format dieser)Bearbeiten: Laut dem Kommentar von Mr Me zu dieser Antwort scheint die Komprimierung jetzt für JPG / WebP-Formate verfügbar zu sein (siehe https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL ). .
Soweit ich weiß, können Sie Bilder nicht mit Leinwand komprimieren, sondern die Größe ändern. Wenn Sie canvas.toDataURL verwenden, können Sie das zu verwendende Komprimierungsverhältnis nicht auswählen. Sie können sich canimage ansehen, das genau das tut, was Sie wollen: https://github.com/nfroidure/CanImage/blob/master/chrome/canimage/content/canimage.js
Tatsächlich reicht es oft aus, nur die Größe des Bildes zu ändern, um seine Größe zu verringern. Wenn Sie jedoch weiter gehen möchten, müssen Sie die neu eingeführte Methode file.readAsArrayBuffer verwenden, um einen Puffer mit den Bilddaten abzurufen.
Verwenden Sie dann einfach eine DataView, um den Inhalt gemäß der Bildformatspezifikation zu lesen ( http://en.wikipedia.org/wiki/JPEG oder http://en.wikipedia.org/wiki/Portable_Network_Graphics ).
Es wird schwierig sein, mit der Komprimierung von Bilddaten umzugehen, aber es ist schlimmer, es zu versuchen. Auf der anderen Seite können Sie versuchen, die PNG-Header oder die JPEG-Exif-Daten zu löschen, um Ihr Bild zu verkleinern. Dies sollte einfacher sein.
Sie müssen eine weitere DataWiew in einem anderen Puffer erstellen und diese mit dem gefilterten Bildinhalt füllen. Dann müssen Sie nur noch Ihren Bildinhalt mit window.btoa in DataURI codieren.
Lassen Sie mich wissen, wenn Sie etwas Ähnliches implementieren, wird es interessant sein, den Code durchzugehen.
quelle
Für die JPG-Bildkomprimierung können Sie die beste Komprimierungstechnik namens JIC (Javascript Image Compression) verwenden. Dies wird Ihnen definitiv helfen -> https://github.com/brunobar79/JIC
quelle
Ich habe die Funktion eines Kopfes so verbessert:
die Verwendung davon:
genießen ;)
quelle
Ich finde, dass es eine einfachere Lösung gibt als die akzeptierte Antwort.
Gemäß Ihrer Frage:
Meine Lösung:
Erstellen Sie einen Blob mit der Datei direkt mit
URL.createObjectURL(inputFileElement.files[0])
.Gleich wie akzeptierte Antwort.
Gleich wie akzeptierte Antwort. Erwähnenswert ist, dass Leinwandgröße notwendig ist und zu verwenden
img.width
undimg.height
zu setzencanvas.width
undcanvas.height
. Nichtimg.clientWidth
.Holen Sie sich das verkleinerte Bild von
canvas.toBlob(callbackfunction(blob){}, 'image/jpeg', 0.5)
. Die Einstellung'image/jpg'
hat keine Auswirkung.image/png
wird ebenfalls unterstützt. Machen Sie ein neuesFile
Objekt im Innern descallbackfunction
Körpers mitlet compressedImageBlob = new File([blob])
.Fügen Sie neue versteckte Eingaben hinzu oder senden Sie sie über Javascript . Der Server muss nichts dekodieren.
Überprüfen Sie https://javascript.info/binary auf alle Informationen. Nachdem ich dieses Kapitel gelesen hatte, kam ich auf die Lösung.
Code:
Dieser Code sieht weit weniger beängstigend aus als die anderen Antworten.
Aktualisieren:
Man muss alles hineinstecken
img.onload
. Andernfallscanvas
kann die Breite und Höhe des Bildes nicht korrekt ermittelt werden, wenn die Zeitcanvas
zugewiesen wird.3.4MB
.png
Dateikomprimierungstest mitimage/jpeg
gesetztem Argument.quelle