Art of CodeArt of Code

The Art of Code is a MA/MFA class that I am teaching at Multidisciplinary New Media department in Paris College of Art. The course provides an introduction to coding for artists and designers who are willing to learn and use it as a form of creative expression.

This website documents
the course materials. If you have any questions, you can contact me on Twitter.

Export

Pixels vs. physical space

In traditional print software, calculations between the digital space and the physical space are handled. They don't require manual calculations. If you want to print on an A4 paper, you can create a canvas that's size is A4 (297mm ✕ 210mm) with PPI (Pixels Per Inch) you desire and voilà.

However, when we create images for print in a system that is made for digital medium, like p5.js (design tool Sketch is also similar in this way), we have to make our own calculations to achieve our desired print size in high quality.

When we create a canvas in p5.js with canvas(400, 300) and we place a rectangle using rect(200, 150, 20), we know how the result would look like in digital. But how do we calculate the size it will print?

Screens

Screens that we all use today are made out of pixels. CRT monitors and vector monitors are different, but we don't use them anymore. Pixels are the smallest units on screens.

Although there is a catch, an additional concept introduced by many smartphones and screens is "pixel density." Companies started to fit more pixels into small space to increase the detail of the image on their screen. A typical smartphone screen might have anything between 320 PPI and 570 PPI, whereas a 43 inch Full HD TV screen has 51 PPI. An important factor is the distance between the monitor (or print) and the viewer. A public square display doesn't need to have as many pixels per inch as much as a smartphone.

Pixel size

Handling all sizes across different devices would be a nightmare without some standardization. That is why pixel density is used by manufacturers to specify roughly the ratio of pixel size compared to a more standard screen (160 PPI). For example, an iPhone 11 has a pixel density of 3x. That is how we would see roughly similar (not same) sized output across different screens when they are in their native resolution. If you run displayDensity() you would get your screen's density in p5.js.

Fortunately, all this pixel density is handled natively by software, including p5.js library, so you don't have to worry about it until you decide to do image processing or to print.

Pixel density

Paper sizes

International paper sizes are standardized in ISO 216. A series is the most popular one within it. North American formats are different, and I won't talk about those, but you can quickly adapt the following guidelines to fit them.

A series paper sizes

How do we calculate pixel dimensions to print on an A4?

One inch is 25.4mm. We want to print in 300 PPI. So, paper size times PPI divided by an inch, should give us the pixel sizes we need.



297mm * 300ppi / 25.4mm = 3508px
210mm * 300ppi / 25.4mm = 2480px

Ok, great, so we know that we need to create a sketch with a canvas size of 3508px by 2480px. However, a canvas of this size would probably run slowly. It'll be even slower if we want to print in bigger sizes, requiring larger canvases. To solve this, we will create our sketch in a scaled downsize so it'll be fast and easy to work. Below is a table for common A sizes. We will use 4x scaled-down dimensions as the working size for our sketch.

mm inches 300ppi pixels 4x scaled-down
A0 841 × 1189 33.1 × 46.8 7016 × 9920 1754 × 2480
A1 594 × 841 23.4 × 33.1 4960 × 7016 1240 × 1754
A2 420 × 594 16.5 × 23.4 3508 × 4960 877 × 1240
A3 297 × 420 11.7 × 16.5 2480 × 3508 620 × 877
A4 210 × 297 8.3 × 11.7 1754 × 2480 438 × 620
A5 148 × 210 5.8 × 8.3 1240 × 1754 310 × 219
A6 105 × 148 4.1 × 5.8 877 × 1240 109 × 310

But we still need a large image to export. So, the moment we want to export, we will scale it up to full size during one frame, export it, and then re-scale it back down. That works very well because we only need a single frame to print.


let scaleRatio = 1;
let exportRatio = 4;
let buffer;
let canvas;
let a3Paper = {
  width: 3508,
  height: 2480
}

function setup() {
  let w = a3Paper.width / exportRatio;
  let h = a3Paper.height / exportRatio;

  buffer = createGraphics(w, h);
  canvas = createCanvas(w, h);

  // Adjust according to screens pixel density.
  exportRatio /= pixelDensity();
}

function draw() {
  background(220);

  // Clear buffer each frame
  buffer.clear();
  // Transform (scale) all the drawings
  buffer.scale(scaleRatio);
  // Make all the drawing to the buffer instead of canvas
  buffer.circle(width/2, height/2, 100);

  // Draw buffer to canvas
  image(buffer, 0, 0);
}

function exportHighResolution() {
  scaleRatio = exportRatio;

  // Re-create buffer with exportRatio and re-draw
  buffer = createGraphics(scaleRatio*width, scaleRatio*height);
  draw();

  // Get timestamp to name the ouput file
  let timestamp = new Date().getTime();

  // Save as PNG
  save(buffer, str(timestamp), 'png');

  // Reset scaleRation back to 1, re-create buffer, re-draw
  scaleRatio = 1;
  buffer = createGraphics(width, height);
  draw();
}

function keyReleased() {
  if (key == 'e' || key == 'E') {
    exportHighResolution();
  }
}