2

I am trying to implement a feature that draws an image at a specific point of a UIImageView.

1.) So the user makes a photo 2.) Photo gets displayed to the user in a UIImageView in "Aspect Fit" 3.) User clicks on the UIImageView to put a image at the tapped point 4.) Combined Image is displayed

code:

extension UIImage {
func image(byDrawingImage image: UIImage, inRect rect: CGRect) -> UIImage! {
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    image.draw(in: rect)
    let result = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return result
}}

source

    @IBAction func imageTapped(_ sender: UITapGestureRecognizer) {


    let pointTapped = sender.location(in: imageDIsplay)

    imageDIsplay.image = originalImage?.image(byDrawingImage: #imageLiteral(resourceName: "checkmark.png"), inRect: CGRect(x: originalImage!.size.width / imageDIsplay.frame.width * pointTapped.x, y: originalImage!.size.height / imageDIsplay.frame.height * pointTapped.y, width: 100, height: 100))

}

my problem: The "checkmark Image" is never at the exact point where I clicked.

I tried a lot instead of originalImage!.size.width / imageDIsplay.frame.width to get a better ratio including CGRect AVMakeRectWithAspectRatioInsideRect(CGSize aspectRatio, CGRect boundingRect);. But nothing works correctly.

What do I miss?

THANKS! Sarah

sarahaha
  • 95
  • 1
  • 8
  • " Photo gets displayed to the user in a UIImageView in "Aspect Fit" " That's the problem. The point where the user clicks _in the image view_ is not the same as the point where the user clicks _in the image_, because the image view is changing the size/position of the image in order to display it. You need to calculate back to image coordinates in order to know where to place the checkmark. – matt Jun 10 '18 at 15:21
  • "I tried a lot" Okay, so you do seem to realize that that's the problem. But you have not shown what you tried so it's impossible to say what you're doing wrong. – matt Jun 10 '18 at 15:23
  • One more thing: even after you solve that problem, you need to decide where to draw the checkmark image in relation to the click point. Do you want it with its top left at the click point? Or with its _center_ at the click point? It seems to me that the user will naturally expect the latter. – matt Jun 10 '18 at 15:26
  • Exactly the image should be in the center related to the click point. And yes I realize that this is the problem. "I tried a lot" I was saying that I was trying a lot relationships to get the correct ratio like let actualSize = AVMakeRect(aspectRatio: (originalImage?.size)!, insideRect: imageDIsplay.frame).size.height let imageSize = originalImage!.size.height let ratio = imageSize / actualSize. but I am not sure if I am on the correct way.... – sarahaha Jun 10 '18 at 15:47

1 Answers1

4

You're definitely on the right track. It will be useful to have on hand a working utility for converting a point in image view bounds to a point in image bounds when the image is displayed in "aspect fit" content mode:

extension UIImageView {
    func convertPointToImageCoordinates(_ p:CGPoint) -> CGPoint {
        switch self.contentMode {
        case .scaleAspectFit:
            let r = AVMakeRect(
                 aspectRatio: self.image!.size, insideRect: self.bounds)
            let scale = self.image!.size.width / r.width
            var p2 = CGPoint(x: p.x - r.minX, y: p.y - r.minY)
            p2 = CGPoint(x: p2.x * scale, y: p2.y * scale)
            return p2
        default:
            fatalError("not written")
        }
    }
}

Now you can obtain the tapped coordinate with respect to the original image, so you can decide where to place the checkmark image in relation to that.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Does `UIImageView` not set the transform matrix? – David Berry Jun 10 '18 at 17:06
  • 1
    @DavidBerry Transform matrix of what? A UIImage is not a view so it has no transform. And if it altered its _own_ transform, the view would _itself_ be distorted. It just draws the image according to the content mode, just as with any view drawing. – matt Jun 10 '18 at 17:48
  • But the `UIImageView` is (obviously) a view and does have a transform matrix. I'd assume it uses that matrix to correctly scale and draw the image. Of course we all know what that means :) Haven't actually looked at it, just thinking how I'd do it if I were writing the view. – David Berry Jun 11 '18 at 03:48
  • @DavidBerry I prefer to know about how it does actually work. – matt Jun 11 '18 at 03:56
  • @DavidBerry I am curious on your solution @ matt thanks a lot for your reply it works like a charm at least I got close :-D Of course I voted your answer up - you will see it if I got enough reputations :) – sarahaha Jun 11 '18 at 19:21
  • I don't actually have one, just kibitzing on @matt's with something I would hope would work but haven't actually tried. – David Berry Jun 11 '18 at 22:38