argb_test.go (2829B)
1 package icns 2 3 import ( 4 "bytes" 5 "errors" 6 "image" 7 "image/color" 8 "testing" 9 ) 10 11 // argbElement builds an ARGB payload for a gradient, returning it and the 12 // image it describes. 13 func argbElement(side int) (payload []byte, want *image.NRGBA) { 14 pixels := side * side 15 planes := make([]byte, pixels*4) 16 want = image.NewNRGBA(image.Rect(0, 0, side, side)) 17 for y := 0; y < side; y++ { 18 for x := 0; x < side; x++ { 19 i := y*side + x 20 c := color.NRGBA{ 21 R: uint8(x * 255 / side), 22 G: uint8(y * 255 / side), 23 B: 0x80, 24 A: uint8(255 - x*128/side), 25 } 26 // Alpha leads, then the colour channels. 27 planes[i] = c.A 28 planes[pixels+i] = c.R 29 planes[pixels*2+i] = c.G 30 planes[pixels*3+i] = c.B 31 want.SetNRGBA(x, y, c) 32 } 33 } 34 return append([]byte("ARGB"), rleLiterals(planes)...), want 35 } 36 37 func TestDecodeARGB(t *testing.T) { 38 t.Parallel() 39 const side = 16 40 payload, want := argbElement(side) 41 42 t.Run("sidebar icon", func(st *testing.T) { 43 data := file(encodeElement("ic04", payload)) 44 desc, err := Probe(bytes.NewReader(data)) 45 if err != nil { 46 st.Fatal(err) 47 } 48 if len(desc) != 1 || desc[0].ImageFormat != ImageFormatARGB { 49 st.Fatalf("Probe = %v, want one ARGB icon", desc) 50 } 51 img, err := Decode(bytes.NewReader(data)) 52 if err != nil { 53 st.Fatal(err) 54 } 55 if !imageCompare(img, want) { 56 st.Fatal("the decoded icon differs from the source") 57 } 58 }) 59 60 t.Run("compressed run", func(st *testing.T) { 61 // A flat image compresses to repeats, which exercises the other half 62 // of the run-length decoder. icsb is 18 pixels, not 16. 63 const icsbSide = 18 64 planes := make([]byte, icsbSide*icsbSide*4) 65 for i := range planes { 66 planes[i] = 0xFF 67 } 68 data := file(encodeElement("icsb", append([]byte("ARGB"), packRLE(planes)...))) 69 img, err := Decode(bytes.NewReader(data)) 70 if err != nil { 71 st.Fatal(err) 72 } 73 if got := img.Bounds().Dx(); got != 18 { 74 st.Fatalf("decoded a %dpx icon, want 18", got) 75 } 76 if got := color.NRGBAModel.Convert(img.At(9, 9)).(color.NRGBA); got != (color.NRGBA{0xFF, 0xFF, 0xFF, 0xFF}) { 77 st.Fatalf("centre = %v, want opaque white", got) 78 } 79 }) 80 81 t.Run("png in an ARGB capable type", func(st *testing.T) { 82 // These types hold either format, so the payload has to decide. 83 data := file(encodeElement("ic05", pngBytes(t, 32))) 84 desc, err := Probe(bytes.NewReader(data)) 85 if err != nil { 86 st.Fatal(err) 87 } 88 if desc[0].ImageFormat != ImageFormatPNG { 89 st.Fatalf("format = %s, want PNG", desc[0].ImageFormat) 90 } 91 if _, err := Decode(bytes.NewReader(data)); err != nil { 92 st.Fatal(err) 93 } 94 }) 95 96 t.Run("truncated planes", func(st *testing.T) { 97 data := file(encodeElement("ic04", []byte("ARGB\x01\x02\x03"))) 98 if _, err := Decode(bytes.NewReader(data)); !errors.Is(err, ErrMalformed) { 99 st.Fatalf("error = %v, want ErrMalformed", err) 100 } 101 }) 102 }