ios
ios에서 적은 메모리로 이미지를 만들기(공부)
코코넛딩
2024. 12. 13. 08:53
참조한 블로그입니다.
https://velog.io/@o_joon_/Swift-Image-and-Memory
[Swift] Image and Memory
WWDC2018에서 설명한 이미지와 메모리의 연관성 및 이미지의 최적화에 대해 알아보자.
velog.io
iOS : 이미지와 메모리
개요
- 이미지와 관련된 메모리는 파일 용량이 아닌 이미지 해상도와 관련이 있다.
이미지 렌더링 과정
- 이미지 렌더링하는데 사용되는 메모리양
이미지 파일 : 590KB, 2028 * 1536
다음 과 같은 조건을 갖는 이미지 파일을 불러올 때 사용되는 메모리는 10MB
20배 많은 메모리를 차지함 - 많은 메모리가 쓰이는 이유
- Load
- 메모리에 데이터화된 이미지가 load된다.
- Decode
- 로그된 이미지를 GPU가 읽을 수 있는 형태로 decode한다.
- 해당 과정에서 JPEG로 압축된 파일을 압축 해제하며 10MB가 된다.
- Render
- decode된 이미지를 렌더링하여 이미지의 형태로 변경한다.
- Load
UIGraphicsImageRenderer
- UIGraphicsBeginImageContextWithOptions
- 항상 SRGB를 사용한다.
- 픽셀당 4바이트 사용
- Alpha 8과 Wide(픽셀당 8바이트 필요)처럼 더 작거나 큰 포맷을 사용할 수 없다.
- Alpha 8
- 픽셀당 1바이트를 필요로 함
- alpha 값 하나로만 이루어져있다.
- SRGB보다 75% 적은 메모리를 사용한다.
- 모노크롬(흑백 텍스트), 마스크(투명도)에 사용됨
- Alpha 8
- 항상 SRGB를 사용한다.
// Circle via UIGraphicsImageRenderer
let bounds = CGRect(x: 0, y: 0, width:300, height: 100)
let renderer = UIGraphicsImageRenderer(size: bounds.size)
let image = renderer.image { context in
// Drawing Code
UIColor.black.setFill()
let path = UIBezierPath(roundedRect: bounds,
byRoundingCorners: UIRectCorner.allCorners,
cornerRadii: CGSize(width: 20, height: 20))
path.addClip()
UIRectFill(bounds)
}
// 블루색으로 바꿔었지만 여전히 픽셀 당 1byte를 사용하는 이미지임
let imageView = UIImageView(image: image)
imageView.tintColor = .blue
- UIGraphicsImageRenderer
- 최적의 포맷을 알아서 적용시켜 준다고 한다.
- ios 12 부터 사용가능
- 장점
- 메모리 관리
- 렌더링 완료시 자동으로 메모리 해제
- 메모리 누수를 방지
- GPU 활용
- GPU 가속을 활용하여 렌더링 기능을 향상시킬 수 있다.
- CPU 부담을 줄이고, 더 빠르고 효율적으로 렌더링할 수 있게한다.
- UIGraphicsBeginImageContextWithOptions는 주로 CPU 기반으로 렌더링을 처리하므로 성능에서 다소 제한이 있을 수 있다.
- 해상도 자동 관리
- 디스플레이 해상도에 맞는 이미지를 자동으로 생성하여, Retina 디스플레이와 같은 고해상도 디스플레이어에서 더 선명한 이미지를 출력할 수 있다. 이때 scale 속성을 자동으로 관리한다.
- UIGraphicsBeginImageContextWithOptions에서는 scale을 명시적으로 설정해야 하므로, 고해상도 지원에 있어 더 많은 수동 조정이 필요할 수 있습니다.
- 메모리 관리
- 위의 코드는 검정색 원을 그리는 코드이다.
- 시스템이 자동으로 Alpha 8 포맷을 사용하여 SRGB를 사용할 떄 보다 75% 적게 메모리를 사용한다.
- SRGB와 품질은 동일하다.
- tintColor를 파란색으로 바꾸어도 픽셀당 1바이트만 사용하여 메모리는 훨씬 적게 사용하면서 색상을 입힐 수 있다.
- 렌더링할 때 적용되는 색상이 변경되는 것 뿐, 이미지의 실제 데이터를 건드리는 것이 아니기 때문에 메모리를 추가로 사용하지 않음
이미지 리사이징
UIGraphicsImageRenderer
- UIImage를 통해 리사이징 하기 때문에 이미지의 크기를 바꾸는 과정에서 비효율적이다.
- 이미지 전체 정보를 압축해제하여 메모리에 로드한다.
- UIImage 객체는 내부적으로 이미지의 크기, 위치 및 다른 속성을 관리하기 위해 내부의 좌표공간을 사용한다.
- 이미지를 회전, 크기 조정 또는 반전 작업을 위해서는 이 좌표 공간들을 변환하는데에 비용이 많이 든다.
Image I/O
- Image I/O는 Foundation, UIKit와 같은 프레임 워크 입니다.
- 해당 프레임워크를 통해 대부분의 이미지 파일 형식을 읽고 쓸 수 있고 효율적이면서 색상관리나 메타데이터 접근을 제공합니다.
- ImageIO는 이미지를 효율적으로 다운샘플링 할 수 있으며, 해당 프레임워크의 Streaming API를 이용하여 다운 샘플링에 필요한 사이즈와 메타데이터를 제외한 더티 메모리들은 사용하지 않습니다.
- ImageIO는 UIImage가 아닌 CGImage로 작업을 하는데, CGImage는 UIImage와 다르게 크기와 스케일등의 정보를 제외한 데이터만 가지고 있습니다.