Building a digital painting studio from scratch with Processing

Published by Tim on Saturday June 18, 2022

Last modified on December 4th, 2024 at 17:55

A few weeks ago I met the German artist Arno Beck, whose work I find absolutely great. Arno is a painter and deals with the transfer of digital phenomena into the physical world. Inspired by his painting I developed a digital painting software with Processing in this session.

Thanks to johnny_ctrl for the editing!

YouTube

By loading the video, you agree to YouTube’s privacy policy.
Learn more

Load video

paintingstudio.pde

PImage[] images;

PGraphics source;
PGraphics target;
PGraphics result;

PGraphics comp;

PGraphics artboard;

PImage buffer;
PImage currImage;

int POSTER_W = 580;
int POSTER_H = 810;

float TILES_X = POSTER_W / 5;
float TILES_Y = POSTER_H / 5;

int sx, sy, sw, sh, dx, dy, dw, dh;

float scalar = 1;

float offsetX = 0;
float offsetY = 0;

float coutoutW = 30;

float threshold = 150;

void setup() {
  size(1740, 810);

  source = createGraphics(POSTER_W, POSTER_H);
  target = createGraphics(POSTER_W, POSTER_H);
  result = createGraphics(POSTER_W, POSTER_H);
  artboard = createGraphics(900, 900);

  comp = createGraphics(POSTER_W, POSTER_H);

  images = new PImage[9];

  images[0] = loadImage("1.jpg");
  images[1] = loadImage("2.jpg");
  images[2] = loadImage("3.jpg");
  images[3] = loadImage("4.jpg");
  images[4] = loadImage("5.jpg");
  images[5] = loadImage("6.jpg");
  images[6] = loadImage("7.jpg");
  images[7] = loadImage("8.jpg");
  images[8] = loadImage("9.jpg");

  currImage = images[int(random(images.length))];
}

void draw() {
  background(#00ff00);
  drawSource();
  drawTarget();
  drawResult();


  image(source, 0, 0);
  image(target, POSTER_W, 0);
  image(result, POSTER_W + POSTER_W, 0);
  noFill();
  stroke(#00ff00);
  strokeWeight(3);
  drawArtboard();

  rect(mouseX, mouseY, sw, sh);
  rect(mouseX + POSTER_W, mouseY, sw, sh);

  render();
}

artboard.pde

void drawArtboard() {
  artboard.beginDraw();
  artboard.background(0);
  artboard.imageMode(CENTER);
  PImage buffer = target.get();
  artboard.image(buffer,artboard.width/2,artboard.height/2);
  artboard.endDraw();
}

randomComposition.pde

void randomComposition() {
  
  int padding = 50;
  
  comp.beginDraw();
  comp.background(255);

  float diameter = random(300);

  comp.fill(0);
  comp.noStroke();
  comp.ellipse(random(padding,POSTER_W-padding), random(padding,POSTER_H-padding), diameter, diameter);
  comp.stroke(0);
  comp.strokeWeight(8);
  comp.strokeCap(RECT);
  comp.line(random(padding,POSTER_W-padding), random(padding,POSTER_H-padding), random(padding,POSTER_W-padding), random(padding,POSTER_H-padding));
  comp.endDraw();
}

render.pde

void render() {
  if (frameCount % 10 == 0) {
    artboard.save("out/" + nf(frameCount, 6) + ".png");
  }
}

result.pde

void drawResult() {

  float tileW = result.width / TILES_X;
  float tileH = result.height / TILES_Y;

  PImage buffer = target.get();

  result.beginDraw();
  result.background(#f1f1f1);

  result.noStroke();

  for (int x = 0; x < TILES_X; x++) {
    for (int y = 0; y < TILES_Y; y++) {

      int px = int(x*tileW);
      int py = int(y*tileH);
      color c = buffer.get(px, py);
      float b = brightness(c);

      if (b < threshold) {
        result.fill(0);
      } else {
        result.fill(#f1f1f1);
      }

      result.push();
      result.translate(x*tileW, y*tileH);
      result.rect(0, 0, tileW, tileH);
      result.pop();
    }
  }

  result.endDraw();
}

source.pde

void drawSource(){
  source.beginDraw();
  source.background(0);
  source.imageMode(CENTER);
  source.push();
  source.translate(source.width/2 + offsetX, source.height/2 + offsetY);
  source.scale(scalar);
  source.image(currImage,0,0);
  source.pop();
  source.endDraw();
}

target.pde

void drawTarget() {
  target.beginDraw();

  buffer = source.get();

  if (frameCount == 1) {
    target.background(#ffffff);
  }

  sx = mouseX;
  sy = mouseY;
  sw = int(coutoutW);
  sh = int(coutoutW);

  dx = mouseX;
  dy = mouseY;
  dw = int(coutoutW);
  dh = int(coutoutW);

  if (mousePressed) {
    target.copy(buffer, sx, sy, sw, sh, dx, dy, dw, dh);
  }


  target.endDraw();
}

ui.pde

void keyReleased() {
  if (key == '1') {
    currImage=images[0];
  }
  if (key == '2') {
    currImage=images[1];
  }
  if (key == '3') {
    currImage=images[2];
  }
  if (key == '4') {
    currImage=images[3];
  }
  if (key == '5') {
    currImage=images[4];
  }
  if (key == '6') {
    currImage=images[5];
  }
  if (key == '7') {
    currImage=images[6];
  }
  if (key == '8') {
    currImage=images[7];
  }
  if (key == '9') {
    currImage=images[8];
  }

  if (key == 'r') {
    scalar = random(1, 5);
    offsetX = random(-800, 800);
    offsetY = random(-800, 800);
  }

  if (key == 't') {
    randomComposition();
    currImage = comp.get();
  }
  if (key == 'e') {
    scalar = 1;
    offsetX = 0;
    offsetY = 0;
  }
}

void mouseWheel(MouseEvent event) {
  float e = event.getCount();
  coutoutW += e*10;
}

Related

Links

Enjoying the content?

I put a lot of love and effort into developing content on Creative Coding. Since 2018, I have published 219 interviews, case studies, and tutorials, along with over 280 lessons in 17 online courses – and there's more to come! If you'd like to support my work and help keep this platform evolving, please consider supporting me on Patreon. Thank you very much!

Speaking Image

Monthly Newsletter

Fresh perspectives circling around Creative Coding, Design and Technology, every first Friday of the month, directly to your inbox.

Related

Demystify Technology

The guiding principle in my teaching and in the development of this platform is “Demystify Technology”. The Problem When people […]

Studio visit: Julian Hespenheide

Two thousand and twenty-four. At the “Barceloneta” metro station, a few hundred meters from the beach, stands an old dot-matrix […]

Hannah Gmeiner on Permacomputing in Graphic Design

In an age of increasing digital consumption, Hannah, a recent visual communication graduate, explored “Permacomputing”—a sustainable approach to technology inspired […]

DEMO 2025 – My Submissions

Limitations have always been playing a major role in my creative work; I was only able to develop my best […]

Tameem Sankari on Creative Coding for Large Media Corporations

In this interview, Copenhagen-based creative director Tameem Sankari shares his journey into Creative Coding, combining Processing, Blender, and Adobe CC. […]

Sam Griffith connects Creative Coding with Enviromentalism

In this post I’d like to introduce you to Sam Griffith, a talented graphic designer based in Detroit, to discuss […]

Throwback: My Talk at Demo Festival 2022

The next edition of the DEMO Festival is already approaching and I am currently developing a brand new talk for […]

Powers of Two – 128kb by Lena Weber

20 = 1 21 = 222 = 323 = 824 = 1625 = 3226 = 6427 = 128 … »In […]

A Call for Coding Designers

This is a call for coding designers. It aims to serve as a proposal and a provocation for creative work […]

p5.js Design Tools Directory

Hi! In this post I’ll collect case studies and direct links to tools that people have built with p5.js and […]

A p5.js starter template for the 128kb Challenge

Your 128kb journey starts here! This is a template you can use to start developing your idea within the 128kb […]

Omid Nemalhabib explores the intersection of Creative Coding and Perso-Arabic Typography

In 2022, I spontaneously posted a story on Instagram: If anyone out there is also in Rotterdam, I’d love to […]

The 128kb Framework and its Aesthetic Characteristics

One day in early 2024 I started to experiment with a new idea. I wrote down a set of rules […]

A conversation with Talia Cotton

During OFFF Festival here in Barcelona, many interesting people come around! This interview with Talia Cotton came about almost by […]

Lena Weber about her collaboration with A. G. Cook

Lena: This 10-minute visualiser for A. G. Cooks album teaser featuring my python archive generator, is one of my favourite […]

A conversation with Anna Shams Ili

Hi Anna! It was super nice to meet you at the PCD CPH, I really liked your talk in which […]

Coding Systems: New Workshop Dates!

When I held Martin Lorenz’s new book in my hands and turned it onto its back, I was a little […]

My new writing project “downgrade” is live

Hey folks, I hope you are doing great! You may have already read one or two of my essays that […]

Join the 128kb challenge!

Instagram, Twitter, TikTok… All the main platforms that technically have the required features to connect emerging communies for Creative Coding […]

Ruder Processing Unit by Kevin Koch

In my teaching at universities and in workshops, I have met many very enthusiastic and highly talented people who have […]

A reflection on Processing Community Day Copenhagen 2023

I’ve been travelling a lot in the last few months. Still, it was only during a short stay in Copenhagen […]

Ksawery Kirklewski on his Symphony in Acid

For me, it’s by far the most inspiring project of the last few years: “Symphony in Acid”, a collaboration between […]

Coding Systems

How does Creative Coding relate to the broad term “systems theory”? This question has been the subject of many conversations […]

Computer Cursive by Tay Papon Punyahotra

One of the first exercises I assign to my students in my seminars is called “Random Compositions”. Basically, it’s quite […]

Vera Molnar Reconstructed 3/3

Click here to login or connect!To view this content, you must be a member of Tim's Patreon at €7 or […]

Vera Molnar Reconstructed 2/3

Click here to login or connect!To view this content, you must be a member of Tim's Patreon at €7 or […]

Vera Molnar Reconstructed 1/3

Click here to login or connect!To view this content, you must be a member of Tim's Patreon at €7 or […]

My brand new course “Building Tools” is live!

I am really excited to announce that I’ve finally released my brand new course Building Tools today! I just added […]