在高分辨率图像上绘制形状?

Draw a shape over a high res image?

我希望能够在特定位置的高分辨率照片(例如 8 像素图像)上画一条线。

这很简单,已经有很多关于它的帖子,但我的问题是 CGContext "drawing space" 似乎与高分辨率图像不一样。

我可以画线并保存图像,但我的问题是在特定位置画线。我的坐标空间似乎彼此不同。我认为一定有一个我遗漏的比例因子,或者我的理解一团糟。

所以我的问题是:

如何在图像上绘图,即 "aspect fit" 到屏幕(但分辨率更高)并使绘图(在本例中为一条线)在屏幕上的相同位置以及最终的全分辨率合成图像?

示例图片:

红线是我画的线。它应该从开始目标 (theTarget) 的中心到结束目标 (theEnd) 的中心。

我已经简化了我的绘图功能以便在这里发布,但我怀疑我的整个 thinking/approach 是错误的。

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var imageView: UIImageView!  
@IBOutlet weak var theTarget: UIImageView!
@IBOutlet weak var theEnd: UIImageView!

var lineColor = UIColor.redColor()
var targetPos : CGPoint!
var endPos : CGPoint!
var originalImage : UIImage!

override func viewDidLoad() {
    super.viewDidLoad()

    imageView.image = UIImage(named: "reference.jpg")
    originalImage = imageView.image

    drawTheLine() 
}


func drawTheLine () {
    UIGraphicsBeginImageContext(originalImage!.size);

    // Draw the original image as the background
    originalImage?.drawAtPoint(CGPointMake(0, 0))

    // Pass 2: Draw the line on top of original image
    let context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 10.0);

    targetPos = theTarget.frame.origin
    endPos = theEnd.frame.origin

    CGContextMoveToPoint(context, targetPos.x, targetPos.y);
    CGContextAddLineToPoint(context, endPos.x, endPos.y)
    CGContextSetStrokeColorWithColor(context, lineColor.CGColor)
    CGContextStrokePath(context);

    imageView.image = UIGraphicsGetImageFromCurrentImageContext()
}

@IBAction func saveButton(sender: AnyObject) {
    // Create new image

   let newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIImageWriteToSavedPhotosAlbum(newImage!, nil, nil, nil )
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


@IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
    let translation = recognizer.translationInView(self.view)
    if let view = recognizer.view {
        view.center = CGPoint(x:view.center.x + translation.x,
            y:view.center.y + translation.y)
    }
    recognizer.setTranslation(CGPointZero, inView: self.view)

    //redraw the line
    drawTheLine()

    print("the start pos of the line is: ", theTarget.frame.origin, " and end pos is: ", theEnd.frame.origin)

}


}

我前一段时间遇到了这个问题,所以我写了一个 UIImageView 扩展,当填充模式为 .ScaleAspectFit.[=15= 时,将图像视图的坐标映射到图像坐标中]

extension UIImageView {

    func pointInAspectScaleFitImageCoordinates(point:CGPoint) -> CGPoint {

        if let img = image {

            let imageSize = img.size
            let imageViewSize = frame.size

            let imgRatio = imageSize.width/imageSize.height // The ratio of the image before scaling.
            let imgViewRatio = imageViewSize.width/imageViewSize.height // The ratio of the image view

            let ratio = (imgRatio > imgViewRatio) ? imageSize.width/imageViewSize.width:imageSize.height/imageViewSize.height // The ratio of the image before scaling to after scaling.

            let xOffset = (imageSize.width-(imageViewSize.width*ratio))*0.5 // The x-offset of the image on-screen (as it gets centered)
            let yOffset = (imageSize.height-(imageViewSize.height*ratio))*0.5 // The y-offset of the image on-screen (as it gets centered)

            let subImgOrigin = CGPoint(x: point.x*ratio, y: point.y*ratio); // The origin of the image (relative to the origin of the view)

            return CGPoint(x: subImgOrigin.x+xOffset, y: subImgOrigin.y+yOffset);
        }
        return CGPointZero
    }
}

您应该能够很容易地在 drawTheLine 函数中使用它:

func drawTheLine () {
    UIGraphicsBeginImageContext(originalImage!.size);

    // Draw the original image as the background
    originalImage?.drawAtPoint(CGPointMake(0, 0))

    // Pass 2: Draw the line on top of original image
    let context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 10.0);

    targetPos = imageView.pointInAspectScaleFitImageCoordinates(theTarget.frame.origin)
    endPos = imageView.pointInAspectScaleFitImageCoordinates(theEnd.frame.origin)

    CGContextMoveToPoint(context, targetPos.x, targetPos.y);
    CGContextAddLineToPoint(context, endPos.x, endPos.y)
    CGContextSetStrokeColorWithColor(context, lineColor.CGColor)
    CGContextStrokePath(context);

    imageView.image = UIGraphicsGetImageFromCurrentImageContext()
}