Swift - Image Resizing

민경준·2022년 11월 8일
0

최근 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 ] ") 
		![](https://velog.velcdn.com/images/jxxnnee/post/bcf4a3c6-d587-4d1f-83f4-a78f85413341/image.png)
return
	} 
	
	completionHandler(img) 
}

CGSize로 방식을 바꿔 주니 정상적으로 리사이징이 작동했다.

그렇다면 두 방식에 어떤 차이가 있는걸까? 일단 두 방식 모두 이미지 크기 조절을 하는 함수는 맞다.

CGAffineTransform(scaleX:Y:)에 대해서 알아보자

init(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) 에 대해서 알아보자

applying(_:)

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:)에 대해서 알아보자

CGSize

A structure that contains width and height values.

정의 : 높이와 넓이의 값을 포함하는 구조체이다.

구조체 내부를 살펴보자

정말 말 그대로 높이와 넓이에 대한 값만 포함하고 있다.

이 값들을 가지고 내가 보낸 img를 그리도록 지시 했으니 제대로 동작을 했던 것이다.

한가지 더, UIGraphicsBeginImageContext(CGSize:) 에 대해서 설명 하자면 내가 원하는 img 를 그리기 전에 도화지를 하나 만든다고 생각하면 된다. 그리고 그 도화지의 사이즈, 투명도, 스케일 등을 지정해 줄 수 있다.

물론 도화지 사이즈가 내가 그릴 그림보다 작으면 그림이 잘리게된다.

그리고 모두 그렸으면 UIGraphicsGetImageFromCurrentImageContext()로 현재 그림을 그려 둔 도화지를 그대로 가져오고 UIGraphicsEndImageContext()로 그리기를 종료 해주는 것이다.

profile
iOS Developer 💻

0개의 댓글