ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [개발자 문석읽기] UIImage
    iOS 2020. 10. 10. 16:00
    728x90
    의역과 오역이 있을 수 있습니다. 참고해서 봐주세요 :)

     

    UIImage 는 앱에서 이미지 데이터를 관리하는 객체입니다. 앱은 제한된 메모리를 사용하기 때문에 image 다루는 일은 굉장히 중요합니다. 그럼에도 제대로 모르고 사용했던 것 같아요 :) 오늘은 UIImage문서를 정독해보겠습니다.

    ‼️ 핵심 요약

    임에도 꽤 길군요.. 정말 다 중요한 내용 같습니다 ;)
    • UIImage는 모든 포멧을 지원하긴 하지만 PNG와 JPEG에 최적화 되어있다. 특히 원본 손실이 없는 PNG가 권장된다.
    • UIImage는 반드시 데이터가 필요하다. 빈 데이터나 draw contents로는 UIImage를 만들 수 없다.
      (단, UIKit은 UIGraphicsGetImageFromCurrentImageContext()를 제공하긴 한다.)
    • 이미지는 불변 데이터이기 때문에 모든 스레드에서 안전하게 생성하고 사용할 수 있다.
    • asset이나 bundle에 있는 이미지를 생성하기 위해서 named 를 사용한다. named를 사용해서 생성하면 자동으로 이미지 데이터를 캐시하기 때문에 빈번히 사용하는 이미지를 만들 때 적합하다.
    • 번들에 없는 이미지를 생성하기 위해서 imageWithContentsOfFile: or init(contentsOfFile:) 를 사용한다. 매번 디스크에서 load하기 때문에 반복적으로 사용되는 이미지에는 권장되지 않는다.
    • animatedImage(with:duration:) and animatedImageNamed(_:duration:) 를 사용해서 애니메이션을 만들 수도 있다.
    • UIImagePickerController를 사용해서 카메라나 포토 라이브러리에 접근할 수 있다. 단 사용자 권한이 필요하다.
    • stretchable image는 resizableImage(withCapInsets:) or resizableImage(withCapInsets:resizingMode:) 를 사용해서 인셋을 정의해서 만드는데, 상하좌우에 인셋을 주면서 9개 영역으로 나눈 부분에서, 모서리 네 곳의 크기는 고정되고 나머지 부분이 늘어난다.
    • 이미지를 비교할 때는 반드시 원본 데이터를 비교하는 isEqual(_:) 메소드를 사용해야한다.
    • UIImage의 내부 데이터에 직접 접근할 순 없지만, cgImage(core graphics)나 ciImage(core image) 같은 속성을 사용해 검색은 가능하다.
    • pngData, jpegData(compressionQuality:) 같은 메소드를 사용해 NSData 객체를 만들 수 있다.

     


     

    Overview

    모든 종류의 이미지 데이터를 표현하기 위해 UIImage를 사용하세요, 기본적인 플랫폼에서 제공되는 이미지 포멧 데이터를 관리하는 데 유용합니다. 이미지 객체들은 immutable 합니다. 그래서 항상 디스크에 있는 이미지 파일이나, programmatically 하게 생성된 이미지 데이터 처럼 존재하는 데이터에서 생성합니다. 하나의 이미지 객체는 하나의 이미지 또는 애니메이션에 사용할 연속적인 이미지를 포함할 수 있습니다.

    이미지 객체를 여러가지 방법으로 사용할 수 있습니다.

    • 이미지를 보여주기 위해 UIImageView에 할당
    • buttons, sliders, segment controls 같은 system controls을 커스텀 하는 데 사용
    • 뷰나 다른 graphics context 에 직접 그리기
    • 이미지 데이터가 필요할 수 있는 다른 API에 이미지 전달

    비록 이미지 객체가 모든 platform-navtive 이미지 데이터를 지원하지만, PNG나 JPEG 가 권장됩니다. 이미지 객체는 읽고 나타내는 데 두 포멧에 최적화 되어있습니다. 그리고 이 포멧들이 다른 포멧에 비해 더 좋은 성능을 제공합니다. 특히 PNG는 손실이 없기 때문에 앱에서 이미지를 다룰 때 추천됩니다.

    Creating Image Objects

    UIImage 클래스의 메소드를 사용해 이미지를 만들 때, 파일 또는 데이터 구조에 반드시 기존 이미지 데이터가 있어야 합니다. 빈 이미지는 만들 수 없고, 그려 넣을 수 없습니다. 이미지 객체를 생성하기 위해 많은 옵션이 있으며, 특정 상황에 가장 적합합니다.

    • init(named:in:compatibleWith:) (or init(named:)) 는 image asset이나 main bundle (또는 알고 있는 다른 번들) 에 있는 이미지 파일을 만드는 데 사용합니다. 왜냐하면 이 메소드는 자동으로 이미지 데이터를 캐시합니다. 특히 자주 사용하는 이미지들을 만들 때 추천됩니다.
    • imageWithContentsOfFile: or init(contentsOfFile:) 는 번들에 없는 초기 데이터에서 이미지 데이터를 생성합니다. 매번 디스크에서 새로 load 하기 때문에 같은 이미지를 반복적으로 load 하는 데는 사용하지 않는 게 좋습니다.
    • animatedImage(with:duration:) and animatedImageNamed(_:duration:) 는 여러 개의 순차적 이미지로 구성된 단일 UIImage 객체를 생성합니다. UIImageView에 결과 이미지를 설치해서 인터페이스에서 애니메이션을 만듭니다.

    다른 메소드들은 Core Graphics images나 자체적으로 만든 이미지 데이터 같은 특정 데이터 타입들의 애니메이션을 만들 때 사용합니다. UIKit 은 UIGraphicsGetImageFromCurrentImageContext() 함수를 제공하는데, 직접 그린 콘텐츠로 이미지를 만들기 위해 사용합니다. 이 함수는 당신의 drawing commands를 캡쳐하기 위해 사용하는 비트맵 기반의 graphics context 와 함께 사용됩니다.

    💡 Note 
    이미지 객체는 불변적이기 때문에 생성한 이후에는 속성을 변경할 수 없습니다. 대부분의 속성들은 첨부하는 이미지 파일이나 이미지 데이터의 메타데이터를 사용해 자동적으로 설정됩니다. 이미지 객체의 불변적인 성질은 모든 스레드에서 만들고 사용하는 것이 안전하다는 걸 의미합니다.

    이미지 에셋은 앱에서 이미지를 관리하는 가장 손쉬운 방법입니다. 새로만든 Xcode 프로젝트는 프로젝트 마다 하나의 assets 라이브러리를 가지고 있고 여러 이미지 셋을 추가할 수 있습니다. 하나의 이미지 셋은 앱에서 사용되는 단일 이미지의 variations 이 포함됩니다. 하나의 단일 이미지 셋은 다른 platforms, 다른 trait environments (compact or regular), 다른 scale factors 를 위한 다양한 버전을 제공할 수 있습니다.

    추가적으로 디스크에서 이미지를 로드하기 위해서 사용자에게 UIImagePickerController 객체를 사용해서 카메라, 포토 라이브러리에서 이미지를 제공하도록 요청할 수 있습니다. 이미지 피커는 이미지를 선택하기 위해 커스텀 UI 를 제공합니다. 유저의 이미지들에 접근하기 특정한 사용자 권한이 필요합니다. 이미지 피커에 대한 자세한 정보는 UIImagePickerController를 참고하세요.

    Defining a Stretchable Image

    stretchable image는 기본 이미지 데이터가 미적으로 만족스러운 방식으로 복제될 수 있는 영역을 정의하는 이미지 입니다. Strechable images 는 사용 가능한 영역을 채우기 위해 늘리고 줄일 수 있는 배경을 만드는 데 사용됩니다.

    stretchable image는 resizableImage(withCapInsets:) or resizableImage(withCapInsets:resizingMode:) 메소드를 사용해 기존의 이미지에 inset 들을 더해서 정의합니다. inset 들은 이미지를 둘 또는 더 많은 영역으로 세분화합니다. 각 inset은 0이 아닌 값을 지정하면 아래 그림과 같이 9개의 부분으로 나뉩니다.

    이미지의 위 아래 insets은 고정 높이를 유지하고, 왼쪽과 오른쪽 insets의 내부 영역은 고정된 너비를 유지합니다.

    아래 그림은 사용 가능한 영역을 채우기 위해 9개의 부분이 어떻게 늘어나는지를 보여줍니다. 수평 및 수직 inset 안에 있기 때문에 이미지의 코너들은 크기가 변하지 않습니다.

    Comparing Images

    isEqual(:) 메소드는 두 이미지가 동일한 이미지 데이터를 갖는지 확인하는 유일한 방법입니다. 생성한 이미지 객체는 캐시된 동일한 이미지 데이터로 만들어도 서로 다를 수 있습니다. isEqual(:) 는 실제 이미지 데이터를 비교하기 때문에 이미지가 같은지 확인하는 유일한 방법입니다. 아래는 이미지를 비교하는 정확하고 잘못된 방법을 보여줍니다.

    let image1 = UIImage(name: "MyImage")
    let image2 = UIImage(name: "MyImage")
    
    if image1 != nil && image1!.isEqual(image2) {
    	// 올바른 방법. 기술적으로 image data를 비교합니다.
    }
    
    if image1 == image2 {
    	// 잘못된 방법! 객체를 직접 비교하기 때문에 제대로 비교되지 않을 수 있습니다.
    }

     

    Accessing the Image Data

    이미지 객체들은 내부의 이미지 데이터에 직접 접근할 수 있는 방법을 제공하지 않습니다. 하지만 앱에서 사용하기 위해 다른 포멧에 있는 이미지 데이터를 검색할 수 있습니다. 특히 cgImage 와 ciImage 속성을 사용해서 Core Graphics 와 Core Image 와 호환되는 이미지 버전을 검색 할 수 있습니다. pngData() 와 jpegData(compressionQuality:) 함수를 사용해서 PNG와 JPEG 포멧 데이터를 갖는 NSData 객체를 생성 할 수 있습니다.

     

    감사합니다. 

     

    참고

    developer.apple.com/documentation/uikit/uiimage

    댓글

Designed by Tistory.