【问题标题】:Cropping the same UIImage with the same CGRect gives different results用相同的 CGRect 裁剪相同的 UIImage 会产生不同的结果
【发布时间】:2017-01-23 16:04:05
【问题描述】:

我在应用中有以下功能:

  1. 用户拍摄(或选择)一张图片(以下简称originalImage)。
  2. originalImage 被发送到某个外部 API,它返回我需要添加到 originalImage 的点坐标数组。
  3. 由于点始终位于一个区域(面部),我想裁剪靠近面部边界的originalImage,并仅向用户显示裁剪结果。
  4. 显示裁剪结果后,我会一个一个地添加点。

这是完成这项工作的代码(除了发送图像,假设它已经发生了)

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方法被调用时,同一图像的不同区域被裁剪(并显示)尽管@ 987654328@ 是一样的,originalImage 的大小是完全一样的。

有什么想法吗,伙计们?

顺便说一句,如果我显示 originalImage 而不裁剪它,一切都会顺利进行。

【问题讨论】:

    标签: ios swift2 uiimage crop


    【解决方案1】:

    最终在大约 10 小时的净时间后(以及 stackoverflow 社区的大量帮助:-)我设法解决了这个问题:

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

    在这一行:

    UIGraphicsBeginImageContextWithOptions(sourceImage.size, true, 0)
    

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

    UIGraphicsBeginImageContextWithOptions(sourceImage.size, true, 1)
    

    这完全解决了问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-11
      相关资源
      最近更新 更多