델파이/C++빌더는 최근의 2010 버전에서부터 WIC(Windows Imaging Components)를 통해 TIFF와 RAW 포맷까지 지원하게 되었습니다. 이제 지원하는 델파이와 C++빌더에서 지원하는 이미지 포맷은 BMP, ICO, WMF/EMF, JPG, GIF, PNG, TIFF, RAW까지 늘어났습니다. 이제 웬만하면 따로 그래픽 포맷을 위한 외부 라이브러리를 쓰지 않아도 될 정도가 됐죠.
PNG 이미지는 델파이와 C++빌더의 2009 버전부터 기본적으로 지원이 되는데요. JPG나 GIF도 좋은 포맷이고 흔히 사용되지만, PNG 포맷은 여러모로 더 특별한 면이 있습니다. PNG의 탁월한 장점을 몇 가지 들어보면…
1. 자연색의 사진을 표현할 때, 유손실 압축인 JPG에 비해 PNG는 무손실이기 때문에 화질이 더 좋습니다. 물론 유손실인 JPG 포맷의 장점이 파일 크기의 최소화에 있기는 하지만, 파일 크기를 줄이기 위해 압축률을 높이면 화질 손실이 커집니다. PNG는 원본 화질을 100% 그대로 유지하면서도 크기는 최소화됩니다.
2. GIF와 비교하면 PNG는 같은 무손실 압축이면서도 압축률이 더 높습니다. 무손실 압축 차원에서 사진 압축률은 GIF를 압도합니다. (개인적으로, 디지털카메라에서 JPG 외에 선택을 RAW가 아닌 PNG로 하면 좋겠다는 생각이 듭니다)
3. GIF는 오직 256 컬러에서만 투명 효과가 가능합니다. GIF의 원래 표준이 8비트 컬러였기 때문인 것 같습니다. 따라서 GIF 포맷에서 투명 처리를 하려면 화질이 떨어질 수밖에 없는 8비트 컬러만 사용할 수 있습니다. (위의 주사위 샘플 이미지가 그 단적인 예입니다)
4. 투명 효과에서 있어서는, 단순히 투명 색깔만 지정할 수 있는 GIF와 달리, PNG의 투명 효과는 반투명까지 가능한 알파채널 방식입니다.(일반적인 32비트일 경우) 그래서 훨씬 미려한 효과를 낼 수 있죠. 컬러를 표현하는 32비트 중에 알파채널 값이 8비트이기 때문에, 실제 컬러 표현에는 24비트만 사용됩니다. 덕분에 애플리케이션이나 웹의 아이콘 등의 UI를 표현할 때 더없이 미려한 모양이 나옵니다. 알파채널 효과가 들어간 아이콘과 단순한 투명/불투명 아이콘은 하늘과 땅 차이의 느낌입니다.
5. 이것은 알파채널로 인한 부수적인 장점인데, 32비트 컬러에서 알파채널이 되기 때문에 이미지의 가로/세로를 줄여서 보여줄 경우에도 안티알리어싱이 거의 나타나지 않고 부드럽게 표시됩니다.
이번 포스트의 주제는, 이런 PNG 이미지를 델파이와 C++빌더의 UI 디자인에서 쓰는 경우 알파 채널 적용이 제대로 되지 않는 경우의 원인과 해결책에 대한 것입니다.
델파이나 C++빌더에서 PNG 이미지를 TImage에 올리거나 TBitBtn에 올렸을 때에는 아무런 문제도 생기지 않습니다. 그런데 TImageList에 올리려고 했을 때는 좀 골치아픈 문제가 생깁니다.
툴바, 리스트뷰, 트리뷰아이콘이나 TButton에 새로 지원되는 이미지 기능 등을 사용하려면 이미지리스트에 올려서 연결해야 하는데요. 이렇게 이미지리스트에 png 이미지를 올리면, 투명하게 나타나야 할 영역이 까맣게 나타나는 경우가 있습니다.
이미지리스트에 PNG 이미지를 올렸을 때 투명색이 제대로 나타나지 않는 이런 현상의 이유에는, 두가지 원인이 있습니다.
먼저, 이미지리스트에 PNG 이미지를 올렸을 때 투명 효과가 나오려면, 이미지리스트의 ColorDepth 속성이 cd32Bit로 되어 있어야 합니다. (기본값은 cdDeviceDependent 입니다)
이것은 당연한 문제로, 투명 효과 처리가 된 PNG 파일이 32비트 포맷(컬러 24비트, 알파블렌딩 8비트)이므로, 알파 채널 데이터에 따라 제대로 투명하게 표현하려면 당연히 32비트가 되어야 합니다.
(개발자들 사이에서는 이 문제와 관련하여 DrawingStyle 속성도 dsTransparent로 해야 한다는 말도 있는데, 여러 가지로 테스트해본 결과 아무런 관련이 없었습니다)
다른 하나는, 좀 황당할 수도 있는 문제인데… 개발자 PC의 화면 컬러수가 32비트 컬러여야 합니니다. 개발자 PC의 화면 컬러가 32비트보다 적은 8비트 컬러 즉 256 컬러 상태이면 투명 효과가 나타나야 할 부분이 까맣게 나타나게 됩니다. 요즘에야 개발자 PC가 32비트 컬러가 안되는 경우가 그리 많지는 않겠지만, 메모리 등의 문제로 일부러 화면 컬러수를 16비트로 낮추는 개발자들도 간혹 있을 것입니다. 또 개발 PC를 원격 접속하는 경우에도 터미널 서비스에 의해 강제로 16비트 컬러로 설정된 화면을 보게 됩니다.
여러번 테스트해본 결과, 여기서 ‘개발자 PC’라는 조건은, 더 정확히 말하자면 이미지리스트에 PNG 이미지를 추가하는 순간 화면 해상도의 문제입니다. 즉 PNG 이미지가 추가되는 시점에 화면 해상도가 32비트 컬러여야 합니다. 그러니까, 이 문제는 런타임에 발생하는 문제가 아니라 디자인타임에 PNG가 추가되는 순간의 처리에 문제가 있어서 추가되는 시점에 이미 투명 설정이 깨져 들어가는 것입니다.
다시 말해, 이 문제를 비켜가는 한 가지 방법은, 실제 개발자 PC는 32비트 컬러가 아니더라도, 32비트 컬러인 다른 PC에서 이미지리스트에 png 이미지를 추가한 후 그 이미지리스트 컴포넌트를 그대로 텍스트로 복사해서 개발자 PC의 폼디자이너에 붙여넣으면 된다는 얘기입니다.
(이 문제는 델파이/C++빌더 XE 버전에서는 다른 방식으로 해결되어서, 32비트 컬러가 아닌 상태에서 PNG 이미지를 추가하더라도 정상적으로 알파채널 투명 처리가 됩니다)
이 건과 관련이 있는 한 가지 추가 정보를 알려드리면… 폼 디자인 상태에서 TImage 컴포넌트는 JPG나 GIF, PNG 등의 이미지를 추가하면 원본 이미지의 포맷 그대로 폼에 저장하지만, TImageList의 경우는 PNG 이미지를 내부적으로 비트맵으로 변경하여 저장합니다. 따라서 디자인타임에 정적으로 이미지리스트에 PNG 이미지를 추가한 경우, PNG의 압축으로 실행 파일 크기 감소 효과가 없습니다. 만약 아이콘으로 PNG를 아주 많이 사용해서 그 크기를 줄이려는 목적이라면, PNG 이미지들을 별도의 리소스로 저장해둔 후 런타임에 이미지리스트로 불러들여서 써야 하겠지요.
하나더 추가적으로 말씀드리자면 Project – Option – Application – Enable runtime themes에 체크박스를 해제해도 저렇게 검정색으로 나옵니다. 즉, 매니페스트와도 관련 된 문제일 수 있습니다.
ㅇ ㅏ.. 좋은 정보네요… PNG 추가 할려했더니.. Transparent가 안먹어서 한참 고생 했습니다.. ㅜㅜ
정말 그렇네요. 정보 감사합니다. ^^
비트버튼이나 스피드버튼에서 bmp 외의 jpg나 png등 다른 포맷의 이미지는 사용할 수 없습니까?
TImage에는 TPicture 타입의 Picture 속성이 있죠. 여기에는 다시Graphic 속성이 있고, 이 속성의 타입은 TGraphic이므로 그에서 상속받는 TBitmap, TJPEGImage, TGIFImage, TPNGImage, TWICImage 등을 모두 사용할 수 있습니다.
반면 TBitBtn이나 TSpeedButton의 Glyph 속성은 TPicture가 아닌 TBitmap 타입입니다. 따라서 TBitmap 이외의 어떤 그래픽도 올릴 수가 없습니다. 물론, jpg나 gif 등이 꼭 필요하다면, 동적으로 코드에서 Bitmap으로 Assign해서 올릴 수는 있죠.
사실.. 생각해보면 TBitBtn이나 TSpeedButton은 최근에는 효용성이 많이 낮아지고 있습니다. 특히 TBitBtn의 경우는 TButton에서 이미지 지원이 되고, 게다가 이미지 지원 방식이 TBitBtn에 비해 더 강력하고 유연한 ImageList 연결 방식이기 때문에 TBitBtn을 쓸 일은 거의 없다시피 하죠.