제가 이 블로그를 통해서 한동안 mp4 형식의 동영상 컨텐츠를 만드는 방법 및 예제들을 종종 소개를 드려왔었습니다. 사실 IDL에서 만들 수있는 유사한 성격의 컨텐츠로서는 오늘 소개하고자 하는 anination GIF도 있습니다. 물론 엄밀히 말하면 동영상 형식의 파일이라고 볼 수는 없지만, 시각적으로는 사실상 동영상이라고 봐도 무방한 방식입니다. 예전에 animation GIF 제작 예제를 한 차례 소개해드린 적이 있었습니다(링크 참조). 여기서 소개되었던 예제의 경우는 DG(Direct Graphics) 기반의 방법이었던 반면, 오늘 소개해드릴 방법은 NG(New Graphics) 기반입니다. 즉, NG 기반으로 구현된 그래픽의 컨텐츠를 변화시켜가면서 각 스냅샷을 개별 프레임으로 집어넣어 animation GIF 파일로 만들어내는 예제를 보기로 하겠습니다.
먼저 기반이 되는 그림을 그려 봅시다. 다음과 같이 SINE 곡선을 그리기 위한 x, y를 준비하고 이를 PLOT 함수에 투입하면서 적절히 속성들을 조절하였습니다. 이렇게 하면 다음과 같은 간단한 SINE 곡선을 그릴 수 있습니다.
x = FINDGEN(361)
y = SIN(x*!DTOR)
win = WINDOW(DIMENSIONS=[600, 500])
p = PLOT(x, y, XRANGE=[0, 360], YRANGE=[-1, 1], XTICKINTERVAL=90, $
COLOR='magenta', THICK=2, /CURRENT)
이제 이 그림의 특성을 조금씩 변화시키면서 각 스텝을 ani-gif 파일의 프레임으로 넣기 위한 준비가 필요합니다. 여기서는 SINE 곡선의 폭(amplitude)을 +1부터 -1까지 0.02의 간격으로 변화시켜보겠습니다. 즉, 이러한 단계를 밟아나가면 곡선의 형태가 순차적으로 변화하게 되는데요. GIF 생성에 앞서 그냥 화면상의 그래픽으로만 이 변화를 표출하기 위하여 다음과 같은 내용을 작성하였습니다.
amps = -FINDGEN(101)*0.02+1
FOR j = 0, N_ELEMENTS(amps)-1 DO BEGIN
y = SIN(x*!DTOR)*amps[j]
p.SetData, x, y
ENDFOR
여기서는 먼저 진폭에 해당되는 값들을 amps라는 배열로 만듭니다. 그리고 반복문 안에서는 y에 해당되는 배열을 얻는데 있어서 이 진폭을 곱해주도록 하고, 이렇게 변화된 y가 곡선의 형태에 반영될 수 있도록 해줍니다. 이를 위하여 플롯 개체에 대하여 SetData 메서드를 적용하였습니다. 이 SetData 메서드에 관한 자세한 내용이 혹시나 궁금하시다면 이 링크를 참조하시기 바랍니다. 이 내용이 제대로 실행되면, 아마 SINE 곡선의 패턴이 연속적으로 변하는 모습을 화면상에서 볼 수 있을 것입니다.
이제 화면상으로 보이는 이러한 변화를 ani-GIF 파일의 형태로 담아보고자 합니다. 이를 위해서는 방금 위에서 봤던 프로그램의 내용에 ani-GIF 생성을 위한 내용들이 추가되어야 합니다. 이러한 내용이 추가된 버전은 다음과 같습니다.
amps = -FINDGEN(101)*0.02+1
wfile = 'anim_plot_ng.gif'
FOR j = 0, N_ELEMENTS(amps)-1 DO BEGIN
y = SIN(x*!DTOR)*amps[j]
p.SetData, x, y
cap = win.CopyWindow()
frame = COLOR_QUAN(cap, 1, r, g, b)
WRITE_GIF, wfile, frame, r, g, b, /MULTIPLE, DELAY_TIME=10, REPEAT_COUNT=0
ENDFOR
WRITE_GIF, wfile, /CLOSE
이전의 내용과 비교해서 달라진 부분들을 보면, 먼저 생성하고자 하는 GIF 파일의 이름을 wfile이라는 변수로 담았습니다. 그리고 반복문 안에서는 세 줄이 추가되어 있는데요. 먼저 그래픽창의 내용을 캡쳐하여 이미지 배열로 가져오는 CopyWindow라는 메서드가 사용되었습니다. 이 메서드는 마치 DG 체계의 TVRD 함수와 유사한 역할을 수행합니다. 다만 여기서 유의할 점은, 캡쳐하여 가져오는 이미지 배열이 8비트 단색광이 아닌 24비트 RGB 기반의 형태라는 점입니다. 이것이 왜 유의할 점이냐 하면, GIF라는 포맷은 그 특성상 RGB기반의 이미지를 받아들이지 못합니다. 8비트 기반의 단색광으로 된 이미지만이 GIF로 저장이 가능합니다.
따라서 캡쳐된 24비트 이미지를 8비트 이미지로 변환하는 과정이 중간에 필요한데, 그 변환의 역할을 담당하는 것이 바로 COLOR_QUAN이라는 함수입니다. 이 COLOR_QUAN 함수를 실행하면, 24비트였던 cap의 내용을 8비트 기반의 배열인 frame으로 바꿔줍니다. 다만, COLOR_QUAN 함수의 내용을 보면 r, g, b라는 인수들도 보이는데, 이들은 입력인수가 아니라 출력인수입니다. 즉, 사전에 값을 정의해서 투입하는 값들이 아니라, 원래 존재하지 않았지만 COLOR_QUAN 함수가 실행됨으로써 얻어지게 되는 인수들입니다. 이 r, g, b는 8비트 형태로 만들어진 이미지 배열인 frame의 개별 화소값들이 0~255의 256단계로 나눠지는데 있어서 각 단계 값마다 어떤 색상이 부여되어 있는가에 대한 약속, 즉 컬러테이블 정보를 담게 됩니다. 이 r, g, b는 바로 뒤에 이어서 사용되는 WRITE_GIF 명령에서 입력인수로서 활용되기 위하여, 이렇게 COLOR_QUAN을 통하여 얻은 것이라고 보면 됩니다.
그리고 WRITE_GIF 명령을 보면 기본적으로 파일(wfile)과 이미지 배열(frame)이 입력인수로서 들어갑니다. 그런데 그 외에도 추가된 키워드들이 보이는데, 모두 ani-GIF를 만들기 위한 옵션들이라는 점을 주목해야 합니다. 먼저 /MULTIPLE 키워드는 말 그대로여러 장의 이미지들이 하나의 GIF 파일에 들어가도록 할 것이라는 의미입니다. 그리고 DELAY_TIME 키워드는 각 프레임별 이미지사이의 간격을 1/100초 단위의 시간으로 나타내는 정수값이 됩니다. 따라서 이 값이 10이라면 1/10초가 되는 셈이고, 그 역수로 따져보면 1초당 10 프레임이 돌아간다는 의미가 됩니다. 100이라면 1초에 1 프레임인 셈입니다. 그리고 REPEAT_COUNT라는 키워드는 ani-GIF 파일이 재생될 때 처음부터 마지막 프레임까지의 한 사이클을 총 몇 번 반복하도록 할 것이냐를 명시하는 것인데, 이값을 0으로 하면 무한 반복 재생하라는 의미입니다. 즉, 반복문내에서 이러한 명령들이 실행됨으로써 GIF 파일에 각 스텝별 스냅샷을 프레임으로 하나하나 삽입됩니다. 그리고 반복문이 모두 종료된 후에는 WRITE_GIF 명령을 /CLOSE 키워드와 함께 사용함으로써 파일에 쓰기 과정을 명시적으로 종료해줘야 합니다.
이러한 모든 과정들이 수행되면 anim_plot_ng.gif라는 animation GIF 파일이 생성됩니다. 그 모습은 다음과 같습니다.
이 파일의 경우는 초당 10 프레임의 속도로 재생되도록 만들어진 케이스입니다. 만약에 DELAY_TIME 키워드의 값을 2로 설정하면초당 50 프레임의 빠른 속도로 재생되는 파일을 만들 수도 있습니다. 다음 그림이 이렇게 만들어진 경우입니다.
결국 animation GIF 형식의 동영상을 만드는데 있어서 신경써야 할 부분은 크게 두가지입니다. 첫번째는, 각 프레임별 스냅샷을 어떻게 만들 것인가에 대한 것인데 이것은 아무래도 전체적인 흐름 및 시나리오를 어떻게 구성할 것인가에 의한 실제 컨텐츠의 설계 및 구성에 관한 문제가 됩니다. 전적으로 프로그래머의 기획력(?)에 달려 있다고 보면 됩니다. 두번째는, GIF 포맷의 특성상 8비트 256단계의 화소값 기반의 이미지만 지원된다는 점입니다. 따라서 다양한 컬러 표현이 필요한 이미지(인물사진, 풍경화 등)의 경우는 사실 GIF 포맷에 적합하지는 않습니다. 하지만, 오늘 예제로 본 그림처럼 색상 구성이 복잡하지 않은 경우라면 큰 문제가 되지는 않을 것입니다.
오늘은 NG 체계에서의 방법으로 소개를 드렸지만, DG 체계의 경우도 큰 흐름은 유사합니다. 다만 프레임별 그림을 그리고 그 화면을 캡쳐하는데 있어서 DG 체계의 방법들이 사용되어야 한다는 점만 다를 뿐입니다. 나중에 기회가 된다면, 오늘 소개된 내용을 기반으로 DG 체계에서의 방법도 소개해보기로 하겠습니다.
'IDL > New Graphics' 카테고리의 다른 글
NG체계에서 다중 플롯 그리기 (Multi-Plot in NG) [1] (0) | 2016.02.17 |
---|---|
CLIP 속성의 이해와 응용 [1] (0) | 2016.01.29 |
플롯위에 이미지 중첩하기 (0) | 2016.01.06 |
에러바(Error Bar)의 표출 (0) | 2015.12.17 |
플롯(Plot)을 다중으로 중첩하여 표출하는 방법 (축까지 추가) (0) | 2015.12.14 |