Amnon Owed 라는 작가가 Creative Applications Network 에 게시한 글 'Generative Typography with Processing – Tutorial' 에 함께 첨부된 Processing 예제입니다. 이 글에 따르면 튜토리얼은 코드를 사용하여 타이포그라피의 창조적 가능성을 탐색하는 방법을 보여주기 위해 만들어졌습니다. Type을 기본형으로 하여 다양한 기술과 알고리즘으로 그래픽을 얻어내는 팁들을 담고 있습니다.
Generative Typography with Processing – Tutorial
Generative Typography – github
// 사용할 수 있는 폰트목록을 console에 출력한다
String[] fontList = PFont.list();
printArray(fontList);
PFont font;
void setup() {
// Canvas 사이즈를 정한다
size(1280, 720);
// 사용할 수 있는 폰트목록을 console에 출력한다
String[] fontList = PFont.list();
printArray(fontList);
// 원하는 폰트를 PFont로 얻어서 지정한다
font = createFont("Georgia", 400);
textFont(font);
// text를 상단 왼쪽을 기준으로 정렬되게 한다
textAlign(LEFT, TOP);
// Canvas에 원하는 text를 그린다
background(255);
fill(0);
text("Hello!", 0, 0);
}
PFont font;
void setup() {
// Canvas 사이즈를 정한다
size(1280, 720);
// 원하는 폰트를 PFont로 얻어서 지정한다
font = createFont("Georgia", 400);
textFont(font);
// text를 상단 왼쪽을 기준으로 정렬되게 한다
textAlign(LEFT, TOP);
// Canvas에 원하는 text를 그린다
background(255);
fill(0);
text("Hello!", 0, 0);
// 캔버스 전체(가로 0~width, 세로 0~height)에 10px 간격으로 x,y 지점을 찾는다
for(int x=0; x<width; x += 10){
for(int y=0; y<height; y += 10){
// 해당 좌표 픽셀의 색깔이 원하는 색깔이 맞는지 판별한다
// 맞다면 중괄호 안의 코드를 실행한다
if( get(x, y) == color(0) ){
// 그려질 원의 색깔을 정한다
fill(255, 0, 0);
// 해당 좌표에 가로세로 10, 10, 크기의 원을 그린다
ellipse(x, y, 10, 10);
}
}
}
}
프로세싱엔 마치 레이어처럼 이미지를 분리해서 그리는 PGraphics라는 데이터타입이 있다. 텍스트 실루엣을 PGraphics에 그린후 숨겨놓고 실루엣의 좌표만 얻어서 그래픽을 표현할 수 있다.
PFont font;
PGraphics pg;
void setup() {
// Canvas 사이즈를 정한다
size(1280, 720);
// Canvas와 같은 크기로 PGraphics를 생성한다.
pg = createGraphics(width, height);
// 원하는 폰트를 PFont로 얻어서 지정한다
font = createFont("Georgia", 400);
// PGraphics에 원하는 text를 그린다
pg.beginDraw();
pg.background(255);
pg.textFont(font);
pg.textAlign(LEFT, TOP);
pg.fill(0);
pg.text("Hello!", 0, 0);
pg.endDraw();
// Canvas 의 배경을 칠한다
background(255);
// 캔버스 전체(가로 0~width, 세로 0~height)에 10px 간격으로 x,y 지점을 찾는다
for(int x=0; x<width; x += 10){
for(int y=0; y<height; y += 10){
// 해당 좌표 픽셀의 색깔이 원하는 색깔이 맞는지 판별한다
// 맞다면 중괄호 안의 코드를 실행한다
if( pg.get(x, y) == color(0) ){
// 그려질 원의 색깔을 정한다
fill(255, 0, 0);
// 해당 좌표에 가로세로 10, 10, 크기의 원을 그린다
ellipse(x, y, 10, 10);
}
}
}
}
PFont font;
PGraphics pg;
// Particle 배열을 만든다
Particle[] particle;
// 생성될 Particle의 처음 번호를 변수 담아준다
int particleNum = 0;
void setup() {
// Canvas 사이즈를 정한다
size(1280, 720);
// Canvas와 같은 크기로 PGraphics를 생성한다.
pg = createGraphics(width, height);
// 원하는 폰트를 PFont로 얻어서 지정한다
font = createFont("Georgia", 400);
// PGraphics에 원하는 text를 그린다
pg.beginDraw();
pg.background(255);
pg.textFont(font);
pg.textAlign(LEFT, TOP);
pg.fill(0);
pg.text("Hello!", 0, 0);
pg.endDraw();
// Canvas 의 배경을 칠한다
background(255);
// Particle 배열 안에 최대로 담을 수 있는 공간을 만들어준다
// particle이 Canvas 안에 10px 간격으로 생기니 가로세로를 10으로 나눠 곱한다
particle = new Particle[width/10 * height/10];
// 캔버스 전체(가로 0~width, 세로 0~height)에 10px 간격으로 x,y 지점을 찾는다
for(int x=0; x<width; x += 10){
for(int y=0; y<height; y += 10){
// 해당 좌표 픽셀의 색깔이 원하는 색깔이 맞는지 판별한다
// 맞다면 중괄호 안의 코드를 실행한다
if( pg.get(x, y) == color(0) ){
// 실루엣이 있는 좌표에 Particle을 생성한다
particle[particleNum] = new Particle(x, y, 10, color(255,0,0));
// 생성된 Particle을 그려준다
particle[particleNum].display();
// 다음 Particle을 생성하기 위해 번호를 1 올려준다
particleNum ++;
}
}
}
}
// Particle 객체를 만든다
class Particle{
// 필요한 변수를 생성한다
float x;
float y;
float size;
color c;
// new 키워드를 통해서 각 Particle을 생성할때 어떻게 변수를 받을지 작성한다
Particle(float x_, float y_, float size_, color c_){
x = x_;
y = y_;
size = size_;
c = c_;
}
// Particle을 시각화할 함수를 만든다
void display(){
fill(c);
ellipse(x, y, size, size);
}
}
PFont font;
PGraphics pg;
// Particle 배열을 만든다
Particle[] particle;
// 생성될 Particle의 처음 번호를 변수 담아준다
int particleNum = 0;
void setup() {
// Canvas 사이즈를 정한다
size(1280, 720);
// Canvas와 같은 크기로 PGraphics를 생성한다.
pg = createGraphics(width, height);
// 원하는 폰트를 PFont로 얻어서 지정한다
font = createFont("Georgia", 400);
// PGraphics에 원하는 text를 그린다
pg.beginDraw();
pg.background(255);
pg.textFont(font);
pg.textAlign(LEFT, TOP);
pg.fill(0);
pg.text("Hello!", 0, 0);
pg.endDraw();
// Particle 배열 안에 최대로 담을 수 있는 공간을 만들어준다
// particle이 Canvas 안에 10px 간격으로 생기니 가로세로를 10으로 나눠 곱한다
particle = new Particle[width/10 * height/10];
// 캔버스 전체(가로 0~width, 세로 0~height)에 10px 간격으로 x,y 지점을 찾는다
for(int x=0; x<width; x += 10){
for(int y=0; y<height; y += 10){
// 해당 좌표 픽셀의 색깔이 원하는 색깔이 맞는지 판별한다
// 맞다면 중괄호 안의 코드를 실행한다
if( pg.get(x, y) == color(0) ){
// 실루엣이 있는 좌표에 Particle을 생성한다
particle[particleNum] = new Particle(x, y, 10, color(255,0,0));
// 다음 Particle을 생성하기 위해 번호를 1 올려준다
particleNum ++;
}
}
}
}
// 애니메이션 효과를 주기위해 display함수를 draw에 작성한다
void draw(){
background(255);
for(int i=0; i<particleNum; i++){
particle[i].display();
}
}
// Particle 객체를 만든다
class Particle{
// 필요한 변수를 생성한다
float x;
float y;
float size;
color c;
// new 키워드를 통해서 각 Particle을 생성할때 어떻게 변수를 받을지 작성한다
Particle(float x_, float y_, float size_, color c_){
x = x_;
y = y_;
size = size_;
c = c_;
}
// Particle을 시각화할 함수를 만든다
void display(){
// 각 Particle의 x좌표를 움직여 전광판같은 효과를 준다
x++;
if(x > width) x = 0;
fill(c);
ellipse(x, y, size, size);
}
}
// Particle 객체를 만든다
class Particle{
// 필요한 변수를 생성한다
// 본래위치
float x;
float y;
// 움직인 위치
float moveX;
float moveY;
float size;
color c;
// new 키워드를 통해서 각 Particle을 생성할때 어떻게 변수를 받을지 작성한다
Particle(float x_, float y_, float size_, color c_){
x = x_;
y = y_;
size = size_;
c = c_;
moveX = x;
moveY = y;
}
// Particle을 시각화할 함수를 만든다
void display(){
// 랜덤으로 움직인 값을 임시로 담아둔다
float tempX = moveX + random(-3, 3);
float tempY = moveY + random(-3, 3);
// 움직인 값이 일정범위를 넘어가면 다시 계산해서 경계를 넘어가지 않게한다
while(dist(tempX, tempY, x, y) > 10){
tempX = moveX + random(-3, 3);
tempY = moveY + random(-3, 3);
}
// 경계를 넘지않는 값을 얻으면 값을 담는다
moveX = tempX;
moveY = tempY;
fill(c);
ellipse(moveX, moveY, size, size);
}
}
// Particle 객체를 만든다
class Particle{
// 필요한 변수를 생성한다
// 본래위치
float x;
float y;
// 움직인 위치
float moveX;
float moveY;
float size;
color c;
// new 키워드를 통해서 각 Particle을 생성할때 어떻게 변수를 받을지 작성한다
Particle(float x_, float y_, float size_, color c_){
x = x_;
y = y_;
size = size_;
c = c_;
moveX = x;
moveY = y;
}
// Particle을 시각화할 함수를 만든다
void display(){
// frameCount에 따라 sin값에 변화를 주는데
// x,y위치에따라 조금씩 다르게하여 파동을 만든다
moveX = x + sin(frameCount*0.1 + x*0.01) * 5;
moveY = y + cos(frameCount*0.1 + y*0.01) * 5;
fill(c);
ellipse(moveX, moveY, size, size);
}
}
// Particle 객체를 만든다
class Particle{
// 필요한 변수를 생성한다
float x;
float y;
//최대 크기와 현재크기
float maxSize;
float size;
color c;
// new 키워드를 통해서 각 Particle을 생성할때 어떻게 변수를 받을지 작성한다
Particle(float x_, float y_, float size_, color c_){
x = x_;
y = y_;
maxSize = size_;
// 각 Particle 이 0~최대크기 사이에서 랜덤하게 시작하게한다
size = maxSize * random(0, 1);
c = c_;
}
// Particle을 시각화할 함수를 만든다
void display(){
// 매프레임마다 0.1씩 커지게한다
size += 0.1;
// 최대크기에 다다르면 0으로 돌아간다
if(size > maxSize) size = 0;
fill(c);
ellipse(x, y, size, size);
}
}
import processing.pdf.*;
boolean record;
void setup() {
size(400, 400);
}
void draw() {
// Draw something good here
background(255);
ellipse(width/2, height/2, 200, 200);
}
// Use a keypress so thousands of files aren't created
void mousePressed() {
saveFrame( "image.jpg" );
}
import processing.pdf.*;
boolean record;
void setup() {
size(400, 400);
}
void draw() {
if (record) {
// Note that #### will be replaced with the frame number. Fancy!
beginRecord(PDF, "frame-####.pdf");
}
// Draw something good here
background(255);
ellipse(width/2, height/2, 200, 200);
if (record) {
endRecord();
record = false;
}
}
// Use a keypress so thousands of files aren't created
void mousePressed() {
record = true;
}