mirror of
https://github.com/golang/go
synced 2024-11-19 10:34:46 -07:00
image/png: use branch-free abs function
benchmark old ns/op new ns/op delta BenchmarkPaeth 5.06 6.02 +18.97% BenchmarkDecodeGray 1010551 956911 -5.31% BenchmarkDecodeNRGBAGradient 3877813 3754160 -3.19% BenchmarkDecodeNRGBAOpaque 3194058 3079094 -3.60% BenchmarkDecodePaletted 699243 700211 +0.14% BenchmarkDecodeRGB 2835733 2692120 -5.06% BenchmarkDecodeInterlacing 3651805 3563124 -2.43% BenchmarkEncodeGray 4399183 4404113 +0.11% BenchmarkEncodeNRGBOpaque 13323627 13306485 -0.13% BenchmarkEncodeNRGBA 15840092 15751188 -0.56% BenchmarkEncodePaletted 4396622 4404373 +0.18% BenchmarkEncodeRGBOpaque 13320475 13279189 -0.31% BenchmarkEncodeRGBA 36898392 36781002 -0.32% LGTM=nigeltao R=nigeltao CC=golang-codereviews https://golang.org/cl/117290043
This commit is contained in:
parent
d3fb02b5c5
commit
0100afbdcc
@ -4,6 +4,21 @@
|
||||
|
||||
package png
|
||||
|
||||
// intSize is either 32 or 64.
|
||||
const intSize = 32 << (^uint(0) >> 63)
|
||||
|
||||
func abs(x int) int {
|
||||
// m := -1 if x < 0. m := 0 otherwise.
|
||||
m := x >> (intSize - 1)
|
||||
|
||||
// In two's complement representation, the negative number
|
||||
// of any number (except the smallest one) can be computed
|
||||
// by flipping all the bits and add 1. This is faster than
|
||||
// code with a branch.
|
||||
// See Hacker's Delight, section 2-4.
|
||||
return (x ^ m) - m
|
||||
}
|
||||
|
||||
// paeth implements the Paeth filter function, as per the PNG specification.
|
||||
func paeth(a, b, c uint8) uint8 {
|
||||
// This is an optimized version of the sample code in the PNG spec.
|
||||
@ -16,16 +31,9 @@ func paeth(a, b, c uint8) uint8 {
|
||||
pc := int(c)
|
||||
pa := int(b) - pc
|
||||
pb := int(a) - pc
|
||||
pc = pa + pb
|
||||
if pa < 0 {
|
||||
pa = -pa
|
||||
}
|
||||
if pb < 0 {
|
||||
pb = -pb
|
||||
}
|
||||
if pc < 0 {
|
||||
pc = -pc
|
||||
}
|
||||
pc = abs(pa + pb)
|
||||
pa = abs(pa)
|
||||
pb = abs(pb)
|
||||
if pa <= pb && pa <= pc {
|
||||
return a
|
||||
} else if pb <= pc {
|
||||
@ -44,16 +52,9 @@ func filterPaeth(cdat, pdat []byte, bytesPerPixel int) {
|
||||
b = int(pdat[j])
|
||||
pa = b - c
|
||||
pb = a - c
|
||||
pc = pa + pb
|
||||
if pa < 0 {
|
||||
pa = -pa
|
||||
}
|
||||
if pb < 0 {
|
||||
pb = -pb
|
||||
}
|
||||
if pc < 0 {
|
||||
pc = -pc
|
||||
}
|
||||
pc = abs(pa + pb)
|
||||
pa = abs(pa)
|
||||
pb = abs(pb)
|
||||
if pa <= pb && pa <= pc {
|
||||
// No-op.
|
||||
} else if pb <= pc {
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func abs(x int) int {
|
||||
func slowAbs(x int) int {
|
||||
if x < 0 {
|
||||
return -x
|
||||
}
|
||||
@ -21,9 +21,9 @@ func abs(x int) int {
|
||||
// It is a straight port of the sample code in the PNG spec, section 9.4.
|
||||
func slowPaeth(a, b, c uint8) uint8 {
|
||||
p := int(a) + int(b) - int(c)
|
||||
pa := abs(p - int(a))
|
||||
pb := abs(p - int(b))
|
||||
pc := abs(p - int(c))
|
||||
pa := slowAbs(p - int(a))
|
||||
pb := slowAbs(p - int(b))
|
||||
pc := slowAbs(p - int(c))
|
||||
if pa <= pb && pa <= pc {
|
||||
return a
|
||||
} else if pb <= pc {
|
||||
|
Loading…
Reference in New Issue
Block a user