Outline
In this week’s lab you will:
-
create a new social-networking platform for sharing pictures of cereal
-
???
-
profit!!!
But seriously, you’ll:
-
keep practising your “loop a function over some objects” skills
-
learn about image processing in p5
Pre-lab checklist
Before you attend your lab session, make sure:
-
you can fork, pull & push to GitLab
-
you understand the basics of objects: especially what properties and methods are (as covered in the week 5 lecture)
-
you’re aware that all the p5 functionality to do with images is bundled together inside the
p5.Image
object (see the reference for a refresher)
Introduction
Find a partner in your labs Teams channel! If someone has advertised themselves but not found a partner, reply to their comment and a tutor will set up a meeting for you to collaborate in. If no-one is currently advertising, make a message advertising yourself. There isn’t going to be much actual pair-work today, but it’ll still be nice to have someone to bounce ideas off of while you’re working!
We (humans) are visual creatures. We drew pictures of antelopes on cave walls for a long time, and then we invented the internet and now we have instagram1. And you know another thing that humans like doing? Eating breakfast cereal.
Send a message to your labs Teams channel—how could you exploit people’s love of pictures and eating cereal to make 1 billion dollars?
Since you’re in lab 8 now the lab content won’t hold your hand quite as much as in earlier labs. But if you get stuck, don’t feel like you have to just sit there and do nothing—ask your partner for some help, or message one of your tutors. Remember, we’re all on this learning journey together.
Fork and then clone the lab 8 template repo, open it in VSCode and start the live server as usual. You’ll notice there’s a number in the bottom-right corner of your sketch—this is part of the template. It’s showing the current frames per second reading (FPS) so it’s an indication of how smoothly your sketch is running. If everything’s going fine, it’ll hover around 60.
Part 1: setting the scene
Yep, that’s right, we’re going to create a new social network (or at least the interface for one). This social network is called Instagrains and the motto is:
Bringing people together. Through cereal.
Inspiring stuff. Because the motto is about bringing people together, you’re going to need a way to show where the people are—i.e. a map.
Using Google image search, find
a map of Canberra/Australia/the world (your choice) to use as a “backdrop” for
your Instagrains sketch. Make sure that the image is available under a suitable
licence (e.g. creative commons). Once you’ve found one, save it into your
assets/
folder (you’ll notice there are bunch of other image files in there as
well—you’ll use them soon but just ignore them for the moment).
You know the background()
function you’ve been using all along? Well, you can use an image as your
background (instead of just a plain colour).
In your sketch, create a new p5.Image
object using loadImage()
and pass
it as the argument to
background()
. Remember to
declare a variable (call it whatever you like) to keep track of this image
object.
Here’s a hot tip—try creating the image object inside the
preload()
function instead of the
usual setup()
one. They both happen
just once at the start of the sketch, but the preload()
function is a bit
nicer for things which take a bit of time—they present the viewer with a
“loading…” message, which is better than a blank screen.
One of the challenges with image loading (or other heavy processing in p5) is
that from a responsiveness perspective you want to do all the time-consuming
“loading” work at the start (so that once the sketch is running then it runs
smoothly). However, one problem with the
preload()
and
setup()
functions is that they’re
called before p5 knows the width
and height
of the canvas, so those
variables are set to 0
at that time (this may have caused you problems in the
past). One way around this is to use
windowWidth
and
windowHeight
, which are
defined in preload()
and setup()
. Can you think of other solutions?
Once you’ve got your background image filling your whole canvas, remember that it’s a background image, so you don’t want it to stand out too much. One way to deal with this is to do a bit of image processing using one of p5’s built-in image filters. These are methods (functions which are properties of the object itself) so you’ll need to use the dot syntax to access them, e.g.
bgImage.filter(BLUR, 10);
There are a few different filters available (and the parameters mean different
things for each one). Have a look at the
reference for the full list, although
remember that you want to call the filter method on a
p5.Image object (e.g.
bgImage.filter()
), not the plain filter()
function (which applies the filter
to the whole canvas)
Once you’ve got a subtle, not-too-distracting background for the Instagrains interface it’s time to move on to the next part.
Part 2: share your cereal with the world
The basic component of Instagrains v1.0 is called a grain, which is just:
- a photo of some cereal
- the location of the person who’s eating it
That’s it—pretty simple, hey. It’s all about the MVP.
Send a message to your labs Teams chat—what can you tell about how the interface is going to work when you’re done? What parts do you think you’ll be implementing in today’s lab?
Someone else on the Instagrain team has already implemented the “upload the
photo” functionality, so the image files are already in the assets/
folder (as
.jpg
files). Your job in this part is to write the code to draw these photos
on the map background you made in part 1.
If you look at the top of sketch.js
, you’ll notice an array of strings—each
of these is the filename of a “cereal bowl” image in your assets/
folder.
createGrain()
You’ll notice that there’s a createGrain()
function “skeleton” provided in the
template—it doesn’t do anything at first, but your job in this part is to
write the code so that it:
-
takes a
filename
andx
andy
parameters as input (this is already there in the skeleton) -
loads that image from the
assets/
folder -
returns an object which contains all the stuff essential to using the grain in the future
The template contains code to call createGrain()
every second to create a new
grain (as long as there are still new pictures of grain bowls).
Fill out the createGrain()
function in the template so that it actually does
something useful (although you won’t see it on the screen until you write the
drawGrain()
function—which you’ll do next).
drawGrain()
The createGrain()
function doesn’t draw the grain on the map. That’s
drawGrain()
’s job. This time there’s no skeleton—you get to write the full
function yourself.
What arguments should the drawGrain()
function take?
Write the drawGrain()
function. Once createGrain()
and drawGrain()
are
working together, use a for loop over the grains
array to draw them all on
the map.
Once you’re drawing your grain bowl pictures on the map, then Instagrain v1.0 is done. Congratulations!
Part 3: make it interesting
You can probably think of lots of ways to make this better, though. Here are a few ideas, but don’t feel limited to this list. If you come up with some other cool idea then you should try to build it—ask your tutor for ideas on how to make it happen if you’re not sure how you’d do it.
-
make each grain show up in a particular place that you choose
-
make the interface change over time (so it’s not so static)
-
add filters (i.e. can you do some image processing on the grains)
-
make it so that when you click on a grain bowl, something happens?
-
add captions (maybe even hashtags) for each grain bowl
-
cycle through multiple images for each Instagrain user (i.e. make a gif)
-
add sound to the sketch (if you do, remember to add the p5.Sound library to your sketch
-
re-design the interface to make a statement about how ridiculous it is that we spend so much time and energy looking at pictures of food on our phones
As you try things, watch the “speedo” in the bottom left-hand corner—are there some things in particular which make the frame rate drop?
Break it down: scintillating pixels
An alternate way to do image processing is to get and set the colours of the
individual pixels directly. p5.Image
provides two methods for doing this:
-
.get(x, y)
returns the colour of the pixel at positionx
,y
-
.set(x, y, color)
allows you to set the colour of the pixel at positionx
,y
Scintillating Pixels is a famous2 sketch by Tim Brook which uses a couple of nested loops to create interesting pixel patterns:
Don’t be fooled by the simplicity of this code. I’ve seen people do amazing things with it. In fact it was run as a contest when Kieran took COMP1720.
What are the advantages/disadvantages of this “direct pixel manipulation” approach vs the built-in image filters you used earlier in the lab?
Summary
Congratulations! In this lab you:
-
practiced your “loop a function over some objects in an array” skills
-
learned about image processing in p5
-
created a new social-networking platform for sharing pictures of cereal and made the world a better place
Remember to commit your code and push it up to Gitlab, and log out of the lab computer. If you made a real difference in the world, you can share it with your friends using the test URL: https://comp1720.cecs.anu.edu.au/uXXXXXXX/lab-8/
-
I think a few things happened in the middle as well, but hey—this isn’t a history course. You’ll have to go somewhere else to learn that stuff :) ↩
-
famous by COMP1720 standards, anyway ↩