Processing can do more than just draw shapes, it can also load images, vector files (from Illustrator but in SVG format), fonts, and sounds.
Media needs to be stored in a special folder relative to the sketch .pde file called data
. We haven't really touched on this before, but you may have noticed that when you save a sketch, Processing puts it into a folder with the name of the sketch. So, if I create a sketch and save it as my_sketch
, Processing saves a file called my_sketch.pde
in a folder called my_sketch
When you want to add media as part of your sketch, you can choose the media from Menu > Sketch > Add File. Let's try that, but first here's a folder of stuff we can download from processing.org to get our media from...
Create a new sketch, save it as test_image
. Choose Menu > Sketch > Add File. Add lunar.jpg
from the folder we just downloaded. Now look in the data folder in the test_image
folder.
Processing automatically put the image into the data folder. Handy!
To get an image to display in the Display Window takes four steps:
PROCESSING
Example 7-1: Load An Image
PImage myImage; void setup() { size(480, 120); myImage = loadImage("lunar.jpg"); } void draw() { image(myImage, 0, 0); }
loadImage(imageName) - be careful with the image name, better if you don't use spaces (in general), and capitalization matters (unlike Windows or OSX).
image(imageObject, xLocation, yLocation) - imageObject has to be the variable you created with the PImage datatype (PImage as in Processing Image). It's fairly common in coding to have special datatype variable into which you put, through a specialized function, an object of a particular nature. (Other examples are PFont, PGraphics, PShader, and PVector)
Let's do the same as the previous but with two images. You can add as many as you want, but you have to stick them in a PImage variable with loadImage()
PROCESSING
Example 7-2: Load More Images
PImage myImage1; PImage myImage2; void setup() { size(480, 120); myImage1 = loadImage("lunar.jpg"); myImage2 = loadImage("capsule.jpg"); } void draw() { image(myImage1, -110, 0); image(myImage1, 130, 0, 240, 120); image(myImage2, 300, 0, 240, 120); }
Because you can set the x and y locations and the width and height of a given image, you can change them dynamically in the draw() loop.
PROCESSING
Example 7-3: Mousing Around with Images
PImage myImage; void setup() { size(480, 120); myImage = loadImage("lunar.jpg"); } void draw() { background(0); image(myImage, 0, 0, mouseX*2, mouseY*2); }
GIF and PNG images can contain transparency data. In a GIF file, any given pixel can be opaque or transparent, in what's called 1-bit transparency. PNG images, on the other hand, can contain a range of opacity/transparency from 0 (completely transparent) to 255 (completely opaque), known as 8-bit transparency (28 = 256). This layer of transparency values is called an alpha channel
.
Let's put a transparent GIF in front of another GIF...
PROCESSING
Example 7-4: Transparency with GIF
PImage myImage; void setup() { size(480, 120); myImage = loadImage("clouds.gif"); } void draw() { background(255); image(myImage, 0, 0); image(myImage, 0, mouseY * -1); }
PNGs have alpha channels and are a lot less clunky/chunky than a GIF.
PROCESSING
Example 7-5: Transparency with PNG
PImage myImage; void setup() { size(480, 120); myImage = loadImage("clouds.png"); } void draw() { background(255); image(myImage, 0, 0); image(myImage, 0, mouseY * -1); }
Fonts are the most reliable when you load them into the Processing environment explicitly. You use PFont to spec the datatype for a variable, then load the .ttf font into the variable with createFont(). Make sure the font file you want to use is in the data folder!
PROCESSING
Example 7-6: Drawing with Fonts
PFont myFont; void setup() { size(480, 120); myFont = createFont("SourceCodePro-Regular.ttf", 32); textFont(myFont); } void draw() { background(102); textSize(32); text("That's one small step for man...", 25, 60); textSize(16); text("That's one small step for man...", 27, 90); }
PROCESSING
Example 7-8: Store Text in a Box
PFont myFont; String myQuote = "That's one small step for man..."; void setup() { size(480, 120); myFont = createFont("SourceCodePro-Regular.ttf", 24); textFont(myFont); } void draw() { background(102); text(myQuote, 26, 24, 240, 100); }
You can use vector graphics created in Adobe Illustrator (or Inkscape, an open-source vector graphics tool) in a special format called SVG (Scalable Vector Graphics). Like bitmap images, they need to be in the data folder of the sketch. And the easiest way to add them is to save your sketch before you write it and use the Menu > Sketch > Add File... to import the .svg file.
Like images, you have to set up a variable of the data-type PShape, then load the variable with loadShape("filename.svg"), then use shape(varName, xLocation, yLocation, optionalSizeWidth, optionalSizeHeight) to have it appear in the Display Window.
In this example we'll import an SVG file called "network.svg" into the sketch before we start coding...
PROCESSING
Example 7-9: Draw with Shapes (Ex 6-9 1st Ed.)
PShape mySVG; void setup() { size(480, 120); mySVG = loadShape("network.svg"); } void draw() { background(0); shape(mySVG, 30, 10); shape(mySVG, 180, 10, 280, 280); }
Shapes are relatively easy to scale. You can set the center of the scaling from the default upper left corner to the center of the shape with shapeMode(CENTER)
PROCESSING
Example 7-10: Scaling Shapes
PShape mySVG; void setup() { size(480, 120); shapeMode(CENTER); mySVG = loadShape("network.svg"); } void draw() { background(0); float myScale = map(mouseX, 0, width, 10, 800); shape(mySVG, 30, 10); shape(mySVG, 180, 10, myScale, myScale); }
Scalable Vector Graphics are very cool and a bit tricky to create. In the above example, we used a file called network.svg
to create the sketch. Here's the graphic in a web page:
And here's the SVG code:
There are 1,843 lines of code to create the file!
PROCESSING
Example 7-11: Creating a New Shape (Not in 1st Ed.)
PShape dino; void setup() { size(480, 120); dino = createShape(); dino.beginShape(); dino.fill(153, 176, 180); // Grey Green dino.vertex(50,120); dino.vertex(100,90); dino.vertex(110,60); dino.vertex(80,20); dino.vertex(210,60); dino.vertex(160,80); dino.vertex(200,90); dino.vertex(140,100); dino.vertex(130, 120); dino.endShape(); } void draw() { background(204); translate(mouseX-120, 0); shape(dino, 0, 0); }
BTW, this does the same thing as translate()
void draw() { background(204); shape(dino, mouseX-120, 0); }
You can use Adobe Illustrator to create your SVG files, but there's a trick to it.
Here's a dino.ai file (zipped) we can use that enhances our vector creature.
Here's the trick. You can save an Illustrator file in the .svg format, but Processing won't accept it without some settings jiggery-pokery. To whit: When saving as an SVG, expand the Advances Options of the SVG Options panel when you save the file and set the CSS properties to Presentation Attributes.
This get's rid of CSS styles in the SVG file, which Processing doesn't support.
PROCESSING
Using Illustrator (not in 1st edition)
PShape illustratorDino; void setup() { size(480, 120); illustratorDino = loadShape("dino.svg"); } void draw() { background(204); shape(illustratorDino, mouseX - (width/2), mouseY - (height/2)); }
PROCESSING
Robot 5 (Robot 4 in 1st Ed.)
PShape bot1; PShape bot2; PShape bot3; PImage landscape; float easing = 0.05; float offset = 0; void setup() { size(720, 480); bot1 = loadShape("robot1.svg"); bot2 = loadShape("robot2.svg"); bot3 = loadShape("robot3.svg"); landscape = loadImage("alpine.jpg"); } void draw() { // Set the background to the "landscape" image, this // image must be the same width and height as the program background(landscape); // Set the left/right offset and apply easing to make // the transition smooth float targetOffset = map(mouseY, 0, height, -40, 40); offset += (targetOffset - offset) * easing; // Draw the left robot shape(bot1, 85 + offset, 65); // Draw the right robot smaller and give it a smaller offset float smallerOffset = offset * 0.7; shape(bot2, 510 + smallerOffset, 140, 78, 248); // Draw the smallest robot, give it a smaller offset smallerOffset *= -0.5; shape(bot3, 410 + smallerOffset, 225, 39, 124); }