package test import ( "bytes" "image" "image/color" "image/draw" "image/gif" "image/jpeg" "image/png" "math/rand" "testing" "golang.org/x/image/webp" ) var ( variantRed = color.NRGBA{R: 255, A: 255} variantGreen = color.NRGBA{G: 255, A: 255} variantBlue = color.NRGBA{B: 255, A: 255} ) func variantSolidImage(width int, height int, fill color.NRGBA) *image.NRGBA { canvas := image.NewNRGBA(image.Rect(0, 0, width, height)) draw.Draw(canvas, canvas.Bounds(), image.NewUniform(fill), image.Point{}, draw.Src) return canvas } func encodePNG(t *testing.T, source image.Image) []byte { t.Helper() var buffer bytes.Buffer if err := png.Encode(&buffer, source); err != nil { t.Fatalf("png encode failed: %v", err) } return buffer.Bytes() } func encodeJPEG(t *testing.T, source image.Image) []byte { t.Helper() var buffer bytes.Buffer if err := jpeg.Encode(&buffer, source, &jpeg.Options{Quality: 90}); err != nil { t.Fatalf("jpeg encode failed: %v", err) } return buffer.Bytes() } func solidPNG(t *testing.T, width int, height int) []byte { t.Helper() return encodePNG(t, variantSolidImage(width, height, variantRed)) } func stripedImage(t *testing.T) *image.NRGBA { t.Helper() canvas := image.NewNRGBA(image.Rect(0, 0, 40, 20)) for x := 0; x < 40; x++ { fill := variantGreen if x < 10 { fill = variantRed } if x >= 30 { fill = variantBlue } for y := 0; y < 20; y++ { canvas.SetNRGBA(x, y, fill) } } return canvas } func noisyImage(width int, height int) *image.NRGBA { generator := rand.New(rand.NewSource(7)) canvas := image.NewNRGBA(image.Rect(0, 0, width, height)) for offset := 0; offset < len(canvas.Pix); offset += 4 { canvas.Pix[offset] = uint8(generator.Intn(256)) canvas.Pix[offset+1] = uint8(generator.Intn(256)) canvas.Pix[offset+2] = uint8(generator.Intn(256)) canvas.Pix[offset+3] = 255 } return canvas } func animatedGIF(t *testing.T) []byte { t.Helper() return encodeGIF(t, 2) } func stillGIF(t *testing.T) []byte { t.Helper() return encodeGIF(t, 1) } func encodeGIF(t *testing.T, frames int) []byte { t.Helper() palette := color.Palette{color.White, color.Black} animation := &gif.GIF{} for frame := 0; frame < frames; frame++ { paletted := image.NewPaletted(image.Rect(0, 0, 8, 8), palette) paletted.SetColorIndex(frame, frame, 1) animation.Image = append(animation.Image, paletted) animation.Delay = append(animation.Delay, 10) } var buffer bytes.Buffer if err := gif.EncodeAll(&buffer, animation); err != nil { t.Fatalf("gif encode failed: %v", err) } return buffer.Bytes() } func decodeImage(t *testing.T, content []byte) (image.Image, string) { t.Helper() decoded, format, err := image.Decode(bytes.NewReader(content)) if err != nil { t.Fatalf("decode failed: %v", err) } return decoded, format } func decodedSize(t *testing.T, content []byte) (int, int) { t.Helper() config, _, err := image.DecodeConfig(bytes.NewReader(content)) if err != nil { t.Fatalf("decode config failed: %v", err) } return config.Width, config.Height } func webpSize(t *testing.T, content []byte) (int, int) { t.Helper() config, err := webp.DecodeConfig(bytes.NewReader(content)) if err != nil { t.Fatalf("webp decode config failed: %v", err) } return config.Width, config.Height } func pixelAt(decoded image.Image, x int, y int) color.NRGBA { return color.NRGBAModel.Convert(decoded.At(x, y)).(color.NRGBA) } func padSizedPNG(t *testing.T, size int) []byte { t.Helper() content := solidPNG(t, 8, 8) if len(content) > size { t.Fatalf("base png is larger than %d bytes", size) } return append(content, make([]byte, size-len(content))...) }