Javascript Fun: Build a Photo Editor App! | Chris Dixon | Skillshare

Javascript Fun: Build a Photo Editor App!

Chris Dixon, Web Developer & Online Teacher

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
12 Lessons (1h 5m)
    • 1. Introduction

      1:53
    • 2. Creating the HTML structure

      6:52
    • 3. Styling with CSS

      4:50
    • 4. Drawing to the canvas

      12:47
    • 5. Uploading and displaying images

      9:12
    • 6. Understanding pixels

      5:16
    • 7. Looping through image data

      7:04
    • 8. Greyscale, sepia and invert effects

      6:40
    • 9. Adding additional effects

      6:14
    • 10. Clearing effects

      2:54
    • 11. Thank you!

      1:03
    • 12. Follow me on Skillshare!

      0:23

About This Class

Welcome to the Javascript fun series!

For web design or development, there is 3 must know technologies, HTML, CSS, and Javascript.

The main aim of the Javascript fun series is to take your knowledge of these 3 (only a little is required!), and put them into practice by building a series of educational, yet fun projects show you exactly how they work perfectly together. Working on projects and solving problems is a great way to learn.

The project we will build in this course will be a Javascript Photo Editing App.

All the required tools are free to download, I will be using the following:

Visual Studio Code Text Editor: https://code.visualstudio.com

Chrome Web Browser: https://www.google.co.uk/chrome/browser

We begin by creating the user interface with HTML. The we apply styling using CSS.

Then we add Javascript, this is where the real magic happens!

You will learn things such as:

  • Creating HTML interfaces
  • Styling with CSS
  • Incorporating Javascript and linking external files
  • Variables
  • Const and let
  • ES6 Arrow Functions
  • Event handlers
  • Manipulating the DOM
  • Drawing to the canvas
  • Using the canvas 2d context
  • Working with file readers
  • Uploading images
  • How pixels are structured
  • Looping through pixel data
  • Manipulating and replacing pixels on the canvas
  • And much more!

So if you are looking to move on and put your skills into practice using with real projects, take this course now!

Transcripts

1. Introduction: Hey, guys, and welcome to the JavaScript fun series. My name is Chris, and I'm here to show you how to use HTML, CSS, and JavaScript, and then put them all together to build a fun and exciting projects. The project which we'll build in this course is a photo editing application. This application is a great way to see how we can work with not only JavaScript, but also the HTML Canvas and file uploader elements, too. We begin by creating the user interface using HTML. [inaudible] is pretty simple but it will lay the foundation for all project by adding the buttons, file uploader, and also the HTML Canvas. After this, we'll move on to adding the styling using CSS. It will make our application look a lot nicer. Just like the HTML, the CSS is pretty minimal. Most of the work in this project is with JavaScript. This app will have a file uploader at the top of the page where the user can select an image they want to use. We then read the contents of this file and display it onto the canvas. After that, we use JavaScript to loop through all of the pixel data on the canvas. This will allow us to create effects, to manipulate the pixel data, to add some effects to the image, such as greyscale, the sepia effects, and also swapping around the red, green, and blue values. In just a short time, this course covers so much, such as working with file readers, pixel data, working with the canvas, along with plenty of JavaScript fundamentals, such as events, looping, and functions. Thank you for your interest and let's get started. 2. Creating the HTML structure: We're now going to jump straight in to adding HTML for our photo editor application. The HTML for this project is pretty straightforward. All we need to do is add the basic HTML structure and then also add a file input at the top here. Underneath here, we need to add a series of buttons, which are going to trigger some JavaScript to then add some effects to all photos. The final piece of HTML is one that we can't see just at the moment and this is the actual converse, which is just below on here, and this will be the area where our photos appear on the screen. So just like any other project we need to go ahead and add a new project folder. I'm going to add mine on the desktop and call this photo editor. I'll be using the Visual Studio code throughout this project, but of course you can use any text editor which you prefer. So I'm going to open up Visual Studio Code, drag over the project folder and then we can add the index.html as a new file. So I have a command and control "N," or you can click on this little icon just on here. Create a new file called index.html and there we go. So I'm going to be using the built-in Emmett shortcut of HTML:5. Then if we hit "tab", we'll then have the basic HTML structure, which we'll need. You see all this pretty stands, we have the HTML, the heads, and also the body sections. Inside the head, we have the title and also some meta tags to add some information for our site. Inside the title we can change this from documents to photo editor and then it opens this up inside the browser. So we'll have some options to open this up. We can even go inside the project folder on the desktop and double-click on the index page. Or in Visual Studio Code, we can also go over to the file and then go to "Copy path" and then paste this in as a new tab, and there we go. So that's how we start projects which we need to add some HTML2. I'm going to begin up at the very top of the body section and start with the file uploader. This is going to have a "div", as a wrapper? Then an ID of upload. The first thing we need is a label and an input. So this label is going to have some attributes. So the first one is going to be for uploader, the text of select file, and then after here we're going to add our inputs and the inputs, it should stay open inside. The types this time is going to be of file since we're going to be uploading a photo to display on the screen. We need to add the ID of uploader and this needs to match the for attribute, the label. So this label is named to this input just here. Save that's and check this is working, okay. Which is there's a label of Select File and also I'll choose file option. So we take a look at the finished version here. The next thing we need to do now is add these buttons for the effects and also the clear button at the end. This is going to be pretty straightforward. All we need to do is add a "div" again as a rapper. We'll give this an ID of buttons which is used for the CSS, and then we can add our buttons. The first one with the texts of grayscale and then let's copy this line and paste this in. Next one is going to be for the Sepia effects. Then next up we have the invert. So add invert inside here. After this we also have the buttons which are going to switch around the red, green, and blue values. So the fourth one is going to change the reds, greens and blue value to be red, blue, green. So we need to add this in again, and this one is going to be red, green, and blue. So RGB, and this will convert to BGR, which is the blue, green, and red. Next up again, we have the RGB colors and this one is going to be GBR, green, blue, and reds. So keep going into that now and the last one of this group is going to be RGB, and this is going to be turned into green, red, and blue. Then right at the end, we'll add a clear button to remove our effects. Lets bring this up over to the browser, and we now have our various buttons. So the final piece for this HTML is the canvas. Canvas is the thing that makes all this work by displaying the images on the screen and then we can loop through all the different pixel values on the canvas and changes using JavaScript. So back over to the index.html, we'll create one more rapid div, and inside here we can add the canvas elements. We're going to give the canvas an ID so we can target this with JavaScript's of canvas. There we go. So if we save this and then reload the browser, we shouldn't see anything on the screen at the moment. This is because we haven't drawn to the Canvas just yet. So it's basically just empty for now. So the canvas is a HTML elements, which we'll be using to draw our images too. It can be used to draw almost any type of graphics from lines and shapes, photos, right through to complex 3D shapes. Although in this course we'll only access the 2D features or what's called the 2D context. Well, Monday soon, when we get to the JavaScript section. So this is all HTML we need for this project. Majority of the work we'll be using JavaScript. But in the next video we'll get to work with adding some styling using CSS. 3. Styling with CSS: Just like in the last video when we added the HTML, the style of this course is going to be pretty straightforward to. We're just going to add some basic styling for our file inputs and also for these buttons at the top too. Because we don't have a lot in place, I'm just going to add this in the index dot HTML. Hop in the head section rather than agonist to a separate file. Just after the page title, we can open up the style tags. Before we give this first section with the file uploader, an ID of upload, we can now target this in the CSS with the hash, because it's an ID, and the name of upload. The person want to do is align the section in the middle. We have text-align center. Let's add this in the upload section, a background color. You can choose any color which you prefer, but I'm going to keep it simple and go for light blue. Then a border radius to the outside of 10 pixels. Give that a save, reload, and there we go. We also need a little bit of margin for all these inputs, just to give it a little bit of space in top and bottom. Below upload, we can add the inputs and then add some margin to the top and bottom. So two m's on the top and bottom, and zero on the left and right. Let's see what effect this has in the browser. We've got a blue background color, but we're missing the border radius. Let's go back up and change this to be border radius. There we go. That's much better. Now we can get to work on these buttons just below this. We're going to set this to be the display type of Flex. We can use the Flexbox. Let's space these buttons out evenly across the page. We give the buttons. The ID of button is just here. Underneath the inputs, let's target this with a hash, name, buttons. Set the display type to be Flex, which will allow us to work with the Flexbox with these buttons, and also the justify contents, which we can set to the value of space evenly. If we now save this and reload, these buttons now have equal spacing across the page or across the main flex axis. You also need little margin on the top and bottom sides and spacing. We can add margin. We'll keep this consistent with the inputs by adding two m's on the top and bottom, zero on the left and right, a border of one pixel, a solid line. Then this same light blue color to keep the color consistent. Give this a save and then refresh. This blue border, we also need to add the 10 pixels radius. We'll also add some padding to give these buttons some spacing. Underneath the border, the border radius of 10 pixels, and then some padding of 10 pixels too. See how this is looking. This is the container. Now let's add some styling to the individual buttons. We can select the button just with the element's name of button. A background of light blue. A border radius, we'll keep this consistent of 10 pixels, the width of 10 m, and then a 10 pixels padding to button 2. Give that a save and then over to the browser, hit "Reload". The final piece of styling we need to do is to make the canvas the full width of the page. We won't see the effects just yet, but we are concerned with the canvas elements and then add the max width of 100 percent. Of course, we won't see any effect on the page, because we've not drawn anything to the converse just yet. What's drawn to the canvas is something which we'll look at in the next video. 4. Drawing to the canvas: Welcome back. Now we're going to get to work with the Canvas, and actually drawing to this Canvas too. We're going to start by creating an external file called the script.js, and this will handle all the JavaScript for this project. First of all, if we go to the index dot html, and then down at the very bottom of the body section, let's create our script tags. Then inside here we're going to add the script source, and set this equal to the final path, which is just going to be scripts dot js. Keep that saved, and then if you open up the sidebar, and at the same level as the index dot html, we can create our scripts dot js file, which is going to handle all of the actions we need to manipulate the pixels on the screen. Before we can actually draw into the Canvas, we need to first select the Canvas elements, which we are going to store inside the constant. Let's have our constant of Canvas instead it'll be documentsdot getElementByID. It will alter the index page. We gave the Canvas an ID of Canvas. So we can select it with it's name. Inside the brackets, we can add Canvas. Next step, we then need to access what is called the rendering context. This allows us to access a range of drawing functions. So we can manipulate what is actually on the Canvas. We can also store this in the constant, which is short for context of ctx. Then select our Canvas, which is just here, and then dot getContext inside the brackets. We then access the 2D context because we're not working with any of the 3D features in this project. Next, the ctx reference, which is just here. We're then going to use this each time we want to draw into Canvas. For example we could use the filltext method to draw a text on the Canvas. So access ctx dot fillText. This method is going to take in the string which we want to display so that you say, "Canvas text". Then we can add our x, and y coordinates. We want this text to appear on the Canvas, so by default, if no signs of Canvas is specified, the Canvas will default to 300 pixels wide, and 150 pixels tall. So we set this to be 100, and then 50. This will make sure this fits inside the Canvas area. Save this, and then reload. It's pretty small, but you can see our Canvas text is now on the screen. Let's try one more. If we want to draw a rectangle, we can access ctx dot strokeRect. This will add just the outline of the rectangle, and the first two positions we add of zero, zero is going to be the starting position of the rectangle. Zero, zero will be in the top left hand corner. Then we set how wide, and how long we want this to be. We can set this to be 100 by 100. Refresh, and there's our rectangle outline. If we wanted this to be the outline of the full Canvas, we could use in JavaScript, we could select our Canvas, and set it to be the full width, and also we can set the height just like that, and then save that, and then refresh the browser. Now we can see this default, 300 by 150 pixels Canvas, which we mentioned before. This is the default size, and we can go ahead, and change this or we could even change this using CSS or we can add to the height, and width attributes inside the Canvas elements. So here we've added a stroke which is just the outline of the rectangle. We can also use fill rect, which will fill the rectangle with a solid color. So let's remove ctx dot strokeRects, and this time we use ctx dot fillRect, inside here. This works just like the stroke from before. The first two positions which I'm going to add as zero zero, is the top left hand corner of the canvas, and this is where we want the rectangle to begin. This time we're just going to set a 50 by 50 pixels wide rectangle. If we save this, and then reload, the default color, which you see on the Canvas is black. We can change this by setting the fill style color. So just to move our rectangle here, we can set ctx dot fillStyle. We can set this to be any color just like CSS. We can even use a color name such as red, which we see just here or we can also set a hash value. So let's change red to be the hash value of eeeddd. Reload, and now we see a light color on the screen. So this is how we can draw rectangles to the screen. We also have full control of basically our pen, and now we want to move it over the Canvas. We have some methods called moveTo, and also lineTo, which allows to draw to any coordinates on the Canvas. To do this, I'm going to set a new fill style. So it stands out, and I'll set this to a color of red. We then need to specify that we want to begin path. We have ctx dot beginPath. This begin path method will either start a new path or it will reset a column path. We can then go ahead, and move to a certain position on the Canvas. We move with ctx dot moveTo. I'm going to move this to the center of the Canvas. We can use this with JavaScript. So Canvas dot width divided by two, and then the y position of Canvas dot height, again divided by two to keep this in the center of the Canvas. Now we've moved our panel to the center. We're now going to create a line, and you insert a t on the screen there. If you want to see this then reload the browser. We won't see anything on the screen yet because we've not drawn any lines to the Canvas. All we've done is move to the position where we want to start. Actually to draw these lines, we need to use ctx dot lineTo. So you can draw to any position on the Canvas which you want. I want to go for 250, and then 50. Let's see how this looks. We don't see anything on the Canvas just yet. This is because we need to set the stroke or the fill. The stroke is the outline, just like before when we looked at the rectangles. So after all of these lines, we need to set ctx dot stroke, and now if we go to the browser, we should see the line now in place. Let's go ahead, and add another lineTo to keep this going. So again above the stroke, we can add ctx dot lineTo. This time we're going to set the values of 250, and then 100, and if they're saved then over to the browser, and there's our second line on a position of 250, 100. Now we can go ahead, and add a new lineTo methods, and add this to go to the start just here or we also have a method available tools called Close Path, which will take us back to the beginning. So after the second lineTo, we use ctx dot closePath inside the brackets, we just leave this empty. Then this will automatically go back to the start, saving then reloads, and now this closes off our triangle along with the stroke to make the outline. We could also change this stroke to be fill. This will make a solid color inside the middle et.cetera. Just have a neat basic outline. So this is some basic uses of the Canvas. The final thing we're going to look at in this video is how to add an image to the Canvas. This is obviously really important to our project. Let's go back over to Visual Studio, and take a look at how we can add an image. So let's remove all these examples. We leave the two constants at the top. Then we're going to create a new constant called image or img, and save this to a new image. The next thing we need to do is set an image source. We need to go ahead, and grab an image to use in this project. I have one on the desktop, and it's also available to download with this course too. Inside the photo editor, just open up this folder, and then drag over the image. One is called iceland dot jpg. So we can go ahead, and set the image source. We do this by accessing the image constants of img dot source. Then we can go ahead and, set this to our file path. Mine is in the same folder. This can be simply iceland dot jpg. If we could just save, we won't see anything on the browser at the moment because to set this on the screen we then need to actually draw the image using this context just above. So we set the ctx dot drawImage, inside the bracket we set the image which we want to place on the Canvas, which is stored in the constant called img. We can then set the position on the Canvas where we want to draw this. So zero, zero, we'll set this in the top left-hand corner. Save, and then load the browser. It reloads. We still don't see the image which we're expecting on the Canvas. One of the things we need to do before placing this on the Canvas is actually wait for the image to load. We can do this with an onload method. So img dot onload. Now we can set this to a ES6 arrow function, and then move draw image inside this function, and now if we go over to the browser, it reloads. We now see the image is placed on the Canvas. The image is larger than the 300 by 150 default Canvas size. So to make it fit, we can go ahead, and add some more values to the draw image method. Let's set the width to be 300, and height to be 150 as much of a Canvas. Reloads, and there's our image now the same size as the Canvas. Another thing we can do is rather than hardcoding the image to be 300 by 150, we could also adjust the Canvas. So the Canvas dot width, and set this equal to be the same size as the image with img dot width, and also the same for the height. So we'll set the Canvas dot height to be equal to the image dot height, and save. Now we can remove our hardcoded values from here, simply leaving in the image that we want to load on the starting position of the top left of the Canvas. If we now go over to the browser, and reload, we now see that the Canvas is stretching to be the same size as the image. So this is a basic overview of some things we can do with the canvas. Next, we will be making use of the file uploader, which we added at the top of the project just here, and we'll display the new image onto the Canvas using the same draw image method. 5. Uploading and displaying images: Welcome back. In this video, we're going to be using the file uploader, which we added in the HTML just here. We're going to be selecting a image of the computer and then displaying this as the image source on the Canvas. If you've already done so, head over to the script.js and then clean up our code by removing any of the examples from the last video. You can leave in this image section from the last video, as we'll also be reusing this code in this video too. The first thing we need to do is create a new file reader, this file reader object is going to allow us to read the contents of a file, or in our case, an image which is stored on the user's computer. Just above our constants of image, let's make some space and create new constant called reader. Set to a new JavaScript FileReader, so we'll come back to this in just a moment, but this will allow us to use the File, Upload the inputs. We add in the HTML, select an image, and then set this as the image source for Canvas. The next thing to do is to now grab a reference to this file uploader. In the HTML, in the input we gave this a id of uploader. We can now grab this in the JavaScript down at the bottom and store this in a constant called imageLoader and set this to be documents.getElementById. Then passing the Id of uploader. We then want to list now for any changes to this file input, we when a user adds a new image, would amount to trigger a function which is going to make all of this work. Add the imageLoader then.addEventListener, it's going to listen out for any events on our file inputs. The events that we want to listen for is the change event, this will be triggered when a new image has been uploaded. When this happens, we want to run our own custom function, I'm going to call this function uploadImage. Then we can go ahead and create a function above, so let's set up a ES6 arrow function, so const uploadImage and set this to an arrow function. There we go. This function is going to receive the events details which are passed over from this event listener. We're going to store this in the value of e so we can access this inside the function. If only passing in one value just like this, we can also remove the brackets. Before we set the FileReader, we is going to read the contents of the file of the users computer, so let's do a quick console log inside here, console.log, and we can check out the value of reader, give it a save and then over to the browser, open up the console. Then you can select the file of our computer. Lets go for these Iceland image once more and then open this up. Inside a here we can see the results of null. This is currently null because we need to grab the file data, which is stored inside this event here, and then pass this to the file reader for it to then read and then until we code in it. This file data which you have stored in this event just here. Well, this a variable is passed from the file which we'll upload, so let's do a console.log and the value of e and we can see how we can grab this image data to reload and then choose the file once more. Open this up, we can grab this file information if you open up the events and then scroll down to the event targets, which is this inputs. Then inside this targets, scroll down to files, files contains the data which we need for this image. Open this up and hit up position zero we can see we have all the file information, such as the name, the last modified, the dates, and also the size of the file, so now have all these file data see locked here. This needs to be read by something which can understand all of this. Unfortunately, the file reader has a method which we can use called read as data URL. This read as data URL method is used to read the contents of this uploaded file or this image. We'll go off to our function and set this now, remove the console.log, we can then access our read variable and then use the method of ReadAsDataURL. Inside this method would now need to pass in our file data, which we know was e.targets.files. We only have one file, so this is an index position of zero and this is the data we've seen before inside of this console.Log at position zero. Now once again, if we go ahead and do a console.log and the log the volume of reader once more, open this up choose a file, select our image and now we see the file reader now has a result. Open this up and this result is the image data which we now pass in. Right now have a result inside of a file reader rather than the value of null, which we seem for. Back over to our function, we can now remove this console.log. Inside here we now have the file data we need stored inside this reader, but now just need to add a onload function, so wait until the file reader is ready. Add reader.onload, set this to a arrow function. Then we can go ahead and copy the image section from earlier, which displays the image to the screen, so copy this full onload section, what if I cut it out of the project. Then we can paste this inside the file reader section. We can also grab this image source, so cut this out and then paste this just after the image.onload section, paste this in. Rather than adding a hard coded value of iceland.jpg we can instead set the image source to be the reader.results, which is the file data which we added with the file uploader. Now if we give this a save and then, over to the browser, refresh and then choose a file. Click on our image and there we go. Now we see the file has been uploaded and added to the Canvas as the image source. Hopefully this is working for you too. I understand there's quite a lot going on here, so let's do a quick recap, so over to the projects. The first thing we did is grab the file inputs and then stored it into a variable called imageLoader. We then listened for any changes using the addEventListener here. Listen for any changes, which will then go ahead and trigger a function called uploadImage, which we have just here. Then we created a FileReader variable just about the top here. This FileReader allows us to read the contents of any files, or in our case, any images which are stored on the user computer. When this uploadImage function runs, it then gets any file data pass to automatically. I will store it in a variable called e, all this can be any name which you prefer. This file info is then passed to our file reader using readDataAsURL, which will understand this image data which is passed to it. Finally, once our reader and image has finish loading, we then go ahead and set the Canvas width and heights to be the same as the image. We then place this image on the Canvas using the drawImage method, which we looked at earlier. Then we set the image source to be the final result. Great. This is a big part of our project now done. With our images now uploading, next we're going to learn about how to access all of the pixels which make up these images. Once we understand more about pixels, we can then play around with them to create our effects. 6. Understanding pixels: To understand how to manipulate images to under effects, helps me to understand how pixels make up our images. We can grab the pixel data from our canvas using a method available called getimageData. If we go over to our script.js, and then outside of our upload image function, I'm going to create a constant called imageData. It's going to be equal to ctx.getImageData, which we're going to use to grab all the pixel data from the canvas. We want to select the full canvas width and height. The first two values is the starting position, which I'm going to set out the top left-hand corner of 0, 0. We're then going to set the width of the canvas. Again, just like earlier, you can hack all this width a fixed value, such as 300 by 150 or in case the canvas changes in the future we can select the canvas.width and also the canvas.height. Let's see what we're dealing with a console log. As console log is the value of imageData, which is this variable just here. With that save and then reload. Open up the console and right-click "Inspect". Click on Console tab, and there's the value of our imageData. If we open up our imageData just here, we see inside this data here we have an array like structure, which contains 180,000 pixel values. We also see below we have our height and width of 150 and 300. This next part is really important to understand when working with pixels. If we go ahead and multiply our width and the height of the canvas, this results in a value of 45,000. Why instead do we get 180,000 values returned to us, which is exactly four times what we get here? Well, this is because each pixel on the canvas is made up of four channels. We have the red, the green, the blue, and also the alpha, which sets the transparency. If we go ahead and open up this data, this one here and open up these drop down arrows, we can see the results of each one of these 180,000 values. Currently each value is set to zero, this is because we have no image data loaded. We just see results from an empty canvas. For even though this is empty, the first four values, which is these first four zeros just here. This is one pixel and each pixel contains this red, green, blue, and alpha value. Each pixel has four pieces of data and this is a second satirist here. This is why we get to a 180,000 values rather than 45,000 which we've seen before. If you want to go ahead and see the actual pixel data, rather than only zero just here, we can grab these two lines or code here, put these out and then place them in our uploadImage function. So inside the image.onload section, we're going to add this just after the image has been drawn. Save this and then reload, choose our image, open this up. Then once our image is on the canvas, we then get this console log of ImageData. If we open up this ImageData, we can see this time we have more pixels than before. This is because the canvas width and the height has been set by the size of the image. Also if we go ahead and open up this data, which contains all the pixel data from the image and you can open up any of these which you like. Again, just like before, these first four values is the first pixel and then this is a second pixel just below here. The first value is the red and the green, the blue and the Alpha. All these values are between 0-255, just like when working with RGBA colors in CSS. If we scroll down, all of these four channels, seems to be 255. This is the Alpha, the Alpha and the Alpha here, which means that transparency is fully solid, whereas zero would be transparent. With this knowledge of how pixels are made up using the four channels, and knowing that we get four times the amount of values back using the getimageData, we will use what you've learned in this video by looping through these pixels and changing them to be different values. 7. Looping through image data: With this knowledge of how we can work with pixel data, we're now going to loop through all the pixels on our canvas and begin to make some changes to these values. The first thing we want to do over in this script.js is to create a new function which is going to grab our pixel data. We're then going to loop through it all and then change the values one by one. We're then going to place these values back onto the canvas with a new method called putImageData, and then this will display the results on the canvas which will then override the current image. Over in this script.js, let's go down to the very bottom. After our EventListener let's create a new function, so const. I'm going to call this change, create a function. Then inside here I'm going to grab our image data which we used before. We don't need this image data inside this function or this console log anymore. So let's cut the image data out of here, go down to our function of change and paste this in. In just a bit, we're going to link this Change button to one of our buttons on here. This is then going to go ahead and grab all the image data from the canvas and store it inside our variable. If you remember from before, we moreover need console and we output it to the image data. All of the pixel values was stored inside the property called data. That's set of a constant called data, and it's just going to be a short cut for our ImageData.data. After this we can then go ahead and create a for loop which is constantly through all of this pixel data you have stored here, and then we can select the individual values. So for. I'm going to create our variable of i, and set this to an initial value of zero. We'll then want to keep going while i is less than data.length. Ie, this is going to keep running while there's still pixel data available inside here. Then the next part is really important. We say i plus equal 4. Plus equal 4 will increment the value of i by four on each loop. We do this because as we already know, each pixel has four values: the red, green, blue, and Alpha. So incrementing by four on each loop will be the beginning of each sets of pixel data. Create our loop body with the curly braces, then we can go ahead and set the new pixel data, data i. I'll answer this to be any value which we choose, so let's go for 255. Data i will be the first value on each loop, so each set of four values in the pixel. The first one in the set is red. Data i will affect the red colors on the canvas. We can then go ahead and override the existing image just after this for loop with ctx. This time instead of getImageData, we're going to use putImageData, so place the new pixel data back onto the canvas. The data we want to place onto the canvas is our imageData. This is going to be at position 0, 0, which is the top-left of the canvas. All that's left to do is to grab one of our HTML buttons to then trigger this change function. Under the function we can select our first button with documents.querySelectorAll. Then we want to select our button, so inside the brackets we can add our button which is the name of our elements. Before in the Index page remember we have lots of buttons. Once you select the first one, which is our index position 0. I'll add zero inside the square brackets here and then we can add our EventListener to this button. We're going to listen out for any click events on the button, which is then going to run our change function. Add this in. If we go over to the browser, reload, and then select an image, open this up and click on our first button. We now see some changes have been added to the canvas. We now have a red color being applied. Remember from before we mentioned that data i is the first of the four values we can change. If you want to select the green rather than red, we can select "i plus 1", refresh, and then we can open this up once more. It's all in green, It's the maximum value of 255. Finally, let's try the blue which is i plus 2. This is the maximum value and load up our image once more and our first button. One of blues is set to the maximum of 255. Just so it's a little bit more clear what we're doing here, we can add a console log and then log our imageData, reload and open up the console, select our image, then click on over blue effects. If we open this up, open up our data, and select any of these values inside here. If we look at all of our pixel data here, we have red, green, and blue. This is 255, Alpha, then red, green blue again, which we set to 255, then Alpha. Red, green, blue, and then Alpha. If we scroll through all of these values, we can see that all now set to 255. Because when we we're looping through in sets of four, these are the four values which we are manipulating. I is the value of reds, i plus 1 is value of green, i plus 2 is value of blue, and i plus 3 is the Alpha channel. This is all we need to do to apply effects to our image. It's just the case of adjusting the color values of our pixels depending on which affect we want to apply. This is what we'll begin to do in the next video. 8. Greyscale, sepia and invert effects: With the knowledge we now have of adjusting the pixel values, we can now add some effects and link them to our buttons, just down here. First, let's go over to the script.js. We created a function which is looping through all of the pixel data on the canvas and then currently we setting the blue value to be the maximum of 255. Let's begin by changing this function to be our grayscale function, which is going to be hooked up to our first button. We also need to change the function name inside the event listener to match. This is a grayscale too. For the grayscale effect, we already have a lot of the data in place that we need to perform a task. I'm going to create a constant called gray. Inside of the for loop, create a constant called gray and we're going to set this equal to a value which is going to be a adjusted value of the red, green, and blue values. Let's select the first one of data I, which is the red. Also add this the green, so data I plus 1 and then finally the blue, which is data I plus 2. We go over red, green, and blue values all added together. Now to make the grayscale effects, we can alter these three values. For the red, I'm going to multiply this by 0.21. The green value, I'm going to multiply this by a value of 0.71 and then the blue, multiply this by 0.07. Now these values are up to you. You kind of a little play around with these and see which works best for you. But these are good for the general guide to how to make a grayscale effect. Now all we need to do is use this gray value and add it to our red, green, and blue values. Let's set the red to be equal to a constant of gray, and then add this in two more times. Our green value is I plus 1, and I plus 2 for the blue. Give that save and then if we go over to the browser, hit reload, choose our image and then hit grayscale and there's our grayscale effect now applied back to the image. The next one we're going to setup is the second button here, which is the CPU function. We're going to reuse a lot the same code for the grayscale effects, but we'll just add some extra red and green values to give it a warmer version of our grayscale. Over to our scripts, let's copy this grayscale function. Copy this from the bottom right up to the constant name, and then paste it in just below. We can call this one the sepia, which is S-E-P-I-A and then down at the bottom, if we duplicate this line for the event listener, this time it puts in number one, and change grayscale to be sepia. Now we need to work with our function. We can still use the average, so the only difference is we need to add some extra values to this red and green. We can still use it gray, which we setup inside the constants, but add some extra red values. I'm going to add 95, and for the green I'm going to add a value of 58. Again, you can play around with these and see which one suits you best. Give that a save, and now this is hooked up to the button, we can test this out. Select our image and the sepia effects and this is just like our grayscale function, but it makes it a little bit warmer and it's kind of has the effect of some old fashion photos which you may have seen in the past. The next one we're going to get to work on in this video is the invert function. The invert effect is also known as a reversed image. The colors are reversed, so for example, black will become white and so on. This will give the effect we used to see when getting the negatives after developing photos. To do this, we can copy the CP function, and then just below this, we can paste this in. Therefore, we can reuse a lot of the same code. We don't need this gray section on here. In fact we can also remove these console logs from before, so they should be in all three of our functions. Back down to the third one, I'm going to rename this invert and duplicate the event listener. This needs to be button number two, which is the third one in the list and then change the function name to invert. We're just going to work with the pixel data this time. We're not going to be adding the three values together, like we did with the grayscale and CP functions. Let's remove these three sections here. Some of the gray from all three lines and then to do this, we need to deduct each one of these three values from 255. So 255 and then denote data I, and then we need to do the same for the green. But this time it's I plus 1, and blue is I plus 2. Let's start opening the browser, so save and then refresh. Pull up our image, and let's try invert and that's it. The invert function is working correctly too. Good, we now have our first three effects working. In the upcoming video, we'll be creating more effects by swapping around the red, green, and blue values along with this clear button at the end, which will remove any of the effects and reinstate the original image. 9. Adding additional effects: For the final four effects which we're going to add to this photo editor, is just a case of swapping around the red, green and blue values when we loop through each one of the pixels. So for example, this is going to be the first function which we are going to be creating, which is going to swap the red, green and blue values, to be a value of red, blue and green. So we're effectively swapping the blue and green values around but its particular function. Will then swap the red, green and blue values to be equal to blue, green and red and then to green, blue and red and green, red and blue. Let's start with this red, blue and green version, by copying our inverse function. We can paste this in just below and changes to be a function name which matches of red, blue, and green, or RBG for short. We can then make sure that this button is hooked up to our function. This is the third button. It's also a click event listener and RBG, which matches our function name. So let's begin by removing the 255 values which we used from the inverse function and now it's just a case of swapping around these values. As we can see from the button name, the value of red, which is the first value, is going to remain the same for this function. So the data i is still going to be equal to data i. All we need to do is swap the green and blue values round for the second and third line. So the second line, we need to change around, so this is currently equal to green and we want to assign this to be the value of blue, which is going to be i plus 2. The third one now is a little different, currently we have the blue value set here and then we want to reassign this to be the value of green, which is i plus 1. However, just above, we've already re-assign the value of one to be equal to two, so we need to store this value inside of a constant, so it's the same as it was originally. We can do this at the top of our for loop, we can set a constant equal to the value of green, which is going to store the original green color, which is available from data i plus 1. So now we can change this and we can reuse this inside of our loop. So now the blue color is set to be the original green color before we've reassigned it on this line here. This is all we need to do now for this function, so give this a save and if we go over to the browser, we can try this out with our picture. Click on our button and the colors are now being swapped out. We now see the blue and green values are being swapped around, leaving a nice looking effects. Let's now do the same for our final three effects. So let's copy this function, paste this in just below. This one is going to be for BGR. Let's change it around the first value, which is currently red. We want to set this to be the value of blue. We can grab this with i plus 2. The green value this time is going to stay the same, so this is i plus 1, so the third value, which is blue, we want to swap this out to be the color of red. Since again, we already reassign in the red value, we need to store the original value from our loop and the red can be accessed with data, i. Swap out our variable name, we'll hook this up to the button in just a moment. For now though, let's copy this and add in our last two functions. The second last one is going to be the values of green, blue and red. So to begin, we want the green value on the first line and green is i plus 1, we then want blue and we can set this to be i plus 2, which pops out our green and blue. The third value is the red color, which we already have set from the last function, so we can leave this as it is. Remember we don't want to set this to be data i, which you see here because this value has already been updated with the value of i plus 1. So here we are grabbing the original red color from our loop and then possibly seen as our value. The last one we need to add if we copy this is going to be our last effect of the projects and this is going to be the color value of green, red and blue. The first value you want to grab is green and this is okay since this is from i plus 1. The second one is a value of red, which again, we already have stored inside of our constants. The last value is for blue and we can grab this from data i plus 2. Down at the very bottom, we can link these to our functions, so we've got the RBG value, let's paste this in three more times, so we've got RBG, the second one is BGR, we then have GBR and then finally GRB. Then change our button numbers which we're targeting, so four, five and six, save this and over to our projects, let's select our image and we can test this out. We've already tried the first one, so let's go for blue, green and red, that works fine. Let's try out the second, the last effect. Okay, good and then finally the green, red and blue and this gives us some nice looking effects to our image. It's a little bit inconvenient selecting a new image each time we want to try out a new button but in the next video we're going to link up our clear button to restore the image back to the Canvas. 10. Clearing effects: The final step for this project is to add the functionality for this clear button. This will remove any effects and reinstate the original image. Doing this is pretty simple. Again, we'll write a function which will be triggered when this clear button is clicked. This will access the file reader's original results and set it to be the image source. Let's go ahead and create a function. So just after our last grb function. Let's create a new function called clear changes, set this to an ES6 function. Then what we need to is access the results of our file reader. If we go up to the top of all functions, and we'll go back to the start of our code. If you remember from earlier on in this course, we set the image source for the covers to be equal to the reader.results, which is just here. This holds the information about the original image. All we need to do is go back down and set the image source to again be equal to the reader.results. Scroll down. Inside of our clear changes function, all I need to do is again insert that the image.source to be equal to this reader.results. Then link this to our clear button. Add a new button, which is number seven. This is going to be called clear changes. If we go up and do a console log, and we'll add the value of our reader. Let's just comment this out. Reload. Open up the console. [inaudible] all images. If we click the clear to trigger the function, remember we have our image stored in these results here. This is why we use reader.result. I'll give that a save. We can remove the console log. Now you close the console down, select our image. If we add any effects, we can now click on the clear button. Then this resets the image back to the original form. This works with all the buttons. So this is our project completed. I hope you had some fun and learned some new things along the way. Feel free to go ahead and customize the look and feel of the app. Even go ahead and create some additional effects. Bye for now, and thanks for taking this course. 11. Thank you!: Congratulations for reaching the end of this course. I hope this course has given you a better idea of how HTML, CSS and JavaScript can all fit together to create a useful and fun project. We've covered quite a lot in this course from JavaScript fundamentals such as loops, functions and constants right through to more specialists things such as handling file data, manipulating pixels and also drawing to the Canvas. We began by creating the user interface and applying some basic styling and then it was all about using JavaScript from learning how to draw to the converse, uploading images and also reading file data. Through out the learning involved looping through pixel data and how to change the values. Thank you from me for taking this course, I hope you've learned some new skills along the way and also enjoyed building these projects. 12. Follow me on Skillshare!: A huge congratulations from me for reaching the end of this class. I hope you really enjoyed it and gained some knowledge from it. If you've enjoyed this class, make sure you check out the rest of my classes here on Skillshare, and also follow me for any updates and also to be informed of any new classes as they become available. So thank you once again, good luck, and hopefully I'll see you again in a future class.