美文网首页
iOS UIImageWriteToSavedPhotosAlb

iOS UIImageWriteToSavedPhotosAlb

作者: 齐舞647 | 来源:发表于2020-03-16 18:28 被阅读0次

引子:
需求,把UIImage保存图片到相册。
看似很简单的需求,踩了一个坑,记录一下。

正常步骤:

  • 第一步,添加长按手势到UIImageView上。
func addLongPressGestureRecognizer() {
     let longPress = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressClick))
     self.qrImageView.isUserInteractionEnabled = true
     self.qrImageView.addGestureRecognizer(longPress)
}
  • 第二步:添加长按事件,并使用核心APIUIImageWriteToSavedPhotosAlbum
@objc func longPressClick() {
      let alert = UIAlertController(title: "是否将二维码保存到相册?", message: nil, preferredStyle: .alert)
      let action = UIAlertAction(title: "确定", style: .default) { [weak self] (action) in
          guard let `self` = self else {
              return
          }
          UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.image(image:didFinishSavingWithError:contextInfo:)), nil) // 保存到相册
      }
      let cancel = UIAlertAction(title: "取消", style: .cancel, handler: nil)
      alert.addAction(action)
      alert.addAction(cancel)
      self.present(alert, animated: true, completion: nil)
}
  • 第三步:实现一个回调方法:- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
@objc func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
      if error == nil {
          UIView.makeStaticToast("保存成功")
      } else {
          UIView.makeStaticToast("保存失败")
      }
}

遇到的坑:

  • 描述:保存成功,但打开相册并未找到照片。

原因是该UIImage是通过CIImage转过来的,
而实际上只能识别CGImage转过来的或者本身就是UIImage

  • 解决方案:将UIImage -> CIImage -> CGImage -> UIImage
let cgImage = CIContext().createCGImage(image.ciImage!, from: image.ciImage!.extent)
let uiImage = UIImage.init(cgImage: cgImage!)
UIImageWriteToSavedPhotosAlbum(uiImage, self, #selector(self.image(image:didFinishSavingWithError:contextInfo:)), nil) // 保存到相册

问题的本质:

UIImage、CGImage、CIImage的本质区别是什么?

  • CGImage:A bitmap image or image mask.
    基于像素的矩阵,每个点都对应了图片中点的像素信息。

A CGImage can only represent bitmaps. Operations in CoreGraphics, such as blend modes and masking require CGImageRefs. If you need to access and change the actual bitmap data, you can use CGImage. It can also be converted to NSBitmapImageReps.
用来描述bitmaps,如果需要访问和更改实际的位图数据,可以使用CGImage。

  • CIImage:A representation of an image to be processed or produced by Core Image filters.

A CIImage is an immutable object that represents an image. It is not an image. It only has the image data associated with it. It has all the information necessary to produce an image. You typically use CIImage objects in conjunction with other Core Image classes such as CIFilter, CIContext, CIColor, and CIVector. You can create CIImage objects with data supplied from variety of sources such as Quartz 2D images, Core Videos image, etc. It is required to use the various GPU optimized Core Image filters. They can also be converted to NSBitmapImageReps. It can be based on the CPU or the GPU.
对象也是线程安全的,它并不是一张图片。
它包含了所有生成一张图片所有的必要信息。
常用在CIFilter, CIContext, CIColor, CIVector。跟GPU的处理相关。(如滤镜)

  • UIImage:An object that manages image data in your app.

UIImage object is a high-level way to display image data. You can create images from files, from Quartz image objects, or from raw image data you receive. They are immutable and must specify an image’s properties at initialization time. This also means that these image objects are safe to use from any thread. Typically you can take NSData object containing a PNG or JPEG representation image and convert it to a UIImage.
UIImage对象是显示图像数据的高级方法。您可以从文件、Quartz图像对象或接收的原始图像数据创建图像。它们是不可变的,必须在初始化时指定图像的属性。这也意味着这些图像对象可以安全地从任何线程中使用。通常你能取得NSData对象包含一个PNG或JPEG表现图像并且转换它到一个UIImage。

主要区别:

1. 使用imageWithCGImage生成的UIImage
  • 重新生成UIImage,会把生成它的CGImageRef保存下来
  • image.CIImage = nil
2. 使用imageWithCIImage生成的UIImage
  • 重新生成UIImage,会把生成它的CIImage保存下来
  • image.CGImage = nil

PS:关于CGImage与CIImage的详细资料

\ imageWithCGImage imageWithCIImage
1 重新生成UIImage,
会把生成它的CGImageRef保存下来
重新生成UIImage,
会把生成它的CIImage保存下来
2 image.CIImage = nil image.CGImage = nil

猜测UIImageWriteToSavedPhotosAlbum方法底层会使用image.cgImage,转换成照片,再保存照片到相册。

因此,不能直接使用CIImage转换成的UIImage,因为CIImage转成的image.cgImage = nil

所以,最终解决方案是:UIImage -> CIImage -> CGImage -> UIImage

相关文章

网友评论

      本文标题:iOS UIImageWriteToSavedPhotosAlb

      本文链接:https://www.haomeiwen.com/subject/xsnnehtx.html