在开发中,有时会遇到对图片的处理需求,在 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.Drawdraw.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的一种特殊形式,当 DrawMaskmask 参数为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 库相关推荐

  1. 「GoCN酷Go推荐」go语言位操作库 — bitset

    bitset库实现了bitsets数据结构,这是一种正整数和布尔值映射关系的结构,它比map[uint]bool更高效 什么是bitsets✦ bitsets基本思想是用一个bit位来标记某个元素对应 ...

  2. 【GoCN酷Go推荐】ip2location 解析 IP 地址库

     简介 很多时候,我们获取了用户ip,但是想知道更多信息,怎么办?使用ip2location吧. 这个库,可以从IP地址快速查找国家,地区,城市,纬度,经度,邮政编码,时区,ISP,域名,连接类型,I ...

  3. 【GoCN酷Go推荐】Html解析利器-goquery库

    简介 什么是goquery? goquery是由Go实现的基于Go的net/html包和CSS选择器库cascadia的HTML解析库. 由于net/html解析器需要UTF-8编码,goquery也 ...

  4. Android之Google推荐的图片加载库Glide介绍

    原文链接:Google推荐的图片加载库Glide介绍 作者 : nuuneoi 译者 : jianghejie 校对者 :

  5. Google推荐的图片加载库Glide于Picasso比较

    在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载库,作者是bumptech.这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官 ...

  6. 「GoCN酷Go推荐」后现代时代远程办公网络问题的golang开源解决方案 —— PairMesh...

    PairMesh是什么? Pairmesh是一款先进的虚拟局域网(VPN)工具,用来搭建与访问安全,易用,高性能的点对点的软件定义虚拟局域网,为远程办公的网络连接问题提供了开箱即用的解决方案. 拥抱开 ...

  7. 「GoCN酷Go推荐」Golang轻量级桌面程序wails2教学

    01 推荐理由 不依赖cgo!不依赖cgo!不依赖cgo!真的不依赖cgo,且跨平台,原生渲染 无嵌入式浏览器,轻量级,生成的文件很小,而且只有一个可执行文件就可运行. 02 功能介绍 后端使用标准 ...

  8. 「GoCN酷Go推荐」Golang的Ealstic链接库

    背景介绍 Elasticsearch是一个分布式.高扩展.高实时的搜索与数据分析引擎,用于海量文档的搜索.有些项目会将Elasticsearch当做存储海量数据的数据库使用,可见其查询性能之高效.作为 ...

  9. 「GoCN酷Go推荐」golang 跨平台部署利器

    1 研究背景 go程序部署时,直接将编译好的文件在服务器上运行即可,一般无需安装所依赖的第三方库. Linux下部署分为以下几种方式: 使用nohup 命令 使用 Supervisord管理 使用sy ...

最新文章

  1. python语音翻译-python利用有道翻译实现“语言翻译器”的功能
  2. mybatis.xml中sql编写规范
  3. 半斤八两中级破解 (四) TCP_UDP协议转向本地验证
  4. 系统架构设计师难吗?IT行业员工的最高荣耀是什么
  5. gsmake —— golang版gradle
  6. 关于Tomcat双击startup.bat文件一闪而过问题
  7. Mysql limit 子查询
  8. 漫步数理统计二十二——二项及相关分布
  9. 无废话ExtJs 入门教程八[脚本调试Firefox:firebug]
  10. [渝粤教育] 西南科技大学 机械工程测试技术 在线考试复习资料
  11. 内外网同时使用-路由配置
  12. 建立ad-hoc网络 // 电脑设置wifi热点 (Win10)
  13. FastReport Mono 2023.1 Crack
  14. owasp top10
  15. 苹果开发者账号 你的支付授权失败,请核对你的信息并重试
  16. Mac 判断终端是否走了代理服务器的方法
  17. ssh和rsh的区别、Linux rsh命令
  18. 划词翻译—多种翻译平台集合体积不足1mb——QTranslate
  19. oracle运维与mysql_运维日记| MySQL/Oracle深度解析之一:逻辑读
  20. Tomcat 中文文档(一)

热门文章

  1. r7 3700x和r7 3800x哪个性价比高 r73700x和r73800x哪个更值得买
  2. SpringCloud微服务权限管理系统
  3. svn导致桌面图标带蓝色问号,加号等svn标记问题解决
  4. 【分享】QY-RK3288开发板硬件说明书
  5. c语言单精度浮点数规格化,对浮点数的一些理解
  6. Nitro PDF用户记录数据库被盗
  7. html右下角的广告特效,jQuery实现的右下角广告窗体跟随效果示例
  8. 荣耀出货量下滑出击千元机市场,小米压力有点大
  9. 如何重装计算机操作系统,老电脑怎么重装操作系统
  10. Arishmoon Tony的高考素材本.1