25 The Go image/draw package go图片/描绘包:图片/描绘包的基本原理
The Go image/draw package go图片/描绘包:图片/描绘包的基本原理
29 September 2011
Introduction
Package image/draw defines only one operation: drawing a source image onto a destination image, through an optional mask image. This one operation is surprisingly versatile and can perform a number of common image manipulation tasks elegantly and efficiently.
Composition is performed pixel by pixel in the style of the Plan 9 graphics library and the X Render extension. The model is based on the classic "Compositing Digital Images" paper by Porter and Duff, with an additional mask parameter: dst = (src IN mask) OP dst
. For a fully opaque mask, this reduces to the original Porter-Duff formula: dst = src OP dst
. In Go, a nil mask image is equivalent to an infinitely sized, fully opaque mask image.
The Porter-Duff paper presented 12 different composition operators, but with an explicit mask, only 2 of these are needed in practice: source-over-destination and source. In Go, these operators are represented by the Over
and Src
constants. The Over
operator performs the natural layering of a source image over a destination image: the change to the destination image is smaller where the source (after masking) is more transparent (that is, has lower alpha). The Src
operator merely copies the source (after masking) with no regard for the destination image's original content. For fully opaque source and mask images, the two operators produce the same output, but the Src
operator is usually faster.
Geometric Alignment
Composition requires associating destination pixels with source and mask pixels. Obviously, this requires destination, source and mask images, and a composition operator, but it also requires specifying what rectangle of each image to use. Not every drawing should write to the entire destination: when updating an animating image, it is more efficient to only draw the parts of the image that have changed. Not every drawing should read from the entire source: when using a sprite that combines many small images into one large one, only a part of the image is needed. Not every drawing should read from the entire mask: a mask image that collects a font's glyphs is similar to a sprite. Thus, drawing also needs to know three rectangles, one for each image. Since each rectangle has the same width and height, it suffices to pass a destination rectangle r
and two points sp
and mp
: the source rectangle is equal to r
translated so that r.Min
in the destination image aligns with sp
in the source image, and similarly for mp
. The effective rectangle is also clipped to each image's bounds in their respective co-ordinate space.
The DrawMask
function takes seven arguments, but an explicit mask and mask-point are usually unnecessary, so the Draw
function takes five:
// Draw calls DrawMask with a nil mask. 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)
The destination image must be mutable, so the image/draw package defines a draw.Image
interface which has a Set
method.
type Image interface {image.ImageSet(x, y int, c color.Color) }
Filling a Rectangle
To fill a rectangle with a solid color, use an image.Uniform
source. The ColorImage
type re-interprets a Color
as a practically infinite-sized Image
of that color. For those familiar with the design of Plan 9's draw library, there is no need for an explicit "repeat bit" in Go's slice-based image types; the concept is subsumed by Uniform
.
// image.ZP is the zero point -- the origin. draw.Draw(dst, r, &image.Uniform{c}, image.ZP, draw.Src)
To initialize a new image to all-blue:
m := image.NewRGBA(image.Rect(0, 0, 640, 480)) blue := color.RGBA{0, 0, 255, 255} draw.Draw(m, m.Bounds(), &image.Uniform{blue}, image.ZP, draw.Src)
To reset an image to transparent (or black, if the destination image's color model cannot represent transparency), use image.Transparent
, which is an image.Uniform
:
draw.Draw(m, m.Bounds(), image.Transparent, image.ZP, draw.Src)
Copying an Image
To copy from a rectangle sr
in the source image to a rectangle starting at a point dp
in the destination, convert the source rectangle into the destination image's co-ordinate space:
r := image.Rectangle{dp, dp.Add(sr.Size())} draw.Draw(dst, r, src, sr.Min, draw.Src)
Alternatively:
r := sr.Sub(sr.Min).Add(dp) draw.Draw(dst, r, src, sr.Min, draw.Src)
To copy the entire source image, use sr = src.Bounds()
.
Scrolling an Image
Scrolling an image is just copying an image to itself, with different destination and source rectangles. Overlapping destination and source images are perfectly valid, just as Go's built-in copy function can handle overlapping destination and source slices. To scroll an image m by 20 pixels:
b := m.Bounds() p := image.Pt(0, 20) // Note that even though the second argument is b, // the effective rectangle is smaller due to clipping. draw.Draw(m, b, m, b.Min.Add(p), draw.Src) dirtyRect := b.Intersect(image.Rect(b.Min.X, b.Max.Y-20, b.Max.X, b.Max.Y))
Converting an Image to RGBA
The result of decoding an image format might not be an image.RGBA
: decoding a GIF results in an image.Paletted
, decoding a JPEG results in a ycbcr.YCbCr
, and the result of decoding a PNG depends on the image data. To convert any image to an image.RGBA
:
b := src.Bounds() m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy())) draw.Draw(m, m.Bounds(), src, b.Min, draw.Src)
Drawing Through a Mask
To draw an image through a circular mask with center p
and radius r
:
type circle struct {p image.Pointr 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{255}}return color.Alpha{0} }draw.DrawMask(dst, dst.Bounds(), src, image.ZP, &circle{p, r}, image.ZP, draw.Over)
Drawing Font Glyphs
To draw a font glyph in blue starting from a point p
, draw with an image.ColorImage
source and an image.Alpha mask
. For simplicity, we aren't performing any sub-pixel positioning or rendering, or correcting for a font's height above a baseline.
src := &image.Uniform{color.RGBA{0, 0, 255, 255}} mask := theGlyphImageForAFont() mr := theBoundsFor(glyphIndex) draw.DrawMask(dst, mr.Sub(mr.Min).Add(p), src, image.ZP, mask, mr.Min, draw.Over)
Performance
The image/draw package implementation demonstrates how to provide an image manipulation function that is both general purpose, yet efficient for common cases. The DrawMask
function takes arguments of interface types, but immediately makes type assertions that its arguments are of specific struct types, corresponding to common operations like drawing one image.RGBA
image onto another, or drawing an image.Alpha
mask (such as a font glyph) onto an image.RGBA
image. If a type assertion succeeds, that type information is used to run a specialized implementation of the general algorithm. If the assertions fail, the fallback code path uses the generic At
and Set
methods. The fast-paths are purely a performance optimization; the resultant destination image is the same either way. In practice, only a small number of special cases are necessary to support typical applications.
By Nigel Tao
Related articles
- HTTP/2 Server Push
- Introducing HTTP Tracing
- Generating code
- Introducing the Go Race Detector
- Go maps in action
- go fmt your code
- Organizing Go code
- Debugging Go programs with the GNU Debugger
- The Go image package
- The Laws of Reflection
- Error handling and Go
- "First Class Functions in Go"
- Profiling Go Programs
- Spotlight on external Go libraries
- A GIF decoder: an exercise in Go interfaces
- Introducing Gofix
- Godoc: documenting Go code
- Gobs of data
- C? Go? Cgo!
- JSON and Go
- Go Slices: usage and internals
- Go Concurrency Patterns: Timing out, moving on
- Defer, Panic, and Recover
- Share Memory By Communicating
- JSON-RPC: a tale of interfaces
转载于:https://www.cnblogs.com/kaid/p/9698531.html
25 The Go image/draw package go图片/描绘包:图片/描绘包的基本原理相关推荐
- java 向word中添加excel附件并向excel单元格中加入图片并压缩图片并根据图片动态控制单元格高度宽度
word中加入excel附件 excel单元格中插入图片 word freemarker Excel poi 制作, jxl 插入图片 压缩图片/宽高,动态控制单元格高度与宽度 1.word 需要模板 ...
- 基于golang制作倾斜图片水印保护图片来源
目录 一.前言 二.核心实现思路 三.完整实现步骤 1. 平铺水印图像 2. 整体倾斜水印图像 3. 调整水印区域和透明度 四.最后成品代码 一.前言 在我的上一篇文章中,我们学会了使用 image/ ...
- [js高手之路]深入浅出webpack教程系列9-打包图片(file-loader)用法
[js高手之路]深入浅出webpack教程系列索引目录: [js高手之路]深入浅出webpack教程系列1-安装与基本打包用法和命令参数 [js高手之路]深入浅出webpack教程系列2-配置文件we ...
- java水印图片,Java添加水印+图片水印+文字水印
水印的处理...以下有两种方式: 第一种是添加文字水印: 第二种是添加图片水印 现在贴上代码 2种的源码 package com.yjf.image; import java.awt.AlphaCom ...
- python自带的PIL库扩展图片大小给图片加上文字描述
利用python自带的PIL库扩展图片大小给图片加上文字描述.大多都是库函数调用,只是给定图片宽度后计算文字所需行数的代码需要写. 代码比较丑,but it works. #!/usr/bin/env ...
- python将图片转换为字符_python如何将图片转换为字符图片
简介 一个简单的python程序,将图片转换为字符图片. (为了简便,很多参数写死了,自己看着改吧. (←∀←)) 正文 原图(侵删) 结果图 源码 [更多细节]-->戳这里 #-*- codi ...
- 压缩图片和改变图片图形
压缩图片和改变图片图形 GitHub网址:https://github.com/qianshao1030/BitmapDemo 包名:compile 'jp.wasabeef:glide-transf ...
- Python 将矩形图片转为圆形图片
使用PIL库将矩形图片转为原型图片 from PIL import Image, ImageDraw, ImageFilterdef crop_max_square(pil_img):return c ...
- PHP 合成图片并在图片上加文字
/*** Info: PHP把一张图片作为背景和另一张图片合成新图片*/public function createImage(){$path_1 = 'XXXXX/attachment/images ...
- python add picture显示过大_利用Python自带PIL库扩展图片大小给图片加文字描述的方法示例...
前言 最近的一个项目中需要在图片上添加文字,使用了OpenCV,结果发现利用opencv给图像添加文字有局限.可利用的字体类型比较少,需要安装Freetype扩展,比较复杂.而且不能用putText函 ...
最新文章
- python动态数组的最大值_python实现动态数组的示例代码
- gantt markdown
- VS创建props属性表并在新项目中导入props属性表
- VMDNS服务器未响应,vmware克隆虚拟机后进行网络配置
- 在SAP云平台的CloudFoundry环境下消费ABAP On-Premise OData服务
- java 最后的异常_java – 最后不要抛出堆栈溢出异常
- 高校再陷版权纷争:MATLAB遭禁用后,又一基础软件严查盗版
- Windows的特色
- Java安全 – JCE (Blowfish算法报错)
- VUE 浏览器最强插件——极简插件
- c语言人物游戏代码大全,(c语言)游戏中由人物各种信息组成的结构体
- Python-Telnet连接工具类
- 这是 iPhone 6主板?包含 802.11ac WiFi、NFC 芯片
- ubuntu linux崩溃,ubuntu linux qq崩溃问题的解决方法以及原因
- 最新Flutter 微信分享功能实现
- pandas25 if else语句(多数据df选择)( tcy)
- python求方程的根_python计算方程式根的方法
- 2020 4月 月末总结(飞速流逝的一个月)
- Python打包为exe文件
- Android Studio第一次安装app到夜神模拟器报错