Last active
December 24, 2018 13:59
-
-
Save Curookie/43dc1cbe7e00e5e77fe5e178cadafa37 to your computer and use it in GitHub Desktop.
낭만적인 이미지 언어 Piet!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
네덜란드의 화가인 피트 몬드리안(Piet Mondrian)의 이름을 딴 이 언어는 비트 이미지로 간단한 프로그래밍을 할 수 있다. | |
예술로 코딩하는 느낌이라서 너무 매력적이다. (~프로포즈 할때 사용할 수도?~) | |
★ 시작 | |
https://www.bertnase.de/npiet/ 여기서 최신 IDE셋을 받는다. | |
(2018/10 기준) npiet-1.3e.tar.gz 파일 받으면 됨. | |
만들면서 느낀점은 제작 프로세스는 간단하다. | |
1. 만들 그림을 생각한다. | |
2. 만들 문구(프로그램)을 생각한다. | |
3. 2번의 생각을 바탕으로 그림의 사이즈를 예상해 정한다. | |
4. 절차적으로 도트를 찍으며 프로그램을 작성한다. | |
(이때 예술적인 요소를 살릴려면 '흰색 코델'과 switch(),pointer(),'검은 코델'을 잘 활용해 원하는 색을 원하는 위치에 찍을 수 있게 해야한다.) | |
5. 어느정도 진행 후 디버깅을 하면 좋다. (추후 수정이 어렵기 때문) | |
★ 우선 코딩은 2가지 방법이 있다. | |
1. foogol문법을 사용해서 코딩 후 npiet-foogol.exe로 이미지 생성하는 법. | |
- 이 방법은 빠르고 쉽지만 원하는 이미지가 예술적이게 나오기 힘들다. | |
2. Piet언어를 이해한 후 npietedit.tcl로 픽셀을 찍어서 코딩하는 법. | |
(함수의 종류만 이해해도 괜찮다. Edit에서 친절하게 색, 밝기 차이값은 잡아주기 때문) | |
- 픽셀 찍는 에디터가 TCL파일이여서 TCL을 실행시킬 수 있도록 설치가 필요. https://www.activestate.com/activetcl/downloads | |
- PPM파일로 저장되며 PPM-> PNG https://convertio.co/kr/ppm-png/ 로 변환하면된다. | |
- 100 보다 큰 사이즈를 원한다면 npietedit.tcl 에디터를 직접 수정해야한다. (128*128크기 지원안되서 기본 켜지는 크기값과 확대되는 비율 코드 수정해서 적용함.) | |
- 아니면 포샵이나 도트 찍는걸로 진짜 그 색 값만 저장해서 찍어서 진행해도 된다. | |
★ 컴파일은 여러방법이 있겠지만 3가지 방법을 소개한다. | |
1. cmd로 npiet.exe이용해서 실행 - 이 방법을 이용하면 trace.png도 얻을 수 있다.(디버깅가능) npiet.exe -tpic hello.png 이런식으로 명령어 치면 됨.(트레이스 이미지) npiet.exe -t hello.png 이건 트레이스 스탭 단위로 다 볼 수 있음. | |
2. Online Site를 이용 - 컴파일 사이트에 들어가서 사진올리고 excute 누르면 끝. | |
(공유 시 유용 - 개인적으로 컴파일,에디터 페이지를 만들 수도 있다. '툴과 개발진' 사이트에 들어가보면 openSource를 제공함) | |
3. python으로 실행하기 - http://www.dangermouse.net/esoteric/piet/Piet_py.txt 에서 Piet.py를 만든다음, 몇 가지만 수정해서 쓰면된다. | |
def neighbors(self,x,y): | |
sys.setrecursionlimit(50000); //여기에 재귀 횟수 제한 높이는 코드 넣기 | |
for (dx,dy) in ((0,1),(0,-1),(1,0),(-1,0)): | |
if self._is_valid(x+dx,y+dy) and \ | |
//Interpreter 클래스 맨 아래에 실행용 코드 추가 | |
def run(self): | |
while True: | |
self.step() | |
이제 컴파일하려면 main()함수나 상속해서 아래와 같이하면 된다. | |
interpreter = Interpreter("image.png",PVM()) | |
interpreter.step() | |
//한 step씩 디버깅할때 step() 사용 | |
interpreter = Interpreter("image.png",PVM()) | |
interpreter.run() | |
//처음부터 끝까지 실행할 때 run() 사용 | |
★ 참고 자료 | |
Piet 언어 소개 페이지 | |
https://www.bertnase.de/npiet | |
Piet 언어 온라인 컴파일 사이트 | |
https://www.bertnase.de/npiet/npiet-execute.php | |
Piet 예제 | |
http://www.dangermouse.net/esoteric/piet/samples.html | |
웹 Piet IDE | |
https://gabriellesc.github.io/piet/ | |
http://zobier.net/piet/ | |
툴과 개발진 | |
http://www.dangermouse.net/esoteric/piet/tools.html | |
PPM-> PNG | |
https://convertio.co/kr/ppm-png/ | |
파이썬 실행기 | |
http://www.dangermouse.net/esoteric/piet/Piet_py.txt | |
파이썬 실행 클래스 설명 | |
http://www.majcher.com/code/piet/Piet-Interpreter.html | |
Out(Char)일때 Unicode 표 | |
https://unicode-table.com/en/#004C | |
튜토리얼 | |
http://homepages.vub.ac.be/~diddesen/piet/index.html | |
**텍스트를 유니코드 숫자(Decimal)로 바꿔주는 사이트 | |
https://www.browserling.com/tools/text-to-decimal | |
★ Piet 언어 분석 | |
Piet 프로그램에서 단위 정사각형을 코델(Codel)이라고 하며 각 코델마다 특정 색깔이 칠해져있다. | |
이는 비트맵 이미지의 픽셀에 대응되는 개념이다. 같은 색깔의 코델이 상하좌우로 연결된 블록이 프로그램의 최소 실행 단위가 된다. | |
맨 처음 실행되는 블록은 가장 왼쪽 위 코델이 포함된 블록이며, 규칙에 따라 다음에 실행될 블록으로 이동하는 과정을 반복한다. | |
현재 블록에서 어떤 블록으로 이동할지를 결정하기 위해 DP(Direction Pointer)와 CC(Codel Chooser)라는 두 가지 값이 존재한다. | |
DP의 값은 왼쪽, 오른쪽, 위쪽, 아래쪽 중 하나이고, CC의 값은 왼쪽 혹은 오른쪽 중 하나이다. | |
프로그램이 처음 실행될 때 DP의 값은 오른쪽, CC의 값은 왼쪽이다. 어떤 블록으로 이동할지를 선택하는 기준은 다음과 같다. | |
- 현재 블록의 코델들 중에서 DP의 방향으로 가장 멀리 위치한 코델들을 찾는다. 블록이 볼록하지 않은 경우 이 코델들은 이어지지 않은 형태일 수 있다. | |
- 위에서 찾은 코델들 중 DP 방향을 향했을 때 CC의 방향으로 가장 끝에 있는 코델을 선택한다. | |
이 때 CC의 방향은 상대적인 방향임에 유의하라. 예를 들어, DP가 아래쪽을 가리키고 CC가 오른쪽을 가리키는 경우, | |
선택되는 코델은 가장 왼쪽에 있는 코델이 된다. | |
- 위에서 선택한 코델에서 DP의 방향으로 맞닿은 코델이 포함된 블록이 다음 블록이 된다. | |
표현식은 아래와 같다. | |
eg. step 12, try 3, dp=up and cc=right as 12.3 u/r | |
한 마디로 DP는 진행방향이고, CC는 조건문 겸, 진행방향이 문제가 생겼을 경우 이동시키는 진행방향의 상대적 좌우방향이다. | |
DP→일때 CC는↓or↑밖에 안됨 | |
검은색 블록 혹은 이미지의 경계 바깥은 이동할 수 없는 구역이다. | |
만약 다음으로 이동하려는 블록이 검은색이거나 이미지의 경계를 벗어나는 경우는 다음의 방법으로 진행한다. | |
1. CC의 값이 왼쪽인 경우 오른쪽으로, 오른쪽인 경우 왼쪽으로 바꾼 후 다시 이동을 시도한다. | |
2. CC의 값을 바꾼 후에도 이동할 수 없는 경우, CC의 값을 유지하며 DP를 시계방향으로 회전한 후 다시 이동을 시도한다. | |
3. 시계방향으로 회전한 후에도 이동할 수 없는 경우, 1번으로 되돌아간다. | |
4. 위 과정을 계속 반복하여 총 8가지의 경우를 모두 시도했는데도 이동할 수 있는 블록을 찾지 못한 경우, 프로그램이 종료된다. | |
화이트 블록은 자유로운 공간(여백미?) 다음 색을 찾아가기 위한 통과하는 공간이다. | |
- DP방향을 따라 직선으로 이동한다. | |
- 제한구역에 도달하면 CC를 토글시킨다. DP는 시계방향으로 돈다. | |
- 색상있는 코델을 찾지 못하고 흰색 전체를 돌았을 경우 종료하고 나온다. | |
색의 사이클은 다음과 같다. 총 6개 색 red -> yellow -> green -> cyan -> blue -> magenta -> red | |
밝기의 사이클은 다음과 같다. 총 3가지의 밝기 light -> normal -> dark -> light | |
특별한 색 두개 흰색, 검은색 | |
18가지+ 2가지 = 20가지색으로 코딩하는거 (다른색을 넣을 경우 검은색으로 취급한다.) | |
Piet는 자료구조를 스택만 사용한다. 자료형도 INT나 Unicode 문자 값만 제공한다. | |
명령어를 다음과 같이 제공한다. | |
Lightness change | |
Hue change None 1 Darker 2 Darker | |
None push pop | |
1 Step add subtract multiply | |
2 Steps divide mod not | |
3 Steps greater pointer switch | |
4 Steps duplicate roll in(number) | |
5 Steps in(char) out(number) out(char) | |
push: Pushes the value of the colour block just exited on to the stack. Note that values of colour blocks are not automatically pushed on to the stack - this push operation must be explicitly carried out. | |
pop: Pops the top value off the stack and discards it. | |
add: Pops the top two values off the stack, adds them, and pushes the result back on the stack. | |
subtract: Pops the top two values off the stack, calculates the second top value minus the top value, and pushes the result back on the stack. | |
multiply: Pops the top two values off the stack, multiplies them, and pushes the result back on the stack. | |
divide: Pops the top two values off the stack, calculates the integer division of the second top value by the top value, and pushes the result back on the stack. If a divide by zero occurs, it is handled as an implementation-dependent error, though simply ignoring the command is recommended. | |
mod: Pops the top two values off the stack, calculates the second top value modulo the top value, and pushes the result back on the stack. The result has the same sign as the divisor (the top value). If the top value is zero, this is a divide by zero error, which is handled as an implementation-dependent error, though simply ignoring the command is recommended. (See note below.) | |
not: Replaces the top value of the stack with 0 if it is non-zero, and 1 if it is zero. | |
greater: Pops the top two values off the stack, and pushes 1 on to the stack if the second top value is greater than the top value, and pushes 0 if it is not greater. | |
pointer: Pops the top value off the stack and rotates the DP clockwise that many steps (anticlockwise if negative). | |
switch: Pops the top value off the stack and toggles the CC that many times (the absolute value of that many times if negative). | |
duplicate: Pushes a copy of the top value on the stack on to the stack. | |
roll: Pops the top two values off the stack and "rolls" the remaining stack entries to a depth equal to the second value popped, by a number of rolls equal to the first value popped. A single roll to depth n is defined as burying the top value on the stack n deep and bringing all values above it up by 1 place. A negative number of rolls rolls in the opposite direction. A negative depth is an error and the command is ignored. If a roll is greater than an implementation-dependent maximum stack depth, it is handled as an implementation-dependent error, though simply ignoring the command is recommended. | |
in: Reads a value from STDIN as either a number or character, depending on the particular incarnation of this command and pushes it on to the stack. If no input is waiting on STDIN, this is an error and the command is ignored. If an integer read does not receive an integer value, this is an error and the command is ignored. | |
out: Pops the top value off the stack and prints it to STDOUT as either a number or character, depending on the particular incarnation of this command. | |
~와 개재밌다ㅋㅋㅋㅋㅋㅋ~ | |
롤(roll)은 매우 유용한 기능이다. | |
스택에서 2개를 꺼내는데 | |
맨위에(첫번째)꺼는 부호로 위로 올릴지 내릴지 정하고 수치로 내리고 올리는 횟수. | |
부호는 양수이면 수치만큼 올린다. 음수이면 수치만큼 내린다. | |
두번째는 양수만으로 롤할 범위를 정한다. 5개 요소를 가지고 순서를 바꿀려면 5이면 됨. | |
ex) 스택에 아래와 같이 7개의 요소가 있는 상태에서 롤을 하면 3범위에서 1 만큼 (+)올리는 것이다. | |
1 | |
3 | |
100 | |
39 | |
77 | |
999 | |
144 | |
결과) | |
39 [한 칸 올라감] | |
100 [한 칸 올라감] | |
77 [맨 위에 있었으므로 맨 아래로 내려옴] | |
999 [범위안에 없으므로 영향없음] | |
144 [범위안에 없으므로 영향없음] | |
이걸 잘 활용하면 숫자 재활용에 유용하다. | |
난 이걸로 (내 프로필을 담은 프로그램 = 케릭터)를 제작하고 있다. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment