【问题标题】:Capture UIView and Save as Image捕获 UIView 并保存为图像
【发布时间】:2013-06-13 06:15:58
【问题描述】:

首先我在UIImageView 上添加UILable,然后在我截取UIView 之后,图像无法正确捕获UIView 框架我还附上了图像网址。

1) Original Image Link:

2) After Capture the image Link:

代码:

UIGraphicsBeginImageContext(viewImage.frame.size);
[viewImage.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *vwImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

NSData *data=UIImagePNGRepresentation(vwImage);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
// NSString *imgName = [NSString stringWithFormat:imagename];
NSString *strPath = [documentsDirectory stringByAppendingPathComponent:imagename];
[data writeToFile:strPath atomically:YES];

【问题讨论】:

  • 我认为截图是正确的。我在另一边看到的问题。您确定您的 UIView 与源图像的大小相同吗?如果不是,那么您是否将 UIImage 添加到您的视图而不更改其大小?你确定吗? :) 'Couse 如果你有一个大小为 200x500 的图像,但你在大小为 300x700 的 UIView 上绘制它,允许 UIView 拉伸图像以使其占据所有空间,那么你将获得 UIView 大小的屏幕截图,而不是源图片
  • 当我将捕获的图像保存在照片库中时,日期显示不正确
  • 啊,好的,现在知道了。尝试在此处查看我的答案:stackoverflow.com/questions/16062974/… 有一个完全可用的代码供您使用
  • 使用性能更好的API回答stackoverflow.com/questions/4334233/…

标签: ios objective-c ios6 swift3


【解决方案1】:

您可以截取任何UIView 的屏幕截图或捕获任何UIView 并使用以下代码将其保存为图像。

- (UIImage *)captureView {

    //hide controls if needed
    CGRect rect = [self.view bounds];

    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.view.layer renderInContext:context];   
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;

}

【讨论】:

  • 当我将捕获的图像保存在照片库中时,日期显示不正确
  • 你试试这个方法??并更改 UILable 的 Autoresize 属性
  • 嘿点击你的主视图并选择文件检查器并取消选中 Autolayout 属性可能是它的问题
【解决方案2】:

这样试试,

UIGraphicsBeginImageContext(viewImage.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextFillRect(ctx, viewImage.frame);     

[viewImage.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *vwImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

NSData *data=UIImagePNGRepresentation(vwImage);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
// NSString *imgName = [NSString stringWithFormat:imagename];
NSString *strPath = [documentsDirectory stringByAppendingPathComponent:imagename];
[data writeToFile:strPath atomically:YES];

【讨论】:

    【解决方案3】:

    你可以使用下面的代码来

    UIGraphicsBeginImageContext(pictureView.bounds.size); 
                    
    [pictureView.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
    

    【讨论】:

      【解决方案4】:

      拍摄 UIView 的快照

      将您的视图传递给此函数,它将自行处理所有事情(无需设置边界或框架

      - (UIImage *)takeSnapshotOfView:(UIView *)view
      {
          UIGraphicsBeginImageContext(CGSizeMake(view.frame.size.width, view.frame.size.height));
          [view drawViewHierarchyInRect:CGRectMake(0, 0, view.frame.size.width, view.frame.size.height) afterScreenUpdates:YES];
          UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
      
          return image;
      }
      

      【讨论】:

      • [view.layer renderInContext:ctx] 在互联网上到处提出的解决方案是抛出 CGGetColorAlpha EXC_BAD_ACCESS,但这就像一个魅力。谢谢!
      • 对 drawViewHierarchyInRect 而不是 .layer renderInContext 大加赞赏。它具有更好的质量,在我的用例中是唯一有效的,因为它包含整个层次结构
      【解决方案5】:

      Swift 3 版本:

      func takeSnapshotOfView(view:UIView) -> UIImage? {
          UIGraphicsBeginImageContext(CGSize(width: view.frame.size.width, height: view.frame.size.height))
          view.drawHierarchy(in: CGRect(x: 0.0, y: 0.0, width: view.frame.size.width, height: view.frame.size.height), afterScreenUpdates: true)
          let image = UIGraphicsGetImageFromCurrentImageContext()
          UIGraphicsEndImageContext()
          return image
      }
      

      【讨论】:

        【解决方案6】:

        如果您希望捕获的图像保持其原始质量,请尝试此操作。

        - (UIImage *)captureViewWithAllSubView:(UIView *)view {
            UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0f);
            [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
            UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            return capturedImage;
        }
        

        【讨论】:

          【解决方案7】:

          在 Swift 5 中作为扩展:

          extension UIView {
          
              func takeSnapshot() -> UIImage? {
                  UIGraphicsBeginImageContext(CGSize(width: self.frame.size.width, height: self.frame.size.height - 5))
                  let rect = CGRect(x: 0.0, y: 0.0, width: self.frame.size.width, height: self.frame.size.height)
                  drawHierarchy(in: rect, afterScreenUpdates: true)
                  let image = UIGraphicsGetImageFromCurrentImageContext()
                  UIGraphicsEndImageContext()
                  return image
              }
          }
          
          extension UIImage {
          
              func saveToPhotoLibrary(_ completionTarget: Any?, _ completionSelector: Selector?) {
                  DispatchQueue.global(qos: .userInitiated).async {
                      UIImageWriteToSavedPhotosAlbum(self, completionTarget, completionSelector, nil)
                  }
              }
          }
          
          extension UIAlertController {
          
              func present() {
                  guard let controller = UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.rootViewController else {
                      return
                  }
                  controller.present(self, animated: true)
              }
          }
          

          在您的UIView 子类中:

          func saveImage() {
              let selector = #selector(self.onImageSaved(_:error:contextInfo:))
              takeSnapshot()?.saveToPhotoLibrary(self, selector)
          }
          
          @objc private func onImageSaved(_ image: UIImage, error: Error?, contextInfo: UnsafeRawPointer) {
              if let error = error {
                  let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
                  ac.addAction(UIAlertAction(title: "OK", style: .default))
                  ac.present()
              } else {
                  let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
                  ac.addAction(UIAlertAction(title: "OK", style: .default))
                  ac.present()
              }
              onImageSaved?()
          }
          

          【讨论】:

            猜你喜欢
            • 2017-07-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多