在高分辨率图像上绘制形状?
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()
}
我希望能够在特定位置的高分辨率照片(例如 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()
}