1

I am developing a system for image filter with html5 canvas, however, as I am at the beginning I have emerged me some doubts and mistakes.

Here's what I've developed so far:

$(document).ready(function() {
    $("#uploadImagem").change(function(e) {
        var _URL = window.URL || window.webkitURL,
        arquivo = e.target.files[0],
        tipoImagem = /image.*/,
        reader,
        imagem;

        if(!arquivo.type.match(tipoImagem)) {
            alert("Somente imagens são aceitas!");
            return;
        }

        imagem = new Image();

        imagem.onload = function() {
            if(this.width > 600 || this.height > 400) {
                alert("Somente imagens com largura máxima de 600px e altura máxima de 400px");
                return;
            } else {
                $("#filtrarImagem").width(this.width).height(this.height);
            }
        };

        imagem.src = _URL.createObjectURL(arquivo);

        reader = new FileReader();
        reader.onload = fileOnload;
        reader.readAsDataURL(arquivo);
    });

    function fileOnload(e) {
        var $img = $("<img>", {src: e.target.result}),
        canvas = $("#filtrarImagem")[0],
        context = canvas.getContext("2d");

        $img.load(function() {
            context.drawImage(this, 0, 0);
        });
    }
});
  1. When I do imagem.onload... I wish, if the image pixels were greater than 600 and 400 he gave the alert and stop there, but even so the image appears on the canvas.
  2. In the same imagem.onload... function, if the image pixels correspond to the canvas required (id = "filtrarImagem") is the size of the image, but the image to the canvas becomes smaller than the original uploaded, and she was to occupy all the canvas and get the original size.

How to continue?

Igor
  • 645
  • 4
  • 16
  • 37

2 Answers2

1

You have two separate handlers for image loading. There is no need to set two image sources with the same URL, just reuse a single image for both checking size and setting canvas size as well as draw it into the canvas.

I would suggest the following steps (you tagged the question with jQuery but I would highly recommend working in vanilla JavaScript when you work with non-DOM oriented elements such as canvas).

Example

if (typeof window.URL === "undefined") window.URL = window.webkitURL;

$("input")[0].onchange = function(e) {
  var arquivo = e.target.files[0],
      imagem = new Image();

  if (!arquivo.type.match(/image.*/)) {
    alert("Somente imagens são aceitas!");
    return;
  }

  // STEP 1: load as image
  imagem.onload = doSetup;
  imagem.src = URL.createObjectURL(arquivo)
};

// STEP 2: now that we have the image loaded we can check size and setup canvas
function doSetup() { 
  URL.revokeObjectURL(this.src);  // clean up memory for object-URL
  
  if (this.width > 600 || this.height > 400) {
    alert("Too big!");
    return;                       // exit!
  }
  
  // image OK, setup canvas
  var c = $("canvas")[0];         // work with the element itself, not the jQuery object
  c.width = this.width;           // important: use canvas.width, not style or css
  c.height = this.height;
  
  // draw in image
  var ctx = c.getContext("2d");
  ctx.drawImage(this, 0, 0);
  // NEXT: ... from here, invoke filter etc.
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file"><br><canvas></canvas>
0

The jQuery width() and height() functions use CSS to change the size of the canvas which does not do what you would expect it to do. Change the width and height attributes of the canvas element directly.

The reason why your check for the size does not prevent the image from being drawn, is because your check is in the handler for imagem.onload in $("#uploadImagem").change while the drawing happens in $img.onload assigned from reader.onload. These two events are processed independently. One of them returning prematurely does not prevent the other from being executed.

Community
  • 1
  • 1
Philipp
  • 67,764
  • 9
  • 118
  • 153