Time for action – the imageEffects object

We will now create a new object called imageEffects to encapsulate all of the code for our image effects and put it in a new file, imageEffects.js. The imageEffects object will be a global static object defined using the revealing module pattern.

Note

With the revealing module pattern, you define a set of functions in a private scope and then return an anonymous object that reveals which of those methods you want to be public. This works well for defining static objects.

Let's start by defining the imageEffects object and adding two helper functions which will remain private. They are used to get and set the image data for the entire canvas:

var imageEffects = function()
{
    function getImageData(canvas)
    {
        return canvas.getContext("2d").getImageData(0, 0,
            canvas.width, canvas.height)
    }
    
    function putImageData(canvas, imageData)
    {
        canvas.getContext("2d").putImageData(imageData, 0, 0);
    }

The getImageData() method takes a canvas and returns the image data for the entire canvas. The putImageData() method takes a canvas and image data as parameters and puts the image data back into the canvas.

Let's implement our first effect; inverting the colors of an image. The invert() method takes the canvas as a parameter. Inverting colors is very simple. We just take each color channel for each pixel and subtract its value from the maximum color value of 255:

    function invert(canvas)
    {
        var imageData = getImageData(canvas);
        var data = imageData.data;
        for (var i = 0; i < data.length; i += 4)
        {
            data[i]   = 255 - data[i];   //red
            data[i+1] = 255 - data[i+1]; //green
            data[i+2] = 255 - data[i+2]; //blue
            //data[i+3] is alpha
        }
        
        putImageData(canvas, imageData);
    }

First we get the image data for the canvas and then loop over the bytes, incrementing by four every time because there are four bytes for each pixel. Each color channel value is inverted and set back into the byte. The alpha amount is unchanged. Then we put the image data back onto the canvas.

Now let's finish the imageEffects object off. We need to return an anonymous object that defines all of the methods that we want to be public. The only one we have so far is the invert() method:

    return {
        invert: invert
    };
}();

Notice that we have open and close parenthesis at the end of the function declaration. That immediately executes the function and assigns the anonymous object returned to the imageEffects variable. So now we have an imageEffects object with an invert() public method.

Now we need to hook up our Effects menu items to the imageEffects object. We can do this in the menuItemClicked() method of PhotoPadApp. Previously we gave our menu element a data-option custom attribute of "applyEffect". So we will check for that:

function menuItemClicked(option, value)
{
    if (option == "applyEffect")
    {
        imageEffects[value](canvas);
    }
}

We have given our Invert menu item element a data-value custom attribute set to "invert". We will use this to dynamically access the invert() method in the imageEffects object, just like we did for data binding in Chapter 3, The Devil is in the Details. We pass in the canvas object as a parameter. For "invert", this is equivalent to calling imageEffects.invert(canvas). We will implement all of our menu items in this way so that they automatically bind to a method in the imageEffects object.

What just happened?

We created an imageEffects object to hold all of our image effects algorithms. We implemented an effect to invert the colors of an image. We hooked up the Effects menu using custom data attributes to bind the menu items to methods in the imageEffects object.

Now let's open up our application in the browser and give it a try. After loading an image, choose Invert from the Effects menu and you should see the inverted image:

What just happened?
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.45.162