摘要

直接操作图片来实现它的缩放或者填充多余空间,首选 UIGraphicsBeginImageContext 函数来实现,它就相当于一个画布,你甚至可以用它来涂鸦。

最近有一个需求,就是将图片先等比例缩放到指定大小,然后将空余出来空间填充为黑色,返回指定大小的图片。

这种直接操作图片的需求,就要考虑使用 UIGraphicsBeginImageContext 函数实现。它可以理解为一个画布,我们只需要把图片放在画布的对应位置,把画布的多余地方全部涂成黑色就完成。

实现

先看代码,然后再分析:

func rescaleAndPading(_ image: UIImage, targetSize: CGSize) -> UIImage? {
let max = max(image.width, image.height)
let ratio = Float(targetSize.width) / Float(max) let (newWidth, newHeight) = ( Int(Float(image.width) * ratio),
Int(Float(image.height) * ratio)
) let (tarWidth, tarHeight) = ( Int(targetSize.width),
Int(targetSize.height)
) let deltaW = tarWidth - newWidth
let deltaH = tarHeight - newHeight let (y, x) = ( deltaH / 2,
deltaW / 2
) // 创建绘图上下文环境
UIGraphicsBeginImageContext(targetSize)
let context = UIGraphicsGetCurrentContext()
// 黄色背景
context?.setFillColor(UIColor.yellow.cgColor)
context?.fill(CGRect(x: 0, y: 0, width: tarWidth, height: tarHeight))
image.draw(in: CGRect(x: x, y: y, width: newWidth, height: newHeight))
// 获取上下文里的内容,将视图写入到新的图像对象
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}

看代码,总结出逻辑很简单,就是首先根据目标的 size 来计算出需要缩放的比例(按照最大边来处理),计算出图片在画布中的对应位置和缩放后的宽高。

最后就是重头戏,调用 UIGraphicsBeginImageContext 来绘画。这里要留意几个参数的设置:

  • UIGraphicsBeginImageContext(targetSize) 中的 targetSize 是设置画布的大小。
  • image.draw(in:) 是图片在画布中的 rect 。
  • context 是画布的对象
  • context?.setFillColor(_) 是设置画布的颜色,若不设置,默认为 black(黑色)
  • context?.fill()是设置画布填充的 rect。

重点

如果是前面留意逻辑时,会发现逻辑中是先放置图片,然后填充空余空间,但是代码中是先填充全部空间,然后再放置图片,这是为什么?

经过测试后发现,后绘制的区域会覆盖掉先前已经绘制的区域,所以代码中的处理就是防止填充区域覆盖图片区域。

另外

时间仓促,说的东西可能不全面,在你实现过程中遇到什么问题,评论区给我留言,我会尽快回复。

Swift-技巧(一)缩放并填充图片的更多相关文章

  1. vc++ mfc 里保存缩放的bmp图片 不失真

    void CSaveView::OnFileSave() { BITMAP info;//原始图片 m_bitmap.GetBitmap(&info); CDC DC1; DC1.Create ...

  2. Android 手势检测实战 打造支持缩放平移的图片预览效果(下)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39480503,本文出自:[张鸿洋的博客] 上一篇已经带大家实现了自由的放大缩小图 ...

  3. ImageMagick: DrawImage(Image*,DrawInfo*) 绘制填充图片时卡住的原因分析

    今天傍晚在测试的时候无意发现有两个动画会卡住,正常情况下,20秒就完成的操作,突然卡住. CPU:95%+,经过30 - 50秒左右后,程序又能正常的向下执行,结果是对的. 这种情况不是每次都发生,有 ...

  4. Swift - UITableView展开缩放动画

    Swift - UITableView展开缩放动画 效果 源码 https://github.com/YouXianMing/Swift-Animations // // HeaderViewTapA ...

  5. PHP的图片处理类(缩放、加图片水印和剪裁)

    <!--test.php文件内容--> <?php //包含这个类image.class.php include "image.class.php"; $img ...

  6. Flex 绘制圆形并填充图片

    注意:Ellipse 绘制椭圆,当width = height 时 则绘制圆形. BitmapFill:填充图片 <s:Group id="gpimgUser" width= ...

  7. css技术之用最高和最宽的限制“max-height和max-width”做图片同比例缩放,达到图片不变形目的,做出批量打印图片功能,页面打印“window.print()”

    一.简介 他们是为流而生的,像width/height这种定死的砖头式布局,min-width/max-width就没有存在的意义 ,min-width/max-width一定是自适应布局或流体布局中 ...

  8. swift 点击button改变其内填充图片,达到选中的效果

    先看下效果: 点击后: 实现:在页面拖一个button,然后在所在页面声明其变量和一个点击事件 声明: @IBOutlet weak var BtnZiDong: UIButton! 点击事件函数: ...

  9. iOS swift 启动页加载广告(图片广告+视频广告)

    一般app在启动的时候都会有广告页,广告页用来加载自己的或者第三方的广告,广告的展示形式也多种多样,最近在看swift相关的东西,这里将提供支持加载图片广告和视频广告的解决方案 思路: 我们知道在加载 ...

随机推荐

  1. 基于Typora的Latex代码书写并移植到word中

    如何使用Markdown编译器 编辑Latex公式 并嵌入word内 ​ 前言:对于科研党来讲,在论文中数学公式的展示是必不可少的一环,但是如果不使用公式的格式去敲,那么公式就会过于难看,会大大降低你 ...

  2. 微信小程序+腾讯云直播的实时音视频实战笔记

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. 【PHP数据结构】二叉树的遍历及逻辑操作

    上篇文章我们讲了许多理论方面的知识,虽说很枯燥,但那些都是我们今天学习的前提,一会看代码的时候你就会发现这些理论知识是多么地重要了.首先,我们还是要说明一下,我们学习的主要内容是二叉树,因为二叉树是最 ...

  4. 【PHP数据结构】队列的相关逻辑操作

    在逻辑结构中,我们已经学习了一个非常经典的结构类型:栈.今天,我们就来学习另外一个也是非常经典的逻辑结构类型:队列.相信不少同学已经使用过 redis . rabbitmq 之类的缓存队列工具.其实, ...

  5. 解决IE浏览器 点击子元素重复调用执行 mouseover 与mouseout兼容性问题

    将函数配对换为下面2个就可以解决兼容性问题. mouseenter() mouseleave(0

  6. $.ajax 常用的套路

    $.ajax 常用的套路 (function(){ window.webApi = new Object(); webApi.get = function(url,data,callback){ $. ...

  7. base64原理,使用场景

    Base64编码,是我们程序开发中经常使用到的编码方法.它是一种基于用64个可打印字符来表示二进制数据的表示方法.它通常用作存储.传输一些二进制数据编码方法!也是MIME(多用途互联网邮件扩展,主要用 ...

  8. P7276-送给好友的礼物【dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P7276?contestId=39577 题目大意 \(n\)个点的一棵树,\(k\)个关键点,两个人从根出发分别走 ...

  9. join方法个人理解

    首先抛出对join的疑问 如果我有一个a线程,一个b线程 那此时 a.start(); b.start(); a.join(); b.join(); 是否意思是a线程先执行完,然后再执行b线程; 如果 ...

  10. IIS部署WCF详细教程

    前言: 前段时间接手了公司一个十几年前的老项目,该项目对外提供的服务使用的是WCF进行通信的.因为需要其他项目需要频繁的使用该WCF服务,所以我决定把这个WCF部署到IIS中避免每次调试运行查看效果. ...