[Intro] Hello fellow Scratchers!
Question – How do we detect the colour of a pixel in Scratch? Now sure, if we know the colour we are
looking for, we can just ask Scratch directly. Using a tiny costume as a colour detector,
position it at the mouse-pointer when space is pressed, and then IF we’re touching this exact
orange colour, we say “Orange!”, otherwise, meh! Excellent, that works a treat, and we can extend
it to add in more colours… But, what if we don’t know what colours to expect, did you know that
Scratch can display over 16 million unique colours! I don’t suppose you fancy adding an
IF ELSE check for each and every one right? No, me neither… But there are times when we could really
do with being able to do this! Like if I wanted to pick a colour from an image and draw with it?
We’ll be coding that up today… Or if we want to scan and manipulate, not a single pixel of colour,
but an entire screen? Now things start to get wild! Just wait until episode two where I will
show you some amazing new ideas that have recently revolutionised full screen image
scanning in Scratch – It’s mind blowing! But, we must start simple, so are you ready for this!
Great – let’s get Scratching! [RGB Color theory]
So a little bit of RGB color theory – Take a look at this little pen project, feel free to
copy it and have a play – I’ll put a link to it in the video description. You’ll see we have these
three sliders, one for each of the red, - green, - and blue colour values. Now when mixed together,
we can create any one of the 16 million different colours that Scratch is capable of displaying.
You’ll see the maths expression for calculating the combined colour value is given here…
We add together the three values of red, green and blue, but ensure to first multiply red
by 65,535 (that’s 256 squared), and green by 256, and blue stays as it is.
Once summed, the resultant colour value can be used in the set pen color block as we are here,
or, as it happens in a touching color block too – And that is going to be very handy indeed!
[Beginner Level – Brute force 16.7 million Colours]
So, back to our colour detection project, We have a tiny sprite, it’s costume is just a simple 2x2
pixel square, centred on the drawing canvas. When the space key is pressed,
this tiny costume goes to the mouse-pointer ready to check for touching colours.
Now we can use an IF touching color, but instead of using the color picker to choose the color,
we can create a new valiable, named “color”,
for this sprite only, and drop it right into the touching color block like that! Funky.
We start by setting this color to 0. And then use a repeat loop to cycle
through all possible colours. 16 million right? But we need to be accurate here,
Multiply together 256 shades of red, with 256 shades of green and 256 shades of blue. Gosh
yes - 16,777,216 colors to test against!?! Wow… Well here goes nothing, drop in the touching color
check. And each time around the loop we change color by 1 so as to keep trying the next color.
That’s the loop sorted. Let’s drop in a say block for when we find the matching color,
why not just say the color value for now. And to finish it off, we stop this script.
There’s no point continuing this huge loop if the desired colour has been found.
Ok!!! Shall we give that a test? Mouse over the red hat, and press space… And it’s
off… You can see the color variable simply flying through the possible colour values…
Nothing has matched yet. Let’s see it full-screen. 16.7 million checks… That’s a lot…
Ok… I’m skipping the video forward. And… There! Success, this was colour value
15,738,896, and it took Scratch a whole 59 seconds to find it!
Gotta say, I’m very pleased we did find the colour,
but a little disappointed at how long it took! But gosh, what could we do to speed this up?
[Colour Sensitivity] Well… knowing how Scratch’s colour detection
works can guide us to some sweet optimisations. Turns out that although Scratch can display
16 million colours, it cannot actually detect all 16 million of them, it’s not that sensitive.
Therefore testing every colour is actually wasteful and unnecessary. To show this,
you’ll find we can still detect every colour even if we skip along by 16 at a time.
Let’s give it a go; Trying a green…
Oh wow – Did you see how fast that was? Perhaps I was lucky with the colour.
Try again with a bright red. Ok yeah – Do you think that was like 4 seconds?
Whatever it was, it was MUCH faster than the full minute it took last time.
[Define Get Color and Pen] So with that initial success,
and before we go further, let’s make our script more official. Make a new custom block,
naming it “Get Color” and make sure to tick the “run without screen refresh” box.
We’ll drop everything from the set color block under the new define script, and drop the new Get
Color block from where they came. Splendid. And now that we are getting colour values
back from our Get Color script, it would be nice to be able to see the colour that we’ve picked.
We can do this by enabling the Pen extension.
Usefully, the “set pen color” block accepts the same color values as the touching color block,
so we drop that variable in here to match the found color.
So we can set pen size to 50, I want to draw a circle at the top right of the screen using the
picked color. Go to x of 210, and y of 150. Then pen down to draw, and straight away, pen up.
If I click the script, there we go, it’s drawn in the color we last picked…
And since we can see the color, we won’t need this “say block” any longer.
Oops, don’t forget to join up these scripts… And then let’s give that a test.
Super cool – We can click around, and yeah, the colours are definitely the right ones
– nice to be able to confirm that! [Red, Green & Blue]
So, back to our Get Color Script. When we skip by 16 here, what we are doing is actually skipping
just the blue colour channel. But, the green & red channels are just as viable for skipping
so I’m really positive we can get this running faster still. But skipping the other channels
is not quite as straight forward to explain without perhaps starting this script over again.
Create three new variables. “red” for this sprite only, “green” for this sprite only, & “blue”
also for this sprite only. We begin by setting red to 0.
Then we can loop over all 256 values of red, with a change red by 1.
We can do the same for green.
And again for blue. Great, so let’s put these together.
Begin with the red outer loop. Then the green loop goes inside,
but above the change red block. And blue, inside that,
again above the change green block. A loop, within a loop, within a loop.
If we run that (and hit space), we see Scratch blasting through all possible values of red, green
and blue. This will be once more cycling through all 16 million combinations of the three colors,
but… the color variable is not yet being calculated. We need this for
our colour checks, so we need that color maths. Start by setting color to blue. To this we add
green multiplied by 256.
And lastly we add to this the red variable,
multiplied by 256 * 256 (or 65,536 if you like) And that’s it, that will give us our color value,
so this will test the colour as before. But note, we were previously skipping by 16, and now we’ve
gone back to adding only 1 to our blue variable? So this is why I said previously we were only
skipping blue values. Blue is the innermost colour in this loop. Once again then we should change
blue by 16. And of course if we are skipping by 16 each time, we don’t want to be repeating
256 times any longer. Work out how many times to repeat by dividing 256 by the skip value 16.
And safely drop the detection script in before we change blue.
Cool!!! Let’s run the project! Now pressing space on a red colour and we wait.
See the red, green & blue variables spin… And there, we found our colour,
and you can certainly see as expected, that the red component of the colour is much
greater than the blue and green channels. Sweet. Try it on blue… Wow, blue is always a lot quicker
isn’t it. It’s nice seeing the colour breakdowns. [Skipping the Red and Blue channels too]
So now that we have split apart the different channels, it’s easier to put in the separate
skips for each one. I have a good feeling that this will really speed things up, so I’m going
to put in a stopwatch timer. Just reset timer when key is pressed, and then with a new variable
TIME. Set time to timer at the end. Let’s just confirm the speed for the colour red…
Yeah 4 and a half seconds! So, can we beat this by adding further skips.
Come down to the bottom of the Get Color script. So simple now. We just need to change
these two skips. But be careful, unlike the blue channel, the red & green skips must be set to 8.
Scratch is a little more sensitive to these colours than blue it turns out.
And we scroll back up, and adjust the repeat loops.
These are now both 256 divided by 8 skips. Yeah! Excited to give this a try!
So can this beat a time of 4 and a half seconds.
I’ll press space on red… wait for it… wait for it… Umm… is it
working? Hold on!!! Wait it’s already finished, I missed it. And the time is reading 0? What the!
This is outrageous – Now don’t get too excited, this doesn’t mean it’s running instantaneously,
it is still taking some time, only the timer reporter is not detailed enough to give us
the real speed readout. However, wow, it is so much faster than it before right? So cool.
[Further Optimisations] Right, let’s talk further optimisations.
Everything we do in scratch takes a little time, so these divisions, we can simplify… 256/8 is 32.
Same for this one. And 256 / 16 is 16. Then we have a 256 * 256… That is, 65,536.
You may have already thought using “change color by” blocks here wasn’t that efficient.
We can replace these with additions. The only reason I code them like this is to prevent my
lines getting too long. We’ll need two additions.
And then color is red * 65536, + green * 256, + blue.
So that’s a little long, but not too bad I guess. Stuff it back in to the main script.
There, so that’s a little neater… But it won’t make it a whole lot faster I’m guessing.
[Most Concise] To get this as fast as possible,
perhaps we can rearrange these loops to avoid having to do all this maths in the
first place… It may not be quite so obvious what it’s doing, but it’s worth seeing.
So we’ll go back to resetting the color variable at the top of the script.
Next we bring in each of the three loops, a repeat 32, 32 & 16.
Then the color check comes next, but instead of changing the blue variable,
we are going right back to change the color variable. Again by 16. So as we know now, that is
updating the blueness of the color. Now, to skip greens, we will change color by,
and because greens are multiplied by 256, this would be 8 * 256… except, we’ve already changed
colour by 16 * 16, that’s 256 itself, so taking that into account, we only move on by 7 256s.
Splendid – We can do just the same for the red channel too. change color by 7 * 65536.
If we test that now…
Yep, that works just as well. And it’s a far more concise a script without the need for any of the
red, green or blue variables. Pretty neat! So that is our completed script. It’s perfect
for coding up paint packages, I’ll quickly add some painting
scripts now just to show you what I mean. Just loop forever, waiting for the mouse down.
Then set the pen color, set the pen size, and pen down. We are drawing. Repeat until the
mouse is no longer down, and keep moving the mouse-pointer to draw the lines.
Then after the mouse button is released, we pen up.
Just before we test, you may want to stuff a hide block at the top here
to avoid accidentally dragging this sprite around the stage… anyhow, let’s test full screen.
Here we go, I can paint in the current pen color… Then pressing space on a red colour,
now I can draw in red! Yay. And blue… yep… Any colour we can see, we can paint with.
Kinda means we can touch up a photo, by using colour matching like this.
Very fun! Very fun indeed! Why don’t you drop me a comment under the video to let me know what you
could imagine doing with this get color block! Better still, if you create something awesome,
then there’s a Scratch Studio linked under the video description,
please comment your project in there and then we can all enjoy seeing what you have made! So fun.
[Next Episode] Sadly that is where I need to finish this episode,
Now that we have a working colour detector, we are all set to begin looking at image scanning.
Taking the colour of every pixel on the screen and storing it for use later on. Problem is, image
scanning requires us to detect the colour of every pixel on the stage, that’s 172,000 screen pixels…
So even a fast color detector like this one will take a long, long time to scan a whole screen.
But, fear not – We have some amazingly clever scripting ahead that will make scanning so much
faster you will not believe it! [Outro]
Well I hope you enjoyed this episode, it was really just a grounding, and as I say,
the real fun is yet to come! But if you are excited for part 2 then smash that like button
and subscribe & click the bell icon so you don’t miss the next episode the moment it comes out!
If like many other Scratchers you just can’t wait to see what’s next,
then you too can join the early access channel membership. There’s all sorts of perks to be had,
and we’d love to have you on board with us :D. Ok, so that’s it from me today,
I hope you have a great week ahead, and Scratch on Guys!