热门标签 | 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)
        }
    }
}

推荐阅读
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • iOS Swift中如何实现自动登录?
    本文介绍了在iOS Swift中如何实现自动登录的方法,包括使用故事板、SWRevealViewController等技术,以及解决用户注销后重新登录自动跳转到主页的问题。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
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社区 版权所有