美文网首页
图形处理

图形处理

作者: 微笑_d797 | 来源:发表于2019-01-09 15:28 被阅读0次

    图形绘制(第一天)

    湖中倒影

    画一个图片的倒影

    
    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)!)
        }
    }
    

    相关文章

      网友评论

          本文标题:图形处理

          本文链接:https://www.haomeiwen.com/subject/fylgrqtx.html