如果您的程序将进行需要大多数(如果不是全部)像素数据的计算,那么rgba.Pix()
显着优于img.At()
。如果您只需要图像中单个或几个像素的像素数据,请使用img.At()
(计算的开销rgba.Pix()
在这种情况下,先决条件太高)。
以下是各种测试负载的结果,每个负载的持续时间是 10 个样本的平均值。
Method |
1x1 |
1000x667 |
3840x2160 |
1000x667 + computation |
1000x667 only 5x5 accessed |
img.At() |
195ns |
30.211071ms |
294.885396ms |
853.345043ms |
42.431μs
|
rgba.Pix() |
719ns |
7.786029ms |
77.700552ms |
836.480063ms |
6.791461ms
|
我们可以看到如何对于微小的 1x1 图像以及我们将 for 循环限制为上限 5 的图像,使用img.At()
导致更快的执行时间。但是,对于获取每个像素的用例,rgba.Pix()
带来更好的性能。随着总时间的增加以及之间的差异,我们对每个像素进行的计算越多,这种性能的改进就越不明显。img.At()
and rgba.Pix()
变得不那么明显,如“1000x667 + 计算”在上表中。
这是使用的测试代码:
func main() {
resp, err := http.Get("IMAGE URL GOES HERE")
if err != nil {
panic(err)
}
defer resp.Body.Close()
img, _, err := image.Decode(resp.Body)
if err != nil {
panic(err)
}
var start time.Time
var duration time.Duration
samples := 10
var sum time.Duration
fmt.Println("Samples: ", samples)
sum = time.Duration(0)
for i := 0; i < samples; i++ {
start = time.Now()
usingAt(img)
duration = time.Since(start)
sum += duration
}
fmt.Println("*** At avg: ", sum/time.Duration(samples))
sum = time.Duration(0)
for i := 0; i < samples; i++ {
start = time.Now()
usingPix(img)
duration = time.Since(start)
sum += duration
}
fmt.Println("*** Pix avg: ", sum/time.Duration(samples))
}
func usingAt(img image.Image) {
bounds := img.Bounds()
width, height := bounds.Max.X, bounds.Max.Y
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
r, g, b, _ := img.At(x, y).RGBA()
_ = uint8(r >> 8)
_ = uint8(g >> 8)
_ = uint8(b >> 8)
}
}
}
func usingPix(img image.Image, targetColor colorful.Color) {
bounds := img.Bounds()
width, height := bounds.Max.X, bounds.Max.Y
rgba := image.NewRGBA(bounds)
draw.Draw(rgba, bounds, img, bounds.Min, draw.Src)
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
index := (y*width + x) * 4
pix := rgba.Pix[index : index+4]
_ = pix[0]
_ = pix[1]
_ = pix[2]
}
}
}
1000x667 仅 5x5 访问取代了height
and width
在 for 循环中使用 5 和 5,限制访问的像素数量。
1000x667 + 计算实际上通过比较每个像素与目标颜色的颜色距离来使用 RGB 值色彩缤纷 https://github.com/lucasb-eyer/go-colorful的DE2000计算。