최근 Swift 에서 이미지 리사이징을 위해서 코드를 찾아 봤던 적이 있다.
UIImage를 매개변수로 받아서 UIImage를 반환값으로 가지는 Function을 가져와서 사용하였는데
코드의 내용은 아래와 같았다.
/// UIKit에서 이미지 리사이징
/// 원본: UIImage, 결과: UIImage
func resize(image: UIImage, scale: CGFloat,
completionHandler: ((UIImage?) -> Void)?)
{
let transform = CGAffineTransform(scaleX: scale, scaleY: scale)
let size = image.size.applying(transform)
UIGraphicsBeginBeginImageContext(size)
image.draw(in: CGRect(origin: .zero, size: size))
let resultImage = UIGraphicsGetImageFromCurrentContext()
UIGraphicsEndImageContext()
completionHandler(resultImage)
}
출처 : https://soooprmx.com/archives/9670
처음에 코드에 대해서 자세히 살펴보지도 않고 scaleX, scaleY에 원하는 사이즈를 입력하여 코드를 실행 했더니 전혀 작동을 하지 않았다.
그래서 리사이징에 대해서 더 검색도 해보고 여기저기 자문을 구한 결과 다른 방식으로 사이즈 값을 지정할 수 있다는 사실을 알게 되었고 일단은 다른 방식으로 사이즈 값을 지정 해주도록 했다.
그 방식의 코드는 아래와 같다.
func resize(w: CGFloat, h: CGFloat, completionHandler: ((UIImage?) -> Void))
{
let size = CGSize(width: w, height: h)
UIGraphicsBeginImageContext(size)
self.draw(in: CGRect(x: 0, y: 0, width: 480, height: 640))
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
guard let img = resultImage else {
print(" [ FAIED TO IMAGE RESIZING ] ")

return
}
completionHandler(img)
}
CGSize로 방식을 바꿔 주니 정상적으로 리사이징이 작동했다.
그렇다면 두 방식에 어떤 차이가 있는걸까? 일단 두 방식 모두 이미지 크기 조절을 하는 함수는 맞다.
CGAffineTransform(scaleX:Y:)
에 대해서 알아보자
Returns an affine transformation matrix constructed from scaling values you provide.
정의 : 사용자가 제공한 스케일링 값으로 구성된 affine 변환 좌표계를 반환한다.
여기서 얘기하는 affine 변환 좌표계란?
위와 같은 모양의 xyz 좌표계를 뜻한다. CGAffineTransform(scaleX:Y:)
은 2D 그래픽 도면을 위한 affine 변환 좌표계이기 때문에 z 좌표를 뜻하는 세번째 행렬은 항상 (0, 0, 1) 이다.
그리고 이 함수에서 사용하는 방정식은 아래와 같다.
x' = x*Sx
y' = y*Sy
즉, 현재 좌표에 몇 배를 곱하여 새로운 좌표값을 도출하여 넓이와 높이를 결정해주는 함수이다.
이런 함수에다가 원하는 사이즈랍시고 300/500 이렇게 넣어줬으니 작동할리가...
그렇다면 다음줄에 있는 image.size.applying(transform)
에 대해서 알아보자
Returns the height and width resulting from a transformation of an existing height and width.
정의 : 기존 높이와 너비의 변환에 따른 높이와 너비를 반환한다.
이것만 읽고서는 감이 잘 안잡힌다. 반환값에 대한 설명을 봐보자
기존의 사이즈에 affine transform matrix 를 적용함으로써 발생한 새로운 사이즈에 대한 높이와 너비를 반환한다.
그러니까, 기존 높이와 너비를 값으로 좌표계를 만들어서 CGAffineTransform(scaleX:Y:)
으로 위에서 언급 했던 방정식을 적용하여 다시 높이와 너비로 반환을 해준다는 것이다.
아래와 같이 사이즈를 조절 해줄 수 있다.
출처 : https://hyerios.tistory.com/14
이어서, CGSize(width:height:)
에 대해서 알아보자
A structure that contains width and height values.
정의 : 높이와 넓이의 값을 포함하는 구조체이다.
구조체 내부를 살펴보자
정말 말 그대로 높이와 넓이에 대한 값만 포함하고 있다.
이 값들을 가지고 내가 보낸 img를 그리도록 지시 했으니 제대로 동작을 했던 것이다.
한가지 더, UIGraphicsBeginImageContext(CGSize:)
에 대해서 설명 하자면 내가 원하는 img 를 그리기 전에 도화지를 하나 만든다고 생각하면 된다. 그리고 그 도화지의 사이즈, 투명도, 스케일 등을 지정해 줄 수 있다.
물론 도화지 사이즈가 내가 그릴 그림보다 작으면 그림이 잘리게된다.
그리고 모두 그렸으면 UIGraphicsGetImageFromCurrentImageContext()
로 현재 그림을 그려 둔 도화지를 그대로 가져오고 UIGraphicsEndImageContext()
로 그리기를 종료 해주는 것이다.