From 500caaeda74dd9c660279036293f4b2997cf0b03 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 9 Sep 2017 09:42:37 +0200 Subject: Add vendor --- vendor/golang.org/x/image/webp/decode.go | 272 ++++++++++++++++++++ vendor/golang.org/x/image/webp/decode_test.go | 296 ++++++++++++++++++++++ vendor/golang.org/x/image/webp/nycbcra/nycbcra.go | 194 ++++++++++++++ vendor/golang.org/x/image/webp/webp.go | 30 +++ 4 files changed, 792 insertions(+) create mode 100644 vendor/golang.org/x/image/webp/decode.go create mode 100644 vendor/golang.org/x/image/webp/decode_test.go create mode 100644 vendor/golang.org/x/image/webp/nycbcra/nycbcra.go create mode 100644 vendor/golang.org/x/image/webp/webp.go (limited to 'vendor/golang.org/x/image/webp') diff --git a/vendor/golang.org/x/image/webp/decode.go b/vendor/golang.org/x/image/webp/decode.go new file mode 100644 index 0000000..111f358 --- /dev/null +++ b/vendor/golang.org/x/image/webp/decode.go @@ -0,0 +1,272 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.6 + +package webp + +import ( + "bytes" + "errors" + "image" + "image/color" + "io" + + "golang.org/x/image/riff" + "golang.org/x/image/vp8" + "golang.org/x/image/vp8l" +) + +var errInvalidFormat = errors.New("webp: invalid format") + +var ( + fccALPH = riff.FourCC{'A', 'L', 'P', 'H'} + fccVP8 = riff.FourCC{'V', 'P', '8', ' '} + fccVP8L = riff.FourCC{'V', 'P', '8', 'L'} + fccVP8X = riff.FourCC{'V', 'P', '8', 'X'} + fccWEBP = riff.FourCC{'W', 'E', 'B', 'P'} +) + +func decode(r io.Reader, configOnly bool) (image.Image, image.Config, error) { + formType, riffReader, err := riff.NewReader(r) + if err != nil { + return nil, image.Config{}, err + } + if formType != fccWEBP { + return nil, image.Config{}, errInvalidFormat + } + + var ( + alpha []byte + alphaStride int + wantAlpha bool + widthMinusOne uint32 + heightMinusOne uint32 + buf [10]byte + ) + for { + chunkID, chunkLen, chunkData, err := riffReader.Next() + if err == io.EOF { + err = errInvalidFormat + } + if err != nil { + return nil, image.Config{}, err + } + + switch chunkID { + case fccALPH: + if !wantAlpha { + return nil, image.Config{}, errInvalidFormat + } + wantAlpha = false + // Read the Pre-processing | Filter | Compression byte. + if _, err := io.ReadFull(chunkData, buf[:1]); err != nil { + if err == io.EOF { + err = errInvalidFormat + } + return nil, image.Config{}, err + } + alpha, alphaStride, err = readAlpha(chunkData, widthMinusOne, heightMinusOne, buf[0]&0x03) + if err != nil { + return nil, image.Config{}, err + } + unfilterAlpha(alpha, alphaStride, (buf[0]>>2)&0x03) + + case fccVP8: + if wantAlpha || int32(chunkLen) < 0 { + return nil, image.Config{}, errInvalidFormat + } + d := vp8.NewDecoder() + d.Init(chunkData, int(chunkLen)) + fh, err := d.DecodeFrameHeader() + if err != nil { + return nil, image.Config{}, err + } + if configOnly { + return nil, image.Config{ + ColorModel: color.YCbCrModel, + Width: fh.Width, + Height: fh.Height, + }, nil + } + m, err := d.DecodeFrame() + if err != nil { + return nil, image.Config{}, err + } + if alpha != nil { + return &image.NYCbCrA{ + YCbCr: *m, + A: alpha, + AStride: alphaStride, + }, image.Config{}, nil + } + return m, image.Config{}, nil + + case fccVP8L: + if wantAlpha || alpha != nil { + return nil, image.Config{}, errInvalidFormat + } + if configOnly { + c, err := vp8l.DecodeConfig(chunkData) + return nil, c, err + } + m, err := vp8l.Decode(chunkData) + return m, image.Config{}, err + + case fccVP8X: + if chunkLen != 10 { + return nil, image.Config{}, errInvalidFormat + } + if _, err := io.ReadFull(chunkData, buf[:10]); err != nil { + return nil, image.Config{}, err + } + const ( + animationBit = 1 << 1 + xmpMetadataBit = 1 << 2 + exifMetadataBit = 1 << 3 + alphaBit = 1 << 4 + iccProfileBit = 1 << 5 + ) + if buf[0] != alphaBit { + return nil, image.Config{}, errors.New("webp: non-Alpha VP8X is not implemented") + } + widthMinusOne = uint32(buf[4]) | uint32(buf[5])<<8 | uint32(buf[6])<<16 + heightMinusOne = uint32(buf[7]) | uint32(buf[8])<<8 | uint32(buf[9])<<16 + if configOnly { + return nil, image.Config{ + ColorModel: color.NYCbCrAModel, + Width: int(widthMinusOne) + 1, + Height: int(heightMinusOne) + 1, + }, nil + } + wantAlpha = true + + default: + return nil, image.Config{}, errInvalidFormat + } + } +} + +func readAlpha(chunkData io.Reader, widthMinusOne, heightMinusOne uint32, compression byte) ( + alpha []byte, alphaStride int, err error) { + + switch compression { + case 0: + w := int(widthMinusOne) + 1 + h := int(heightMinusOne) + 1 + alpha = make([]byte, w*h) + if _, err := io.ReadFull(chunkData, alpha); err != nil { + return nil, 0, err + } + return alpha, w, nil + + case 1: + // Read the VP8L-compressed alpha values. First, synthesize a 5-byte VP8L header: + // a 1-byte magic number, a 14-bit widthMinusOne, a 14-bit heightMinusOne, + // a 1-bit (ignored, zero) alphaIsUsed and a 3-bit (zero) version. + // TODO(nigeltao): be more efficient than decoding an *image.NRGBA just to + // extract the green values to a separately allocated []byte. Fixing this + // will require changes to the vp8l package's API. + if widthMinusOne > 0x3fff || heightMinusOne > 0x3fff { + return nil, 0, errors.New("webp: invalid format") + } + alphaImage, err := vp8l.Decode(io.MultiReader( + bytes.NewReader([]byte{ + 0x2f, // VP8L magic number. + uint8(widthMinusOne), + uint8(widthMinusOne>>8) | uint8(heightMinusOne<<6), + uint8(heightMinusOne >> 2), + uint8(heightMinusOne >> 10), + }), + chunkData, + )) + if err != nil { + return nil, 0, err + } + // The green values of the inner NRGBA image are the alpha values of the + // outer NYCbCrA image. + pix := alphaImage.(*image.NRGBA).Pix + alpha = make([]byte, len(pix)/4) + for i := range alpha { + alpha[i] = pix[4*i+1] + } + return alpha, int(widthMinusOne) + 1, nil + } + return nil, 0, errInvalidFormat +} + +func unfilterAlpha(alpha []byte, alphaStride int, filter byte) { + if len(alpha) == 0 || alphaStride == 0 { + return + } + switch filter { + case 1: // Horizontal filter. + for i := 1; i < alphaStride; i++ { + alpha[i] += alpha[i-1] + } + for i := alphaStride; i < len(alpha); i += alphaStride { + // The first column is equivalent to the vertical filter. + alpha[i] += alpha[i-alphaStride] + + for j := 1; j < alphaStride; j++ { + alpha[i+j] += alpha[i+j-1] + } + } + + case 2: // Vertical filter. + // The first row is equivalent to the horizontal filter. + for i := 1; i < alphaStride; i++ { + alpha[i] += alpha[i-1] + } + + for i := alphaStride; i < len(alpha); i++ { + alpha[i] += alpha[i-alphaStride] + } + + case 3: // Gradient filter. + // The first row is equivalent to the horizontal filter. + for i := 1; i < alphaStride; i++ { + alpha[i] += alpha[i-1] + } + + for i := alphaStride; i < len(alpha); i += alphaStride { + // The first column is equivalent to the vertical filter. + alpha[i] += alpha[i-alphaStride] + + // The interior is predicted on the three top/left pixels. + for j := 1; j < alphaStride; j++ { + c := int(alpha[i+j-alphaStride-1]) + b := int(alpha[i+j-alphaStride]) + a := int(alpha[i+j-1]) + x := a + b - c + if x < 0 { + x = 0 + } else if x > 255 { + x = 255 + } + alpha[i+j] += uint8(x) + } + } + } +} + +// Decode reads a WEBP image from r and returns it as an image.Image. +func Decode(r io.Reader) (image.Image, error) { + m, _, err := decode(r, false) + if err != nil { + return nil, err + } + return m, err +} + +// DecodeConfig returns the color model and dimensions of a WEBP image without +// decoding the entire image. +func DecodeConfig(r io.Reader) (image.Config, error) { + _, c, err := decode(r, true) + return c, err +} + +func init() { + image.RegisterFormat("webp", "RIFF????WEBPVP8", Decode, DecodeConfig) +} diff --git a/vendor/golang.org/x/image/webp/decode_test.go b/vendor/golang.org/x/image/webp/decode_test.go new file mode 100644 index 0000000..b27468a --- /dev/null +++ b/vendor/golang.org/x/image/webp/decode_test.go @@ -0,0 +1,296 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.6 + +package webp + +import ( + "bytes" + "fmt" + "image" + "image/png" + "io/ioutil" + "os" + "strings" + "testing" +) + +// hex is like fmt.Sprintf("% x", x) but also inserts dots every 16 bytes, to +// delineate VP8 macroblock boundaries. +func hex(x []byte) string { + buf := new(bytes.Buffer) + for len(x) > 0 { + n := len(x) + if n > 16 { + n = 16 + } + fmt.Fprintf(buf, " . % x", x[:n]) + x = x[n:] + } + return buf.String() +} + +func testDecodeLossy(t *testing.T, tc string, withAlpha bool) { + webpFilename := "../testdata/" + tc + ".lossy.webp" + pngFilename := webpFilename + ".ycbcr.png" + if withAlpha { + webpFilename = "../testdata/" + tc + ".lossy-with-alpha.webp" + pngFilename = webpFilename + ".nycbcra.png" + } + + f0, err := os.Open(webpFilename) + if err != nil { + t.Errorf("%s: Open WEBP: %v", tc, err) + return + } + defer f0.Close() + img0, err := Decode(f0) + if err != nil { + t.Errorf("%s: Decode WEBP: %v", tc, err) + return + } + + var ( + m0 *image.YCbCr + a0 *image.NYCbCrA + ok bool + ) + if withAlpha { + a0, ok = img0.(*image.NYCbCrA) + if ok { + m0 = &a0.YCbCr + } + } else { + m0, ok = img0.(*image.YCbCr) + } + if !ok || m0.SubsampleRatio != image.YCbCrSubsampleRatio420 { + t.Errorf("%s: decoded WEBP image is not a 4:2:0 YCbCr or 4:2:0 NYCbCrA", tc) + return + } + // w2 and h2 are the half-width and half-height, rounded up. + w, h := m0.Bounds().Dx(), m0.Bounds().Dy() + w2, h2 := int((w+1)/2), int((h+1)/2) + + f1, err := os.Open(pngFilename) + if err != nil { + t.Errorf("%s: Open PNG: %v", tc, err) + return + } + defer f1.Close() + img1, err := png.Decode(f1) + if err != nil { + t.Errorf("%s: Open PNG: %v", tc, err) + return + } + + // The split-into-YCbCr-planes golden image is a 2*w2 wide and h+h2 high + // (or 2*h+h2 high, if with Alpha) gray image arranged in IMC4 format: + // YYYY + // YYYY + // BBRR + // AAAA + // See http://www.fourcc.org/yuv.php#IMC4 + pngW, pngH := 2*w2, h+h2 + if withAlpha { + pngH += h + } + if got, want := img1.Bounds(), image.Rect(0, 0, pngW, pngH); got != want { + t.Errorf("%s: bounds0: got %v, want %v", tc, got, want) + return + } + m1, ok := img1.(*image.Gray) + if !ok { + t.Errorf("%s: decoded PNG image is not a Gray", tc) + return + } + + type plane struct { + name string + m0Pix []uint8 + m0Stride int + m1Rect image.Rectangle + } + planes := []plane{ + {"Y", m0.Y, m0.YStride, image.Rect(0, 0, w, h)}, + {"Cb", m0.Cb, m0.CStride, image.Rect(0*w2, h, 1*w2, h+h2)}, + {"Cr", m0.Cr, m0.CStride, image.Rect(1*w2, h, 2*w2, h+h2)}, + } + if withAlpha { + planes = append(planes, plane{ + "A", a0.A, a0.AStride, image.Rect(0, h+h2, w, 2*h+h2), + }) + } + + for _, plane := range planes { + dx := plane.m1Rect.Dx() + nDiff, diff := 0, make([]byte, dx) + for j, y := 0, plane.m1Rect.Min.Y; y < plane.m1Rect.Max.Y; j, y = j+1, y+1 { + got := plane.m0Pix[j*plane.m0Stride:][:dx] + want := m1.Pix[y*m1.Stride+plane.m1Rect.Min.X:][:dx] + if bytes.Equal(got, want) { + continue + } + nDiff++ + if nDiff > 10 { + t.Errorf("%s: %s plane: more rows differ", tc, plane.name) + break + } + for i := range got { + diff[i] = got[i] - want[i] + } + t.Errorf("%s: %s plane: m0 row %d, m1 row %d\ngot %s\nwant%s\ndiff%s", + tc, plane.name, j, y, hex(got), hex(want), hex(diff)) + } + } +} + +func TestDecodeVP8(t *testing.T) { + testCases := []string{ + "blue-purple-pink", + "blue-purple-pink-large.no-filter", + "blue-purple-pink-large.simple-filter", + "blue-purple-pink-large.normal-filter", + "video-001", + "yellow_rose", + } + + for _, tc := range testCases { + testDecodeLossy(t, tc, false) + } +} + +func TestDecodeVP8XAlpha(t *testing.T) { + testCases := []string{ + "yellow_rose", + } + + for _, tc := range testCases { + testDecodeLossy(t, tc, true) + } +} + +func TestDecodeVP8L(t *testing.T) { + testCases := []string{ + "blue-purple-pink", + "blue-purple-pink-large", + "gopher-doc.1bpp", + "gopher-doc.2bpp", + "gopher-doc.4bpp", + "gopher-doc.8bpp", + "tux", + "yellow_rose", + } + +loop: + for _, tc := range testCases { + f0, err := os.Open("../testdata/" + tc + ".lossless.webp") + if err != nil { + t.Errorf("%s: Open WEBP: %v", tc, err) + continue + } + defer f0.Close() + img0, err := Decode(f0) + if err != nil { + t.Errorf("%s: Decode WEBP: %v", tc, err) + continue + } + m0, ok := img0.(*image.NRGBA) + if !ok { + t.Errorf("%s: WEBP image is %T, want *image.NRGBA", tc, img0) + continue + } + + f1, err := os.Open("../testdata/" + tc + ".png") + if err != nil { + t.Errorf("%s: Open PNG: %v", tc, err) + continue + } + defer f1.Close() + img1, err := png.Decode(f1) + if err != nil { + t.Errorf("%s: Decode PNG: %v", tc, err) + continue + } + m1, ok := img1.(*image.NRGBA) + if !ok { + rgba1, ok := img1.(*image.RGBA) + if !ok { + t.Fatalf("%s: PNG image is %T, want *image.NRGBA", tc, img1) + continue + } + if !rgba1.Opaque() { + t.Fatalf("%s: PNG image is non-opaque *image.RGBA, want *image.NRGBA", tc) + continue + } + // The image is fully opaque, so we can re-interpret the RGBA pixels + // as NRGBA pixels. + m1 = &image.NRGBA{ + Pix: rgba1.Pix, + Stride: rgba1.Stride, + Rect: rgba1.Rect, + } + } + + b0, b1 := m0.Bounds(), m1.Bounds() + if b0 != b1 { + t.Errorf("%s: bounds: got %v, want %v", tc, b0, b1) + continue + } + for i := range m0.Pix { + if m0.Pix[i] != m1.Pix[i] { + y := i / m0.Stride + x := (i - y*m0.Stride) / 4 + i = 4 * (y*m0.Stride + x) + t.Errorf("%s: at (%d, %d):\ngot %02x %02x %02x %02x\nwant %02x %02x %02x %02x", + tc, x, y, + m0.Pix[i+0], m0.Pix[i+1], m0.Pix[i+2], m0.Pix[i+3], + m1.Pix[i+0], m1.Pix[i+1], m1.Pix[i+2], m1.Pix[i+3], + ) + continue loop + } + } + } +} + +// TestDecodePartitionTooLarge tests that decoding a malformed WEBP image +// doesn't try to allocate an unreasonable amount of memory. This WEBP image +// claims a RIFF chunk length of 0x12345678 bytes (291 MiB) compressed, +// independent of the actual image size (0 pixels wide * 0 pixels high). +// +// This is based on golang.org/issue/10790. +func TestDecodePartitionTooLarge(t *testing.T) { + data := "RIFF\xff\xff\xff\x7fWEBPVP8 " + + "\x78\x56\x34\x12" + // RIFF chunk length. + "\xbd\x01\x00\x14\x00\x00\xb2\x34\x0a\x9d\x01\x2a\x96\x00\x67\x00" + _, err := Decode(strings.NewReader(data)) + if err == nil { + t.Fatal("got nil error, want non-nil") + } + if got, want := err.Error(), "too much data"; !strings.Contains(got, want) { + t.Fatalf("got error %q, want something containing %q", got, want) + } +} + +func benchmarkDecode(b *testing.B, filename string) { + data, err := ioutil.ReadFile("../testdata/blue-purple-pink-large." + filename + ".webp") + if err != nil { + b.Fatal(err) + } + s := string(data) + cfg, err := DecodeConfig(strings.NewReader(s)) + if err != nil { + b.Fatal(err) + } + b.SetBytes(int64(cfg.Width * cfg.Height * 4)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Decode(strings.NewReader(s)) + } +} + +func BenchmarkDecodeVP8NoFilter(b *testing.B) { benchmarkDecode(b, "no-filter.lossy") } +func BenchmarkDecodeVP8SimpleFilter(b *testing.B) { benchmarkDecode(b, "simple-filter.lossy") } +func BenchmarkDecodeVP8NormalFilter(b *testing.B) { benchmarkDecode(b, "normal-filter.lossy") } +func BenchmarkDecodeVP8L(b *testing.B) { benchmarkDecode(b, "lossless") } diff --git a/vendor/golang.org/x/image/webp/nycbcra/nycbcra.go b/vendor/golang.org/x/image/webp/nycbcra/nycbcra.go new file mode 100644 index 0000000..101c41f --- /dev/null +++ b/vendor/golang.org/x/image/webp/nycbcra/nycbcra.go @@ -0,0 +1,194 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package nycbcra provides non-alpha-premultiplied Y'CbCr-with-alpha image and +// color types. +// +// Deprecated: as of Go 1.6. Use the standard image and image/color packages +// instead. +package nycbcra // import "golang.org/x/image/webp/nycbcra" + +import ( + "image" + "image/color" +) + +func init() { + println("The golang.org/x/image/webp/nycbcra package is deprecated, as of Go 1.6. " + + "Use the standard image and image/color packages instead.") +} + +// TODO: move this to the standard image and image/color packages, so that the +// image/draw package can have fast-path code. Moving would rename: +// nycbcra.Color to color.NYCbCrA +// nycbcra.ColorModel to color.NYCbCrAModel +// nycbcra.Image to image.NYCbCrA + +// Color represents a non-alpha-premultiplied Y'CbCr-with-alpha color, having +// 8 bits each for one luma, two chroma and one alpha component. +type Color struct { + color.YCbCr + A uint8 +} + +func (c Color) RGBA() (r, g, b, a uint32) { + r8, g8, b8 := color.YCbCrToRGB(c.Y, c.Cb, c.Cr) + a = uint32(c.A) * 0x101 + r = uint32(r8) * 0x101 * a / 0xffff + g = uint32(g8) * 0x101 * a / 0xffff + b = uint32(b8) * 0x101 * a / 0xffff + return +} + +// ColorModel is the Model for non-alpha-premultiplied Y'CbCr-with-alpha colors. +var ColorModel color.Model = color.ModelFunc(nYCbCrAModel) + +func nYCbCrAModel(c color.Color) color.Color { + switch c := c.(type) { + case Color: + return c + case color.YCbCr: + return Color{c, 0xff} + } + r, g, b, a := c.RGBA() + + // Convert from alpha-premultiplied to non-alpha-premultiplied. + if a != 0 { + r = (r * 0xffff) / a + g = (g * 0xffff) / a + b = (b * 0xffff) / a + } + + y, u, v := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8)) + return Color{color.YCbCr{Y: y, Cb: u, Cr: v}, uint8(a >> 8)} +} + +// Image is an in-memory image of non-alpha-premultiplied Y'CbCr-with-alpha +// colors. A and AStride are analogous to the Y and YStride fields of the +// embedded YCbCr. +type Image struct { + image.YCbCr + A []uint8 + AStride int +} + +func (p *Image) ColorModel() color.Model { + return ColorModel +} + +func (p *Image) At(x, y int) color.Color { + return p.NYCbCrAAt(x, y) +} + +func (p *Image) NYCbCrAAt(x, y int) Color { + if !(image.Point{X: x, Y: y}.In(p.Rect)) { + return Color{} + } + yi := p.YOffset(x, y) + ci := p.COffset(x, y) + ai := p.AOffset(x, y) + return Color{ + color.YCbCr{ + Y: p.Y[yi], + Cb: p.Cb[ci], + Cr: p.Cr[ci], + }, + p.A[ai], + } +} + +// AOffset returns the index of the first element of A that corresponds to +// the pixel at (x, y). +func (p *Image) AOffset(x, y int) int { + return (y-p.Rect.Min.Y)*p.AStride + (x - p.Rect.Min.X) +} + +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *Image) SubImage(r image.Rectangle) image.Image { + // TODO: share code with image.NewYCbCr when this type moves into the + // standard image package. + r = r.Intersect(p.Rect) + // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside + // either r1 or r2 if the intersection is empty. Without explicitly checking for + // this, the Pix[i:] expression below can panic. + if r.Empty() { + return &Image{ + YCbCr: image.YCbCr{ + SubsampleRatio: p.SubsampleRatio, + }, + } + } + yi := p.YOffset(r.Min.X, r.Min.Y) + ci := p.COffset(r.Min.X, r.Min.Y) + ai := p.AOffset(r.Min.X, r.Min.Y) + return &Image{ + YCbCr: image.YCbCr{ + Y: p.Y[yi:], + Cb: p.Cb[ci:], + Cr: p.Cr[ci:], + SubsampleRatio: p.SubsampleRatio, + YStride: p.YStride, + CStride: p.CStride, + Rect: r, + }, + A: p.A[ai:], + AStride: p.AStride, + } +} + +// Opaque scans the entire image and reports whether it is fully opaque. +func (p *Image) Opaque() bool { + if p.Rect.Empty() { + return true + } + i0, i1 := 0, p.Rect.Dx() + for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { + for _, a := range p.A[i0:i1] { + if a != 0xff { + return false + } + } + i0 += p.AStride + i1 += p.AStride + } + return true +} + +// New returns a new Image with the given bounds and subsample ratio. +func New(r image.Rectangle, subsampleRatio image.YCbCrSubsampleRatio) *Image { + // TODO: share code with image.NewYCbCr when this type moves into the + // standard image package. + w, h, cw, ch := r.Dx(), r.Dy(), 0, 0 + switch subsampleRatio { + case image.YCbCrSubsampleRatio422: + cw = (r.Max.X+1)/2 - r.Min.X/2 + ch = h + case image.YCbCrSubsampleRatio420: + cw = (r.Max.X+1)/2 - r.Min.X/2 + ch = (r.Max.Y+1)/2 - r.Min.Y/2 + case image.YCbCrSubsampleRatio440: + cw = w + ch = (r.Max.Y+1)/2 - r.Min.Y/2 + default: + // Default to 4:4:4 subsampling. + cw = w + ch = h + } + b := make([]byte, 2*w*h+2*cw*ch) + // TODO: use s[i:j:k] notation to set the cap. + return &Image{ + YCbCr: image.YCbCr{ + Y: b[:w*h], + Cb: b[w*h+0*cw*ch : w*h+1*cw*ch], + Cr: b[w*h+1*cw*ch : w*h+2*cw*ch], + SubsampleRatio: subsampleRatio, + YStride: w, + CStride: cw, + Rect: r, + }, + A: b[w*h+2*cw*ch:], + AStride: w, + } +} diff --git a/vendor/golang.org/x/image/webp/webp.go b/vendor/golang.org/x/image/webp/webp.go new file mode 100644 index 0000000..850cdc8 --- /dev/null +++ b/vendor/golang.org/x/image/webp/webp.go @@ -0,0 +1,30 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package webp implements a decoder for WEBP images. +// +// WEBP is defined at: +// https://developers.google.com/speed/webp/docs/riff_container +// +// It requires Go 1.6 or later. +package webp // import "golang.org/x/image/webp" + +// This blank Go file, other than the package clause, exists so that this +// package can be built for Go 1.5 and earlier. (The other files in this +// package are all marked "+build go1.6" for the NYCbCrA types introduced in Go +// 1.6). There is no functionality in a blank package, but some image +// manipulation programs might still underscore import this package for the +// side effect of registering the WEBP format with the standard library's +// image.RegisterFormat and image.Decode functions. For example, that program +// might contain: +// +// // Underscore imports to register some formats for image.Decode. +// import _ "image/gif" +// import _ "image/jpeg" +// import _ "image/png" +// import _ "golang.org/x/image/webp" +// +// Such a program will still compile for Go 1.5 (due to this placeholder Go +// file). It will simply not be able to recognize and decode WEBP (but still +// handle GIF, JPEG and PNG). -- cgit v1.2.3