UIView를 이미지로 변환하는 방법
UIView를 이미지로 변환하고 내 앱에 저장하고 싶습니다. 누군가가 뷰의 스크린 샷을 찍거나 이미지로 변환하는 방법과이를 앱 (카메라 롤이 아님)에 저장하는 가장 좋은 방법은 무엇입니까? 보기에 대한 코드는 다음과 같습니다.
var overView = UIView(frame: CGRectMake(0, 0, self.view.frame.width/1.3, self.view.frame.height/1.3))
overView.center = CGPointMake(CGRectGetMidX(self.view.bounds),
CGRectGetMidY(self.view.bounds)-self.view.frame.height/16);
overView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(overView)
self.view.bringSubviewToFront(overView)
확장 기능 UIView
이 트릭을 수행해야합니다.
extension UIView {
// Using a function since `var image` might conflict with an existing variable
// (like on `UIImageView`)
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
Apple UIGraphicsBeginImageContext
은 P3 색 영역을 도입하여 iOS 10을 시작하는 것을 권장하지 않습니다 . UIGraphicsBeginImageContext
sRGB 및 32 비트 전용입니다. 그들은 UIGraphicsImageRenderer
완전히 색상이 관리되고 블록 기반이며 PDF 및 이미지에 대한 하위 클래스가 있으며 컨텍스트 수명을 자동으로 관리 하는 새로운 API를 도입했습니다 . 확인 WWDC16 세션 (205) 자세한 내용은 (이미지 렌더링은 11시 50분 마크 주위에 시작)
Edit1 : 모든 기기에서 작동하는지 확인하려면 #available
이전 버전의 iOS 로의 폴 백과 함께 사용 하세요.
extension UIView {
// Using a function since `var image` might conflict with an existing variable
// (like on `UIImageView`)
func asImage() -> UIImage {
if #available(iOS 10.0, *) {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
} else {
UIGraphicsBeginImageContext(self.frame.size)
self.layer.render(in:UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return UIImage(cgImage: image!.cgImage!)
}
}
}
당신은 확장을 사용할 수 있습니다
extension UIImage {
convenience init(view: UIView) {
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in:UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: image!.cgImage!)
}
}
여기에 신속한 3/4 버전이 있습니다.
extension UIImage {
convenience init(view: UIView) {
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in:UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: image!.cgImage!)
}
}
에 의해 영상에 UIView의 변환 drawViewHierarchyInRect : afterScreenUpdates을 : 인 여러 번 빠르게 renderInContext 이상
중요 참고 사항 : viewDidLoad 또는 viewWillAppear 에서이 함수를 호출하지 마십시오 . 뷰가 완전히 표시 /로드 된 후 뷰를 캡처하고 있는지 확인하십시오.
Obj C
UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.opaque, 0.0f);
[myView drawViewHierarchyInRect:myView.bounds afterScreenUpdates:NO];
UIImage *snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
myImageView.image = snapshotImageFromMyView;
편집 된 이미지 사진 앨범 저장
UIImageWriteToSavedPhotosAlbum(snapshotImageFromMyView, nil,nil, nil);
스위프트 3/4
UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.isOpaque, 0.0)
myView.drawHierarchy(in: myView.bounds, afterScreenUpdates: false)
let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
print(snapshotImageFromMyView)
myImageView.image = snapshotImageFromMyView
확장 기능, iOS11, swift3 / 4로 매우 쉽게 일반화
extension UIImage{
convenience init(view: UIView) {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: (image?.cgImage)!)
}
}
Use :
//myView is completly loaded/visible , calling this code after only after viewDidAppear is call
imgVV.image = UIImage.init(view: myView)
// Simple image object
let img = UIImage.init(view: myView)
iOS 10 :
extension UIImage {
convenience init(view: UIView) {
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: (image?.cgImage)!)
}
}
UIGraphicsBeginImageContext(self.view.bounds.size);
self.view.layer.renderInContext(UIGraphicsGetCurrentContext())
var screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
예를 들어 크기보기가있는 경우 : 50 50 at 100,100. 다음을 사용하여 스크린 샷을 찍을 수 있습니다.
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), false, 0);
self.view.drawViewHierarchyInRect(CGRectMake(-50,-5-,view.bounds.size.width,view.bounds.size.height), afterScreenUpdates: true)
var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
iOS 10 및 Swift 3 기준 모범 사례
iOS 9 및 이전 버전을 계속 지원하면서
extension UIView {
func asImage() -> UIImage? {
if #available(iOS 10.0, *) {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
} else {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
defer { UIGraphicsEndImageContext() }
guard let currentContext = UIGraphicsGetCurrentContext() else {
return nil
}
self.layer.render(in: currentContext)
return UIGraphicsGetImageFromCurrentImageContext()
}
}
}
질문이 무엇을 의미하는지 잘 모르겠습니다.
카메라 롤이 아닌 앱에 저장하는 가장 좋은 방법은 무엇입니까?
제 생각에는 이니셜 라이저를 사용한 접근 방식은 두 개의 이미지를 생성하기 때문에 그다지 좋지 않습니다.
나는 이것을 선호한다 :
extension UIView {
var snapshot: UIImage? {
UIGraphicsBeginImageContext(self.frame.size)
guard let context = UIGraphicsGetCurrentContext() else {
return nil
}
layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
Swift 4.2, iOS 10
extension UIView {
// If Swift version is lower than 4.2,
// You should change the name. (ex. var renderedImage: UIImage?)
var image: UIImage? {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in layer.render(in: rendererContext.cgContext) }
}
}
견본
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .blue
let view2 = UIView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))
view2.backgroundColor = .red
view.addSubview(view2)
let imageView = UIImageView(image: view.image)
var snapshot = overView.snapshotViewAfterScreenUpdates(false)
또는 목적 -c
UIView* snapshot = [overView snapshotViewAfterScreenUpdates:NO];
이것은 Xcode 9 / Swift 3.2 / Swift 4 및 Xcode 8 / Swift 3 에서 저에게 적합합니다.
if #available(iOS 10.0, *) {
// for Xcode 9/Swift 3.2/Swift 4 -Paul Hudson's code
let renderer = UIGraphicsImageRenderer(size: view!.bounds.size)
let capturedImage = renderer.image {
(ctx) in
view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
}
return capturedImage
} else {
// for Xcode 8/Swift 3
UIGraphicsBeginImageContextWithOptions((view!.bounds.size), view!.isOpaque, 0.0)
view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: false)
let capturedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return capturedImage!
}
함수 내에서 사용하는 방법은 다음과 같습니다.
fileprivate func captureUIImageFromUIView(_ view:UIView?) -> UIImage {
guard (view != nil) else{
// if the view is nil (it's happened to me) return an alternative image
let errorImage = UIImage(named: "Error Image")
return errorImage
}
// if the view is all good then convert the image inside the view to a uiimage
if #available(iOS 10.0, *) {
let renderer = UIGraphicsImageRenderer(size: view!.bounds.size)
let capturedImage = renderer.image {
(ctx) in
view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
}
return capturedImage
} else {
UIGraphicsBeginImageContextWithOptions((view!.bounds.size), view!.isOpaque, 0.0)
view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: false)
let capturedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return capturedImage!
}
}
함수에서 반환 된 이미지로 작업을 수행하는 방법은 다음과 같습니다.
@IBOutlet weak fileprivate var myCustomView: UIView!
var myPic: UIImage?
let myImageView = UIImageView()
@IBAction fileprivate func saveImageButtonTapped(_ sender: UIButton) {
myPic = captureUIImageFromUIView(myCustomView)
// display the pic inside a UIImageView
myImageView.image = myPic!
}
내가 가지고 엑스 코드 (9) / 스위프트 3.2 / 스위프트 4 폴 허드슨에서 대답 있는 UIImage로 변환하여 UIView를
나는 오래 전에 어딘가에서 Xcode 8 / Swift 3 를 얻었고 어디에서 잊었는지 잊어 버렸습니다 :(
다음과 같은 확장 기능을 사용하여 쉽게 사용할 수 있습니다.
// Take a snapshot from a view (just one view)
let viewSnapshot = myView.snapshot
// Take a screenshot (with every views in screen)
let screenSnapshot = UIApplication.shared.snapshot
// Take a snapshot from UIImage initialization
UIImage(view: self.view)
해당 확장 메서드 / 변수를 사용하려면 다음을 구현하십시오.
UIImage 확장
extension UIImage { convenience init(view: UIView) { if let cgImage = view.snapshot?.cgImage { self.init(cgImage: cgImage) } else { self.init() } } }
UIView 확장
extension UIView { var snapshot: UIImage? { UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0.0) if UIGraphicsGetCurrentContext() != nil { drawHierarchy(in: bounds, afterScreenUpdates: true) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return screenshot } return nil } }
UIApplication 확장
extension UIApplication { var snapshot: UIImage? { return keyWindow?.rootViewController?.view.snapshot } }
또는 iOS 10 이상에서는 새로운 UIGraphicsImageRenderer + 권장되는 drawHierarchy를 사용할 수 있으며, 일부 상황에서는 layer.renderInContext보다 훨씬 빠를 수 있습니다.
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
return renderer.image { _ in
self.drawHierarchy(in: CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height), afterScreenUpdates: false)
}
}
}
감사합니다 @Bao Tuan Diep! 보충제를 추가하고 싶습니다.
코드를 사용하는 경우 :
yourView.layer.render(in:UIGraphicsGetCurrentContext()!)
다음 사항에 유의해야합니다.
- If you had used `autoLayout` or `Masonry` in `yourView` (that you want to convert) .
- If you did not add `yourView` to another view which means that `yourView` was not used as a subview but just an object.
그런 다음 다음을 사용해야합니다 .
[yourView setNeedsLayout];
[yourView layoutIfNeeded];
yourView
이전 에 업데이트 yourView.layer.render(in:UIGraphicsGetCurrentContext()!)
합니다.
그렇지 않으면 요소가없는 이미지 객체를 얻을 수 있습니다.
스위프트 4.2
import Foundation
import UIKit
extension UIImage {
convenience init(view: UIView) {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: (image?.cgImage)!)
}
}
사용 :
let img = UIImage.init (view : self.holderView)
Swift 3 에서 구현 :
클래스 범위를 벗어난 아래 코드를 추가합니다.
extension UIImage {
convenience init(_ view: UIView) {
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: (image?.cgImage)!)
}
}
사용법 :
let image = UIImage( Your_View_Outlet )
나는 이와 같이 @Naveed J. 의 방법을 구현 했으며 매력처럼 작동했습니다.
그의 확장은 다음과 같습니다.
extension UIView { // Using a function since `var image` might conflict with an existing variable // (like on `UIImageView`) func asImage() -> UIImage { let renderer = UIGraphicsImageRenderer(bounds: bounds) return renderer.image { rendererContext in layer.render(in: rendererContext.cgContext) } } }
구현 방법은 다음과 같습니다.
//create an image from yourView to display
//determine the frame of the view/imageimage
let screen = self.superview!.bounds
let width = screen.width / 4 //make image 1/4 width of screen
let height = width
let frame = CGRect(x: 0, y: 0, width: width, height: height)
let x = (screen.size.width - frame.size.width) * 0.5
let y = (screen.size.height - frame.size.height) * 0.5
let mainFrame = CGRect(x: x, y: y, width: frame.size.width, height: frame.size.height)
let yourView = YourView() //instantiate yourView
yourView.frame = mainFrame //give it the frame
yourView.setNeedsDisplay() //tell it to display (I am not 100% sure this is needed)
let characterViewImage = yourView.asImage()
iOS 10부터 사용할 수있는 새로운 UIGraphicsImageRenderer가있는 이니셜 라이저 :
extension UIImage{
convenience init(view: UIView) {
let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
let canvas = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height)
let image = renderer.image { _ in
self.drawHierarchy(in: canvas, afterScreenUpdates: false)
}
self.init(cgImage: (image?.cgImage)!)
}
}
나랑 잘 일해!
Swift4
extension UIView {
func toImage() -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
self.drawHierarchy(in: self.bounds, afterScreenUpdates: false)
let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return snapshotImageFromMyView!
}
}
뷰가 흐릿한 하위 뷰 (예 : UIVisualEffectView 인스턴스)를 포함하는 경우 drawViewHierarchyInRect : afterScreenUpdates 만 작동합니다.
@ViJay Avhad의 대답 은이 경우에 맞습니다.
please try below code.
-(UIImage *)getMainImageFromContext
{
UIGraphicsBeginImageContextWithOptions(viewBG.bounds.size, viewBG.opaque, 0.0);
[viewBG.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
참고 URL : https://stackoverflow.com/questions/30696307/how-to-convert-a-uiview-to-an-image
'developer tip' 카테고리의 다른 글
jquery에서 배열을 어떻게 생성합니까? (0) | 2020.11.10 |
---|---|
내가 소유하지 않은 브랜치에 대한 병합되지 않은 풀 리퀘스트를 어떻게 가져올 수 있습니까? (0) | 2020.11.10 |
Python에서 두 개의 정렬 된 목록 결합 (0) | 2020.11.09 |
Objective-C에서 두 날짜를 비교하는 방법 (0) | 2020.11.09 |
Python을 사용하여 Unix 또는 Linux에서 프로그램의 프로세스 ID를 얻는 방법은 무엇입니까? (0) | 2020.11.09 |