mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
image/jpeg: prepare for new FDCT/IDCT implementations
Preparation for a new unencumbered implementation of fdct.go and idct.go. - Change benchmark not to allocate O(b.N) storage. - Make tests point out where differences are. - Parameterize differ tolerance. Change-Id: Id5dfee40f86de894bad72dd6178ba61ec81ea2da Reviewed-on: https://go-review.googlesource.com/c/go/+/705516 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
f15cd63ec4
commit
27c7bbc51c
1 changed files with 21 additions and 28 deletions
|
|
@ -13,14 +13,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func benchmarkDCT(b *testing.B, f func(*block)) {
|
func benchmarkDCT(b *testing.B, f func(*block)) {
|
||||||
b.StopTimer()
|
var blk block // avoid potential allocation in loop
|
||||||
blocks := make([]block, 0, b.N*len(testBlocks))
|
for b.Loop() {
|
||||||
for i := 0; i < b.N; i++ {
|
for _, blk = range testBlocks {
|
||||||
blocks = append(blocks, testBlocks[:]...)
|
f(&blk)
|
||||||
}
|
}
|
||||||
b.StartTimer()
|
|
||||||
for i := range blocks {
|
|
||||||
f(&blocks[i])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,16 +49,13 @@ func TestDCT(t *testing.T) {
|
||||||
// floats to ints.
|
// floats to ints.
|
||||||
for i, b := range blocks {
|
for i, b := range blocks {
|
||||||
got, want := b, b
|
got, want := b, b
|
||||||
for j := range got {
|
|
||||||
got[j] = (got[j] - 128) * 8
|
|
||||||
}
|
|
||||||
slowFDCT(&got)
|
slowFDCT(&got)
|
||||||
slowIDCT(&got)
|
slowIDCT(&got)
|
||||||
for j := range got {
|
for j := range got {
|
||||||
got[j] = got[j]/8 + 128
|
got[j] = got[j]/8 + 128
|
||||||
}
|
}
|
||||||
if differ(&got, &want) {
|
if d := differ(&got, &want, 2); d >= 0 {
|
||||||
t.Errorf("i=%d: IDCT(FDCT)\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
|
t.Errorf("i=%d: IDCT(FDCT) (diff at %d,%d)\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, d/8, d%8, &b, &got, &want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,12 +64,9 @@ func TestDCT(t *testing.T) {
|
||||||
for i, b := range blocks {
|
for i, b := range blocks {
|
||||||
got, want := b, b
|
got, want := b, b
|
||||||
fdct(&got)
|
fdct(&got)
|
||||||
for j := range want {
|
|
||||||
want[j] = (want[j] - 128) * 8
|
|
||||||
}
|
|
||||||
slowFDCT(&want)
|
slowFDCT(&want)
|
||||||
if differ(&got, &want) {
|
if d := differ(&got, &want, 2); d >= 0 {
|
||||||
t.Errorf("i=%d: FDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
|
t.Errorf("i=%d: FDCT (diff at %d,%d)\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, d/8, d%8, &b, &got, &want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,24 +75,26 @@ func TestDCT(t *testing.T) {
|
||||||
got, want := b, b
|
got, want := b, b
|
||||||
idct(&got)
|
idct(&got)
|
||||||
slowIDCT(&want)
|
slowIDCT(&want)
|
||||||
if differ(&got, &want) {
|
if d := differ(&got, &want, 2); d >= 0 {
|
||||||
t.Errorf("i=%d: IDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
|
t.Errorf("i=%d: IDCT (diff at %d,%d)\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, d/8, d%8, &b, &got, &want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// differ reports whether any pair-wise elements in b0 and b1 differ by 2 or
|
// differ reports whether any pair-wise elements in b0 and b1 differ by more than 'ok'.
|
||||||
// more. That tolerance is because there isn't a single definitive decoding of
|
// That tolerance is because there isn't a single definitive decoding of
|
||||||
// a given JPEG image, even before the YCbCr to RGB conversion; implementations
|
// a given JPEG image, even before the YCbCr to RGB conversion; implementations
|
||||||
// can have different IDCT rounding errors.
|
// can have different IDCT rounding errors.
|
||||||
func differ(b0, b1 *block) bool {
|
// If there is a difference, differ returns the index of the first difference.
|
||||||
|
// Otherwise it returns -1.
|
||||||
|
func differ(b0, b1 *block, ok int32) int {
|
||||||
for i := range b0 {
|
for i := range b0 {
|
||||||
delta := b0[i] - b1[i]
|
delta := b0[i] - b1[i]
|
||||||
if delta < -2 || +2 < delta {
|
if delta < -ok || ok < delta {
|
||||||
return true
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// alpha returns 1 if i is 0 and returns √2 otherwise.
|
// alpha returns 1 if i is 0 and returns √2 otherwise.
|
||||||
|
|
@ -166,12 +159,12 @@ func slowFDCT(b *block) {
|
||||||
sum := 0.0
|
sum := 0.0
|
||||||
for y := 0; y < 8; y++ {
|
for y := 0; y < 8; y++ {
|
||||||
for x := 0; x < 8; x++ {
|
for x := 0; x < 8; x++ {
|
||||||
sum += alpha(u) * alpha(v) * float64(b[8*y+x]) *
|
sum += alpha(u) * alpha(v) * float64(b[8*y+x]-128) *
|
||||||
cosines[((2*x+1)*u)%32] *
|
cosines[((2*x+1)*u)%32] *
|
||||||
cosines[((2*y+1)*v)%32]
|
cosines[((2*y+1)*v)%32]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dst[8*v+u] = sum / 8
|
dst[8*v+u] = sum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Convert from float64 to int32.
|
// Convert from float64 to int32.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue