1

I am using Kinetic for some image processing. What happens is that I crop my image and then by clicking a button I want to make it black and white. For some reason the simple setFilter function is not working in this case, when you do crop first. This is the code for cropping:

    layer.removeChildren();
    layer.clear();
    image = new Kinetic.Image({
        image: canvasImage,
        x: (canvasWidth/2-theSelection.w/2),
        y: (canvasHeight/2-theSelection.h/2),
        width: theSelection.w,
        height: theSelection.h,
        crop: [theSelection.x, theSelection.y, theSelection.w, theSelection.h],
        name: "image_tmp"
    });

    layer.add(image); 
    stage.draw();

And here is the function I decided to use for applying the filter:

    var imgPixels = ctx.getImageData(xx, yy, imgW, imgH);

    for(var y = 0; y < imgPixels.height; y++){
        for(var x = 0; x < imgPixels.width; x++){
            var i = (y * 4) * imgPixels.width + x * 4;
            var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
            imgPixels.data[i] = avg;
            imgPixels.data[i + 1] = avg;
            imgPixels.data[i + 2] = avg;
        }
    }

    ctx.putImageData(imgPixels, xx, yy, 0, 0, imgPixels.width, imgPixels.height);

So now I get my cropped image with the filter, but if I want to continue doing something to the image object, I am getting:

TypeError: a.getType is not a function

I think also that the image object I used to use in my code, is now like undefined.

So for example I want after the filter to do layer.add(image) and I want image variable to be the new black and white one and not the old one.

So does anyone have an idea what is the problem, or how can I make the new imgPixels to be the same as my image. Thanks in advance

novellino
  • 1,069
  • 4
  • 22
  • 51

1 Answers1

0

Is there any reason you didn't use the Kinetic.Filters.Grayscale filter?

Here are 2 ways you can do it:

1) Use setFilter (it works!)

var imageObj = new Image();
imageObj.onload = function() {
  var yoda = new Kinetic.Image({
    x: 200,
    y: 50,
    image: imageObj,
    crop: [0, 0, 50, 100]
  });

  // add the shape to the layer
  layer.add(yoda);

  // add the layer to the stage
  stage.add(layer);

  yoda.setFilter(Kinetic.Filters.Grayscale);
  layer.draw();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';

2) Set the filter property on the image beforehand

var imageObj = new Image();
imageObj.onload = function() {
  var yoda = new Kinetic.Image({
    x: 200,
    y: 50,
    image: imageObj,
    crop: [0, 0, 50, 100],
    filter: Kinetic.Filters.Grayscale
  });

  // add the shape to the layer
  layer.add(yoda);

  // add the layer to the stage
  stage.add(layer);

  //yoda.setFilter(Kinetic.Filters.Grayscale);
  //layer.draw();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';

Either way you don't need to add any new images, the original Kinetic.Image is filtered black & white.

UPDATE

Open this link: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-image-tutorial/

And copy and paste this code, replacing all the code in the link. It's working fine for me..

<!DOCTYPE HTML>
<html>
  <head>
    <style>
      body {
        margin: 0px;
        padding: 0px;
      }
    </style>
  </head>
  <body>
    <button id="crop">Crop</button>
    <button id="gray">Grayscale</button>
    <button id="both">Both</button>
    <div id="container"></div>
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.0.min.js"></script>
    <script defer="defer">
      var yoda;
      var stage = new Kinetic.Stage({
        container: 'container',
        width: 578,
        height: 200
      });
      var layer = new Kinetic.Layer();

      var imageObj = new Image();
      imageObj.onload = function() {
        yoda = new Kinetic.Image({
          x: 200,
          y: 50,
          image: imageObj,
          width: 106,
          height: 118
        });

        // add the shape to the layer
        layer.add(yoda);

        // add the layer to the stage
        stage.add(layer);        
      };
      imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';

      document.getElementById('crop').addEventListener('click', function() {
        yoda.setCrop([20, 20, 50, 50]);
        layer.draw();
      });

      document.getElementById('gray').addEventListener('click', function() {
        yoda.setFilter(Kinetic.Filters.Grayscale);
        layer.draw();
      });

    document.getElementById('both').addEventListener('click', function() {
        yoda.setCrop([20, 20, 50, 50]);
        yoda.setFilter(Kinetic.Filters.Grayscale);
        layer.draw();
      });         

    </script>
  </body>
</html>
projeqht
  • 3,160
  • 3
  • 18
  • 32
  • for some reason when I am using this code, nothing happens to my image. – novellino Sep 19 '13 at 14:52
  • it cannot be onload both things, I do not know if this is a problem. I create and crop the image in one function, and then when I click on a button I do the setFilter but nothing happens. – novellino Sep 19 '13 at 14:59
  • You tried both of the examples above? Remember you have the use `layer.draw()` after calling `setFilter()`. In my second example you don't even have to call setFilter, you can just set the `crop` and `filter` properties when creating the image! – projeqht Sep 19 '13 at 15:02
  • yes I tried both. But I cannot apply them exactly like this in my code. for example I cannot use imageObj.src. This is something I do in the beginning when I load the image. Then I have a button for the crop and then another button for the black&white. – novellino Sep 19 '13 at 15:10
  • The setFilter before I crop my image works fine, the problem is after cropping. – novellino Sep 19 '13 at 15:11
  • How are you setting your `canvasImg`? It's working for me fine, see my updated answer. The only difference is using imageObj.src which shouldn't be a problem. – projeqht Sep 19 '13 at 17:42