image fenstergröße - HTML5 Größe der Bilder vor dem Hochladen anpassen




bildgröße auflösung (9)

Sie können dropzone.js verwenden, wenn Sie einen einfachen Upload-Manager mit Größenanpassung vor den Upload-Funktionen verwenden möchten.

Es hat eingebaute Größenänderungsfunktionen, aber Sie können Ihre eigenen zur Verfügung stellen, wenn Sie möchten.

Hier ist ein Nudel-Scratcher.

Bedenkt, wir haben HTML5 lokalen Speicher und xhr v2 und was nicht. Ich habe mich gefragt, ob jemand ein funktionierendes Beispiel finden könnte oder mir einfach ein Ja oder Nein für diese Frage geben könnte:

Ist es möglich, ein Bild mit dem neuen lokalen Speicher (oder was auch immer) zu skalieren, so dass ein Benutzer, der keine Ahnung von der Größe eines Bildes hat, sein 10mb-Bild auf meine Website ziehen kann, Größe mit dem neuen lokalen Speicher ändern und Dann laden Sie es auf die kleinere Größe hoch.

Ich weiß ganz genau, Sie können es mit Flash, Java-Applets, ActiveX ... machen. Die Frage ist, ob Sie mit Javascript + Html5 tun können.

Ich freue mich auf die Antwort zu diesem Thema.

Ta für jetzt.


Das Ändern der Größe von Bildern in einem Canvas-Element ist im Allgemeinen eine schlechte Idee, da es die billigste Box-Interpolation verwendet. Das resultierende Bild verschlechtert sich merklich in der Qualität. Ich würde empfehlen, http://nodeca.github.io/pica/demo/ verwenden, das stattdessen eine Lanczos-Transformation durchführen kann. Die obige Demo-Seite zeigt den Unterschied zwischen Canvas- und Lanczos-Ansätzen.

Es verwendet auch Web-Worker für die Größenänderung von Bildern parallel. Es gibt auch WEBGL-Implementierung.

Es gibt einige Online-Bildgrößenanpassungen, die Pica verwenden, wie https://myimageresizer.com


fd.append("image", dataurl);

Dies wird nicht funktionieren. Auf der PHP-Seite können Sie keine Datei mit diesem speichern.

Verwenden Sie stattdessen diesen Code:

var blobBin = atob(dataurl.split(',')[1]);
var array = [];
for(var i = 0; i < blobBin.length; i++) {
  array.push(blobBin.charCodeAt(i));
}
var file = new Blob([new Uint8Array(array)], {type: 'image/png', name: "avatar.png"});

fd.append("image", file); // blob file

Änderung der Antwort von Justin , die für mich funktioniert:

  1. Img.onload hinzugefügt
  2. Erweitern Sie die POST-Anfrage mit einem realen Beispiel

function handleFiles()
{
    var dataurl = null;
    var filesToUpload = document.getElementById('photo').files;
    var file = filesToUpload[0];

    // Create an image
    var img = document.createElement("img");
    // Create a file reader
    var reader = new FileReader();
    // Set the image once loaded into file reader
    reader.onload = function(e)
    {
        img.src = e.target.result;

        img.onload = function () {
            var canvas = document.createElement("canvas");
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0);

            var MAX_WIDTH = 800;
            var MAX_HEIGHT = 600;
            var width = img.width;
            var height = img.height;

            if (width > height) {
              if (width > MAX_WIDTH) {
                height *= MAX_WIDTH / width;
                width = MAX_WIDTH;
              }
            } else {
              if (height > MAX_HEIGHT) {
                width *= MAX_HEIGHT / height;
                height = MAX_HEIGHT;
              }
            }
            canvas.width = width;
            canvas.height = height;
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0, width, height);

            dataurl = canvas.toDataURL("image/jpeg");

            // Post the data
            var fd = new FormData();
            fd.append("name", "some_filename.jpg");
            fd.append("image", dataurl);
            fd.append("info", "lah_de_dah");
            $.ajax({
                url: '/ajax_photo',
                data: fd,
                cache: false,
                contentType: false,
                processData: false,
                type: 'POST',
                success: function(data){
                    $('#form_photo')[0].reset();
                    location.reload();
                }
            });
        } // img.onload
    }
    // Load files into file reader
    reader.readAsDataURL(file);
}

Die angenommene Antwort funktioniert gut, aber die Größenanpassungslogik ignoriert den Fall, in dem das Bild nur in einer der Achsen größer ist als das Maximum (z. B. height> maxHeight, aber width <= maxWidth).

Ich denke, der folgende Code kümmert sich um alle Fälle auf eine geradlinigere und funktionellere Weise (ignorieren Sie die typoskriptartigen Anmerkungen, wenn Sie plain javascript verwenden):

private scaleDownSize(width: number, height: number, maxWidth: number, maxHeight: number): {width: number, height: number} {
    if (width <= maxWidth && height <= maxHeight)
      return { width, height };
    else if (width / maxWidth > height / maxHeight)
      return { width: maxWidth, height: height * maxWidth / width};
    else
      return { width: width * maxHeight / height, height: maxHeight };
  }

Korrektur zu oben:

<img src="" id="image">
<input id="input" type="file" onchange="handleFiles()">
<script>

function handleFiles()
{
    var filesToUpload = document.getElementById('input').files;
    var file = filesToUpload[0];

    // Create an image
    var img = document.createElement("img");
    // Create a file reader
    var reader = new FileReader();
    // Set the image once loaded into file reader
    reader.onload = function(e)
    {
        img.src = e.target.result;

        var canvas = document.createElement("canvas");
        //var canvas = $("<canvas>", {"id":"testing"})[0];
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0);

        var MAX_WIDTH = 400;
        var MAX_HEIGHT = 300;
        var width = img.width;
        var height = img.height;

        if (width > height) {
          if (width > MAX_WIDTH) {
            height *= MAX_WIDTH / width;
            width = MAX_WIDTH;
          }
        } else {
          if (height > MAX_HEIGHT) {
            width *= MAX_HEIGHT / height;
            height = MAX_HEIGHT;
          }
        }
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0, width, height);

        var dataurl = canvas.toDataURL("image/png");
        document.getElementById('image').src = dataurl;     
    }
    // Load files into file reader
    reader.readAsDataURL(file);


    // Post the data
    /*
    var fd = new FormData();
    fd.append("name", "some_filename.jpg");
    fd.append("image", dataurl);
    fd.append("info", "lah_de_dah");
    */
}</script>

Ich habe dieses Problem vor ein paar Jahren angepackt und meine Lösung als https://github.com/rossturner/HTML5-ImageUploader auf github hochgeladen

robertcs Antwort verwendet die Lösung, die im Mozilla Hacks Blogpost vorgeschlagen wurde, aber ich fand, dass dies eine wirklich schlechte Bildqualität ergab, wenn die Größe auf einen Maßstab geändert wurde, der nicht 2: 1 (oder ein Vielfaches davon) war. Ich fing an, mit verschiedenen Algorithmen zur Bildgrößenanpassung zu experimentieren, obwohl die meisten am Ende ziemlich langsam waren oder auch keine gute Qualität hatten.

Schließlich habe ich eine Lösung gefunden, die meiner Meinung nach schnell ausgeführt wird und auch eine recht gute Leistung bietet - da die Mozilla-Lösung von 1 Canvas auf einen anderen schnell und ohne Verlust der Bildqualität im Verhältnis 2: 1 bei einem Ziel von x arbeitet Pixel breit und y Pixel hoch, verwende ich diese Canvas-Methode zur Größenänderung, bis das Bild zwischen x und 2 x und y und 2 y ist . An diesem Punkt wende ich mich dann der algorithmischen Bildgrößenanpassung für den letzten "Schritt" der Größenanpassung auf die Zielgröße zu. Nachdem ich mehrere verschiedene Algorithmen ausprobiert hatte, entschied ich mich für die bilineare Interpolation, die von einem Blog stammt, der nicht mehr online ist, aber über das Internet Archive zugänglich ist , was gute Ergebnisse liefert, hier ist der anwendbare Code:

ImageUploader.prototype.scaleImage = function(img, completionCallback) {
    var canvas = document.createElement('canvas');
    canvas.width = img.width;
    canvas.height = img.height;
    canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);

    while (canvas.width >= (2 * this.config.maxWidth)) {
        canvas = this.getHalfScaleCanvas(canvas);
    }

    if (canvas.width > this.config.maxWidth) {
        canvas = this.scaleCanvasWithAlgorithm(canvas);
    }

    var imageData = canvas.toDataURL('image/jpeg', this.config.quality);
    this.performUpload(imageData, completionCallback);
};

ImageUploader.prototype.scaleCanvasWithAlgorithm = function(canvas) {
    var scaledCanvas = document.createElement('canvas');

    var scale = this.config.maxWidth / canvas.width;

    scaledCanvas.width = canvas.width * scale;
    scaledCanvas.height = canvas.height * scale;

    var srcImgData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
    var destImgData = scaledCanvas.getContext('2d').createImageData(scaledCanvas.width, scaledCanvas.height);

    this.applyBilinearInterpolation(srcImgData, destImgData, scale);

    scaledCanvas.getContext('2d').putImageData(destImgData, 0, 0);

    return scaledCanvas;
};

ImageUploader.prototype.getHalfScaleCanvas = function(canvas) {
    var halfCanvas = document.createElement('canvas');
    halfCanvas.width = canvas.width / 2;
    halfCanvas.height = canvas.height / 2;

    halfCanvas.getContext('2d').drawImage(canvas, 0, 0, halfCanvas.width, halfCanvas.height);

    return halfCanvas;
};

ImageUploader.prototype.applyBilinearInterpolation = function(srcCanvasData, destCanvasData, scale) {
    function inner(f00, f10, f01, f11, x, y) {
        var un_x = 1.0 - x;
        var un_y = 1.0 - y;
        return (f00 * un_x * un_y + f10 * x * un_y + f01 * un_x * y + f11 * x * y);
    }
    var i, j;
    var iyv, iy0, iy1, ixv, ix0, ix1;
    var idxD, idxS00, idxS10, idxS01, idxS11;
    var dx, dy;
    var r, g, b, a;
    for (i = 0; i < destCanvasData.height; ++i) {
        iyv = i / scale;
        iy0 = Math.floor(iyv);
        // Math.ceil can go over bounds
        iy1 = (Math.ceil(iyv) > (srcCanvasData.height - 1) ? (srcCanvasData.height - 1) : Math.ceil(iyv));
        for (j = 0; j < destCanvasData.width; ++j) {
            ixv = j / scale;
            ix0 = Math.floor(ixv);
            // Math.ceil can go over bounds
            ix1 = (Math.ceil(ixv) > (srcCanvasData.width - 1) ? (srcCanvasData.width - 1) : Math.ceil(ixv));
            idxD = (j + destCanvasData.width * i) * 4;
            // matrix to vector indices
            idxS00 = (ix0 + srcCanvasData.width * iy0) * 4;
            idxS10 = (ix1 + srcCanvasData.width * iy0) * 4;
            idxS01 = (ix0 + srcCanvasData.width * iy1) * 4;
            idxS11 = (ix1 + srcCanvasData.width * iy1) * 4;
            // overall coordinates to unit square
            dx = ixv - ix0;
            dy = iyv - iy0;
            // I let the r, g, b, a on purpose for debugging
            r = inner(srcCanvasData.data[idxS00], srcCanvasData.data[idxS10], srcCanvasData.data[idxS01], srcCanvasData.data[idxS11], dx, dy);
            destCanvasData.data[idxD] = r;

            g = inner(srcCanvasData.data[idxS00 + 1], srcCanvasData.data[idxS10 + 1], srcCanvasData.data[idxS01 + 1], srcCanvasData.data[idxS11 + 1], dx, dy);
            destCanvasData.data[idxD + 1] = g;

            b = inner(srcCanvasData.data[idxS00 + 2], srcCanvasData.data[idxS10 + 2], srcCanvasData.data[idxS01 + 2], srcCanvasData.data[idxS11 + 2], dx, dy);
            destCanvasData.data[idxD + 2] = b;

            a = inner(srcCanvasData.data[idxS00 + 3], srcCanvasData.data[idxS10 + 3], srcCanvasData.data[idxS01 + 3], srcCanvasData.data[idxS11 + 3], dx, dy);
            destCanvasData.data[idxD + 3] = a;
        }
    }
};

Dies skaliert ein Bild bis zu einer Breite von config.maxWidth unter Beibehaltung des ursprünglichen Seitenverhältnisses. Zum Zeitpunkt der Entwicklung funktionierte das auf dem iPad / iPhone Safari zusätzlich zu den großen Desktop-Browsern (IE9 +, Firefox, Chrome). Ich gehe daher davon aus, dass es angesichts der breiteren Nutzung von HTML5 noch kompatibel sein wird. Beachten Sie, dass der canvas.toDataURL () - Aufruf einen Mime-Typ und eine Bildqualität verwendet, mit der Sie die Qualität und das Ausgabeformat der Datei steuern können (möglicherweise abweichend von der Eingabe, wenn Sie möchten).

Der einzige Punkt, der hier nicht behandelt wird, ist das Beibehalten der Orientierungsinformationen. Ohne Kenntnis dieser Metadaten wird das Bild in der Größe verändert und gespeichert, wobei alle Metadaten innerhalb des Bildes zur Orientierung verloren gehen, was bedeutet, dass Bilder auf einem Tablet-Gerät "auf dem Kopf" waren so gerendert, obwohl sie im Kamerasucher des Gerätes umgedreht worden wären. Wenn dies ein Problem ist, hat dieser Blogbeitrag eine gute Anleitung und Codebeispiele, um dies zu erreichen, die ich sicher in den obigen Code integrieren könnte.


Wenn Sie das Rad nicht neu erfinden wollen, können Sie plupload.com ausprobieren


<style type="text/css"> 
#container{
text-align:center;
width: 100%;
height: 200px; /*set height*/
margin: 0px;
padding: 0px;
background-image:url('../assets/images/img.jpg');
background-size: content; /*scaling down large image to a div*/
background-repeat:no-repeat;
background-position:center;
}
</style>

<div id="container>
<!--inside container-->
</div>




image html5 upload xmlhttprequest local-storage