DDGScreenShot--iOS各种截图,web wkweb生成长图,图片处理

写在前面

最近有这么一个需求,分享页面,分享的是web订单截图,既然是web 就会有超出屏幕的部分,
生成的图片还要加上我们的二维码,这就涉及到图片的合成了。
有了这样的需求,就是各种google.也算解决了自己的需求,另外,也总结了一下,对需求做了下拓展,目前是swift4.0版本。

整合成一个三方库,以下只是部分代码,详细代码及demo请见,github地址https://github.com/dudongge/DDGScreenShot

DDGScreenShot 部分功能演示

image
image
image
image


View生成图片

代码也比较简单 screenShotImage 就是截取后的图片
        let context = UIGraphicsGetCurrentContext()
        context?.saveGState()
        context?.translateBy(x: -self.frame.origin.x, y: -self.frame.origin.y);
         self.layer.render(in: context!)
        let screenShotImage = UIGraphicsGetImageFromCurrentImageContext()
        context?.restoreGState();
        UIGraphicsEndImageContext()

ScrollView生成图片

只要实现原理是计算偏移量,每一屏绘制一次,放在内存里,最后将所有的图片组合成一张图片 screenShotImage就是最终图片
public func DDGContentScrollScreenShot (_ completionHandler: @escaping (_ screenShotImage: UIImage?) -> Void) {
        
        self.isShoting = true
        
        let snapShotView = self.snapshotView(afterScreenUpdates: true)
        snapShotView?.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: (snapShotView?.frame.size.width)!, height: (snapShotView?.frame.size.height)!)
        self.superview?.addSubview(snapShotView!)

        let bakOffset    = self.contentOffset
        
        let page  = floorf(Float(self.contentSize.height / self.bounds.height))
        
        UIGraphicsBeginImageContextWithOptions(self.contentSize, false, UIScreen.main.scale)
        
        self.DDGContentScrollPageDraw(0, maxIndex: Int(page), drawCallback: { [weak self] () -> Void in
            let strongSelf = self
            
            let screenShotImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            strongSelf?.setContentOffset(bakOffset, animated: false)
            snapShotView?.removeFromSuperview()
            
            strongSelf?.isShoting = false
            
            completionHandler(screenShotImage)
        })
        
    }
    
    fileprivate func DDGContentScrollPageDraw (_ index: Int, maxIndex: Int, drawCallback: @escaping () -> Void) {
        
        self.setContentOffset(CGPoint(x: 0, y: CGFloat(index) * self.frame.size.height), animated: false)
        let splitFrame = CGRect(x: 0, y: CGFloat(index) * self.frame.size.height, width: bounds.size.width, height: bounds.size.height)
        
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.3 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in
            self.drawHierarchy(in: splitFrame, afterScreenUpdates: true)
            
            if index < maxIndex {
                self.DDGContentScrollPageDraw(index + 1, maxIndex: maxIndex, drawCallback: drawCallback)
            }else{
                drawCallback()
            }
        }
    }

UIwebView生成图片 && wkwebView

绘制时大同小异,只是wkwebView 调用的绘制方法为:drawHierarchy 其核心代码如下
采用递归,直到拿到最后一个偏移量。
fileprivate func DDGRenderImageView(_ completionHandler: @escaping (_ screenShotImage: UIImage?) -> Void) {
        let ddgTempRenderView = UIView(frame: CGRect(x: 0, y: 0, width: self.contentSize.width, height: self.contentSize.height))
        self.removeFromSuperview()
        ddgTempRenderView.addSubview(self)
        
        self.contentOffset = CGPoint.zero
        self.frame         = ddgTempRenderView.bounds
        
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.3 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in
            let bounds = self.bounds
            UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale)
            
            if (self.DDGContainsWKWebView()) {
                self.drawHierarchy(in: bounds, afterScreenUpdates: true)
            }else{
                self.layer.render(in: UIGraphicsGetCurrentContext()!)
            }
            let screenShotImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            completionHandler(screenShotImage)
        }
    }
fileprivate func shotScreenContentScrollPageDraw (_ index: Int, maxIndex: Int, drawCallback: @escaping () -> Void) {
        
        self.scrollView.setContentOffset(CGPoint(x: 0, y: CGFloat(index) * self.scrollView.frame.size.height), animated: false)
        let splitFrame = CGRect(x: 0, y: CGFloat(index) * self.scrollView.frame.size.height, width: bounds.size.width, height: bounds.size.height)
        
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.3 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in
            self.drawHierarchy(in: splitFrame, afterScreenUpdates: true)
            
            if index < maxIndex {
                self.shotScreenContentScrollPageDraw(index + 1, maxIndex: maxIndex, drawCallback: drawCallback)
            }else{
                drawCallback()
            }
        }
    }

两张图片合为一张(一张底图,一张logo)

在UIImage上做了拓展
let imageRef = self.cgImage
        let w: CGFloat = CGFloat((imageRef?.width)!)
        let h: CGFloat = CGFloat((imageRef?.height)!)
        //以1.png的图大小为画布创建上下文
        UIGraphicsBeginImageContext(CGSize(width: w, height: h))
        self.draw(in: CGRect(x: 0, y: 0, width: w, height: h))
        //先把1.png 画到上下文中
        logo.draw(in: CGRect(x: logoOrigin.x,
                             y: logoOrigin.y,
                             width: logoSize.width,
                             height:logoSize.height))
        //再把小图放在上下文中
        let resultImg: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        //从当前上下文中获得最终图片
        UIGraphicsEndImageContext()
        return resultImg!

在图片上写文字/加标签

同样对UIimage 做了拓展,增加了几个参数
  public func drawTextInImage(text: String,
                         textColor: UIColor,
                         textFont: CGFloat,
                         textBgColor: UIColor,
                         textX: CGFloat,
                         textY: CGFloat )->UIImage {
        //开启图片上下文
        UIGraphicsBeginImageContext(self.size)
        //图形重绘
        self.draw(in: CGRect.init(x: 0, y: 0, width: self.size.width, height: self.size.height))
        //水印文字属性
        let att = [NSAttributedStringKey.foregroundColor: textColor,
                   NSAttributedStringKey.font: UIFont.systemFont(ofSize: textFont),
                   NSAttributedStringKey.backgroundColor: textBgColor]
        //水印文字大小
        let text = NSString(string: text)
        let size =  text.size(withAttributes: att)
        //绘制文字
        text.draw(in: CGRect.init(x: textX, y: textY, width: size.width, height: size.height), withAttributes: att)
        //从当前上下文获取图片
        let image = UIGraphicsGetImageFromCurrentImageContext()
        //关闭上下文
        UIGraphicsEndImageContext()
        return image!
    }

结束语

空间有限,所注代码不全,我把上述功能整理成了最新的带三方库,
以后会加上图片的相关处理,比如美颜,剪切,马赛克,组图等,
附上我的git地址:https://github.com/dudongge/DDGScreenShot
有什么问题也可以联系我QQ:532835032
如果对您有帮助,请您不吝star一下,增加我更新的动力

附上github上READER.ME文件部分内容

## view截屏:
    view.DDGScreenShot { (image) in
         拿到 image 
         各种复杂装逼操作
         、、、、
    }
   ## ScrollView截屏:
    scrollView.DDGContentScrollScreenShot { (image) in
         拿到 image 
         各种复杂装逼操作
         、、、、
    }
  ## webView截屏:
    webView.DDGContentscreenShot { (image) in
         拿到 image 
         各种复杂装逼操作
         、、、、
    }
  ## wkwebView截屏: 方法和webView 一样,内部做了校验
      webView.DDGContentscreenShot { (image) in
           拿到 image 
           各种复杂装逼操作
           、、、、
      }
  ## image 加 logo
     let image = image.composeImageWithLogo( logo: UIImage,
                               logoOrigin: CGPoint,
                               logoSize:CGSize) 
     传入 logo图片,logo位置 logo 大小 就可以得到一张生成好的图片                         
         、、、、
  ## image 加 标签,水印,文字
     let image = image.drawTextInImage(text: String,
                         textColor: UIColor,
                         textFont: CGFloat,
                         textBgColor: UIColor,
                         textX: CGFloat,
                         textY: CGFloat ) 
     传入 文字、文字颜色、字体大小、背景颜色,字体起始位置 就可以得到一张生成好的带标签的图片                         
         、、、、
         注,此方法在提交pod有问题,故将方法屏蔽,有需要的可以拷贝代码,到本地

## 使用pod
     iOS 9.0+, Swift 4.0+(Compatiable)
        使用pod 导入
        pod 'DDGScreenShot', '~> 1.0.1'
        ```

欢迎查看DDGScreenShot

其余功能如下

  1. (一)DDGScreenShot — 复杂屏幕截屏(如view ScrollView webView wkwebView)
  2. (二)DDGScreenShot--iOS 图片处理--多图片拼接
  3. (三)DDGScreenShot--iOS 图片裁剪,切圆角,加边框,你还用cornerRadius,还有更高级的用法
  4. (四)DDGScreenShot—图片擦除功能
  5. (五)DDGScreenShot—截取图片的任意部分
  6. (六)DDGScreenShot —图片加各种滤镜高逼格操作
  7. (七)DDGScreenShot —图片加高斯模糊,老电影效果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容

  • 用到的组件 1、通过CocoaPods安装 2、第三方类库安装 3、第三方服务 友盟社会化分享组件 友盟用户反馈 ...
    SunnyLeong阅读 14,601评论 1 180
  • 天朗云自清 山中云自扬 随意共曲水 欢笑已流觞 2017-08-17
    李和同阅读 94评论 0 0
  • 孤独,在中国文字里解释,孤是王者,独是独一无二,独一无二的王者必需永远接受孤独,他不需要接受任何人的认同,更加不需...
    索菲玛苏阅读 399评论 0 0
  • 今天树儿逃学一天,小家伙表示出很满足的样子。很多事情都会与我好好地沟通协商,表现出非常顺从。我心里那么美啊,树儿又...
    苗苗在故乡阅读 351评论 2 0
  • (五) 子路顶嘴 孔子虽然下学人事上达天命,但人事有否有泰,天命有穷有通,孔子通...
    妙智阅读 2,656评论 1 3