Search code examples
swiftgifsdwebimage

How to save gif added image to camera roll?


I have an image view image. I am opening up Giphy SDK bottom sheet to add gif on my already added image.

I create gif view to add on already added image using this code:

private func createGifView(url: String?) {
        let x = CGFloat.random(in: 0...(parentView.frame.width - 80))
        let y = CGFloat.random(in: 0...(parentView.frame.height - 80))
        let imageView = SDAnimatedImageView(frame: CGRect(x: x, y: y, width: 120, height: 120))
        imageView.isUserInteractionEnabled = true
        if let url = url {
            imageView.sd_setImage(with: URL(string: url), completed: nil)
        }
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(emojiDidMove))
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(emojiDidPinch))
        let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(emojiDidRotate))
        panGesture.delegate = self
        pinchGesture.delegate = self
        rotationGesture.delegate = self
        imageView.addGestureRecognizer(panGesture)
        imageView.addGestureRecognizer(pinchGesture)
        imageView.addGestureRecognizer(rotationGesture)
        parentView.addSubview(imageView)
        guard let rightBarButtonItems = navigationItem.rightBarButtonItems else { return }
        rightBarButtonItems[1].isEnabled = true
    }

I try this code to save gif added image to camera roll:

private func saveEmojiAddedImage() -> UIImage {
        UIGraphicsBeginImageContext(parentView.frame.size)
        parentView.layer.render(in: UIGraphicsGetCurrentContext()!)
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return UIImage(named: "smile")! }

        let imageView = SDAnimatedImageView()
        let animatedImage = SDAnimatedImage(named: "image.gif")
        imageView.image = animatedImage

        imageView.image = image

        let imageData = imageView.image?.sd_imageData(as: .GIF)
        if let data = imageData {
        PHPhotoLibrary.shared().performChanges({
            PHAssetCreationRequest.forAsset().addResource(with: .photo, data: data, options: nil)
        }) { success, error in
            guard success else {
                print("failed to save gif \(error?.localizedDescription)")
                return
            }
            print("successfully saved gif")
        }
        }

        UIGraphicsEndImageContext()
        
        let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: [image], applicationActivities: nil)
        activityViewController.popoverPresentationController?.sourceView = self.view
        self.present(activityViewController, animated: true, completion: nil)
        return image

    }

I am obtaining giphy gif using this function:

extension MainViewController: GiphyDelegate {
    func didSelectMedia(giphyViewController: GiphyViewController, media: GPHMedia) {
        let url = media.url(rendition: .fixedWidth, fileType: .gif)
        createGifView(url: url)
    }
}

enter image description here enter image description here


Solution

  • I solved my problem taking 25 screenshots of gif added imageview using Timer. I added these 25 screenshots to UIImage array and convert it to them video, finally saved to the photo library as a video.

    class MainViewController: UIViewController {
      private var gifImages: [UIImage] = []
      private var gifTimer: Timer?
    
      UIBarButtonItem(barButtonSystemItem: .save,
                                target: self,
                                action: #selector(fireTimer))
    
     @objc func fireTimer() {
            scheduledTimerWithTimeInterval()
        }
    
     private func scheduledTimerWithTimeInterval(){
            gifTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(saveEmojiAddedImage), userInfo: nil, repeats: true)
       }
    
      //MARK: - SaveEmojiAddedImage
      //Final Image
      @objc private func saveEmojiAddedImage() {
           UIGraphicsBeginImageContextWithOptions(parentView.frame.size, true, 0.0)
           parentView.drawHierarchy(in: parentView.bounds, afterScreenUpdates: true)            guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return }
            UIGraphicsEndImageContext()
            if isGIFAdded {
                self.gifImages.append(image)
                indicator.startAnimating()
                view.isUserInteractionEnabled = false
                print("Gif Images Count: \(gifImages.count)")
                if gifImages.count == 25 {
                    self.stopTimer()
                    indicator.stopAnimating()
                    view.isUserInteractionEnabled = true
                }
            }
        }
    
    
        func stopTimer() {
            if gifTimer != nil {
                gifTimer!.invalidate()
                gifTimer = nil
                DispatchQueue.global(qos: .background).async {
                    DispatchQueue.main.async {
                        self.createVideo()
                    }
                }
            }
        }
    

    Create video using 25 screenshots of imageview

     func createVideo()  {
      let settings = CXEImagesToVideo.videoSettings(codec: AVVideoCodecType.h264.rawValue, width: (gifImages[0].cgImage?.width)!, height: (gifImages[0].cgImage?.height)!)
      let movieMaker = CXEImagesToVideo(videoSettings: settings)
      movieMaker.createMovieFrom(images: gifImages){ (fileURL:URL) in
          if self.isSaveVideo {
             PHPhotoLibrary.shared().performChanges({
             PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: fileURL)
               }) { saved, error in
                    self.gifImages.removeAll()
                    if saved {
                         self.gifImages.removeAll()
                         DispatchQueue.main.async {
                            self.presentAlert(withTitle: "Successful", message: "GIF saved successfully")
                         }
                      } else {
                         DispatchQueue.main.async {
                             self.presentAlert(withTitle: "Error", message: "")
                          }
                        }
                    }
                } else {
                    self.gifImages.removeAll()
                    self.videoFileURL = fileURL
                }
            }
        }
    }