So welcome to Unit 6.6, in which we are going to talk about graphics. And in particular, we are implementing the Jack operating system. And the class that is relevant to this module is the Screen class, which we are going to use to handle all the graphical operations of our programs. And in particular, we'll talk about this library, that features several basic operations for a drawing figures and pixels on the screen. And what we'll do in this unit and in the next one, is we'll explore some of the more interesting functions in this library. Now before we do this, I would like to say some general words of introduction about the notion of Graphics. And let us begin with this, with these two figures here that look identical, right? What we have here is Donald Duck trying to understand how computers work in a more direct way then what we do in this course. So the first thing that we'll do is we'll remove the computers so they don't get harmed. And then let us begin to zoom in on Donald Duck. And you will notice that as I zoom in more and more, a glaring difference between these two images reveals itself. And the difference is that the image on the right does not scale nicely, whereas the image on the left scales up perfectly. And the reason for these differences in these graphical effects is due to the fact That the two images are stored using two different techniques. The image on the left is managed using what is known as vector graphics, and the image on the right is an example of bitmap. And what I'd like to do in the next few minutes is discuss the virtues of every one of these techniques. And in particular, I want to focus on vector graphics. So here's an example of some portion of the screen, and let's say that I want to draw this cup on the screen. Well, I will draw it somewhere, it doesn't matter exactly where. And I draw it by simply turning on and off pixels, which is what we can do in Jack, right? In Jack, I'm sorry on the Hack computer, we don't have colors, we have only black and white. Although we can easily add colors, but perhaps not in this course. And so this is the way the cup is going to be drawn on the screen, and here is the bitmap file which is going to store this image. So what I do here is something which is very straightforward, for every pixel which is white I store 0, for every pixel which is black I store 1. And I get a bunch of numbers that, taken together, give me a one-to-one correspondence between the figure and the binary digits. So that's bitmap. If I have an image that consists of a million bits, I'm going to have several hundred of thousands of such tuples in this file. Now here is the very same image stored in vector graphics. Now as you see, instead of actually recording the information in this figure, what I record is set of instructions that specify how to draw the figure. So the first instruction is, draw a line from 3,0 to 11,0, and this will give me the top row of the cup. Then I take advantage of the fact that I have a large rectangle, so I draw a rectangle from 3,1 to 9,5. And so in one shot I describe how to draw, I think 35 pixels, and then I keep on drawing a few more lines in order to complete the specification of this cup. So what are the advantages of vector graphics? Well, if you try to scale up these two cups like we did before, you will notice that the big map doesn't scale up properly. All we have is these bits of information, and therefore, we can try to use all sorts of opportunistic algorithms that compute pixel averages, and so on. But the result will not be satisfying at all to the human eye, whereas in vector graphics we get perfect scaling. Why? Because we have a set of instructions. And if you want to draw the cup on a different resolution, or on a different screen size, all you have to do is manipulate these numbers using some simple proportional constants. And boom, I'm going to get the perfect figure drawn in any resolution that I desire. So, in a nutshell, the vector graphics technique has several very important advantages. First of all it contains relatively little information, because I don't have to record the pixels. I have to record instructions on how to create huge expanses of pixels, and so it doesn't take a lot of space on the disk. And for the same reason I can easily transmit vector graphics images over the internet, because the files are relatively small. And when I get to render this figure on some screen, I can easily scale it up or down. And this is extremely important in a world that is characterized by many different screen sizes. I mean think about cell phones, think about cameras, think about laptops, tablets. It doesn't matter what the target screen is, I can always scale it up efficiently and effectively. And finally, if you like bitmap, well I can always turn it into bitmap. So all together, vector graphics is a very important invention, and that's what we're going to use in our operating system as well. And in particular, the three primitive operations that we're going to explore is, how to draw a single pixel, how to draw a line, and how to draw a circle. And we'll begin with drawing a pixel. Now I must say that there's something which is slightly inaccurate here, draw pixel is something which is, Which is needed, both in, vector graphics and in bit map, right, in bitmap, you also have to draw pixels. So this is perhaps the most fundamental and primitive operation, and I should've put it in a class of itself. Because, drawpixel is absolutely primitive and basic, and on top of it, we can create either bitmap or vector graphics figures. All right, so let's begin with drawing pixels, how do we do it? So I wish to remind you that, when we built the Hack computer, we decided to allocate a certain segment of memory for representing the screen. And basically we took a chunk of 8k registers and we call them the screen memory map. And the contract is such that, if we want to draw some pixels on the screen, we turn on and off various, carefully selected bits in the Memory map. And then the image will be drawn automatically, quote unquote, on the screen. Now how does this work? Well, it works because there is a contract, yet another contract, which is realized by the hardware, which is called refresh, or screen refresh. And the contract is such that, several times each second, there's an automatic and routine refresh. In which the computer is going to take all the bits that it finds in the memory map, and commit them to pixels, which it is going to draw on and off on the physical screen. So that if you want to draw this figure here, once again, we actually draw it in memory, and then everything else is taken care of automatically by the refresh routine. So for example, suppose I want to draw this particular pixel, the pixel which is characterized by 450 and 200. How do I draw it? Well, if I write in Jack, I will probably use something like this command here, drawPixel(450,200). And of course, someone has to take care of this operation, and this someone is the operating system. So the operating system, in particular the OS screen class, is going to have an implementation of the drawPixel routine. And when drawPixel will be asked to draw this particular pixel, here is what it will do. It will figure out somehow that the word that we have to manipulate is word number 22812. And it will also figure out that within this word, we have to turn on the third pixel, or the third bit, from the write. Now, how will it make these calculations? Well, if you will stop the tape and think about it on your own for five, ten minutes, you will be able to easily come up with the mapping. Because, see on the right-hand side on the screen, we have a representation which is 512 pixels wide and 256 pixels deep. And the left we have a RAM which is so many words long of 16-bit words. So the mapping between the two-dimensional space that we have here, and the one-dimensional space that we have there, it's quite straightforward. And if you work out the math, you will discover that here's what you have to do. The address in the RAM of the word that we have to manipulate can be found using this multiplication and addition. And then what we do is, we go to the RAM, and we retrieve the value, which is currently located in this address, plus the base address of the memory map. So, now we have this value in our hand, right? The next thing that we do is we set x modular 16 bit of this value to the current color, which is either one or zero or whatever it is that we wanted to draw. And after we make this manipulation, we take this value, and we store it back where it belongs in the RAM. Now you may ask yourself, why did they bother to first read, and then write? Why didn't they just go in and manipulated this bit directly? Well there are two reasons why I did it, first of all you simply cannot manipulate bits directly, you must operate in chunks of 16 bits. Or if the computer is 64 bits wide, you have to operate in chunks of 64 bits, that's how computers work. So you have to manipulate a whole byte, or a whole word, in order to end up manipulating a single bit. And the reason we had to read it first, is also due to the fact that we may have some other things drawn already in the vicinity of this bit. I mean look at the picture here, We have this little man standing there. And if we just go on and manipulate the bit using the 16 bit operation, we might mess up images which are in the vicinity of this bit. So by reading this bit, I'm sorry, by reading these 16 bits first, and then manipulating only the bit that we have to focus on, without touching the rest of the bits, we are writing this bit safely. And so we retrieve these 16 bits, and then we'll probably use some 16 bit OR operation to add up what we have here with a single bit that you want to manipulate. And then we write it back to the RAM, and the result will be turning on this specific pixel on the screen. So that's how the magic of pixel drawing works, probably slightly more complicated than you thought. Now, notice that the drawPixel subroutine, which belong to the screen class, makes use of the peek and poke subroutines which belong to the memory class. And the memory class of course is something that we've already implemented in previous units. And this is quite routine in operating system modules, this interdependency of one module using another, and that's an example of this interdependency. So we talked about drawPixel, and in the next unit, we'll teach you how to draw a line.