使用相同的CGRect裁剪相同的UIImage会产生不同的结果

时间:2016-09-15 14:58:40

标签: ios swift2 uiimage crop

我在应用程序中有以下功能:

  1. 用户拍摄(或选择)图像(以下称originalImage)。
  2. originalImage被发送到某个外部API,后者返回我需要添加到originalImage的点坐标数组。
  3. 由于点总是位于一个区域(面部),我想裁剪靠近面部边框的originalImage并仅向用户显示裁剪结果。
  4. 显示裁剪结果后,我逐个添加点。
  5. 以下是完成工作的代码(发送图片除外,让我们说它已经发生了)

    class ScanResultViewController{
    
       @IBOutlet weak var scanPreviewImageView: UIImageView!
    
       let originalImage = ORIGINAL_IMAGE //meaning we already have it
    
       let scanDots = [["x":123, "y":123], ["x":234, "y":234]]//total 68 coordinates
    
       var cropRect:CGRect!
    
       override func viewDidLoad() {
          super.viewDidLoad()
    
             self.setScanImage()
       }
    
       override func viewDidAppear(animated: Bool) {
          super.viewDidAppear(animated)
    
          self.animateScan(0)
       }
    
    
       func setScanImage(){
    
          self.cropRect = self.getCropRect(self.scanDots, sourceImage:self.originalImage)
    
          let croppedImage = self.originalImage.imageAtRect(self.cropRect)
    
          self.scanPreviewImageView.image = croppedImage
          self.scanPreviewImageView.contentMode = .ScaleAspectFill
    
       }
    
    
       func animateScan(index:Int){
    
           let i = index
    
           self.originalImage = self.addOnePointToImage(self.originalImage, pointImage: GREEN_DOT!, point: self.scanDots[i])
    
           let croppedImage = self.originalImage.imageAtRect(self.cropRect)
    
           self.scanPreviewImageView.image = croppedImage
           self.scanPreviewImageView.contentMode = .ScaleAspectFill
    
           if i < self.scanDots.count-1{
    
               let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
               dispatch_after(delay, dispatch_get_main_queue()) {
    
                   self.animateScan(i+1)
               }
           }
       }
    
    
       func addOnePointToImage(sourceImage:UIImage, pointImage:UIImage, point: Dictionary<String,CGFloat>)->UIImage{
    
           let rect = CGRect(x: 0, y: 0, width: sourceImage.size.width, height: sourceImage.size.height)
    
           UIGraphicsBeginImageContextWithOptions(sourceImage.size, true, 0)
           let context = UIGraphicsGetCurrentContext()
    
           CGContextSetFillColorWithColor(context, UIColor.whiteColor().CGColor)
           CGContextFillRect(context, rect)
    
           sourceImage.drawInRect(rect, blendMode: .Normal, alpha: 1)
    
           let pointWidth = sourceImage.size.width/66.7
    
           pointImage.drawInRect(CGRectMake(point["x"]!-pointWidth/2, point["y"]!-pointWidth/2, pointWidth, pointWidth), blendMode: .Normal, alpha: 1)
    
           let result = UIGraphicsGetImageFromCurrentImageContext()
           UIGraphicsEndImageContext()
    
           return result
       }
    
    
       func getCropRect(points: Array<Dictionary<String,CGFloat>>, sourceImage:UIImage)->CGRect{
    
           var topLeft:CGPoint = CGPoint(x: points[0]["x"]!, y: points[0]["y"]!)
           var topRight:CGPoint = CGPoint(x: points[0]["x"]!, y: points[0]["y"]!)
           var bottomLeft:CGPoint = CGPoint(x: points[0]["x"]!, y: points[0]["y"]!)
           var bottomRight:CGPoint = CGPoint(x: points[0]["x"]!, y: points[0]["y"]!)
    
           for p in points{
    
               if p["x"]<topLeft.x {topLeft.x = p["x"]!}
               if p["y"]<topLeft.y {topLeft.y = p["y"]!}
    
               if p["x"]>topRight.x {topRight.x = p["x"]!}
               if p["y"]<topRight.y {topRight.y = p["y"]!}
    
               if p["x"]<bottomLeft.x {bottomLeft.x = p["x"]!}
               if p["y"]>bottomLeft.y {bottomLeft.y = p["y"]!}
    
               if p["x"]>bottomRight.x {bottomRight.x = p["x"]!}
               if p["y"]>bottomRight.y {bottomRight.y = p["y"]!}
    
           }
    
           let rect = CGRect(x: topLeft.x, y: topLeft.y, width: (topRight.x-topLeft.x), height: (bottomLeft.y-topLeft.y))
    
           return rect
       }
    
    }
    
    extension UIImage{
    
       public func imageAtRect(rect: CGRect) -> UIImage {
           let imageRef: CGImageRef = CGImageCreateWithImageInRect(self.CGImage, rect)!
           let subImage: UIImage = UIImage(CGImage: imageRef)
    
           return subImage
       }
    
    }
    

    问题:在setScanImage中,准确裁剪并显示所需区域,但调用animateScan方法时,会裁剪同一图像的不同区域(和尽管cropRect是相同的,originalImage的大小完全相同。

    任何想法,伙计们?

    顺便说一句,如果我在没有裁剪的情况下显示originalImage,一切都会顺利进行。

1 个答案:

答案 0 :(得分:0)

所以最后经过大约10个小时的净时间(以及stackoverflow社区的很多帮助 :-)我设法解决了这个问题:

在函数addOnePointToImage中,您需要更改以下内容:

在这一行:

UIGraphicsBeginImageContextWithOptions(sourceImage.size, true, 0)

您需要将最后一个参数(代表比例)更改为1:

UIGraphicsBeginImageContextWithOptions(sourceImage.size, true, 1)

这完全解决了这个问题。