图形处理

2019-01-09  本文已影响0人  微笑_d797

图形绘制(第一天)

湖中倒影

画一个图片的倒影


extension UIImageView {

    /// 创建一个倒影图像
    /// height:裁剪比例
    func refkectedImage(subimgV: UIImageView,height: CGFloat){
        if let context = createBitmapContext(pixelsWidth: subimgV.bounds.size.width, pixelsHight: height),let gradientmaskimage = createGradientImage(pixelsWidth: 1, pixelsHight: height),let cgImage = subimgV.image?.cgImage {


            /// 裁剪+翻转+缩放+添加渐变效果
            context.clip(to: CGRect.init(x: 0, y: 0, width: subimgV.bounds.size.width, height: height), mask: gradientmaskimage)
            context.translateBy(x: 0.0, y: height)
            context.scaleBy(x: 1.0, y: -1.0)

            ///绘制
            context.draw(cgImage, in: subimgV.bounds)

            let reflectionimage = context.makeImage()

            self.image = UIImage.init(cgImage: reflectionimage!)
        }
    }


    private func createBitmapContext(pixelsWidth: CGFloat,pixelsHight: CGFloat) -> CGContext? {
            /// 绘制颜色为灰色的图片 的色彩空间
        let space = CGColorSpaceCreateDeviceGray()
        ///彩色换成
        /// CGColorSpaceCreateDeviceRGB()

        /*
         Create a bitmap context. The context draws into a bitmap which is `width'
         pixels wide and `height' pixels high. The number of components for each
         pixel is specified by `space', which may also specify a destination color
         profile.  Note that the only legal case when `space' can be NULL is when
         alpha is specified as kCGImageAlphaOnly.The number of bits for each component
         of a pixel is specified by `bitsPerComponent'. The number of bytes per pixel
         is equal to `(bitsPerComponent * number of components + 7)/8'. Each row of
         the bitmap consists of `bytesPerRow' bytes, which must be at least
         `width * bytes per pixel' bytes; in addition, `bytesPerRow' must be an
         integer multiple of the number of bytes per pixel. `data', if non-NULL,
         points to a block of memory at least `bytesPerRow * height' bytes.
         If `data' is NULL, the data for context is allocated automatically and freed
         when the context is deallocated. `bitmapInfo' specifies whether the bitmap
         should contain an alpha channel and how it's to be generated, along with
         whether the components are floating-point or integer.
         */
        /*
         创建位图上下文。上下文绘制为“宽度”位图。
         像素宽,像素高。每个组件的数量
         像素由“space”指定,也可以指定目标颜色。
         轮廓。请注意,当“space”可以为空时,唯一的法律案例是
         alpha指定为kcgimagealphaonly。每个组件的位数
         “bitspercomponent”指定像素的。每个像素的字节数
         等于`(bitspercomponent*组件数+7)/8'。每行
         位图由“bytesperrow”字节组成,该字节必须至少为
         `width*bytes per pixel'字节;此外,`bytesprerow'必须是
         每像素字节数的整数倍。“data”,如果非空,
         指向至少“bytesperrow*height”字节的内存块。
         如果“data”为空,则自动分配和释放上下文的数据。
         当上下文解除分配时。`bitmapinfo'指定位图
         应该包含一个alpha通道以及如何生成它,以及
         组件是浮点还是整数。
         */
        let bitmapcontext = CGContext(data: nil, width: Int(pixelsWidth), height: Int(pixelsHight), bitsPerComponent: 8, bytesPerRow: 0, space: space, bitmapInfo: 1)

        return bitmapcontext
    }

    /// 创建渐变图层
    private func createGradientImage(pixelsWidth: CGFloat,pixelsHight: CGFloat) -> CGImage? {
        var cgimage:CGImage?
        let space = CGColorSpaceCreateDeviceGray()
        let bitmapcontext = CGContext(data: nil, width: Int(pixelsWidth), height: Int(pixelsHight), bitsPerComponent: 8, bytesPerRow: 0, space: space, bitmapInfo: 0)!
        var colors:[CGFloat] = [CGFloat(0.0),CGFloat(1.0),CGFloat(1.0),CGFloat(1.0)]
        let grayscalecradient = CGGradient.init(colorSpace: space, colorComponents: &colors, locations: nil, count: 2)

        let gradientstartpoint = CGPoint.zero
        let gradientEndpoint = CGPoint.init(x: 0, y: pixelsHight)
        bitmapcontext.drawLinearGradient(grayscalecradient!, start: gradientstartpoint, end: gradientEndpoint, options: CGGradientDrawingOptions.drawsAfterEndLocation)
        cgimage = bitmapcontext.makeImage()
        return cgimage
    }

}

应用代码

            let imgV = UIImageView()
            imgV.frame = CGRect.init(x: 100, y: 100, width: 100, height: 100)
            let path = Bundle.main.path(forResource: "WechatIMG47", ofType: "png")!
            imgV.image = try UIImage.init(data: Data.init(contentsOf: URL.init(fileURLWithPath: path)))!
            self.view.addSubview(imgV)

            let fimgv = UIImageView()
            fimgv.frame = CGRect.init(x: 100, y: 200, width: 100, height: 50)
            fimgv.alpha = 0.5
            self.view.addSubview(fimgv)

            let height = imgV.bounds.size.height * 0.5
            fimgv.refkectedImage(subimgV: imgV, height: height)

注意创建图层的方法CGBitmapinfo是一个结构体他的构造为 创建上下文的时候传的默认值1 创建渐变图层的时候 传的是0

public struct CGBitmapInfo : OptionSet {

    public init(rawValue: UInt32)

    ///Aplha通道信息遮罩。用这个值来提取alpha信息。这个值明确了位图是否包含了alpha通道和alpha通道是如何生成的 0
    public static var alphaInfoMask: CGBitmapInfo { get }

    
    public static var floatInfoMask: CGBitmapInfo { get }

    public static var floatComponents: CGBitmapInfo { get }
    
    public static var byteOrderMask: CGBitmapInfo { get }
    
    public static var byteOrder16Little: CGBitmapInfo { get }

    public static var byteOrder32Little: CGBitmapInfo { get }

    public static var byteOrder16Big: CGBitmapInfo { get }

    public static var byteOrder32Big: CGBitmapInfo { get }
}

CoreGraphics 和 CAShaplayer(CoreAnimation) 的 优缺点

Core Graphics(占用CPU,性能消耗大,如果没有需求,苹果不建议实现空的drawRect方法;)画得越多,程序就会越慢。因为每次绘制会重绘整个贝塞尔路径(UIBezierPath),随着路径越来越复杂,每次重绘的工作就会增加,直接导致了帧数的下降。
它提供了低级别、轻量级的2d 渲染, 具有无与伦比的输出保真度。使用此框架可以处理基于路径的绘图、转换、颜色管理、屏幕外渲染、图案、渐变和着色、图像数据管理、图像创建和图像屏蔽, 以及 pdf 文档创建、显示和分析

Core Animation(通过GPU来渲染图形,不消耗内存,节省性能;)为这些图形类型的绘制提供了专门的类,并给他们提供硬件支持。CAShapeLayer可以绘制多边形,直线和曲线。CATextLayer可以绘制文本。CAGradientLayer用来绘制渐变。这些总体上都比Core Graphics更快,同时他们也避免了创造一个寄宿图。

用CAShapeLayer替代Core Graphics,性能就会得到提高(.虽然随着路径复杂性的增加,绘制性能依然会下降,但是只有当非常非常浮躁的绘制时才会感到明显的帧率差异。


WechatIMG48.png

添加滤镜

ps上的各种滤镜效果在iOS手机上也可以实现,通过CIFilter来实现

先初始化一个CIFilter初始化方法调用name属性来选择滤镜
设置inputimage要加滤镜的image
调用setDefaults方法
得到outputimage

/// 添加滤镜�
extension UIImage {

    func filterimg() -> UIImage {
        let ciimg = CIImage.init(cgImage: self.cgImage!)
        let context = CIContext.init(options: nil)

        let filter = CIFilter.init(name: "CIPhotoEffectInstant")!
        filter.setValue(ciimg, forKey: "inputImage")
        filter.setDefaults()

        let outputimg = filter.outputImage!
        return UIImage.init(cgImage: context.createCGImage(outputimg, from: outputimg.extent)!)
    }
}
上一篇下一篇

猜你喜欢

热点阅读