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 Setmethods. 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图片/描绘包:图片/描绘包的基本原理相关推荐

  1. java 向word中添加excel附件并向excel单元格中加入图片并压缩图片并根据图片动态控制单元格高度宽度

    word中加入excel附件 excel单元格中插入图片 word freemarker Excel poi 制作, jxl 插入图片 压缩图片/宽高,动态控制单元格高度与宽度 1.word 需要模板 ...

  2. 基于golang制作倾斜图片水印保护图片来源

    目录 一.前言 二.核心实现思路 三.完整实现步骤 1. 平铺水印图像 2. 整体倾斜水印图像 3. 调整水印区域和透明度 四.最后成品代码 一.前言 在我的上一篇文章中,我们学会了使用 image/ ...

  3. [js高手之路]深入浅出webpack教程系列9-打包图片(file-loader)用法

    [js高手之路]深入浅出webpack教程系列索引目录: [js高手之路]深入浅出webpack教程系列1-安装与基本打包用法和命令参数 [js高手之路]深入浅出webpack教程系列2-配置文件we ...

  4. java水印图片,Java添加水印+图片水印+文字水印

    水印的处理...以下有两种方式: 第一种是添加文字水印: 第二种是添加图片水印 现在贴上代码 2种的源码 package com.yjf.image; import java.awt.AlphaCom ...

  5. python自带的PIL库扩展图片大小给图片加上文字描述

    利用python自带的PIL库扩展图片大小给图片加上文字描述.大多都是库函数调用,只是给定图片宽度后计算文字所需行数的代码需要写. 代码比较丑,but it works. #!/usr/bin/env ...

  6. python将图片转换为字符_python如何将图片转换为字符图片

    简介 一个简单的python程序,将图片转换为字符图片. (为了简便,很多参数写死了,自己看着改吧. (←∀←)) 正文 原图(侵删) 结果图 源码 [更多细节]-->戳这里 #-*- codi ...

  7. 压缩图片和改变图片图形

    压缩图片和改变图片图形 GitHub网址:https://github.com/qianshao1030/BitmapDemo 包名:compile 'jp.wasabeef:glide-transf ...

  8. Python 将矩形图片转为圆形图片

    使用PIL库将矩形图片转为原型图片 from PIL import Image, ImageDraw, ImageFilterdef crop_max_square(pil_img):return c ...

  9. PHP 合成图片并在图片上加文字

    /*** Info: PHP把一张图片作为背景和另一张图片合成新图片*/public function createImage(){$path_1 = 'XXXXX/attachment/images ...

  10. python add picture显示过大_利用Python自带PIL库扩展图片大小给图片加文字描述的方法示例...

    前言 最近的一个项目中需要在图片上添加文字,使用了OpenCV,结果发现利用opencv给图像添加文字有局限.可利用的字体类型比较少,需要安装Freetype扩展,比较复杂.而且不能用putText函 ...

最新文章

  1. python动态数组的最大值_python实现动态数组的示例代码
  2. gantt markdown
  3. VS创建props属性表并在新项目中导入props属性表
  4. VMDNS服务器未响应,vmware克隆虚拟机后进行网络配置
  5. 在SAP云平台的CloudFoundry环境下消费ABAP On-Premise OData服务
  6. java 最后的异常_java – 最后不要抛出堆栈溢出异常
  7. 高校再陷版权纷争:MATLAB遭禁用后,又一基础软件严查盗版
  8. Windows的特色
  9. Java安全 – JCE (Blowfish算法报错)
  10. VUE 浏览器最强插件——极简插件
  11. c语言人物游戏代码大全,(c语言)游戏中由人物各种信息组成的结构体
  12. Python-Telnet连接工具类
  13. 这是 iPhone 6主板?包含 802.11ac WiFi、NFC 芯片
  14. ubuntu linux崩溃,ubuntu linux qq崩溃问题的解决方法以及原因
  15. 最新Flutter 微信分享功能实现
  16. pandas25 if else语句(多数据df选择)( tcy)
  17. python求方程的根_python计算方程式根的方法
  18. 2020 4月 月末总结(飞速流逝的一个月)
  19. Python打包为exe文件
  20. Android Studio第一次安装app到夜神模拟器报错

热门文章

  1. 第一次 Zul'grub
  2. R语言之高级数据分析「聚类分析」
  3. 扎心实战案例:麻(shi)雀(zhan)虽小,五脏俱全
  4. python 利用栈实现复杂计算器
  5. [bzoj3509][CodeChef]COUNTARI
  6. 重拾数月前做的微信红包小项目
  7. 近现代科学三大发现:证实佛法真实不虚
  8. [转]asp.net webform 与mvc 共享session
  9. 查看各浏览器各版本的兼容情况
  10. OSChina 周日乱弹 —— 普通人如何面对持刀歹徒