• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Problem beim verkleinern von Bildern

xorg1990

New member
Hallöle, ich/wir haben einem Problem mit einem Plugin was in einem andren Forum eingesetzt wird.
Es sollen Bilder bevor sie auf den Server gelangen auf 500kb verkleinert werden.

Das komische ist sind die Bilder schon <=500kb sagt mir der Server oder das Skript nöö zu groß.
Mann muss das Bild erst vergrößern damit es Angenommen wird.

Andere beschreiben das der "Upload" ewig dauert. Ich tippe hier auf eine Endlosschleife oder ein Callback wird nicht gefeuert.

Aber mir fällt nicht auf was das Problem sein könnte:

Code:
       WCF.Attachment.Upload.prototype._beginCrop = function(formData_, paramNo_, callback_, uploadID_) {
            this._cropCount++;
            var self = this;
            if (!(window.File && window.FileReader && window.ArrayBuffer && window.Blob && window.Uint8Array && canvasSupported && BlobSupport)) {
                this._cropCount--;
                callback_.call(self, formData_, uploadID_);
                return;
            }
            var fr = new FileReader();
            fr.onload = function(frEvent) {
                var img = new Image();
                img.onload = function() {
                    var canvas = document.createElement("canvas");
                    var ctx = canvas.getContext("2d");
                    var ratioX = 1;
                    var ratioY = 1;
                    if (img.width > MESSAGE_ATTACHMENT_SCALE_WIDTH) ratioX = img.width / MESSAGE_ATTACHMENT_SCALE_WIDTH;
                    if (img.height > MESSAGE_ATTACHMENT_SCALE_HEIGHT) ratioY = img.height / MESSAGE_ATTACHMENT_SCALE_HEIGHT;
                    if (MESSAGE_ATTACHMENT_SCALE_KEEP_RATIO) {
                        ratioX = ratioY = Math.max(ratioX, ratioY);
                    }
                    var newWidth = img.width / ratioX;
                    var newHeight = img.height / ratioY;
                    canvas.width = newWidth;
                    canvas.height = newHeight;
                    var tmpCanvas = document.createElement("canvas");
                    var tmpCtx = tmpCanvas.getContext("2d");
                    var steps = Math.floor(Math.abs(Math.max(ratioX, ratioY)));
                    if (steps < 0) steps = 1;
                    if (steps > 5) steps = 5;
                    var stepAddW = (img.width - newWidth) / steps;
                    var stepAddH = (img.height - newHeight) / steps;
                    tmpCanvas.width = img.width;
                    tmpCanvas.height = img.height;
                    tmpCtx.drawImage(img, 0, 0, img.width, img.height);
                    var oldWidth = tmpCanvas.width;
                    var oldHeight = tmpCanvas.height;
                    for (var n = 1; n <= steps; n++) {
                        var tmpWidth = Math.floor(img.width - (n * stepAddW));
                        var tmpHeight = Math.floor(img.height - (n * stepAddH));
                        var intermediateCanvas = document.createElement("canvas");
                        var intermediateCtx = intermediateCanvas.getContext("2d");
                        intermediateCanvas.width = tmpWidth;
                        intermediateCanvas.height = tmpHeight;
                        intermediateCtx.drawImage(tmpCanvas, 0, 0, oldWidth, oldHeight, 0, 0, tmpWidth, tmpHeight);
                        tmpCtx.clearRect(0, 0, tmpCanvas.width, tmpCanvas.height);
                        tmpCtx.drawImage(intermediateCanvas, 0, 0, tmpWidth, tmpHeight, 0, 0, tmpWidth, tmpHeight);
                        oldWidth = tmpWidth;
                        oldHeight = tmpHeight;
                    }
                    ctx.drawImage(tmpCanvas, 0, 0, tmpWidth, tmpHeight, 0, 0, canvas.width, canvas.height);
                    var quality = parseFloat(MESSAGE_ATTACHMENT_SCALE_QUALITY);
                    if (!quality) quality = 0.92;
                    else quality = quality / 100;
                    var newFile = dataURItoBlob(canvas.toDataURL(formData_.parameters[paramNo_].value.type, quality), formData_.parameters[paramNo_].value.type);
                    while (newFile.size > USER_ATTACHMENT_MAXSIZE) {
                        quality -= 0.01;
                        var oldSize = newFile.size;
                        newFile = dataURItoBlob(canvas.toDataURL(formData_.parameters[paramNo_].value.type, quality), formData_.parameters[paramNo_].value.type);
                        if (oldSize == newFile.size) break;
                        if (quality <= 0.5) break;
                    }
                    var withExifInfo = ExifRestorer.restore(img.src, canvas.toDataURL(formData_.parameters[paramNo_].value.type, quality));
                    newFile = dataURItoBlob(withExifInfo, formData_.parameters[paramNo_].value.type);
                    formData_.parameters[paramNo_].value = newFile;
                    self._cropCount--;
                    callback_.call(self, formData_, uploadID_);
                };
                img.onerror = function() {
                    self._realUpload(formData_, paramNo_);
                };
                img.src = frEvent.target.result;
            };
            fr.readAsDataURL(formData_.parameters[paramNo_].value);
        };
Auffällig ist das es keine Überprüfung gibt ob das Bild nicht schon kleiner ist als das was gewünscht ist, in der Auflösung.
Das bedeutet es wird sowohl upgesized als auch downgesized. Find ich persönlich doof.
Bei 20MP Bildern bricht der Browser zusammen auch nicht gut, Passt das nicht mehr in die DataURL?
 
Aha ok, aber warum die Bilder als zu groß erkannt werden wenn die schon <=500kb sind fällt Dir auch nicht auf.
 
Laut den Usern nur bei Bildern knapp unter 500kB.
Dann sind wahrscheinlich die Einstellungen client- und serverseitig nicht 100%ig kompatibel.

Z.B. das Skalieren der Bildes is mehreren Schritten halte ich für keine besonders gute Idee. Die Qualität wird dadurch nicht besser. Auch kann es passieren, dass das Bild verkleinert wird, aber trotzdem mit zu großer Dateigröße hochgeladen wird (Abbruch wegen Qualität oder wegen den Exif-Daten).
 
kkapsner schrieb:
Dann sind wahrscheinlich die Einstellungen client- und serverseitig nicht 100%ig kompatibel.
Hm, ich glaube mann nimmt die Einstellung nur einmalig in einem Backend vor. Es seiden auf den Server läuft php oder ähnliches und es kommt da zu Abweichung aufgrund des Datentypes . Wie z.B
0.1 + 0.2 == 0.3 -> false

kkapsner schrieb:
Z.B. das Skalieren der Bildes is mehreren Schritten halte ich für keine besonders gute Idee. Die Qualität wird dadurch nicht besser.
Ja das stimmt, das hätte man besser lösen könne aber ein Bicubic interpolation oder Lanczos3 wären overdozed weil er dann die Qualität runter schrauben würde.


kkapsner schrieb:
Auch kann es passieren, dass das Bild verkleinert wird, aber trotzdem mit zu großer Dateigröße hochgeladen wird (Abbruch wegen Qualität oder wegen den Exif-Daten).
Ja das meine ich ja, bei einen viel zu Großen Bild z.B 30Mega Pixel bricht alles zusammen, es müsste vorher schon geprüft werden ob das bild zu groß ist bevor verkleinert wird.

Die Einstellung müssen natürlich auch Sinn ergeben man kann nicht sagen Ich möchte ein Bild mit 18MP aber nur 500kb groß. Aber bei unser Menschheit muss man an alles denken.


kkapsner schrieb:
Abbruch wegen Qualität oder wegen den Exif-Daten
An die Exif Daten habe ich nicht gedacht , kann es sein das wenn das Bild knapp unter 500kb ist vom Skript nicht angerührt wird und er nach der While die EXIF Daten reinpackt dann wäre Das Bild zu groß.

Weißt Du zufällig wieviel Byte die EXIF Daten verbrauchen, das müsste man dann von den 500kb subtrahieren.
 
Ein, zwei Fragen habe ich noch.

PNG Bilder werden nur in der Auflösung verkleinert nicht aber in der Dateigröße, warum?

Das ganze ist asynchron programmiert viele User berichten das der Upload lange dauert.
Logisch wenn man 100 Bilder in das Skript packt werden 100 Funktionen asynchron ausgeführt.
oder bin ich falsch? Wäre eine Synchrone Verarbeitung nicht besser so das Bild für Bild abgearbeitet wird?

Bilder aus einer Vollformat Kamera (~20mb) mag das Skript gar nicht:
FF: Image corrupt or truncated. URI in this note truncated due to length.
Chrome sagt mir was das was mit readAsDataURL nicht stimmt und schließt sich dann.
Hier hätte wahrscheinlich durchweg mit BLOB's gearbeitet werden müssen, statt mit Data URL .

Das Problem das Bilder <500kb als zu groß erkannt werden hat sich erübrigt.
Selbst wenn das Bild 500kB wir es dennoch verkleinert gleich vor der while, weil Q nicht 100 sondern 95 ist. Auch wenn das Bild 100kb groß ist wird es verkleinert. Ein Arbeitsschritt der eingespart werden könnte.
Ein Problem gibt es da dennoch die while rechnet nicht mit den Exif Daten. Wenn die bei 495kb stehen bleibt packt er danach die EXIF Daten drauf, somit Bild zu groß.
 
Es seiden auf den Server läuft php oder ähnliches und es kommt da zu Abweichung aufgrund des Datentypes . Wie z.B
Nein, darin kann es nicht liegen, da es hier um Integers geht.
aber ein Bicubic interpolation oder Lanczos3 wären overdozed
Ich würde da einfach den Browser machen lassen...
Weißt Du zufällig wieviel Byte die EXIF Daten verbrauchen
Das kann man nicht pauschal sagen, da das von Bild zu Bild unterschiedlich ist.
PNG Bilder werden nur in der Auflösung verkleinert nicht aber in der Dateigröße, warum?
Wenn man bei einem PNG die Ausmaße verringert, muss sich auch die Dateigröße ändern. Oder was meinst du genau mit "Auflösung"?
Wäre eine Synchrone Verarbeitung nicht besser so das Bild für Bild abgearbeitet wird?
Das würde den Browser nur einfrieren und dann in einen Timeout schicken. Und außerdem kann man den Filereader gar nicht synchron machen.
FF: Image corrupt or truncated. URI in this note truncated due to length.
Das ist genau das, was Dormilich meinte.
Hier hätte wahrscheinlich durchweg mit BLOB's gearbeitet werden müssen, statt mit Data URL .
Genau.
 
kkapsner schrieb:
Wenn man bei einem PNG die Ausmaße verringert, muss sich auch die Dateigröße ändern. Oder was meinst du genau mit "Auflösung"?
Ich meine schon die Ausmaße. PNG Bilder werden Immer als zu groß erkannt kann ich machen was ich will.
Es haben sich auch User beschwert von Mobilen Geräten da ist das Bild auch immer Zu groß.
Anscheint gibt es kein Fallback auf dem Server.

kkapsner schrieb:
Das würde den Browser nur einfrieren und dann in einen Timeout schicken. Und außerdem kann man den Filereader gar nicht synchron machen.
Das ist jetzt schon so, man kann in das System 100 Bilder Reinpacken bei 20 Bildern kann ich ein Kaffee durchlassen. Gut, sitze an einem Mini-ITX System.

Da haben sich auch welche beschwert das der "Upload" lange dauert. Es ist zwar die Verarbeitung aber das weiß ja Normalmesch nicht.
 
Zurück
Oben