2D 게임에서의 이미지 정밀도 줄이기 : ImageMagic 소개
모바일 게임을 제작하다보면 메모리 혹은 패키지 용량 문제로 이미지 파일의 크기를 최소화 시키는 것이 중요하지요. 특히 2D 게임의 경우 더더욱 중요하지요. 그러한 관점으로 이미지를 줄이는 데 있어 많은 방법이 동원되곤 하지요. 버튼같은 경우 9분할 이미지를 사용한다거나, 이펙트같은 경우는 half-size로 줄이는 등등의 여러 방법이 동원되곤 하지요.
출처 : http://renderhjs.net/shoebox/slice9.htm
이러한 이미지 면적 자체를 줄이는 것도 중요하지만, 이미지 정밀도를 낮추는 것도 중요하지요. 픽셀당 4바이트를 차지하던것을 정밀도를 줄여서 2바이트로만 바꿔줘도 크기는 반으로 확 줄어들게 되는 것이지요. 하지만 그 대신 정밀도가 줄어드는 만큼 색의 경계가 두드러지게 티나게 되는 부작용이 발생하게 되지요. Mach Band 또는 Banding Artifacts등으로 불리기도 하는데 이는 디더링 과정을 통해서 극복을 가능케 하지요.
출처 : http://www.codeandweb.com/texturepacker/features
이러한 정밀도를 낮추고 디더링을 해주는 과정은 2D 게임 제작에 있어 매우 중요한 영역을 차지하기 때문에 기능을 지원해주는 툴들이 존재하지요. 그 중 대표적인게 TexturePacker라는 툴이지요. 이 툴은 이미지들을 하나의 이미지 시트로 묶어주어 렌더링 배치를 줄일수 있는 기반을 마련해주기도 하지요. ( 사실 그게 주 기능이지요) 때문에 유니티로 개발을 하던 코코스로 개발을 하던 코로나로 개발을 하던 상관없이 이러한 툴들은 필수적으로 사용이 되어야 하지요. 스프라이트 시트에 대한 설명은 제가 주저리주저리 하는 것 보다는 두 영상이 더 이해하시기 쉬울 것 같네요. ( 뭐 사실 다들 아시는 내용이니 걍 대충 넘어가려구요 ㅋ)
하지만 모든 이미지를 시트로 묶어야만 하는 것은 아니죠. 오히려 시트로 여러 이미지를 묶는 것이 독이 되는 경우도 있지요. 예를 들자면 상점 혹은 인벤토리에서의 아이템 이미지가 있을거예요. 아이템의 이미지들을 하나로 묶은 시트가 있다고 가정해볼까요?
근데 정작 이 시트에서 필요한것은 고작 칼 한자루 뿐인 상황이예요.
게다가 방패, 갑옷, 투구 등등이 각각 서로 다른 스프라이트 시트에 있다면 재수없으면 필요한 정작 이미지의 백배가 넘는 메모리가 낭비 될 수도 있을거예요. 그래서 이러한 경우는 그냥 각각 이미지가 별개의 파일로 존재하는게 나을 수도 있을거예요. ( pow2문제나 서칭 비용 고민은 잠시 내려놓아요 <-무책임ㅋ)
근데, 이때 문제가 발생하네요. 수십여장의 이미지들을 정밀도를 낮추고 디더링을 적용할라니 막막하네요. 포토샵에서 일일이 저장할떄 신경써서할라니 빡세요. 어랏? 알씨가 일괄적으로 이미지 포맷을 변경해주는 기능이 있네요. 컥! 근데 알파채널이 날라갈 뿐더러 디더링 따위는 해주지도 않아요. TexturePacker에서 처리가 가능하지만 이태리 장인마냥 파일을 한땀한땀 찍을라니 성질부터 뻗치네요.
그렇다면 한방에 이미지들의 정밀도를 낮추고 디더링 할 수 있는 방법은 없는것일까요? 왜 없겠어요 있으니 이렇게 제가 글을 싸지르는 것이겠지요. (사실 앞선 내용들은 이를 설명하기 위한 밑밥인걸요 ㅋ) 바로 그 마법이 가능한 ImageMagic 이란 툴을 소개하고자 해요. 사실 아까까지만 해도 이런 고민으로 찾아보다가 지인분의 소개로 마법을 접하고나서 기쁨을 감추지 못하고 똥글을 싸제끼고있네요 ㅎ 요놈 참 물건이더군요. 이미지 포맷 변환 외에도 많은 기능이 존재하는데 커맨드 라인 기반이라 활용도도 매우 높겠더군요. 게다가 오픈소스(라 쓰고 무료라 읽는다)네요. 거두절미하고 일단 받아서 설치 ㄱㄱ 하세요
http://www.imagemagick.org/script/binary-releases.php#windows
그리고 명령 프롬프트 창을 열어서 이미지 파일이 있는 디렉터리로 이동한뒤 다음과 같이 치면 포맷을 변환해요.
convert -dither FloydSteinberg -colors 64 원본.png 대상.png
딱 보시면 옵션중 dither는 디더링 알고리즘을 선택하는 옵션인 것은 알겠어요.(사실 없어도 기본적으로 활성화 되요) 근데 어랏 비트뎁스를 지정하는 것이 아니라 colors란 옵션을 지정하네요. 물론 depth라는 옵션으로 설정 할 수도 있어요. 하지만 colors란 옵션을 통하면 더 많은 용량을 절약할 수 있더라구요. 이 옵션은 말 그대로 몇개의 컬러를 사용 할 것인지를 나타내는 것이예요.
출처 및 참고 : http://www.imagemagick.org/Usage/quantize/#colors
PNG는 팔레트 기반 데이터를 제공하기때문에 총 색 수를 줄여서 용량을 줄일 수 있는 게 가능한가봐요. (이게 OpenGL ES에 올라갈때도 유효한가까지는 잘 모르겠네요;; 누가 알려주세요 ㅠ) 그리고 그 그 제한된 수의 색을 지정하는 데 있어 일정한 간격의 색차를 선택하는 것이 아니라 가변공간분할(Adaptive Spatial Subdivision) 알고리즘을 이용해서 선택한다고 하네요. 가변 공간 분할이 3D 렌더링할 때 컬링 공간 분할때나 봤었지 이미지 변환에서도 쓰이는 줄을 몰랐네요. 싱기방기 ㅋ 정확히 뭐 어떻게 되는건지는 잘 모르겠는데 아래 이미지를 보면 대충 느낌은 오는 것 같네요. (맞나? 맞겠죠?) colors 옵션 뿐만 아니라 다양한 옵션들이 있어서 마음만 먹으면 입맞에 맞게 세세하게 컨트롤이 가능 한 것 같아요.
출처 : http://www.flickr.com/photos/quasimondo/4251382278/sizes/m/in/photostream/
암튼 그래서 커맨드 라인을 통해서 이미지를 컨버팅 할 수 있는데 귀챦은게 하나 있어요. 소스 이미지를 "*.png"로 설정이 가능하지만 이렇게 되면 원본에 덮어 쓰는게 아니라 0.png, 1.png 등 그냥 순차적인 넘버링으로 나와버리는군요. 배치 스크립트로 디렉터리 내 파일 순회하면서 수행토록 해야겠군요. 다음과 같은 내용의 bat 파일을 만들어서 사용을 하면 한시름 덜게되었네요.
for %%f in (*.png) do convert -dither FloydSteinberg -colors 64 %%f %%f
아 이제 끝났네요. 디렉터리내 모든 이미지를 변환하는 저 한문장을 설명하기 위해 주저리 주저리 밑밥이 많았네요. 걍 처음부터 저것만 써놓으면 될것을 말이예요. 그러게 쓰다보니 왜그랬을까 싶네요 ㅋ 간만에 쓰는 글이라 손가락이 간질 간질 했나봐요. 늙으면 말이 많다더니 점점 타이핑이 늘어나는군요. 얼마전 꿈돌이가 성년이 되었다는 소식을 듣고 충격먹어서 제정신이 아닌가봐요. 그냥 나이먹더니 깨랑까랑하나부다 하고 이해해주세요 ㅎ 그럼 모두들 즐개발~