热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何用Swift绘制图像?-HowdoIdrawonanimageinSwift?

Ineedtobeabletoprogrammaticallydrawonanimage,andsavethatimageforlateruse.Say,draw

I need to be able to programmatically draw on an image, and save that image for later use. Say, draw a line on specific x and y coordinates on the image, save the image, and display it onto a simple view controller. How would I go about doing this in Swift? (Preferably Swift 2, I am still in development and haven't updated my mac to Sierra)

Update: Possibly something to do with converting a UIImage to a CGLayer, drawing on it, and then converting it back to a UIImage.

我需要能够以编程的方式绘制图像,并保存该图像以供以后使用。例如,在图像上的特定x和y坐标上画一条线,保存图像,并将其显示在一个简单的视图控制器上。我该如何用Swift来做这件事呢?(最好是Swift 2,我还在开发中,还没有将mac升级到Sierra)更新:可能与将UIImage转换为CGLayer有关,在此基础上进行绘制,然后将其转换回UIImage。

4 个解决方案

#1


5  

It's simple:

很简单:

  1. Make an image graphics context. (Before iOS 10, you would do this by calling UIGraphicsBeginImageContextWithOptions. In iOS 10 there's another way, UIGraphicsImageRenderer, but you don't have to use it if you don't want to.)

    创建一个图像图形上下文。(在ios10之前,您可以通过调用UIGraphicsBeginImageContextWithOptions来实现这一点。在ios10中有另一种方式,UIGraphicsImageRenderer,但如果你不想使用,你也不必使用它。

  2. Draw (i.e. copy) the image into the context. (UIImage actually has draw... methods for this very purpose.)

    将图像绘制(即复制)到上下文中。(用户界面图像实际上画…方法就是为了达到这个目的。

  3. Draw your line into the context. (There are CGContext functions for this.)

    在上下文中画线。(这里有CGContext函数。)

  4. Extract the resulting image from the context. (For example, if you used UIGraphicsBeginImageContextWithOptions, you would use UIGraphicsGetImageFromCurrentImageContext.) Then close the context.

    从上下文中提取生成的图像。(例如,如果您使用UIGraphicsBeginImageContextWithOptions,您将使用UIGraphicsGetImageFromCurrentImageContext)。然后关闭上下文。

#2


6  

All you need to do is create and get an Image Context object and acess all its powerfull drawing methods. You can learn more about the CGContext object features here.

您所需要做的就是创建和获取一个图像上下文对象,并使用它的所有powerfull绘图方法。您可以在这里了解更多关于CGContext对象的特性。

This function draws a line and a circle on an UIImage and returns the modified image:

此函数在UIImage上绘制一条线和一个圆,并返回修改后的图像:

Swift 4

func DrawOnImage(startingImage: UIImage) -> UIImage {

     // Create a context of the starting image size and set it as the current one
     UIGraphicsBeginImageContext(startingImage.size)

     // Draw the starting image in the current context as background       
     startingImage.draw(at: CGPoint.zero)

     // Get the current context
     let cOntext= UIGraphicsGetCurrentContext()!

     // Draw a red line
     context.setLineWidth(2.0)
     context.setStrokeColor(UIColor.red.cgColor)
     context.move(to: CGPoint(x: 100, y: 100))
     context.addLine(to: CGPoint(x: 200, y: 200))
     context.strokePath()

     // Draw a transparent green Circle
     context.setStrokeColor(UIColor.green.cgColor)
     context.setAlpha(0.5)
     context.setLineWidth(10.0)
     context.addEllipse(in: CGRect(x: 100, y: 100, width: 100, height: 100))
     context.drawPath(using: .stroke) // or .fillStroke if need filling

     // Save the context as a new UIImage
     let myImage = UIGraphicsGetImageFromCurrentImageContext()
     UIGraphicsEndImageContext()

     // Return modified image
     return myImage
}

#3


2  

Updated Answer: Once you get the From and To coordinates, here is how to draw a line in a UIImage with those coordinates. From and To coordinates are in image pixels.

更新后的答案:一旦你得到了从和到坐标,这里是如何绘制一条线在一个UIImage与那些坐标。从坐标到坐标都是以图像像素为单位的。

func drawLineOnImage(size: CGSize, image: UIImage, from: CGPoint, to: CGPoint) -> UIImage {

// begin a graphics context of sufficient size
UIGraphicsBeginImageContext(size)

// draw original image into the context
image.drawAtPoint(CGPointZero)

// get the context for CoreGraphics
let cOntext= UIGraphicsGetCurrentContext()

// set stroking width and color of the context
CGContextSetLineWidth(context, 1.0)
CGContextSetStrokeColorWithColor(context, UIColor.blueColor().CGColor)

// set stroking from & to coordinates of the context
CGContextMoveToPoint(context, from.x, from.y)
CGContextAddLineToPoint(context, to.x, to.y)

// apply the stroke to the context
CGContextStrokePath(context)

// get the image from the graphics context 
let resultImage = UIGraphicsGetImageFromCurrentImageContext()

// end the graphics context 
UIGraphicsEndImageContext()

return resultImage }

#4


2  

Details

Xcode 9.1, Swift 4

Xcode 9.1,斯威夫特4

Solution

extension UIImage

扩展用户界面图像

extension UIImage {

    typealias RectCalculatiOnClosure= (_ parentSize: CGSize, _ newImageSize: CGSize)->(CGRect)

    func with(image named: String, rectCalculation: RectCalculationClosure) -> UIImage {
        return with(image: UIImage(named: named), rectCalculation: rectCalculation)
    }

    func with(image: UIImage?, rectCalculation: RectCalculationClosure) -> UIImage {

        if let image = image {
            UIGraphicsBeginImageContext(size)

            draw(in: CGRect(origin: .zero, size: size))
            image.draw(in: rectCalculation(size, image.size))

            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return newImage!
        }
        return self
    }
}

extension UIImageView

扩展UIImageView

    extension UIImageView {

    enum ImageAddingMode {
        case changeOriginalImage
        case addSubview
    }

    func drawOnCurrentImage(anotherImage: UIImage?, mode: ImageAddingMode, rectCalculation: UIImage.RectCalculationClosure) {

        guard let image = image else {
            return
        }

        switch mode {
        case .changeOriginalImage:
            self.image = image.with(image: anotherImage, rectCalculation: rectCalculation)

        case .addSubview:
            let newImageView = UIImageView(frame: rectCalculation(frame.size, image.size))
            newImageView.image = anotherImage
            addSubview(newImageView)
        }
    }
}

Images samples

Parent Image:

父母的形象:

enter image description here

Child Image:

儿童形象:

enter image description here


Usage example 1

func sample1(imageView: UIImageView) {
    imageView.cOntentMode= .scaleAspectFit
    imageView.image = UIImage(named: "parent")?.with(image: "child") { parentSize, newImageSize in
        print("parentSize = \(parentSize)")
        print("newImageSize = \(newImageSize)")
        return CGRect(x: 50, y: 50, width: 90, height: 90)
    }
}

Result 1

结果1

enter image description here


Usage example 2

func sample2(imageView: UIImageView) {
    imageView.cOntentMode= .scaleAspectFit
    imageView.image = UIImage(named: "parent")
    imageView.drawOnCurrentImage(anotherImage: UIImage(named: "child"), mode: .changeOriginalImage) { parentSize, newImageSize in
        print("parentSize = \(parentSize)")
        print("newImageSize = \(newImageSize)")
        let sideLength:CGFloat = 90
        let indent:CGFloat = 50
        return CGRect(x: parentSize.width-sideLength-indent, y: parentSize.height-sideLength-indent, width: sideLength, height: sideLength)
    }
}

Result 2

结果2

enter image description here


Usage example 3

func sample3(imageView: UIImageView) {
    imageView.cOntentMode= .scaleAspectFill
    imageView.clipsToBounds = true
    imageView.image = UIImage(named: "parent")
    imageView.drawOnCurrentImage(anotherImage: UIImage(named: "child"), mode: .addSubview) { parentSize, newImageSize in
        print("parentSize = \(parentSize)")
        print("newImageSize = \(newImageSize)")
        let sideLength:CGFloat = 90
        let indent:CGFloat = 15
        return CGRect(x: parentSize.width-sideLength-indent, y: indent, width: sideLength, height: sideLength)
    }
}

Result 3

结果3

enter image description here

Full sample code

Don't forget to add Solution code here

不要忘记在这里添加解决方案代码

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let imageView = UIImageView(frame: UIScreen.main.bounds)
        view.addSubview(imageView)
        sample1(imageView: imageView)
       // sample2(imageView: imageView)
       // sample3(imageView: imageView)
    }

    func sample1(imageView: UIImageView) {
        imageView.cOntentMode= .scaleAspectFit
        imageView.image = UIImage(named: "parent")?.with(image: "child") { parentSize, newImageSize in
            print("parentSize = \(parentSize)")
            print("newImageSize = \(newImageSize)")
            return CGRect(x: 50, y: 50, width: 90, height: 90)
        }
    }

    func sample2(imageView: UIImageView) {
        imageView.cOntentMode= .scaleAspectFit
        imageView.image = UIImage(named: "parent")
        imageView.drawOnCurrentImage(anotherImage: UIImage(named: "child"), mode: .changeOriginalImage) { parentSize, newImageSize in
            print("parentSize = \(parentSize)")
            print("newImageSize = \(newImageSize)")
            let sideLength:CGFloat = 90
            let indent:CGFloat = 50
            return CGRect(x: parentSize.width-sideLength-indent, y: parentSize.height-sideLength-indent, width: sideLength, height: sideLength)
        }
    }

    func sample3(imageView: UIImageView) {
        imageView.cOntentMode= .scaleAspectFill
        imageView.clipsToBounds = true
        imageView.image = UIImage(named: "parent")
        imageView.drawOnCurrentImage(anotherImage: UIImage(named: "child"), mode: .addSubview) { parentSize, newImageSize in
            print("parentSize = \(parentSize)")
            print("newImageSize = \(newImageSize)")
            let sideLength:CGFloat = 90
            let indent:CGFloat = 15
            return CGRect(x: parentSize.width-sideLength-indent, y: indent, width: sideLength, height: sideLength)
        }
    }
}

推荐阅读
author-avatar
UWBCZ
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有