307

私のコードは通常のデバイスでは問題なく動作しますが、Retina デバイスではぼやけた画像が作成されます。

私の問題の解決策を知っている人はいますか?

+ (UIImage *) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContext(view.bounds.size);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return img;
}
4

17 に答える 17

678

の使用からUIGraphicsBeginImageContextへの切り替え (このページUIGraphicsBeginImageContextWithOptionsに記載されているとおり)。scale (3 番目の引数) に 0.0 を渡すと、画面の倍率と等しい倍率のコンテキストが得られます。

UIGraphicsBeginImageContextは 1.0 の固定倍率を使用するため、iPhone 4 でも他の iPhone とまったく同じ画像が得られます。iPhone 4 を暗黙のうちにスケールアップするときにフィルターを適用しているのか、周囲のすべてのものよりもシャープではないことに脳が気付いているのか、どちらかでしょう。

だから、私は推測します:

#import <QuartzCore/QuartzCore.h>

+ (UIImage *)imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return img;
}

そしてSwift 4では:

func image(with view: UIView) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
    defer { UIGraphicsEndImageContext() }
    if let context = UIGraphicsGetCurrentContext() {
        view.layer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        return image
    }
    return nil
}
于 2010-12-02T12:20:45.047 に答える
238

少なくとも iOS 7 をサポートしている場合、現在受け入れられている回答は古くなっています。

iOS7+ のみをサポートしている場合は、以下を使用する必要があります。

+ (UIImage *) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0f);
    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
    UIImage * snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snapshotImage;
}

スウィフト 4:

func imageWithView(view: UIView) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
    defer { UIGraphicsEndImageContext() }
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
    return UIGraphicsGetImageFromCurrentImageContext()
}

この記事によると、iOS7 の新しい方法drawViewHierarchyInRect:afterScreenUpdates:は より何倍も高速であることがわかりますrenderInContext:基準

于 2014-03-19T02:09:39.333 に答える
29

iOS 迅速

最新の UIGraphicsImageRenderer の使用

public extension UIView {
    @available(iOS 10.0, *)
    public func renderToImage(afterScreenUpdates: Bool = false) -> UIImage {
        let rendererFormat = UIGraphicsImageRendererFormat.default()
        rendererFormat.opaque = isOpaque
        let renderer = UIGraphicsImageRenderer(size: bounds.size, format: rendererFormat)

        let snapshotImage = renderer.image { _ in
            drawHierarchy(in: bounds, afterScreenUpdates: afterScreenUpdates)
        }
        return snapshotImage
    }
}
于 2016-12-01T09:52:37.487 に答える
24

@Tommy と @Dima による回答を改善するには、次のカテゴリを使用して、UIView を UIImage にレンダリングし、背景を透明にし、品質を低下させません。iOS7に取り組んでいます。self(または、実装でそのメソッドを再利用し、参照をイメージに置き換えます)

UIView+RenderViewToImage.h

#import <UIKit/UIKit.h>

@interface UIView (RenderToImage)

- (UIImage *)imageByRenderingView;

@end

UIView+RenderViewToImage.m

#import "UIView+RenderViewToImage.h"

@implementation UIView (RenderViewToImage)

- (UIImage *)imageByRenderingView
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
    UIImage * snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snapshotImage;
}

@end
于 2014-08-30T19:22:25.597 に答える
5

スウィフト 2.0:

拡張メソッドの使用:

extension UIImage{

   class func renderUIViewToImage(viewToBeRendered:UIView?) -> UIImage
   {
       UIGraphicsBeginImageContextWithOptions((viewToBeRendered?.bounds.size)!, false, 0.0)
       viewToBeRendered!.drawViewHierarchyInRect(viewToBeRendered!.bounds, afterScreenUpdates: true)
       viewToBeRendered!.layer.renderInContext(UIGraphicsGetCurrentContext()!)

       let finalImage = UIGraphicsGetImageFromCurrentImageContext()
       UIGraphicsEndImageContext()

       return finalImage
   }

}

使用法:

override func viewDidLoad() {
    super.viewDidLoad()

    //Sample View To Self.view
    let sampleView = UIView(frame: CGRectMake(100,100,200,200))
    sampleView.backgroundColor =  UIColor(patternImage: UIImage(named: "ic_120x120")!)
    self.view.addSubview(sampleView)    

    //ImageView With Image
    let sampleImageView = UIImageView(frame: CGRectMake(100,400,200,200))

    //sampleView is rendered to sampleImage
    var sampleImage = UIImage.renderUIViewToImage(sampleView)

    sampleImageView.image = sampleImage
    self.view.addSubview(sampleImageView)

 }
于 2016-03-09T05:42:13.063 に答える
3

Swift 3.0 の実装

extension UIView {
    func getSnapshotImage() -> UIImage {
        UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
        drawHierarchy(in: bounds, afterScreenUpdates: false)
        let snapshotImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return snapshotImage
    }
}
于 2016-10-07T21:38:48.960 に答える
3

すべての Swift 3 の回答がうまくいかなかったので、最も受け入れられている回答を翻訳しました。

extension UIImage {
    class func imageWithView(view: UIView) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let img: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return img!
    }
}
于 2017-05-09T12:06:24.970 に答える
3

これは、@Dima からの回答に基づくSwift 4 UIView 拡張機能です。

extension UIView {
   func snapshotImage() -> UIImage? {
       UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
       drawHierarchy(in: bounds, afterScreenUpdates: false)
       let image = UIGraphicsGetImageFromCurrentImageContext()
       UIGraphicsEndImageContext()
       return image
   }
}
于 2018-06-06T20:02:12.963 に答える
0

drawRectメソッドで問題が発生することがあるので、これらの回答をより適切に取得しました。あなたもそれを見るかもしれません DrawRectメソッドで立ち往生しているUIViewのキャプチャUIImage

于 2013-02-12T08:24:13.227 に答える
-2

このメソッドでは、ビュー オブジェクトを渡すだけで、UIImage オブジェクトが返されます。

-(UIImage*)getUIImageFromView:(UIView*)yourView
{
 UIGraphicsBeginImageContext(yourView.bounds.size);
 [yourView.layer renderInContext:UIGraphicsGetCurrentContext()];
 UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();
 return image;
}
于 2016-04-12T12:29:51.463 に答える
-6

これを UIView カテゴリのメソッドに追加します

- (UIImage*) capture {
    UIGraphicsBeginImageContext(self.bounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.layer renderInContext:context];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}
于 2013-01-30T06:44:01.247 に答える