본문 바로가기

프로그래밍/Swift

UIGraphicsBeginImageContext의 사용과 알파 채널의 관계

728x90
반응형

영수증 용지를 인쇄하는 기능을 만들던 중 아주 기이한 버그를 발견했다. 인쇄용지 하단에 바코드 이미지를 넣어야 하는데 기존에 사용하던 A 프린터에서는 아무 문제없이 잘 출력이 되는 반면, 새로 도입한 B 프린터에서는 바코드 주변에 테두리가 형성되는 것이다.

 

왼쪽 - A프린터에서 인쇄된 바코드, 오른쪽 - B프린터에서 인쇄된 바코드 예시

 

의심 1) A 프린터에서는 발생하지 않고 B 프린터에서만 발생하기 때문에 B 프린터에 문제가 있다.

첫 번째 의심에 대한 사실이 아니었다. iOS 14 버전에서는 테두리가 발생하지 않았지만 그보다 하위 버전에서만 테두리가 발생한 것이다.

 

의심 2) iOS 14보다 낮은 버전에서 발생하는 버그이다.

iOS 버그인지 확인하기 위해 iOS 14 이하 버전의 환경에서 비슷한 소스코드를 공유하는 다른 앱을 통해 프린팅을 시도했지만 테두리가 발생하지 않았다. 즉, B 프린터 문제도 아니고 iOS 버전 문제도 아닌 소스코드에서 발생한 문제라는 게 확인됐다.

 

테두리 없이 정상적으로 잘 프린팅 되는 앱(B)의 소스코드와 문제가 발생한 앱(A)의 소스코드를 한 줄 한줄 비교해본 결과 차이점을 발견했다. A 앱은 UIGraphicsBeginImageContext을 통해 비트맵 이미지를 생성했고, B 앱에서는 UIGraphicsBeginImageContextWithOptions 사용하고 있었다. 이 둘에 무슨 차이가 있길래 다른 이미지의 결과를 가져온 것일까?

UIGraphicsBeginImageContext(size) // A 앱
        
UIGraphicsBeginImageContextWithOptions(size, false, 0) // B 앱

 

UIGraphicsBeginImageContextsize만을 매개 변수로 받는 반면에 UIGraphicsBeginImageContextWithOptionssize, opaque, scale 세 가지의 매개 변수를 받아서 처리한다.

 

바코드 이미지에 테두리를 만들어낸 원인은 opaque 매개 변수로, 이미지의 불투명 여부를 받는다. 즉, 해당 비트맵 이미지가 '불투명'하다는 것을 인지하고 있을 경우 opaque를 true로 설정하면 되고, 알파 채널을 무시하고 무조건 불투명한 이미지를 만들어 낸다. opaque를 false로 설정하게 되면 비트맵 이미지가 가지고 있는 알파 채널에 따라 그 이미지의 투명도가 결정되도록 한다.

 

따라서 해당 바코드 이미지의 경우 실제 데이터 이미지는 알파 채널에서 불투명하도록 설정되어 있었을 테고, 테두리 border는 투명하게 설정되어 있었을 것이다. 따라서 opaque의 값에 따라 테두리의 불투명도가 결정된 것이다.

 

그런데, 이렇게 잠정 결론을 내리고 다시 생각해보니, 이 결론에 따르면 UIGraphicsBeginImageContext에서 opaque의 default값은 true라는 얘기가 되는데, 좀 석연치 않아서 문서를 살펴봤다.

 

developer.apple.com/documentation/uikit/1623922-uigraphicsbeginimagecontext

 

"This function is equivalent to calling the UIGraphicsBeginImageContextWithOptions(_:_:_:) function with the opaque parameter set to false and a scale factor of 1.0."

 

역시 UIGraphicsBeginImageContext의 opaque 기본값은 false로 되어있었다. 그렇다면 scale의 문제인가?

function 테두리 유무
UIGraphicsBeginImageContext(size)
(= UIGraphicsBeginImageContextWithOptions(size, false, 1.0)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
UIGraphicsBeginImageContextWithOptions(size, true, 1.0)
UIGraphicsBeginImageContextWithOptions(size, true, 0)

 

해당 테스트에 따르면, 테두리는 opaque가 true로 설정되어 있을 때 무조건 나타나고, opaque가 false로 설정되어 있더라도 scale이 1.0일 때 나타난다. 아무리 생각해도 이해가 안 되는 결과다.

 


 

테두리를 없애는 데는 성공했으나, 명확한 원인이 규명되지 않았다. 해당 의문점에 대해서는 조금 더 조사가 필요하여 다시 판단해야 할 필요가 있어 보인다. Apple 문서를 다시 한번 살펴보고 다른 이미지를 통해 다양한 테스트를 해 본 후 다시 결론을 내려야 할 것 같다.

반응형