GMT

사용자 심볼 만들기 2

작성자
heukchoo
작성일
2021-01-17 20:17
조회
398
 

사용자 심볼 만들기 1에서는 GMT에서 제공하는 사용자 심볼파일(*.def)의 작성방법을 알아보았다.

간단한 형태의 심볼은 먼저 소개한 방법에 따라 만들 수 있을 것이다.
하지만 그림과 같이 복잡한 형태를 심볼로 만들 경우 가능은 하겠지만 매우 어려울 것이다.

 
그 해결방안으로 이번 글에서는 이미지 파일을 GMT 심볼파일로 제작하는 방법을 소개한다.

미리 얘기하지만 해당 방법은 직접 고안한 방법으로 다른 더 좋은 방법이 있을 수도 있다.
또한 과정이 복잡하고 고생스러울 수 있지만 최대한 쉽고 편하게 만들 수 있도록 스크립트도 제공한다.

컬러 이미지의 경우에도 적용 가능하지만 과정이 복잡해 질 수 있으므로 흑백 이미지를 기준으로 설명한다.
과정만 이해한다면 컬러 이미지에도 응용할 수 있을 것이다.(컬러 이미지 사용방법은 추후 작성하겠다.)


전체적인 제작 과정

     1. 레스터 이미지 전처리 및 벡터 이미지로 변환
     2. 벡터값 추출 및 GMT 포맷 데이터로 변환
     3. 심볼객체 검토 및 GMT 심볼파일(*.def) 생성
 

사용 툴

     1. GMT
     2. gawk
     3. potrace
     4. cmd 또는 shell

 

potrace

레스터 이미지를 벡터 이미지로 변환하는 툴이다.

http://potrace.sourceforge.net/

위 주소에서 다운받을 수 있으며 GMT나 gawk 설치방법과 동일하므로 따로 설명하지 않는다.
(윈도우, 리눅스 모두 제공)


cmd 또는 shell

스크립트 사용을 위함이며 이번 글에서는 윈도우 cmd 기준으로 설명한다.

 




1 단계 : 레스터 이미지 전처리 및 벡터 이미지로 변환

 
레스터 이미지는 우리가 흔희 쓰는 jpg, gif, bmp 등의 픽셀로 표현되는 이미지 포맷을 말한다.

벡터 이미지는 그림을 구성하는 각 객체를 수치 등의 코드로 표현되는 이미지로 파워포인트의 도형이나 일러스트레이터의 그림 등이 있다.
(pdf, ps, svg, geojson 등의 포맷이 있다.)

 
심볼을 만들고자 하는 그림은 대부분 레스터 이미지이고, GMT 심볼은 벡터 이미지이므로 변환이 필요하다.
벡터 이미지로 변환하는 것은 그림의 윤곽(객체 경계)을 구분 짓는 과정으로 레스터 이미지가 너무 복잡하거나 해상도가 나쁘면 변환 결과가 좋지 않다.

따라서 먼저 단순하고 해상도가 좋은 레스터 이미지를 준비해야 하고 포토샵과 같은 이미지 툴을 사용해서 윤곽을 뚜렷이 하는 전처리 과정이 필요하다.
(원본이 좋다면 전처리 과정은 건너 뛰어도 된다.)
(potrace에서 제공하는 mkbitmap에서 이런 전처리 기능을 제공하고 있지만 이미지 툴이 많으므로 사용하기 편한 방법을 쓰면 되겠다.)

 
다음은 '드래곤볼 손오공'의 그림을 전처리하는 과정이다.



원본 이미지, 만화책의 스캔 이미지라 해상도가 매우 떨어진다.

 


포토샵으로 처리한 결과
"필터 - 선명효과 - 고급선명효과"와 "이미지 - 조정 - 레벨"을 사용해 윤곽선을 뚜렷이 하고, 지우개와 브러시 툴로 잡티 조정을 하였다.
(파일을 날리고 예시로 다시 만든 것이라 이후 결과와 약간 차이날 수 있다. ^^;)

 
레스터 이미지 전처리의 관건은 선명하고 단순하게 하는 것이다.
위의 포토샵 결과로 벡터화를 해도 충분하지만 아래의 svg로 변환처리하는 한단계를 더 거쳤다.
(전처리가 충분하다면 건너 뛰어도 된다.)

potrace 툴을 사용해 svg 포맷의 벡터 이미지로 변환하였다.
(svg를 사용한 것은 확인을 용이하게 하기 위함으로 큰 의미는 없다.)

 
$potrace   파일명.bmp   -s   -o   파일명.svg
 

potrace에 입력가능한 레스터 이미지 포맷은 많지 않다. bmp 포맷을 사용하자.
-s 옵션은 svg 포맷으로 변환한다는 의미이다.
-o 옵션은 출력파일명 설정으로 옵션 다음에 출력할 파일명을 표기한다.

 
svg 포맷의 벡터 이미지를 확인하는 툴은 다양하지만 프로그램 설치가 필요없는 구글 드라이브를 사용하면 된다.

웹에서 구글 드라이브 페이지로 이동 - 구글 드로잉에서 svg 파일 업로드





위의 그림은 svg 이미지를 캡쳐하여 포토샵이나 그림판으로 간소화한 후 다시 bmp 레스터 이미지로 저장한 것이다.
(눈이나 턱아래 선들을 편집)
 





2단계 : 벡터값 추출 및 GMT 포맷 데이터로 변환


이제 위 이미지를 이용해서 GMT에서 사용하기 위한 벡터 이미지로 변환한다.

GMT의 psxy에서 객체를 그릴때 사용하는 입력값이나 def 파일의 값은 객체 구간구간의 위치값(Way point의 x,y 좌표) 이다.

potrace에서 제공하는 벡터 이미지 포맷 중 구간 위치값으로 저장하는 방식은 geojson이있다.
(더 좋은 포맷이 있다면 댓글을..)

 
$potrace   파일명.bmp   -b geojson   -o   파일명.geojson
 

-b 옵션은 출력 포맷 명을 지정한다. geojson으로 지정했다.
나머지는 위의 설명과 같다.(확장자는 임의로 지정했다.)


geojson의 파일을 워드패드로 열어보면 다음과 같은 형식을 보인다.
{
"type": "FeatureCollection",
"features": [
{ "type": "Feature",
"properties": { },
"geometry": {
"type": "Polygon",
"coordinates": [
[[-0.0, 699.4], [0.0, 665.5], [14.3, 654.7], [17.3, 652.4], [20.6, 649.8], [24.0, 647.1], [27.4, 644.4], [30.7, 641.7], [33.8, 639.2], [36.6, 636.8], [39.1, 634.7], [41.4, 632.7], [44.0, 630.5], [46.7, 628.1], [49.6, 625.7], [52.4, 623.3], [55.2, 620.9], [57.7, 618.8], [60.1, 616.9], [64.8, 612.9], [69.6, 608.7], [74.1, 604.7], [78.3, 601.0], [81.8, 597.6], [84.6, 594.9], [86.4, 592.9], [87.0, 591.9], [86.7, 591.3], [86.0, 591.0], [84.9, 591.0], [83.4, 591.2], [81.7, 591.6], [79.8, 592.2], [77.8, 593.0], [75.8, 593.9],
.
.
 

대괄호로 묶인 무수한 좌표 값을 가지며, Type 지정이나 다시 대괄호로 묶여서 각 객체들이 구분되어 있다.

반면, GMT에서 사용가능한 입력포맷은 다음과 같다.
100   200
100   250
>
200   100
300   230
.
.
 
좌표값이 행별로 나열되어 있고, 꺾쇠(>)로 객체가 구분되어 있다.

GMT에서 사용하기 위해선 위의 geojson 포맷을 아래의 포맷으로 변환해야한다.
이를 위한 스크립트는 아래에 종합하여 제시한다.






3단계 : 심볼객체 검토 및 GMT 심볼파일(*.def) 생성


GMT 입력포맷으로 변환 한 뒤, psxy로 그림을 그려 보았다.



선색을 붉은색으로 사용하였다.
각 객체의 외곽선이 잘 취득 되었다.

여기에 -G 옵션을 사용하여 회색으로 채워보았다.



색채움을 사용했을 때 문제가 발생하게 된다.
원하는 그림은 머리와 옷에만 채움이 적용되는 것이다.

해결 방안으로는 def 파일을 만들 때 머리와 옷을 제외한 나머지 객체에 색을 미리 지정하는 것이다.
(손오공의 피부에 해당하는 부분을 흰색으로)

이를 위해서는 GMT 입력 데이터에서 꺾쇠로 구분된 각 객체가 그림의 어느 부분에 해당되는지를 확인하고 일일히 색을 지정해야 한다.

이 과정에 많은 시간이 소요되는데 최대한 스크립트를 활용하여 편하게 작업할 수 있는 방법을 제시한다.
(물론 위 결과에도 만족한다면 건너 뛰고 바로 def 파일로 변환해도 된다.)

 
다음은 앞의 geojson 벡터 이미지 변환과 GMT 입력포맷 데이터 변환 그리고 각 객체별 확인용 그림을 그리는 스크립트이다.

윈도우 cmd를 기준으로 작성하였고 내용 중 '파일명' 부분을 수정하여 bat 파일로 만들어서 사용하면 된다.
(내용은 주석(REM)을 참고)

 
REM bmp 파일을 geojson 포맷으로 변환
potrace 파일명.bmp -b geojson -o 파일명.geojson

REM geojson 포맷을 GMT 입력포맷으로 변환
gawk "/\[\[/ {sub(/\] \],/,\"\n^>\") ; print $0}" 파일명.geojson | gawk "BEGIN{RS=\"]\"}{print $0}" | gawk "{gsub(/\[|,/,\"\") ; print $0}" > 파일명1.txt

REM GMT 입력포맷 데이터에서 각 객체의 시작점에 해당되는 행번호를 별도로 저장
gawk "BEGIN{value=1} /^>/ { print value ; value=NR+1 }" 파일명1.txt > 파일명2.txt

REM GMT 그림을 그릴때 사용할 -R옵션 값을 계산하여 변수(mm)로 설정
gmt info -C 파일명1.txt | gawk "{print $1\"/\"$2\"/\"$3\"/\"$4}" > var.imsy
set /p mm= gnr && $1 == \"^>\" ) exit ; if ( NR >= gnr ) print $0 }" 파일명1.txt > %%i.imsy_xy

REM 전체 객체 그림(붉은색선)에 각 객체 그림(파란색선)을 덧붙여 작성, 파일명은 시작점 행번호
type 파일명1.txt | gmt psxy -JX5c -R%mm% -W0.1p,red -L -K > %%i.ps
type %%i.imsy_xy | gmt psxy -J -R -W0.3p,blue -L -O >> %%i.ps

REM ps파일을 png파일로 변환
gmt psconvert -A -Tg -P %%i.ps

REM 임시파일 삭제
del %%i.imsy_xy
del %%i.ps

)
 

위 스크립트로 각 객체별 그림을 만들어서 '폴더'에 넣고 '아주 큰 아이콘 보기'로 확인해 보면 각 객체가 전체 그림에서 어느 부분인지 쉽게 알 수 있다.

각 이미지의 파일명은 GMT 입력 데이터에서 각 객체가 시작되는 행번호를 나타내므로 def 로 변환할 때 참고하면 된다.
(손오공은 28개 객체로 구분됐다.)





위의 스크립트를 실행하면 '파일명2.txt' 파일이 생성된다.
'파일명2.txt' 파일은 '파일명1.txt' 파일에서 각 객체의 시작점에 해당되는 행번호를 저장한 것이다.
저장된 행번호 수는 객체수와 동일하다.
('손오공'예제의 경우 28개의 행번호가 나열되어 있다.)

 
'손오공' 예제의 경우 스타일 지정을 하지 않는 객체들(머리, 옷 등)과 스타일 지정을 하는 객체들(피부)의 2개 그룹으로 구분된다.

우선 '파일명2.txt' 파일을 '그룹1.txt'와 '그룹2.txt'의 파일로 복사한다.
그룹1은 스타일 지정을 하지 않는 객체들, 그룹2는 스타일 지정을 하는 객체들로 임의로 정했다.

위 폴더의 그림을 검토하여 '그룹1.txt' 파일에 있는 28개의 객체 행번호를 편집하여 스타일 지정을 하지 않을 객체들의 행번호만 남긴다.

'그룹2.txt' 파일도 마찬가지로 편집하여 스타일 지정을 하는 객체들의 행번호만 남긴다.

 
객체 검토와 그룹 작업이 끝났으면, 다음의 스크립트를 이용해 def 파일을 생성한다.
(앞선 스크립트의 '파일명1.txt'와 '파일명2.txt' 파일이 있어야 한다.)

 
REM 이 스크립트는 전 단계에서 생성된 '파일명1.txt'와 '파일명2.txt' 파일이 있어야 함

REM 사용자 심볼 파일명 지정(def확장자는 제외하고 표기)
set output=파일명

REM 사용자 심볼파일 헤더 생성(#다음의 문자 수정가능)
echo #사용자 심볼입니다. > %output%.def

REM 그룹2의 객체 스타일 지정
set style_g=-Gwhite
set style_w=-W0.1,blue

REM 심볼 중심을 좌표원점으로 변환하기 위한 조정값을 산출하여 변수에 입력
gmt info -C 파일명1.txt | gawk "{ print ($2+$1)/2 }" > cor_varx.imsy
gmt info -C 파일명1.txt | gawk "{ print ($4+$3)/2 }" > cor_vary.imsy
set /p corvx=

REM 그룹1의 def 파일 작성(for 문)
for /F %%i in ('type 그룹1.txt') do (

REM 각 객체별로 GMT 입력포맷 데이터를 분리하고 조정값 적용하여 심볼파일에 저장
gawk -v gnr=%%i -v cvx=%corvx% -v cvy=%corvy% "{ if ( NR > gnr && $1 == \"^>\" ) exit ; if ( NR == gnr ) print $1-cvx,$2-cvy,\"M\" ; if ( NR > gnr ) print $1-cvx,$2-cvy,\"D\" }" 파일명1.txt > %%i.imsy_def

)

 

REM 그룹2의 def 파일 작성(for 문)
for /F %%i in ('type 그룹2.txt') do (

REM 각 객체별로 GMT 입력포맷 데이터를 분리하고 조정값 적용 및 객체 스타일 지정하여 심볼파일에 저장
gawk -v stg=%style_g% -v stw=%style_w% -v gnr=%%i -v cvx=%corvx% -v cvy=%corvy% "{ if ( NR > gnr && $1 == \"^>\" ) exit ; if ( NR == gnr ) print $1-cvx,$2-cvy,\"M \"stg\" \"stw ; if ( NR > gnr ) print $1-cvx,$2-cvy,\"D\" }" 파일명1.txt > %%i.imsy_def

)

 

REM 분리되어 생성된 def파일 병합(for 문)
for /F %%i in ('type 파일명2.txt') do (

type %%i.imsy_def >> %output%.def

)

REM 임시파일 삭제
del *.imsy_def

REM 생성된 심볼을 테스트 하기 위한 그림 작성
echo 0 0 | gmt psxy -JX10c -R-10/10/-10/10 -Ba2 -W0.1,red -Ggray -Sk%output%/0.3p > 테스트.ps
 

위 스크립트에서 파일명은 원하는 대로 수정한다.
(사용자 심볼 파일명도 원한다면 지정)

중요한 것은 파란색으로 표시한 객체 스타일 지정 변수의 선언과 for 문이다.

객체 스타일 지정 변수 선언에서, 그룹2의 객체는 흰색으로 채울 것이므로 -Gwhite 옵션을 썼다.

또한, 객체의 테두리 선의 굵기와 색을 지정했다.
(테두리 선은 테스트를 위한 것으로 추후에는 제외하였다.
'-W0.1p,blue' 부분만 삭제하면 된다.)

 
스크립트에 for 문이 3개 작성되어 있는데, 마지막의 for 문은 def 파일 병합용으로서 수정할 필요 없다.
(다만, 스크립트 내에 위치는 for 문 중에서 마지막에 두어야 한다.)

그 위의 for 문은 그룹1과 그룹2의 def 파일을 생성한다.

두 번째 for 문(그룹2)은 스타일 지정을 위해 gawk 명령의 -v 옵션으로 앞서 선언한 'style_g'와 'style_w' 변수를 사용하였다.

 
만일 만들고자 하는 심볼의 객체 그룹이 3개 또는 그 이상이라면 위 스크립트에서 style 변수 지정과 해당 그룹의 for 문을 추가해야 한다.

 
마지막 행은 테스트 이미지를 생성하기 위한 것으로 예제의 결과는 다음과 같다.
 



원하는 대로 피부 부분은 흰색으로 표현되었다.

원본 그림의 크기 때문에 def의 좌표 범위가 0~700정도가 되는데 이 때문인지 심볼의 크기를 0.3p로 매우 작게 그려야 위의 그림 크기가 된다.
(거슬리는 부분이지만, 심볼 크기를 조정하면 되니 문제는 없다.)

 테두리선 스타일을 삭제하고 goku.def 로 다시 제작한 뒤 다양한 조건의 심볼 옵션을 주어 그려보았다.

 
echo -100 30 0.1p > symbol_position_size.dat
echo 40 -70 0.05p >> symbol_position_size.dat

gmt pscoast -JM15c -R0/360/-80/80 -Ba40f20/a20f10WeSn -Df -S190/240/250 -G250/250/190 -W0.1p,100/100/100 -N1 -K > test.ps

type symbol_position_size.dat | gmt psxy -J -R -B -Skgoku -Gblack -K -O >> test.ps

echo 100 60 0.08p | gmt psxy -J -R -B -Skgoku -Wred -K -O >> test.ps

echo 160 -20 0.1p | gmt psxy -J -R -B -Skgoku -Ggreen -W0.2p,red,. -K -O >> test.ps

echo -60 -30 0.05p | gmt psxy -J -R -B -Skgoku -Gblue -O >> test.ps
 



 
좀 더 연구해서 보다 편리하게 제작하는 방법을 고민해봐야 겠다.

 
전체 0