【GoCN酷Go推荐】Golang 图片处理 — image 库
在开发中,有时会遇到对图片的处理需求,在 Python中, PIL/Pillow 库非常强大和易用。
而 Golang 语言中,处理图片的标准库 image
也可以实现一些基本操作。
image
库支持常见的 PNG、JPEG、GIF 等格式的图片处理, 可以对图片进行读取、裁剪、绘制、生成等操作。
读取、新建图片
读取
图片的读取,和文件的读取类似,只需要使用 os.Open()
函数,获取一个输入流,然后将数据流进行解码操作。
需要注意的是,在解码阶段,要将不同类型的图片的解码器先进行注册,这样才不会报unknown format
的错误。
package mainimport ("fmt""image"_ "image/png""os"
)func main() {f, err := os.Open("./gopher.png")if err != nil {panic(err)}img, formatName, err := image.Decode(f)if err != nil {panic(err)}fmt.Println(formatName)fmt.Println(img.Bounds())fmt.Println(img.ColorModel())
}
Decode
方法返回的第一个值是一个 image.Image
类型接口。不同的颜色模型的图片返回不同类型的值。该接口有三个方法:
type Image interface {ColorModel() color.Model // 返回图片的颜色模型Bounds() Rectangle // 返回图片的长宽At(x, y int) color.Color // 返回(x,y)像素点的颜色
}
image 库中很多结构都实现了该接口,对于一些标准库中没有实现的功能,我们也可以自己实现该接口去满足。
新建
如果是需要新建一个图片,可以使用image.NewRGBA()
方法。
img := image.NewRGBA(image.Rect(0, 0, 300, 300))
这里的 NewRGBA
方法返回的是一个实现了 image.Image
接口的 image.RGBA
类型数据。这里是一个300*300的透明背景的图片。
保存图片
保存图片和保存文件也类似,需要先将图片编码,然后以数据流的形式写入文件。
img := image.NewRGBA(image.Rect(0, 0, 300, 300))outFile, err := os.Create("gopher2.png")
defer outFile.Close()
if err != nil {panic(err)
}
b := bufio.NewWriter(outFile)
err = png.Encode(b, img)
if err != nil {panic(err)
}
err = b.Flush()
if err != nil {panic(err)
}
裁剪图片
图片的裁剪主要使用SubImage()
方法,如下:
img := image.NewRGBA(image.Rect(0, 0, 300, 300))
subImage := img.SubImage(image.Rect(0, 0, 20, 20))
该方法将从创建的300 * 300的图片裁剪出20 * 20 像素的子图片。
绘制图片
绘制图片主要使用到 draw.Draw
和draw.DrawMask
方法。
func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op)func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op)
Draw
Draw
方法各个参数含义如下:
dst 绘图的背景图
r 背景图的绘图区域
src 要绘制的图
sp src 对应的绘图开始点
op 组合方式
以下代码是将一个 Gopher 的图案绘制到了一张黑色背景空白图的左上角。
f, err := os.Open("./gopher.png")
if err != nil {panic(err)
}
gopherImg, _, err := image.Decode(f) // 打开图片img := image.NewRGBA(image.Rect(0, 0, 300, 300))
for x := 0; x < img.Bounds().Dx(); x++ { // 将背景图涂黑for y := 0; y < img.Bounds().Dy(); y++ {img.Set(x, y, color.Black)}
}
draw.Draw(img, img.Bounds(), gopherImg, image.Pt(0, 0), draw.Over) // 将gopherImg绘制到背景图上
DrawMask
DrawMask
方法多了一个遮罩蒙层参数mask
,以及蒙层的起始位置参数 mp
。
Draw
方法是 DrawMask
的一种特殊形式,当 DrawMask
的 mask
参数为nil时,即为Draw
方法。
DrawMask
将背景图上的绘图区域起始点、要绘制图的起始点、遮罩蒙层的起始点进行对齐,然后对背景图上的绘图矩阵区域执行 Porter-Duff合并操作。
下面是给图片加一个圆形遮罩的示例:
func drawCirclePic() {f, err := os.Open("./gopher.png")if err != nil {panic(err)}gopherImg, _, err := image.Decode(f)d := gopherImg.Bounds().Dx()//将一个cicle作为蒙层遮罩,圆心为图案中点,半径为边长的一半c := circle{p: image.Point{X: d / 2, Y: d / 2}, r: d / 2} circleImg := image.NewRGBA(image.Rect(0, 0, d, d))draw.DrawMask(circleImg, circleImg.Bounds(), gopherImg, image.Point{}, &c, image.Point{}, draw.Over)SavePng(circleImg)
}type circle struct { // 这里需要自己实现一个圆形遮罩,实现接口里的三个方法p image.Point // 圆心位置r int
}func (c *circle) ColorModel() color.Model {return color.AlphaModel
}func (c *circle) Bounds() image.Rectangle {return image.Rect(c.p.X-c.r, c.p.Y-c.r, c.p.X+c.r, c.p.Y+c.r)
}// 对每个像素点进行色值设置,在半径以内的图案设成完全不透明
func (c *circle) At(x, y int) color.Color {xx, yy, rr := float64(x-c.p.X)+0.5, float64(y-c.p.Y)+0.5, float64(c.r)if xx*xx+yy*yy < rr*rr {return color.Alpha{A: 255}}return color.Alpha{}
}
给图片加一个圆角遮罩的示例:
func drawRadiusPic() {f, err := os.Open("./gopher.png")if err != nil {panic(err)}gopherImg, _, err := image.Decode(f)w := gopherImg.Bounds().Dx()h := gopherImg.Bounds().Dy()c := radius{p: image.Point{X: w, Y: h}, r: int(40)}radiusImg := image.NewRGBA(image.Rect(0, 0, w, h))draw.DrawMask(radiusImg, radiusImg.Bounds(), gopherImg, image.Point{}, &c, image.Point{}, draw.Over)SavePng(radiusImg)
}type radius struct {p image.Point // 矩形右下角位置r int
}func (c *radius) ColorModel() color.Model {return color.AlphaModel
}func (c *radius) Bounds() image.Rectangle {return image.Rect(0, 0, c.p.X, c.p.Y)
}// 对每个像素点进行色值设置,分别处理矩形的四个角,在四个角的内切圆的外侧,色值设置为全透明,其他区域不透明
func (c *radius) At(x, y int) color.Color {var xx, yy, rr float64var inArea bool// left upif x <= c.r && y <= c.r {xx, yy, rr = float64(c.r-x)+0.5, float64(y-c.r)+0.5, float64(c.r)inArea = true}// right upif x >= (c.p.X-c.r) && y <= c.r {xx, yy, rr = float64(x-(c.p.X-c.r))+0.5, float64(y-c.r)+0.5, float64(c.r)inArea = true}// left bottomif x <= c.r && y >= (c.p.Y-c.r) {xx, yy, rr = float64(c.r-x)+0.5, float64(y-(c.p.Y-c.r))+0.5, float64(c.r)inArea = true}// right bottomif x >= (c.p.X-c.r) && y >= (c.p.Y-c.r) {xx, yy, rr = float64(x-(c.p.X-c.r))+0.5, float64(y-(c.p.Y-c.r))+0.5, float64(c.r)inArea = true}if inArea && xx*xx+yy*yy >= rr*rr {return color.Alpha{}}return color.Alpha{A: 255}
}
在图案进行圆形、圆角绘制的过程中,因为最小单位是1px,所以可能会有锯齿边缘的问题,解决这个问题可以通过先将原图放大,遮罩后再缩小来解决。
Reference
The Go image/draw package - The Go Blog (golang.org)https://blog.golang.org/image-draw)
Porter-Duff blend 模式 - Xamarin | Microsoft Docs(https://docs.microsoft.com/zh-tw/xamarin/xamarin-forms/user-interface/graphics/skiasharp/effects/blend-modes/porter-duff)
还想了解更多吗?
欢迎加入我们GOLANG中国社区:https://gocn.vip/
《酷Go推荐》招募:
各位Gopher同学,最近我们社区打算推出一个类似GoCN每日新闻的新栏目《酷Go推荐》,主要是每周推荐一个库或者好的项目,然后写一点这个库使用方法或者优点之类的,这样可以真正的帮助到大家能够学习到
新的库,并且知道怎么用。
大概规则和每日新闻类似,如果报名人多的话每个人一个月轮到一次,欢迎大家报名!(报名地址:https://wj.qq.com/s2/7734329/3f51)
扫码也可以加入 GoCN 的大家族哟~
【GoCN酷Go推荐】Golang 图片处理 — image 库相关推荐
- 「GoCN酷Go推荐」go语言位操作库 — bitset
bitset库实现了bitsets数据结构,这是一种正整数和布尔值映射关系的结构,它比map[uint]bool更高效 什么是bitsets✦ bitsets基本思想是用一个bit位来标记某个元素对应 ...
- 【GoCN酷Go推荐】ip2location 解析 IP 地址库
简介 很多时候,我们获取了用户ip,但是想知道更多信息,怎么办?使用ip2location吧. 这个库,可以从IP地址快速查找国家,地区,城市,纬度,经度,邮政编码,时区,ISP,域名,连接类型,I ...
- 【GoCN酷Go推荐】Html解析利器-goquery库
简介 什么是goquery? goquery是由Go实现的基于Go的net/html包和CSS选择器库cascadia的HTML解析库. 由于net/html解析器需要UTF-8编码,goquery也 ...
- Android之Google推荐的图片加载库Glide介绍
原文链接:Google推荐的图片加载库Glide介绍 作者 : nuuneoi 译者 : jianghejie 校对者 :
- Google推荐的图片加载库Glide于Picasso比较
在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载库,作者是bumptech.这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官 ...
- 「GoCN酷Go推荐」后现代时代远程办公网络问题的golang开源解决方案 —— PairMesh...
PairMesh是什么? Pairmesh是一款先进的虚拟局域网(VPN)工具,用来搭建与访问安全,易用,高性能的点对点的软件定义虚拟局域网,为远程办公的网络连接问题提供了开箱即用的解决方案. 拥抱开 ...
- 「GoCN酷Go推荐」Golang轻量级桌面程序wails2教学
01 推荐理由 不依赖cgo!不依赖cgo!不依赖cgo!真的不依赖cgo,且跨平台,原生渲染 无嵌入式浏览器,轻量级,生成的文件很小,而且只有一个可执行文件就可运行. 02 功能介绍 后端使用标准 ...
- 「GoCN酷Go推荐」Golang的Ealstic链接库
背景介绍 Elasticsearch是一个分布式.高扩展.高实时的搜索与数据分析引擎,用于海量文档的搜索.有些项目会将Elasticsearch当做存储海量数据的数据库使用,可见其查询性能之高效.作为 ...
- 「GoCN酷Go推荐」golang 跨平台部署利器
1 研究背景 go程序部署时,直接将编译好的文件在服务器上运行即可,一般无需安装所依赖的第三方库. Linux下部署分为以下几种方式: 使用nohup 命令 使用 Supervisord管理 使用sy ...
最新文章
- python语音翻译-python利用有道翻译实现“语言翻译器”的功能
- mybatis.xml中sql编写规范
- 半斤八两中级破解 (四) TCP_UDP协议转向本地验证
- 系统架构设计师难吗?IT行业员工的最高荣耀是什么
- gsmake —— golang版gradle
- 关于Tomcat双击startup.bat文件一闪而过问题
- Mysql limit 子查询
- 漫步数理统计二十二——二项及相关分布
- 无废话ExtJs 入门教程八[脚本调试Firefox:firebug]
- [渝粤教育] 西南科技大学 机械工程测试技术 在线考试复习资料
- 内外网同时使用-路由配置
- 建立ad-hoc网络 // 电脑设置wifi热点 (Win10)
- FastReport Mono 2023.1 Crack
- owasp top10
- 苹果开发者账号 你的支付授权失败,请核对你的信息并重试
- Mac 判断终端是否走了代理服务器的方法
- ssh和rsh的区别、Linux rsh命令
- 划词翻译—多种翻译平台集合体积不足1mb——QTranslate
- oracle运维与mysql_运维日记| MySQL/Oracle深度解析之一:逻辑读
- Tomcat 中文文档(一)