LEFT | RIGHT |
(no file at all) | |
| 1 // Copyright 2014 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 package webp |
| 6 |
| 7 import ( |
| 8 "bytes" |
| 9 "fmt" |
| 10 "image" |
| 11 "image/png" |
| 12 "os" |
| 13 "testing" |
| 14 ) |
| 15 |
| 16 // hex is like fmt.Sprintf("% x", x) but also inserts dots every 16 bytes, to |
| 17 // delineate VP8 macroblock boundaries. |
| 18 func hex(x []byte) string { |
| 19 buf := new(bytes.Buffer) |
| 20 for len(x) > 0 { |
| 21 n := len(x) |
| 22 if n > 16 { |
| 23 n = 16 |
| 24 } |
| 25 fmt.Fprintf(buf, " . % x", x[:n]) |
| 26 x = x[n:] |
| 27 } |
| 28 return buf.String() |
| 29 } |
| 30 |
| 31 func TestDecodeVP8(t *testing.T) { |
| 32 // The original video-001.png image is 150x103. |
| 33 const w, h = 150, 103 |
| 34 // w2 and h2 are the half-width and half-height, rounded up. |
| 35 const w2, h2 = int((w + 1) / 2), int((h + 1) / 2) |
| 36 |
| 37 f0, err := os.Open("../testdata/video-001.webp.ycbcr.png") |
| 38 if err != nil { |
| 39 t.Fatal(err) |
| 40 } |
| 41 defer f0.Close() |
| 42 img0, err := png.Decode(f0) |
| 43 if err != nil { |
| 44 t.Fatal(err) |
| 45 } |
| 46 |
| 47 // The split-into-YCbCr-planes golden image is a 2*w2 wide and h+h2 high |
| 48 // gray image arranged in IMC4 format: |
| 49 // YYYY |
| 50 // YYYY |
| 51 // BBRR |
| 52 // See http://www.fourcc.org/yuv.php#IMC4 |
| 53 if got, want := img0.Bounds(), image.Rect(0, 0, 2*w2, h+h2); got != want
{ |
| 54 t.Fatalf("bounds0: got %v, want %v", got, want) |
| 55 } |
| 56 m0, ok := img0.(*image.Gray) |
| 57 if !ok { |
| 58 t.Fatal("decoded PNG image is not a Gray") |
| 59 } |
| 60 |
| 61 f1, err := os.Open("../testdata/video-001.webp") |
| 62 if err != nil { |
| 63 t.Fatal(err) |
| 64 } |
| 65 defer f1.Close() |
| 66 img1, err := Decode(f1) |
| 67 if err != nil { |
| 68 t.Fatal(err) |
| 69 } |
| 70 |
| 71 if got, want := img1.Bounds(), image.Rect(0, 0, w, h); got != want { |
| 72 t.Fatalf("bounds1: got %v, want %v", got, want) |
| 73 } |
| 74 m1, ok := img1.(*image.YCbCr) |
| 75 if !ok || m1.SubsampleRatio != image.YCbCrSubsampleRatio420 { |
| 76 t.Fatal("decoded WEBP image is not a 4:2:0 YCbCr") |
| 77 } |
| 78 |
| 79 planes := []struct { |
| 80 name string |
| 81 m1Pix []uint8 |
| 82 m1Stride int |
| 83 m0Rect image.Rectangle |
| 84 }{ |
| 85 {"Y", m1.Y, m1.YStride, image.Rect(0, 0, w, h)}, |
| 86 {"Cb", m1.Cb, m1.CStride, image.Rect(0*w2, h, 1*w2, h+h2)}, |
| 87 {"Cr", m1.Cr, m1.CStride, image.Rect(1*w2, h, 2*w2, h+h2)}, |
| 88 } |
| 89 for _, plane := range planes { |
| 90 dx := plane.m0Rect.Dx() |
| 91 nDiff, diff := 0, make([]byte, dx) |
| 92 for j, y := 0, plane.m0Rect.Min.Y; y < plane.m0Rect.Max.Y; j, y
= j+1, y+1 { |
| 93 got := plane.m1Pix[j*plane.m1Stride:][:dx] |
| 94 want := m0.Pix[y*m0.Stride+plane.m0Rect.Min.X:][:dx] |
| 95 if bytes.Equal(got, want) { |
| 96 continue |
| 97 } |
| 98 nDiff++ |
| 99 if nDiff > 10 { |
| 100 t.Errorf("%s plane: more rows differ", plane.nam
e) |
| 101 break |
| 102 } |
| 103 for i := range got { |
| 104 diff[i] = got[i] - want[i] |
| 105 } |
| 106 t.Errorf("%s plane: m0 row %d, m1 row %d\ngot %s\nwant%s
\ndiff%s", |
| 107 plane.name, y, j, hex(got), hex(want), hex(diff)
) |
| 108 } |
| 109 } |
| 110 } |
LEFT | RIGHT |