); got %v (%v)", n, err)
+ } else if rt := time.Since(start); rt < _400ms {
+ t.Fatalf("w.Write(b[20:]) returned ahead of time (%v)", rt)
+ }
+
+ w.SetTransferSize(100)
+ status := []Status{w.Status(), nextStatus(w.Monitor)}
+ start = status[0].Start
+
+ // Active, Start, Duration, Idle, Bytes, Samples, InstRate, CurRate, AvgRate, PeakRate, BytesRem, TimeRem, Progress
+ want := []Status{
+ Status{true, start, _400ms, 0, 80, 4, 200, 200, 200, 200, 20, _100ms, 80000},
+ Status{true, start, _500ms, _100ms, 100, 5, 200, 200, 200, 200, 0, 0, 100000},
+ }
+ for i, s := range status {
+ if !reflect.DeepEqual(&s, &want[i]) {
+ t.Errorf("w.Status(%v) expected %v; got %v", i, want[i], s)
+ }
+ }
+ if !bytes.Equal(b, w.Writer.(*bytes.Buffer).Bytes()) {
+ t.Errorf("w.Write() input doesn't match output")
+ }
+}
diff --git a/vendor/github.com/mxk/go-flowrate/flowrate/util.go b/vendor/github.com/mxk/go-flowrate/flowrate/util.go
new file mode 100644
index 0000000..4caac58
--- /dev/null
+++ b/vendor/github.com/mxk/go-flowrate/flowrate/util.go
@@ -0,0 +1,67 @@
+//
+// Written by Maxim Khitrov (November 2012)
+//
+
+package flowrate
+
+import (
+ "math"
+ "strconv"
+ "time"
+)
+
+// clockRate is the resolution and precision of clock().
+const clockRate = 20 * time.Millisecond
+
+// czero is the process start time rounded down to the nearest clockRate
+// increment.
+var czero = time.Duration(time.Now().UnixNano()) / clockRate * clockRate
+
+// clock returns a low resolution timestamp relative to the process start time.
+func clock() time.Duration {
+ return time.Duration(time.Now().UnixNano())/clockRate*clockRate - czero
+}
+
+// clockToTime converts a clock() timestamp to an absolute time.Time value.
+func clockToTime(c time.Duration) time.Time {
+ return time.Unix(0, int64(czero+c))
+}
+
+// clockRound returns d rounded to the nearest clockRate increment.
+func clockRound(d time.Duration) time.Duration {
+ return (d + clockRate>>1) / clockRate * clockRate
+}
+
+// round returns x rounded to the nearest int64 (non-negative values only).
+func round(x float64) int64 {
+ if _, frac := math.Modf(x); frac >= 0.5 {
+ return int64(math.Ceil(x))
+ }
+ return int64(math.Floor(x))
+}
+
+// Percent represents a percentage in increments of 1/1000th of a percent.
+type Percent uint32
+
+// percentOf calculates what percent of the total is x.
+func percentOf(x, total float64) Percent {
+ if x < 0 || total <= 0 {
+ return 0
+ } else if p := round(x / total * 1e5); p <= math.MaxUint32 {
+ return Percent(p)
+ }
+ return Percent(math.MaxUint32)
+}
+
+func (p Percent) Float() float64 {
+ return float64(p) * 1e-3
+}
+
+func (p Percent) String() string {
+ var buf [12]byte
+ b := strconv.AppendUint(buf[:0], uint64(p)/1000, 10)
+ n := len(b)
+ b = strconv.AppendUint(b, 1000+uint64(p)%1000, 10)
+ b[n] = '.'
+ return string(append(b, '%'))
+}
diff --git a/vendor/github.com/speps/go-hashids/.editorconfig b/vendor/github.com/speps/go-hashids/.editorconfig
new file mode 100644
index 0000000..edf70ca
--- /dev/null
+++ b/vendor/github.com/speps/go-hashids/.editorconfig
@@ -0,0 +1,5 @@
+root = true
+
+[*]
+indent_style = tab
+indent_size = 4
\ No newline at end of file
diff --git a/vendor/github.com/speps/go-hashids/.gitignore b/vendor/github.com/speps/go-hashids/.gitignore
new file mode 100644
index 0000000..0026861
--- /dev/null
+++ b/vendor/github.com/speps/go-hashids/.gitignore
@@ -0,0 +1,22 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
diff --git a/vendor/github.com/speps/go-hashids/LICENSE b/vendor/github.com/speps/go-hashids/LICENSE
new file mode 100644
index 0000000..9b6e9f8
--- /dev/null
+++ b/vendor/github.com/speps/go-hashids/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2014 Remi Gillig
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/speps/go-hashids/README.md b/vendor/github.com/speps/go-hashids/README.md
new file mode 100644
index 0000000..1960502
--- /dev/null
+++ b/vendor/github.com/speps/go-hashids/README.md
@@ -0,0 +1,76 @@
+go-hashids [](https://ci.appveyor.com/project/speps/go-hashids) [](https://godoc.org/github.com/speps/go-hashids)
+==========
+
+Go (golang) v1 implementation of http://www.hashids.org
+under MIT License (same as the original implementations)
+
+Original implementations by [Ivan Akimov](https://github.com/ivanakimov)
+
+### Setup
+go get github.com/speps/go-hashids
+
+### Example
+```go
+package main
+
+import "fmt"
+import "github.com/speps/go-hashids"
+
+func main() {
+ hd := hashids.NewData()
+ hd.Salt = "this is my salt"
+ hd.MinLength = 30
+ h := hashids.NewWithData(hd)
+ e, _ := h.Encode([]int{45, 434, 1313, 99})
+ fmt.Println(e)
+ d, _ := h.DecodeWithError(e)
+ fmt.Println(d)
+}
+```
+
+### Test results
+
+```
+=== RUN TestEncryptDecrypt
+--- PASS: TestEncryptDecrypt (0.00s)
+ hashids_test.go:22: [45 434 1313 99] -> woQ2vqjnG7nnhzEsDkiYadKa3O71br -> [45 434 1313 99]
+=== RUN TestEncryptDecryptInt64
+--- PASS: TestEncryptDecryptInt64 (0.00s)
+ hashids_test.go:49: [45 434 1313 99 9223372036854775807] -> ZvGlaahBptQNfPOuPjJ51zO3wVzP01 -> [45 434 1313 99 9223372036854775807]
+=== RUN TestEncryptWithKnownHash
+--- PASS: TestEncryptWithKnownHash (0.00s)
+ hashids_test.go:75: [45 434 1313 99] -> 7nnhzEsDkiYa
+=== RUN TestDecryptWithKnownHash
+--- PASS: TestDecryptWithKnownHash (0.00s)
+ hashids_test.go:92: 7nnhzEsDkiYa -> [45 434 1313 99]
+=== RUN TestDefaultLength
+--- PASS: TestDefaultLength (0.00s)
+ hashids_test.go:115: [45 434 1313 99] -> 7nnhzEsDkiYa -> [45 434 1313 99]
+=== RUN TestMinLength
+--- PASS: TestMinLength (0.00s)
+=== RUN TestCustomAlphabet
+--- PASS: TestCustomAlphabet (0.00s)
+ hashids_test.go:150: [45 434 1313 99] -> MAkhkloFAxAoskax -> [45 434 1313 99]
+=== RUN TestDecryptWithError
+--- PASS: TestDecryptWithError (0.00s)
+PASS
+```
+
+### Thanks to all the contributors
+
+* [Harm Aarts](https://github.com/haarts)
+* [Christoffer G. Thomsen](https://github.com/cgt)
+* [Peter Hellberg](https://github.com/peterhellberg)
+* [Rémy Oudompheng](https://github.com/remyoudompheng)
+* [Mart Roosmaa](https://github.com/roosmaa)
+
+Let me know if I forgot anyone of course.
+
+### Changelog
+
+2014/09/13
+
+* Updated to Hashids v1.0.0 (should be compatible with other implementations, let me know if not, was checked against the Javascript version)
+* Changed API
+ * Encrypt/Decrypt are now Encode/Decode
+ * HashID is now constructed from HashIDData containing alphabet, salt and minimum length
diff --git a/vendor/github.com/speps/go-hashids/hashids.go b/vendor/github.com/speps/go-hashids/hashids.go
new file mode 100644
index 0000000..6d8cec1
--- /dev/null
+++ b/vendor/github.com/speps/go-hashids/hashids.go
@@ -0,0 +1,346 @@
+// Go implementation of http://www.hashids.org under MIT license
+// Generates hashes from an array of integers, eg. for YouTube like hashes
+// Setup: go get github.com/speps/go-hashids
+// Original implementations by Ivan Akimov at https://github.com/ivanakimov
+// Thanks to Rémy Oudompheng and Peter Hellberg for code review and fixes
+
+package hashids
+
+import (
+ "errors"
+ "math"
+)
+
+const (
+ // Version is the version number of the library
+ Version string = "1.0.0"
+
+ // DefaultAlphabet is the default alphabet used by go-hashids
+ DefaultAlphabet string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
+
+ minAlphabetLength int = 16
+ sepDiv float64 = 3.5
+ guardDiv float64 = 12.0
+)
+
+var sepsOriginal = []rune("cfhistuCFHISTU")
+
+// HashID contains everything needed to encode/decode hashids
+type HashID struct {
+ alphabet []rune
+ minLength int
+ salt []rune
+ seps []rune
+ guards []rune
+}
+
+// HashIDData contains the information needed to generate hashids
+type HashIDData struct {
+ // Alphabet is the alphabet used to generate new ids
+ Alphabet string
+
+ // MinLength is the minimum length of a generated id
+ MinLength int
+
+ // Salt is the secret used to make the generated id harder to guess
+ Salt string
+}
+
+// NewData creates a new HashIDData with the DefaultAlphabet already set.
+func NewData() *HashIDData {
+ return &HashIDData{Alphabet: DefaultAlphabet}
+}
+
+// New creates a new HashID
+func New() *HashID {
+ return NewWithData(NewData())
+}
+
+// NewWithData creates a new HashID with the provided HashIDData
+func NewWithData(data *HashIDData) *HashID {
+ if len(data.Alphabet) < minAlphabetLength {
+ panic(errors.New("alphabet must contain at least 16 characters"))
+ }
+ // Check if all characters are unique in Alphabet
+ uniqueCheck := make(map[rune]bool, len(data.Alphabet))
+ for _, a := range data.Alphabet {
+ if _, found := uniqueCheck[a]; found {
+ panic(errors.New("duplicate character in alphabet"))
+ }
+ uniqueCheck[a] = true
+ }
+
+ alphabet := []rune(data.Alphabet)
+ salt := []rune(data.Salt)
+
+ seps := make([]rune, len(sepsOriginal))
+ copy(seps, sepsOriginal)
+
+ // seps should contain only characters present in alphabet; alphabet should not contains seps
+ for i := 0; i < len(seps); i++ {
+ foundIndex := -1
+ for j, a := range alphabet {
+ if a == seps[i] {
+ foundIndex = j
+ break
+ }
+ }
+ if foundIndex == -1 {
+ seps = append(seps[:i], seps[i+1:]...)
+ i--
+ } else {
+ alphabet = append(alphabet[:foundIndex], alphabet[foundIndex+1:]...)
+ }
+ }
+ seps = consistentShuffle(seps, salt)
+
+ if len(seps) == 0 || float64(len(alphabet))/float64(len(seps)) > sepDiv {
+ sepsLength := int(math.Ceil(float64(len(alphabet)) / sepDiv))
+ if sepsLength == 1 {
+ sepsLength++
+ }
+ if sepsLength > len(seps) {
+ diff := sepsLength - len(seps)
+ seps = append(seps, alphabet[:diff]...)
+ alphabet = alphabet[diff:]
+ } else {
+ seps = seps[:sepsLength]
+ }
+ }
+ alphabet = consistentShuffle(alphabet, salt)
+
+ guardCount := int(math.Ceil(float64(len(alphabet)) / guardDiv))
+ var guards []rune
+ if len(alphabet) < 3 {
+ guards = seps[:guardCount]
+ seps = seps[guardCount:]
+ } else {
+ guards = alphabet[:guardCount]
+ alphabet = alphabet[guardCount:]
+ }
+
+ return &HashID{
+ alphabet: alphabet,
+ minLength: data.MinLength,
+ salt: salt,
+ seps: seps,
+ guards: guards,
+ }
+}
+
+// Encode hashes an array of int to a string containing at least MinLength characters taken from the Alphabet.
+// Use Decode using the same Alphabet and Salt to get back the array of int.
+func (h *HashID) Encode(numbers []int) (string, error) {
+ numbers64 := make([]int64, 0, len(numbers))
+ for _, id := range numbers {
+ numbers64 = append(numbers64, int64(id))
+ }
+ return h.EncodeInt64(numbers64)
+}
+
+// EncodeInt64 hashes an array of int64 to a string containing at least MinLength characters taken from the Alphabet.
+// Use DecodeInt64 using the same Alphabet and Salt to get back the array of int64.
+func (h *HashID) EncodeInt64(numbers []int64) (string, error) {
+ if len(numbers) == 0 {
+ return "", errors.New("encoding empty array of numbers makes no sense")
+ }
+ for _, n := range numbers {
+ if n < 0 {
+ return "", errors.New("negative number not supported")
+ }
+ }
+
+ alphabet := make([]rune, len(h.alphabet))
+ copy(alphabet, h.alphabet)
+
+ numbersHash := int64(0)
+ for i, n := range numbers {
+ numbersHash += (n % int64(i+100))
+ }
+
+ result := make([]rune, 0, h.minLength)
+ lottery := alphabet[numbersHash%int64(len(alphabet))]
+ result = append(result, lottery)
+
+ for i, n := range numbers {
+ buffer := append([]rune{lottery}, append(h.salt, alphabet...)...)
+ alphabet = consistentShuffle(alphabet, buffer[:len(alphabet)])
+ hash := hash(n, alphabet)
+ result = append(result, hash...)
+
+ if i+1 < len(numbers) {
+ n %= int64(hash[0]) + int64(i)
+ result = append(result, h.seps[n%int64(len(h.seps))])
+ }
+ }
+
+ if len(result) < h.minLength {
+ guardIndex := (numbersHash + int64(result[0])) % int64(len(h.guards))
+ result = append([]rune{h.guards[guardIndex]}, result...)
+
+ if len(result) < h.minLength {
+ guardIndex = (numbersHash + int64(result[2])) % int64(len(h.guards))
+ result = append(result, h.guards[guardIndex])
+ }
+ }
+
+ halfLength := len(alphabet) / 2
+ for len(result) < h.minLength {
+ alphabet = consistentShuffle(alphabet, alphabet)
+ result = append(alphabet[halfLength:], append(result, alphabet[:halfLength]...)...)
+ excess := len(result) - h.minLength
+ if excess > 0 {
+ result = result[excess/2 : excess/2+h.minLength]
+ }
+ }
+
+ return string(result), nil
+}
+
+// DEPRECATED: Use DecryptWithError instead
+// Decode unhashes the string passed to an array of int.
+// It is symmetric with Encode if the Alphabet and Salt are the same ones which were used to hash.
+// MinLength has no effect on Decode.
+func (h *HashID) Decode(hash string) []int {
+ result, err := h.DecodeWithError(hash)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+// Decode unhashes the string passed to an array of int.
+// It is symmetric with Encode if the Alphabet and Salt are the same ones which were used to hash.
+// MinLength has no effect on Decode.
+func (h *HashID) DecodeWithError(hash string) ([]int, error) {
+ result64, err := h.DecodeInt64WithError(hash)
+ if err != nil {
+ return nil, err
+ }
+ result := make([]int, 0, len(result64))
+ for _, id := range result64 {
+ result = append(result, int(id))
+ }
+ return result, nil
+}
+
+// DEPRECATED: Use DecryptInt64WithError instead
+// DecodeInt64 unhashes the string passed to an array of int64.
+// It is symmetric with EncodeInt64 if the Alphabet and Salt are the same ones which were used to hash.
+// MinLength has no effect on DecodeInt64.
+func (h *HashID) DecodeInt64(hash string) []int64 {
+ result, err := h.DecodeInt64WithError(hash)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+// DecodeInt64 unhashes the string passed to an array of int64.
+// It is symmetric with EncodeInt64 if the Alphabet and Salt are the same ones which were used to hash.
+// MinLength has no effect on DecodeInt64.
+func (h *HashID) DecodeInt64WithError(hash string) ([]int64, error) {
+ hashes := splitRunes([]rune(hash), h.guards)
+ hashIndex := 0
+ if len(hashes) == 2 || len(hashes) == 3 {
+ hashIndex = 1
+ }
+
+ result := make([]int64, 0)
+
+ hashBreakdown := hashes[hashIndex]
+ if len(hashBreakdown) > 0 {
+ lottery := hashBreakdown[0]
+ hashBreakdown = hashBreakdown[1:]
+ hashes = splitRunes(hashBreakdown, h.seps)
+ alphabet := []rune(h.alphabet)
+ for _, subHash := range hashes {
+ buffer := append([]rune{lottery}, append(h.salt, alphabet...)...)
+ alphabet = consistentShuffle(alphabet, buffer[:len(alphabet)])
+ number, err := unhash(subHash, alphabet)
+ if err != nil {
+ return nil, err
+ }
+ result = append(result, number)
+ }
+ }
+
+ return result, nil
+}
+
+func splitRunes(input, seps []rune) [][]rune {
+ splitIndices := make([]int, 0)
+ for i, inputRune := range input {
+ for _, sepsRune := range seps {
+ if inputRune == sepsRune {
+ splitIndices = append(splitIndices, i)
+ }
+ }
+ }
+
+ result := make([][]rune, 0, len(splitIndices)+1)
+ inputLeft := input[:]
+ for _, splitIndex := range splitIndices {
+ splitIndex -= len(input) - len(inputLeft)
+ subInput := make([]rune, splitIndex)
+ copy(subInput, inputLeft[:splitIndex])
+ result = append(result, subInput)
+ inputLeft = inputLeft[splitIndex+1:]
+ }
+ result = append(result, inputLeft)
+
+ return result
+}
+
+func hash(input int64, alphabet []rune) []rune {
+ result := make([]rune, 0)
+ for {
+ r := alphabet[input%int64(len(alphabet))]
+ result = append(result, r)
+ input /= int64(len(alphabet))
+ if input == 0 {
+ break
+ }
+ }
+ reversed := make([]rune, len(result))
+ for i, r := range result {
+ reversed[len(result)-i-1] = r
+ }
+ return reversed
+}
+
+func unhash(input, alphabet []rune) (int64, error) {
+ result := int64(0)
+ for i, inputRune := range input {
+ alphabetPos := -1
+ for pos, alphabetRune := range alphabet {
+ if inputRune == alphabetRune {
+ alphabetPos = pos
+ break
+ }
+ }
+ if alphabetPos == -1 {
+ return 0, errors.New("alphabet used for hash was different")
+ }
+
+ result += int64(alphabetPos) * int64(math.Pow(float64(len(alphabet)), float64(len(input)-i-1)))
+ }
+ return result, nil
+}
+
+func consistentShuffle(alphabet, salt []rune) []rune {
+ if len(salt) == 0 {
+ return alphabet
+ }
+
+ result := make([]rune, len(alphabet))
+ copy(result, alphabet)
+ for i, v, p := len(result)-1, 0, 0; i > 0; i-- {
+ p += int(salt[v])
+ j := (int(salt[v]) + v + p) % i
+ result[i], result[j] = result[j], result[i]
+ v = (v + 1) % len(salt)
+ }
+
+ return result
+}
diff --git a/vendor/github.com/speps/go-hashids/hashids_test.go b/vendor/github.com/speps/go-hashids/hashids_test.go
new file mode 100644
index 0000000..ac4f7a0
--- /dev/null
+++ b/vendor/github.com/speps/go-hashids/hashids_test.go
@@ -0,0 +1,178 @@
+package hashids
+
+import (
+ "math"
+ "testing"
+)
+
+func TestEncryptDecrypt(t *testing.T) {
+ hdata := NewData()
+ hdata.MinLength = 30
+ hdata.Salt = "this is my salt"
+
+ hid := NewWithData(hdata)
+
+ numbers := []int{45, 434, 1313, 99}
+ hash, err := hid.Encode(numbers)
+ if err != nil {
+ t.Fatal(err)
+ }
+ dec := hid.Decode(hash)
+
+ t.Logf("%v -> %v -> %v", numbers, hash, dec)
+
+ if len(numbers) != len(dec) {
+ t.Error("lengths do not match")
+ }
+
+ for i, n := range numbers {
+ if n != dec[i] {
+ t.Fail()
+ }
+ }
+}
+
+func TestEncryptDecryptInt64(t *testing.T) {
+ hdata := NewData()
+ hdata.MinLength = 30
+ hdata.Salt = "this is my salt"
+
+ hid := NewWithData(hdata)
+
+ numbers := []int64{45, 434, 1313, 99, math.MaxInt64}
+ hash, err := hid.EncodeInt64(numbers)
+ if err != nil {
+ t.Fatal(err)
+ }
+ dec := hid.DecodeInt64(hash)
+
+ t.Logf("%v -> %v -> %v", numbers, hash, dec)
+
+ if len(numbers) != len(dec) {
+ t.Error("lengths do not match")
+ }
+
+ for i, n := range numbers {
+ if n != dec[i] {
+ t.Fail()
+ }
+ }
+}
+
+func TestEncryptWithKnownHash(t *testing.T) {
+ hdata := NewData()
+ hdata.MinLength = 0
+ hdata.Salt = "this is my salt"
+
+ hid := NewWithData(hdata)
+
+ numbers := []int{45, 434, 1313, 99}
+ hash, err := hid.Encode(numbers)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ t.Logf("%v -> %v", numbers, hash)
+
+ if hash != "7nnhzEsDkiYa" {
+ t.Error("hash does not match expected one")
+ }
+}
+
+func TestDecryptWithKnownHash(t *testing.T) {
+ hdata := NewData()
+ hdata.MinLength = 0
+ hdata.Salt = "this is my salt"
+
+ hid := NewWithData(hdata)
+
+ hash := "7nnhzEsDkiYa"
+ numbers := hid.Decode(hash)
+
+ t.Logf("%v -> %v", hash, numbers)
+
+ expected := []int{45, 434, 1313, 99}
+ for i, n := range numbers {
+ if n != expected[i] {
+ t.Fail()
+ }
+ }
+}
+
+func TestDefaultLength(t *testing.T) {
+ hdata := NewData()
+ hdata.Salt = "this is my salt"
+
+ hid := NewWithData(hdata)
+
+ numbers := []int{45, 434, 1313, 99}
+ hash, err := hid.Encode(numbers)
+ if err != nil {
+ t.Fatal(err)
+ }
+ dec := hid.Decode(hash)
+
+ t.Logf("%v -> %v -> %v", numbers, hash, dec)
+
+ if len(numbers) != len(dec) {
+ t.Error("lengths do not match")
+ }
+
+ for i, n := range numbers {
+ if n != dec[i] {
+ t.Fail()
+ }
+ }
+}
+
+func TestMinLength(t *testing.T) {
+ hdata := NewData()
+ hdata.Salt = "salt1"
+ hdata.MinLength = 10
+ hid := NewWithData(hdata)
+ hid.Encode([]int{0})
+}
+
+func TestCustomAlphabet(t *testing.T) {
+ hdata := NewData()
+ hdata.Alphabet = "PleasAkMEFoThStx"
+ hdata.Salt = "this is my salt"
+
+ hid := NewWithData(hdata)
+
+ numbers := []int{45, 434, 1313, 99}
+ hash, err := hid.Encode(numbers)
+ if err != nil {
+ t.Fatal(err)
+ }
+ dec := hid.Decode(hash)
+
+ t.Logf("%v -> %v -> %v", numbers, hash, dec)
+
+ if len(numbers) != len(dec) {
+ t.Error("lengths do not match")
+ }
+
+ for i, n := range numbers {
+ if n != dec[i] {
+ t.Fail()
+ }
+ }
+}
+
+func TestDecryptWithError(t *testing.T) {
+ hdata := NewData()
+ hdata.Alphabet = "PleasAkMEFoThStx"
+ hdata.Salt = "this is my salt"
+
+ hid := NewWithData(hdata)
+ // hash now contains a letter not in the alphabet
+ dec, err := hid.DecodeWithError("MAkhkloFAxAoskaZ")
+
+ if dec != nil {
+ t.Error("DecryptWithError should have returned nil result")
+ }
+ if err == nil {
+ t.Error("DecryptWithError should have returned error")
+ }
+}
diff --git a/vendor/golang.org/x/image/.gitattributes b/vendor/golang.org/x/image/.gitattributes
new file mode 100644
index 0000000..d2f212e
--- /dev/null
+++ b/vendor/golang.org/x/image/.gitattributes
@@ -0,0 +1,10 @@
+# Treat all files in this repo as binary, with no git magic updating
+# line endings. Windows users contributing to Go will need to use a
+# modern version of git and editors capable of LF line endings.
+#
+# We'll prevent accidental CRLF line endings from entering the repo
+# via the git-review gofmt checks.
+#
+# See golang.org/issue/9281
+
+* -text
diff --git a/vendor/golang.org/x/image/.gitignore b/vendor/golang.org/x/image/.gitignore
new file mode 100644
index 0000000..8339fd6
--- /dev/null
+++ b/vendor/golang.org/x/image/.gitignore
@@ -0,0 +1,2 @@
+# Add no patterns to .hgignore except for files generated by the build.
+last-change
diff --git a/vendor/golang.org/x/image/AUTHORS b/vendor/golang.org/x/image/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/vendor/golang.org/x/image/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/image/CONTRIBUTING.md b/vendor/golang.org/x/image/CONTRIBUTING.md
new file mode 100644
index 0000000..d0485e8
--- /dev/null
+++ b/vendor/golang.org/x/image/CONTRIBUTING.md
@@ -0,0 +1,26 @@
+# Contributing to Go
+
+Go is an open source project.
+
+It is the work of hundreds of contributors. We appreciate your help!
+
+## Filing issues
+
+When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
+
+1. What version of Go are you using (`go version`)?
+2. What operating system and processor architecture are you using?
+3. What did you do?
+4. What did you expect to see?
+5. What did you see instead?
+
+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
+The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+## Contributing code
+
+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
+before sending patches.
+
+Unless otherwise noted, the Go source files are distributed under
+the BSD-style license found in the LICENSE file.
diff --git a/vendor/golang.org/x/image/CONTRIBUTORS b/vendor/golang.org/x/image/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/vendor/golang.org/x/image/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/image/LICENSE b/vendor/golang.org/x/image/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/image/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/image/PATENTS b/vendor/golang.org/x/image/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/image/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/image/README.md b/vendor/golang.org/x/image/README.md
new file mode 100644
index 0000000..9e12d9e
--- /dev/null
+++ b/vendor/golang.org/x/image/README.md
@@ -0,0 +1,17 @@
+# Go Images
+
+This repository holds supplementary Go image libraries.
+
+## Download/Install
+
+The easiest way to install is to run `go get -u golang.org/x/image/...`. You can
+also manually git clone the repository to `$GOPATH/src/golang.org/x/image`.
+
+## Report Issues / Send Patches
+
+This repository uses Gerrit for code changes. To learn how to submit changes to
+this repository, see https://golang.org/doc/contribute.html.
+
+The main issue tracker for the image repository is located at
+https://github.com/golang/go/issues. Prefix your issue with "x/image:" in the
+subject line, so it is easy to find.
diff --git a/vendor/golang.org/x/image/bmp/reader.go b/vendor/golang.org/x/image/bmp/reader.go
new file mode 100644
index 0000000..a0f2715
--- /dev/null
+++ b/vendor/golang.org/x/image/bmp/reader.go
@@ -0,0 +1,199 @@
+// 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.
+
+// Package bmp implements a BMP image decoder and encoder.
+//
+// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html.
+package bmp // import "golang.org/x/image/bmp"
+
+import (
+ "errors"
+ "image"
+ "image/color"
+ "io"
+)
+
+// ErrUnsupported means that the input BMP image uses a valid but unsupported
+// feature.
+var ErrUnsupported = errors.New("bmp: unsupported BMP image")
+
+func readUint16(b []byte) uint16 {
+ return uint16(b[0]) | uint16(b[1])<<8
+}
+
+func readUint32(b []byte) uint32 {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+// decodePaletted reads an 8 bit-per-pixel BMP image from r.
+// If topDown is false, the image rows will be read bottom-up.
+func decodePaletted(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
+ paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette))
+ if c.Width == 0 || c.Height == 0 {
+ return paletted, nil
+ }
+ var tmp [4]byte
+ y0, y1, yDelta := c.Height-1, -1, -1
+ if topDown {
+ y0, y1, yDelta = 0, c.Height, +1
+ }
+ for y := y0; y != y1; y += yDelta {
+ p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width]
+ if _, err := io.ReadFull(r, p); err != nil {
+ return nil, err
+ }
+ // Each row is 4-byte aligned.
+ if c.Width%4 != 0 {
+ _, err := io.ReadFull(r, tmp[:4-c.Width%4])
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return paletted, nil
+}
+
+// decodeRGB reads a 24 bit-per-pixel BMP image from r.
+// If topDown is false, the image rows will be read bottom-up.
+func decodeRGB(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
+ rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height))
+ if c.Width == 0 || c.Height == 0 {
+ return rgba, nil
+ }
+ // There are 3 bytes per pixel, and each row is 4-byte aligned.
+ b := make([]byte, (3*c.Width+3)&^3)
+ y0, y1, yDelta := c.Height-1, -1, -1
+ if topDown {
+ y0, y1, yDelta = 0, c.Height, +1
+ }
+ for y := y0; y != y1; y += yDelta {
+ if _, err := io.ReadFull(r, b); err != nil {
+ return nil, err
+ }
+ p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
+ for i, j := 0, 0; i < len(p); i, j = i+4, j+3 {
+ // BMP images are stored in BGR order rather than RGB order.
+ p[i+0] = b[j+2]
+ p[i+1] = b[j+1]
+ p[i+2] = b[j+0]
+ p[i+3] = 0xFF
+ }
+ }
+ return rgba, nil
+}
+
+// decodeNRGBA reads a 32 bit-per-pixel BMP image from r.
+// If topDown is false, the image rows will be read bottom-up.
+func decodeNRGBA(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
+ rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height))
+ if c.Width == 0 || c.Height == 0 {
+ return rgba, nil
+ }
+ y0, y1, yDelta := c.Height-1, -1, -1
+ if topDown {
+ y0, y1, yDelta = 0, c.Height, +1
+ }
+ for y := y0; y != y1; y += yDelta {
+ p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
+ if _, err := io.ReadFull(r, p); err != nil {
+ return nil, err
+ }
+ for i := 0; i < len(p); i += 4 {
+ // BMP images are stored in BGRA order rather than RGBA order.
+ p[i+0], p[i+2] = p[i+2], p[i+0]
+ }
+ }
+ return rgba, nil
+}
+
+// Decode reads a BMP image from r and returns it as an image.Image.
+// Limitation: The file must be 8, 24 or 32 bits per pixel.
+func Decode(r io.Reader) (image.Image, error) {
+ c, bpp, topDown, err := decodeConfig(r)
+ if err != nil {
+ return nil, err
+ }
+ switch bpp {
+ case 8:
+ return decodePaletted(r, c, topDown)
+ case 24:
+ return decodeRGB(r, c, topDown)
+ case 32:
+ return decodeNRGBA(r, c, topDown)
+ }
+ panic("unreachable")
+}
+
+// DecodeConfig returns the color model and dimensions of a BMP image without
+// decoding the entire image.
+// Limitation: The file must be 8, 24 or 32 bits per pixel.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+ config, _, _, err := decodeConfig(r)
+ return config, err
+}
+
+func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, err error) {
+ // We only support those BMP images that are a BITMAPFILEHEADER
+ // immediately followed by a BITMAPINFOHEADER.
+ const (
+ fileHeaderLen = 14
+ infoHeaderLen = 40
+ )
+ var b [1024]byte
+ if _, err := io.ReadFull(r, b[:fileHeaderLen+infoHeaderLen]); err != nil {
+ return image.Config{}, 0, false, err
+ }
+ if string(b[:2]) != "BM" {
+ return image.Config{}, 0, false, errors.New("bmp: invalid format")
+ }
+ offset := readUint32(b[10:14])
+ if readUint32(b[14:18]) != infoHeaderLen {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ width := int(int32(readUint32(b[18:22])))
+ height := int(int32(readUint32(b[22:26])))
+ if height < 0 {
+ height, topDown = -height, true
+ }
+ if width < 0 || height < 0 {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ // We only support 1 plane, 8 or 24 bits per pixel and no compression.
+ planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34])
+ if planes != 1 || compression != 0 {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ switch bpp {
+ case 8:
+ if offset != fileHeaderLen+infoHeaderLen+256*4 {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ _, err = io.ReadFull(r, b[:256*4])
+ if err != nil {
+ return image.Config{}, 0, false, err
+ }
+ pcm := make(color.Palette, 256)
+ for i := range pcm {
+ // BMP images are stored in BGR order rather than RGB order.
+ // Every 4th byte is padding.
+ pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
+ }
+ return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, nil
+ case 24:
+ if offset != fileHeaderLen+infoHeaderLen {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, nil
+ case 32:
+ if offset != fileHeaderLen+infoHeaderLen {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, nil
+ }
+ return image.Config{}, 0, false, ErrUnsupported
+}
+
+func init() {
+ image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig)
+}
diff --git a/vendor/golang.org/x/image/bmp/reader_test.go b/vendor/golang.org/x/image/bmp/reader_test.go
new file mode 100644
index 0000000..fd6ff64
--- /dev/null
+++ b/vendor/golang.org/x/image/bmp/reader_test.go
@@ -0,0 +1,75 @@
+// Copyright 2012 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 bmp
+
+import (
+ "fmt"
+ "image"
+ "os"
+ "testing"
+
+ _ "image/png"
+)
+
+const testdataDir = "../testdata/"
+
+func compare(t *testing.T, img0, img1 image.Image) error {
+ b := img1.Bounds()
+ if !b.Eq(img0.Bounds()) {
+ return fmt.Errorf("wrong image size: want %s, got %s", img0.Bounds(), b)
+ }
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ c0 := img0.At(x, y)
+ c1 := img1.At(x, y)
+ r0, g0, b0, a0 := c0.RGBA()
+ r1, g1, b1, a1 := c1.RGBA()
+ if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 {
+ return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1)
+ }
+ }
+ }
+ return nil
+}
+
+// TestDecode tests that decoding a PNG image and a BMP image result in the
+// same pixel data.
+func TestDecode(t *testing.T) {
+ testCases := []string{
+ "video-001",
+ "yellow_rose-small",
+ }
+
+ for _, tc := range testCases {
+ f0, err := os.Open(testdataDir + tc + ".png")
+ if err != nil {
+ t.Errorf("%s: Open PNG: %v", tc, err)
+ continue
+ }
+ defer f0.Close()
+ img0, _, err := image.Decode(f0)
+ if err != nil {
+ t.Errorf("%s: Decode PNG: %v", tc, err)
+ continue
+ }
+
+ f1, err := os.Open(testdataDir + tc + ".bmp")
+ if err != nil {
+ t.Errorf("%s: Open BMP: %v", tc, err)
+ continue
+ }
+ defer f1.Close()
+ img1, _, err := image.Decode(f1)
+ if err != nil {
+ t.Errorf("%s: Decode BMP: %v", tc, err)
+ continue
+ }
+
+ if err := compare(t, img0, img1); err != nil {
+ t.Errorf("%s: %v", tc, err)
+ continue
+ }
+ }
+}
diff --git a/vendor/golang.org/x/image/bmp/writer.go b/vendor/golang.org/x/image/bmp/writer.go
new file mode 100644
index 0000000..6947968
--- /dev/null
+++ b/vendor/golang.org/x/image/bmp/writer.go
@@ -0,0 +1,166 @@
+// Copyright 2013 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 bmp
+
+import (
+ "encoding/binary"
+ "errors"
+ "image"
+ "io"
+)
+
+type header struct {
+ sigBM [2]byte
+ fileSize uint32
+ resverved [2]uint16
+ pixOffset uint32
+ dibHeaderSize uint32
+ width uint32
+ height uint32
+ colorPlane uint16
+ bpp uint16
+ compression uint32
+ imageSize uint32
+ xPixelsPerMeter uint32
+ yPixelsPerMeter uint32
+ colorUse uint32
+ colorImportant uint32
+}
+
+func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
+ var padding []byte
+ if dx < step {
+ padding = make([]byte, step-dx)
+ }
+ for y := dy - 1; y >= 0; y-- {
+ min := y*stride + 0
+ max := y*stride + dx
+ if _, err := w.Write(pix[min:max]); err != nil {
+ return err
+ }
+ if padding != nil {
+ if _, err := w.Write(padding); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
+ buf := make([]byte, step)
+ for y := dy - 1; y >= 0; y-- {
+ min := y*stride + 0
+ max := y*stride + dx*4
+ off := 0
+ for i := min; i < max; i += 4 {
+ buf[off+2] = pix[i+0]
+ buf[off+1] = pix[i+1]
+ buf[off+0] = pix[i+2]
+ off += 3
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func encode(w io.Writer, m image.Image, step int) error {
+ b := m.Bounds()
+ buf := make([]byte, step)
+ for y := b.Max.Y - 1; y >= b.Min.Y; y-- {
+ off := 0
+ for x := b.Min.X; x < b.Max.X; x++ {
+ r, g, b, _ := m.At(x, y).RGBA()
+ buf[off+2] = byte(r >> 8)
+ buf[off+1] = byte(g >> 8)
+ buf[off+0] = byte(b >> 8)
+ off += 3
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Encode writes the image m to w in BMP format.
+func Encode(w io.Writer, m image.Image) error {
+ d := m.Bounds().Size()
+ if d.X < 0 || d.Y < 0 {
+ return errors.New("bmp: negative bounds")
+ }
+ h := &header{
+ sigBM: [2]byte{'B', 'M'},
+ fileSize: 14 + 40,
+ pixOffset: 14 + 40,
+ dibHeaderSize: 40,
+ width: uint32(d.X),
+ height: uint32(d.Y),
+ colorPlane: 1,
+ }
+
+ var step int
+ var palette []byte
+ switch m := m.(type) {
+ case *image.Gray:
+ step = (d.X + 3) &^ 3
+ palette = make([]byte, 1024)
+ for i := 0; i < 256; i++ {
+ palette[i*4+0] = uint8(i)
+ palette[i*4+1] = uint8(i)
+ palette[i*4+2] = uint8(i)
+ palette[i*4+3] = 0xFF
+ }
+ h.imageSize = uint32(d.Y * step)
+ h.fileSize += uint32(len(palette)) + h.imageSize
+ h.pixOffset += uint32(len(palette))
+ h.bpp = 8
+
+ case *image.Paletted:
+ step = (d.X + 3) &^ 3
+ palette = make([]byte, 1024)
+ for i := 0; i < len(m.Palette) && i < 256; i++ {
+ r, g, b, _ := m.Palette[i].RGBA()
+ palette[i*4+0] = uint8(b >> 8)
+ palette[i*4+1] = uint8(g >> 8)
+ palette[i*4+2] = uint8(r >> 8)
+ palette[i*4+3] = 0xFF
+ }
+ h.imageSize = uint32(d.Y * step)
+ h.fileSize += uint32(len(palette)) + h.imageSize
+ h.pixOffset += uint32(len(palette))
+ h.bpp = 8
+ default:
+ step = (3*d.X + 3) &^ 3
+ h.imageSize = uint32(d.Y * step)
+ h.fileSize += h.imageSize
+ h.bpp = 24
+ }
+
+ if err := binary.Write(w, binary.LittleEndian, h); err != nil {
+ return err
+ }
+ if palette != nil {
+ if err := binary.Write(w, binary.LittleEndian, palette); err != nil {
+ return err
+ }
+ }
+
+ if d.X == 0 || d.Y == 0 {
+ return nil
+ }
+
+ switch m := m.(type) {
+ case *image.Gray:
+ return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
+ case *image.Paletted:
+ return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
+ case *image.RGBA:
+ return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step)
+ }
+ return encode(w, m, step)
+}
diff --git a/vendor/golang.org/x/image/bmp/writer_test.go b/vendor/golang.org/x/image/bmp/writer_test.go
new file mode 100644
index 0000000..9e5a327
--- /dev/null
+++ b/vendor/golang.org/x/image/bmp/writer_test.go
@@ -0,0 +1,91 @@
+// Copyright 2013 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 bmp
+
+import (
+ "bytes"
+ "fmt"
+ "image"
+ "io/ioutil"
+ "os"
+ "testing"
+ "time"
+)
+
+func openImage(filename string) (image.Image, error) {
+ f, err := os.Open(testdataDir + filename)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return Decode(f)
+}
+
+func TestEncode(t *testing.T) {
+ img0, err := openImage("video-001.bmp")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ buf := new(bytes.Buffer)
+ err = Encode(buf, img0)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ img1, err := Decode(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ compare(t, img0, img1)
+}
+
+// TestZeroWidthVeryLargeHeight tests that encoding and decoding a degenerate
+// image with zero width but over one billion pixels in height is faster than
+// naively calling an io.Reader or io.Writer method once per row.
+func TestZeroWidthVeryLargeHeight(t *testing.T) {
+ c := make(chan error, 1)
+ go func() {
+ b := image.Rect(0, 0, 0, 0x3fffffff)
+ var buf bytes.Buffer
+ if err := Encode(&buf, image.NewRGBA(b)); err != nil {
+ c <- err
+ return
+ }
+ m, err := Decode(&buf)
+ if err != nil {
+ c <- err
+ return
+ }
+ if got := m.Bounds(); got != b {
+ c <- fmt.Errorf("bounds: got %v, want %v", got, b)
+ return
+ }
+ c <- nil
+ }()
+ select {
+ case err := <-c:
+ if err != nil {
+ t.Fatal(err)
+ }
+ case <-time.After(3 * time.Second):
+ t.Fatalf("timed out")
+ }
+}
+
+// BenchmarkEncode benchmarks the encoding of an image.
+func BenchmarkEncode(b *testing.B) {
+ img, err := openImage("video-001.bmp")
+ if err != nil {
+ b.Fatal(err)
+ }
+ s := img.Bounds().Size()
+ b.SetBytes(int64(s.X * s.Y * 4))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Encode(ioutil.Discard, img)
+ }
+}
diff --git a/vendor/golang.org/x/image/codereview.cfg b/vendor/golang.org/x/image/codereview.cfg
new file mode 100644
index 0000000..3f8b14b
--- /dev/null
+++ b/vendor/golang.org/x/image/codereview.cfg
@@ -0,0 +1 @@
+issuerepo: golang/go
diff --git a/vendor/golang.org/x/image/draw/draw.go b/vendor/golang.org/x/image/draw/draw.go
new file mode 100644
index 0000000..dfaa7fc
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/draw.go
@@ -0,0 +1,43 @@
+// Copyright 2015 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 draw provides image composition functions.
+//
+// See "The Go image/draw package" for an introduction to this package:
+// http://golang.org/doc/articles/image_draw.html
+//
+// This package is a superset of and a drop-in replacement for the image/draw
+// package in the standard library.
+package draw
+
+// This file, and the go1_*.go files, just contains the API exported by the
+// image/draw package in the standard library. Other files in this package
+// provide additional features.
+
+import (
+ "image"
+ "image/draw"
+)
+
+// Draw calls DrawMask with a nil mask.
+func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) {
+ draw.Draw(dst, r, src, sp, draw.Op(op))
+}
+
+// DrawMask aligns r.Min in dst with sp in src and mp in mask and then
+// replaces the rectangle r in dst with the result of a Porter-Duff
+// composition. A nil mask is treated as opaque.
+func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
+ draw.DrawMask(dst, r, src, sp, mask, mp, draw.Op(op))
+}
+
+// FloydSteinberg is a Drawer that is the Src Op with Floyd-Steinberg error
+// diffusion.
+var FloydSteinberg Drawer = floydSteinberg{}
+
+type floydSteinberg struct{}
+
+func (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
+ draw.FloydSteinberg.Draw(dst, r, src, sp)
+}
diff --git a/vendor/golang.org/x/image/draw/example_test.go b/vendor/golang.org/x/image/draw/example_test.go
new file mode 100644
index 0000000..bcb4662
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/example_test.go
@@ -0,0 +1,118 @@
+// Copyright 2015 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 draw_test
+
+import (
+ "fmt"
+ "image"
+ "image/color"
+ "image/png"
+ "log"
+ "math"
+ "os"
+
+ "golang.org/x/image/draw"
+ "golang.org/x/image/math/f64"
+)
+
+func ExampleDraw() {
+ fSrc, err := os.Open("../testdata/blue-purple-pink.png")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer fSrc.Close()
+ src, err := png.Decode(fSrc)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ dst := image.NewRGBA(image.Rect(0, 0, 400, 300))
+ green := image.NewUniform(color.RGBA{0x00, 0x1f, 0x00, 0xff})
+ draw.Copy(dst, image.Point{}, green, dst.Bounds(), draw.Src, nil)
+ qs := []draw.Interpolator{
+ draw.NearestNeighbor,
+ draw.ApproxBiLinear,
+ draw.CatmullRom,
+ }
+ const cos60, sin60 = 0.5, 0.866025404
+ t := f64.Aff3{
+ +2 * cos60, -2 * sin60, 100,
+ +2 * sin60, +2 * cos60, 100,
+ }
+
+ draw.Copy(dst, image.Point{20, 30}, src, src.Bounds(), draw.Over, nil)
+ for i, q := range qs {
+ q.Scale(dst, image.Rect(200+10*i, 100*i, 600+10*i, 150+100*i), src, src.Bounds(), draw.Over, nil)
+ }
+ draw.NearestNeighbor.Transform(dst, t, src, src.Bounds(), draw.Over, nil)
+
+ red := image.NewNRGBA(image.Rect(0, 0, 16, 16))
+ for y := 0; y < 16; y++ {
+ for x := 0; x < 16; x++ {
+ red.SetNRGBA(x, y, color.NRGBA{
+ R: uint8(x * 0x11),
+ A: uint8(y * 0x11),
+ })
+ }
+ }
+ red.SetNRGBA(0, 0, color.NRGBA{0xff, 0xff, 0x00, 0xff})
+ red.SetNRGBA(15, 15, color.NRGBA{0xff, 0xff, 0x00, 0xff})
+
+ ops := []draw.Op{
+ draw.Over,
+ draw.Src,
+ }
+ for i, op := range ops {
+ dr := image.Rect(120+10*i, 150+60*i, 170+10*i, 200+60*i)
+ draw.NearestNeighbor.Scale(dst, dr, red, red.Bounds(), op, nil)
+ t := f64.Aff3{
+ +cos60, -sin60, float64(190 + 10*i),
+ +sin60, +cos60, float64(140 + 50*i),
+ }
+ draw.NearestNeighbor.Transform(dst, t, red, red.Bounds(), op, nil)
+ }
+
+ dr := image.Rect(0, 0, 128, 128)
+ checkerboard := image.NewAlpha(dr)
+ for y := dr.Min.Y; y < dr.Max.Y; y++ {
+ for x := dr.Min.X; x < dr.Max.X; x++ {
+ if (x/20)%2 == (y/20)%2 {
+ checkerboard.SetAlpha(x, y, color.Alpha{0xff})
+ }
+ }
+ }
+ sr := image.Rect(0, 0, 16, 16)
+ circle := image.NewAlpha(sr)
+ for y := sr.Min.Y; y < sr.Max.Y; y++ {
+ for x := sr.Min.X; x < sr.Max.X; x++ {
+ dx, dy := x-10, y-8
+ if d := 32 * math.Sqrt(float64(dx*dx)+float64(dy*dy)); d < 0xff {
+ circle.SetAlpha(x, y, color.Alpha{0xff - uint8(d)})
+ }
+ }
+ }
+ cyan := image.NewUniform(color.RGBA{0x00, 0xff, 0xff, 0xff})
+ draw.NearestNeighbor.Scale(dst, dr, cyan, sr, draw.Over, &draw.Options{
+ DstMask: checkerboard,
+ SrcMask: circle,
+ })
+
+ // Change false to true to write the resultant image to disk.
+ if false {
+ fDst, err := os.Create("out.png")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer fDst.Close()
+ err = png.Encode(fDst, dst)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ fmt.Printf("dst has bounds %v.\n", dst.Bounds())
+ // Output:
+ // dst has bounds (0,0)-(400,300).
+}
diff --git a/vendor/golang.org/x/image/draw/gen.go b/vendor/golang.org/x/image/draw/gen.go
new file mode 100644
index 0000000..822bb6a
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/gen.go
@@ -0,0 +1,1404 @@
+// Copyright 2015 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 ignore
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "log"
+ "os"
+ "strings"
+)
+
+var debug = flag.Bool("debug", false, "")
+
+func main() {
+ flag.Parse()
+
+ w := new(bytes.Buffer)
+ w.WriteString("// generated by \"go run gen.go\". DO NOT EDIT.\n\n" +
+ "package draw\n\nimport (\n" +
+ "\"image\"\n" +
+ "\"image/color\"\n" +
+ "\"math\"\n" +
+ "\n" +
+ "\"golang.org/x/image/math/f64\"\n" +
+ ")\n")
+
+ gen(w, "nnInterpolator", codeNNScaleLeaf, codeNNTransformLeaf)
+ gen(w, "ablInterpolator", codeABLScaleLeaf, codeABLTransformLeaf)
+ genKernel(w)
+
+ if *debug {
+ os.Stdout.Write(w.Bytes())
+ return
+ }
+ out, err := format.Source(w.Bytes())
+ if err != nil {
+ log.Fatal(err)
+ }
+ if err := ioutil.WriteFile("impl.go", out, 0660); err != nil {
+ log.Fatal(err)
+ }
+}
+
+var (
+ // dsTypes are the (dst image type, src image type) pairs to generate
+ // scale_DType_SType implementations for. The last element in the slice
+ // should be the fallback pair ("Image", "image.Image").
+ //
+ // TODO: add *image.CMYK src type after Go 1.5 is released.
+ // An *image.CMYK is also alwaysOpaque.
+ dsTypes = []struct{ dType, sType string }{
+ {"*image.RGBA", "*image.Gray"},
+ {"*image.RGBA", "*image.NRGBA"},
+ {"*image.RGBA", "*image.RGBA"},
+ {"*image.RGBA", "*image.YCbCr"},
+ {"*image.RGBA", "image.Image"},
+ {"Image", "image.Image"},
+ }
+ dTypes, sTypes []string
+ sTypesForDType = map[string][]string{}
+ subsampleRatios = []string{
+ "444",
+ "422",
+ "420",
+ "440",
+ }
+ ops = []string{"Over", "Src"}
+ // alwaysOpaque are those image.Image implementations that are always
+ // opaque. For these types, Over is equivalent to the faster Src, in the
+ // absence of a source mask.
+ alwaysOpaque = map[string]bool{
+ "*image.Gray": true,
+ "*image.YCbCr": true,
+ }
+)
+
+func init() {
+ dTypesSeen := map[string]bool{}
+ sTypesSeen := map[string]bool{}
+ for _, t := range dsTypes {
+ if !sTypesSeen[t.sType] {
+ sTypesSeen[t.sType] = true
+ sTypes = append(sTypes, t.sType)
+ }
+ if !dTypesSeen[t.dType] {
+ dTypesSeen[t.dType] = true
+ dTypes = append(dTypes, t.dType)
+ }
+ sTypesForDType[t.dType] = append(sTypesForDType[t.dType], t.sType)
+ }
+ sTypesForDType["anyDType"] = sTypes
+}
+
+type data struct {
+ dType string
+ sType string
+ sratio string
+ receiver string
+ op string
+}
+
+func gen(w *bytes.Buffer, receiver string, codes ...string) {
+ expn(w, codeRoot, &data{receiver: receiver})
+ for _, code := range codes {
+ for _, t := range dsTypes {
+ for _, op := range ops {
+ if op == "Over" && alwaysOpaque[t.sType] {
+ continue
+ }
+ expn(w, code, &data{
+ dType: t.dType,
+ sType: t.sType,
+ receiver: receiver,
+ op: op,
+ })
+ }
+ }
+ }
+}
+
+func genKernel(w *bytes.Buffer) {
+ expn(w, codeKernelRoot, &data{})
+ for _, sType := range sTypes {
+ expn(w, codeKernelScaleLeafX, &data{
+ sType: sType,
+ })
+ }
+ for _, dType := range dTypes {
+ for _, op := range ops {
+ expn(w, codeKernelScaleLeafY, &data{
+ dType: dType,
+ op: op,
+ })
+ }
+ }
+ for _, t := range dsTypes {
+ for _, op := range ops {
+ if op == "Over" && alwaysOpaque[t.sType] {
+ continue
+ }
+ expn(w, codeKernelTransformLeaf, &data{
+ dType: t.dType,
+ sType: t.sType,
+ op: op,
+ })
+ }
+ }
+}
+
+func expn(w *bytes.Buffer, code string, d *data) {
+ if d.sType == "*image.YCbCr" && d.sratio == "" {
+ for _, sratio := range subsampleRatios {
+ e := *d
+ e.sratio = sratio
+ expn(w, code, &e)
+ }
+ return
+ }
+
+ for _, line := range strings.Split(code, "\n") {
+ line = expnLine(line, d)
+ if line == ";" {
+ continue
+ }
+ fmt.Fprintln(w, line)
+ }
+}
+
+func expnLine(line string, d *data) string {
+ for {
+ i := strings.IndexByte(line, '$')
+ if i < 0 {
+ break
+ }
+ prefix, s := line[:i], line[i+1:]
+
+ i = len(s)
+ for j, c := range s {
+ if !('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z') {
+ i = j
+ break
+ }
+ }
+ dollar, suffix := s[:i], s[i:]
+
+ e := expnDollar(prefix, dollar, suffix, d)
+ if e == "" {
+ log.Fatalf("couldn't expand %q", line)
+ }
+ line = e
+ }
+ return line
+}
+
+// expnDollar expands a "$foo" fragment in a line of generated code. It returns
+// the empty string if there was a problem. It returns ";" if the generated
+// code is a no-op.
+func expnDollar(prefix, dollar, suffix string, d *data) string {
+ switch dollar {
+ case "dType":
+ return prefix + d.dType + suffix
+ case "dTypeRN":
+ return prefix + relName(d.dType) + suffix
+ case "sratio":
+ return prefix + d.sratio + suffix
+ case "sType":
+ return prefix + d.sType + suffix
+ case "sTypeRN":
+ return prefix + relName(d.sType) + suffix
+ case "receiver":
+ return prefix + d.receiver + suffix
+ case "op":
+ return prefix + d.op + suffix
+
+ case "switch":
+ return expnSwitch("", "", true, suffix)
+ case "switchD":
+ return expnSwitch("", "", false, suffix)
+ case "switchS":
+ return expnSwitch("", "anyDType", false, suffix)
+
+ case "preOuter":
+ switch d.dType {
+ default:
+ return ";"
+ case "Image":
+ s := ""
+ if d.sType == "image.Image" {
+ s = "srcMask, smp := opts.SrcMask, opts.SrcMaskP\n"
+ }
+ return s +
+ "dstMask, dmp := opts.DstMask, opts.DstMaskP\n" +
+ "dstColorRGBA64 := &color.RGBA64{}\n" +
+ "dstColor := color.Color(dstColorRGBA64)"
+ }
+
+ case "preInner":
+ switch d.dType {
+ default:
+ return ";"
+ case "*image.RGBA":
+ return "d := " + pixOffset("dst", "dr.Min.X+adr.Min.X", "dr.Min.Y+int(dy)", "*4", "*dst.Stride")
+ }
+
+ case "preKernelOuter":
+ switch d.sType {
+ default:
+ return ";"
+ case "image.Image":
+ return "srcMask, smp := opts.SrcMask, opts.SrcMaskP"
+ }
+
+ case "preKernelInner":
+ switch d.dType {
+ default:
+ return ";"
+ case "*image.RGBA":
+ return "d := " + pixOffset("dst", "dr.Min.X+int(dx)", "dr.Min.Y+adr.Min.Y", "*4", "*dst.Stride")
+ }
+
+ case "blend":
+ args, _ := splitArgs(suffix)
+ if len(args) != 4 {
+ return ""
+ }
+ switch d.sType {
+ default:
+ return argf(args, ""+
+ "$3r = $0*$1r + $2*$3r\n"+
+ "$3g = $0*$1g + $2*$3g\n"+
+ "$3b = $0*$1b + $2*$3b\n"+
+ "$3a = $0*$1a + $2*$3a",
+ )
+ case "*image.Gray":
+ return argf(args, ""+
+ "$3r = $0*$1r + $2*$3r",
+ )
+ case "*image.YCbCr":
+ return argf(args, ""+
+ "$3r = $0*$1r + $2*$3r\n"+
+ "$3g = $0*$1g + $2*$3g\n"+
+ "$3b = $0*$1b + $2*$3b",
+ )
+ }
+
+ case "clampToAlpha":
+ if alwaysOpaque[d.sType] {
+ return ";"
+ }
+ // Go uses alpha-premultiplied color. The naive computation can lead to
+ // invalid colors, e.g. red > alpha, when some weights are negative.
+ return `
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+ `
+
+ case "convFtou":
+ args, _ := splitArgs(suffix)
+ if len(args) != 2 {
+ return ""
+ }
+
+ switch d.sType {
+ default:
+ return argf(args, ""+
+ "$0r := uint32($1r)\n"+
+ "$0g := uint32($1g)\n"+
+ "$0b := uint32($1b)\n"+
+ "$0a := uint32($1a)",
+ )
+ case "*image.Gray":
+ return argf(args, ""+
+ "$0r := uint32($1r)",
+ )
+ case "*image.YCbCr":
+ return argf(args, ""+
+ "$0r := uint32($1r)\n"+
+ "$0g := uint32($1g)\n"+
+ "$0b := uint32($1b)",
+ )
+ }
+
+ case "outputu":
+ args, _ := splitArgs(suffix)
+ if len(args) != 3 {
+ return ""
+ }
+
+ switch d.op {
+ case "Over":
+ switch d.dType {
+ default:
+ log.Fatalf("bad dType %q", d.dType)
+ case "Image":
+ return argf(args, ""+
+ "qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
+ "if dstMask != nil {\n"+
+ " _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
+ " $2r = $2r * ma / 0xffff\n"+
+ " $2g = $2g * ma / 0xffff\n"+
+ " $2b = $2b * ma / 0xffff\n"+
+ " $2a = $2a * ma / 0xffff\n"+
+ "}\n"+
+ "$2a1 := 0xffff - $2a\n"+
+ "dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\n"+
+ "dstColorRGBA64.G = uint16(qg*$2a1/0xffff + $2g)\n"+
+ "dstColorRGBA64.B = uint16(qb*$2a1/0xffff + $2b)\n"+
+ "dstColorRGBA64.A = uint16(qa*$2a1/0xffff + $2a)\n"+
+ "dst.Set($0, $1, dstColor)",
+ )
+ case "*image.RGBA":
+ return argf(args, ""+
+ "$2a1 := (0xffff - $2a) * 0x101\n"+
+ "dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*$2a1/0xffff + $2r) >> 8)\n"+
+ "dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*$2a1/0xffff + $2g) >> 8)\n"+
+ "dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*$2a1/0xffff + $2b) >> 8)\n"+
+ "dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*$2a1/0xffff + $2a) >> 8)",
+ )
+ }
+
+ case "Src":
+ switch d.dType {
+ default:
+ log.Fatalf("bad dType %q", d.dType)
+ case "Image":
+ return argf(args, ""+
+ "if dstMask != nil {\n"+
+ " qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
+ " _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
+ " pr = pr * ma / 0xffff\n"+
+ " pg = pg * ma / 0xffff\n"+
+ " pb = pb * ma / 0xffff\n"+
+ " pa = pa * ma / 0xffff\n"+
+ " $2a1 := 0xffff - ma\n"+ // Note that this is ma, not $2a.
+ " dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\n"+
+ " dstColorRGBA64.G = uint16(qg*$2a1/0xffff + $2g)\n"+
+ " dstColorRGBA64.B = uint16(qb*$2a1/0xffff + $2b)\n"+
+ " dstColorRGBA64.A = uint16(qa*$2a1/0xffff + $2a)\n"+
+ " dst.Set($0, $1, dstColor)\n"+
+ "} else {\n"+
+ " dstColorRGBA64.R = uint16($2r)\n"+
+ " dstColorRGBA64.G = uint16($2g)\n"+
+ " dstColorRGBA64.B = uint16($2b)\n"+
+ " dstColorRGBA64.A = uint16($2a)\n"+
+ " dst.Set($0, $1, dstColor)\n"+
+ "}",
+ )
+ case "*image.RGBA":
+ switch d.sType {
+ default:
+ return argf(args, ""+
+ "dst.Pix[d+0] = uint8($2r >> 8)\n"+
+ "dst.Pix[d+1] = uint8($2g >> 8)\n"+
+ "dst.Pix[d+2] = uint8($2b >> 8)\n"+
+ "dst.Pix[d+3] = uint8($2a >> 8)",
+ )
+ case "*image.Gray":
+ return argf(args, ""+
+ "out := uint8($2r >> 8)\n"+
+ "dst.Pix[d+0] = out\n"+
+ "dst.Pix[d+1] = out\n"+
+ "dst.Pix[d+2] = out\n"+
+ "dst.Pix[d+3] = 0xff",
+ )
+ case "*image.YCbCr":
+ return argf(args, ""+
+ "dst.Pix[d+0] = uint8($2r >> 8)\n"+
+ "dst.Pix[d+1] = uint8($2g >> 8)\n"+
+ "dst.Pix[d+2] = uint8($2b >> 8)\n"+
+ "dst.Pix[d+3] = 0xff",
+ )
+ }
+ }
+ }
+
+ case "outputf":
+ args, _ := splitArgs(suffix)
+ if len(args) != 5 {
+ return ""
+ }
+ ret := ""
+
+ switch d.op {
+ case "Over":
+ switch d.dType {
+ default:
+ log.Fatalf("bad dType %q", d.dType)
+ case "Image":
+ ret = argf(args, ""+
+ "qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
+ "$3r0 := uint32($2($3r * $4))\n"+
+ "$3g0 := uint32($2($3g * $4))\n"+
+ "$3b0 := uint32($2($3b * $4))\n"+
+ "$3a0 := uint32($2($3a * $4))\n"+
+ "if dstMask != nil {\n"+
+ " _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
+ " $3r0 = $3r0 * ma / 0xffff\n"+
+ " $3g0 = $3g0 * ma / 0xffff\n"+
+ " $3b0 = $3b0 * ma / 0xffff\n"+
+ " $3a0 = $3a0 * ma / 0xffff\n"+
+ "}\n"+
+ "$3a1 := 0xffff - $3a0\n"+
+ "dstColorRGBA64.R = uint16(qr*$3a1/0xffff + $3r0)\n"+
+ "dstColorRGBA64.G = uint16(qg*$3a1/0xffff + $3g0)\n"+
+ "dstColorRGBA64.B = uint16(qb*$3a1/0xffff + $3b0)\n"+
+ "dstColorRGBA64.A = uint16(qa*$3a1/0xffff + $3a0)\n"+
+ "dst.Set($0, $1, dstColor)",
+ )
+ case "*image.RGBA":
+ ret = argf(args, ""+
+ "$3r0 := uint32($2($3r * $4))\n"+
+ "$3g0 := uint32($2($3g * $4))\n"+
+ "$3b0 := uint32($2($3b * $4))\n"+
+ "$3a0 := uint32($2($3a * $4))\n"+
+ "$3a1 := (0xffff - uint32($3a0)) * 0x101\n"+
+ "dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*$3a1/0xffff + $3r0) >> 8)\n"+
+ "dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*$3a1/0xffff + $3g0) >> 8)\n"+
+ "dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*$3a1/0xffff + $3b0) >> 8)\n"+
+ "dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*$3a1/0xffff + $3a0) >> 8)",
+ )
+ }
+
+ case "Src":
+ switch d.dType {
+ default:
+ log.Fatalf("bad dType %q", d.dType)
+ case "Image":
+ ret = argf(args, ""+
+ "if dstMask != nil {\n"+
+ " qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
+ " _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
+ " pr := uint32($2($3r * $4)) * ma / 0xffff\n"+
+ " pg := uint32($2($3g * $4)) * ma / 0xffff\n"+
+ " pb := uint32($2($3b * $4)) * ma / 0xffff\n"+
+ " pa := uint32($2($3a * $4)) * ma / 0xffff\n"+
+ " pa1 := 0xffff - ma\n"+ // Note that this is ma, not pa.
+ " dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)\n"+
+ " dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)\n"+
+ " dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)\n"+
+ " dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)\n"+
+ " dst.Set($0, $1, dstColor)\n"+
+ "} else {\n"+
+ " dstColorRGBA64.R = $2($3r * $4)\n"+
+ " dstColorRGBA64.G = $2($3g * $4)\n"+
+ " dstColorRGBA64.B = $2($3b * $4)\n"+
+ " dstColorRGBA64.A = $2($3a * $4)\n"+
+ " dst.Set($0, $1, dstColor)\n"+
+ "}",
+ )
+ case "*image.RGBA":
+ switch d.sType {
+ default:
+ ret = argf(args, ""+
+ "dst.Pix[d+0] = uint8($2($3r * $4) >> 8)\n"+
+ "dst.Pix[d+1] = uint8($2($3g * $4) >> 8)\n"+
+ "dst.Pix[d+2] = uint8($2($3b * $4) >> 8)\n"+
+ "dst.Pix[d+3] = uint8($2($3a * $4) >> 8)",
+ )
+ case "*image.Gray":
+ ret = argf(args, ""+
+ "out := uint8($2($3r * $4) >> 8)\n"+
+ "dst.Pix[d+0] = out\n"+
+ "dst.Pix[d+1] = out\n"+
+ "dst.Pix[d+2] = out\n"+
+ "dst.Pix[d+3] = 0xff",
+ )
+ case "*image.YCbCr":
+ ret = argf(args, ""+
+ "dst.Pix[d+0] = uint8($2($3r * $4) >> 8)\n"+
+ "dst.Pix[d+1] = uint8($2($3g * $4) >> 8)\n"+
+ "dst.Pix[d+2] = uint8($2($3b * $4) >> 8)\n"+
+ "dst.Pix[d+3] = 0xff",
+ )
+ }
+ }
+ }
+
+ return strings.Replace(ret, " * 1)", ")", -1)
+
+ case "srcf", "srcu":
+ lhs, eqOp := splitEq(prefix)
+ if lhs == "" {
+ return ""
+ }
+ args, extra := splitArgs(suffix)
+ if len(args) != 2 {
+ return ""
+ }
+
+ tmp := ""
+ if dollar == "srcf" {
+ tmp = "u"
+ }
+
+ // TODO: there's no need to multiply by 0x101 in the switch below if
+ // the next thing we're going to do is shift right by 8.
+
+ buf := new(bytes.Buffer)
+ switch d.sType {
+ default:
+ log.Fatalf("bad sType %q", d.sType)
+ case "image.Image":
+ fmt.Fprintf(buf, ""+
+ "%sr%s, %sg%s, %sb%s, %sa%s := src.At(%s, %s).RGBA()\n",
+ lhs, tmp, lhs, tmp, lhs, tmp, lhs, tmp, args[0], args[1],
+ )
+ if d.dType == "" || d.dType == "Image" {
+ fmt.Fprintf(buf, ""+
+ "if srcMask != nil {\n"+
+ " _, _, _, ma := srcMask.At(smp.X+%s, smp.Y+%s).RGBA()\n"+
+ " %sr%s = %sr%s * ma / 0xffff\n"+
+ " %sg%s = %sg%s * ma / 0xffff\n"+
+ " %sb%s = %sb%s * ma / 0xffff\n"+
+ " %sa%s = %sa%s * ma / 0xffff\n"+
+ "}\n",
+ args[0], args[1],
+ lhs, tmp, lhs, tmp,
+ lhs, tmp, lhs, tmp,
+ lhs, tmp, lhs, tmp,
+ lhs, tmp, lhs, tmp,
+ )
+ }
+ case "*image.Gray":
+ fmt.Fprintf(buf, ""+
+ "%si := %s\n"+
+ "%sr%s := uint32(src.Pix[%si]) * 0x101\n",
+ lhs, pixOffset("src", args[0], args[1], "", "*src.Stride"),
+ lhs, tmp, lhs,
+ )
+ case "*image.NRGBA":
+ fmt.Fprintf(buf, ""+
+ "%si := %s\n"+
+ "%sa%s := uint32(src.Pix[%si+3]) * 0x101\n"+
+ "%sr%s := uint32(src.Pix[%si+0]) * %sa%s / 0xff\n"+
+ "%sg%s := uint32(src.Pix[%si+1]) * %sa%s / 0xff\n"+
+ "%sb%s := uint32(src.Pix[%si+2]) * %sa%s / 0xff\n",
+ lhs, pixOffset("src", args[0], args[1], "*4", "*src.Stride"),
+ lhs, tmp, lhs,
+ lhs, tmp, lhs, lhs, tmp,
+ lhs, tmp, lhs, lhs, tmp,
+ lhs, tmp, lhs, lhs, tmp,
+ )
+ case "*image.RGBA":
+ fmt.Fprintf(buf, ""+
+ "%si := %s\n"+
+ "%sr%s := uint32(src.Pix[%si+0]) * 0x101\n"+
+ "%sg%s := uint32(src.Pix[%si+1]) * 0x101\n"+
+ "%sb%s := uint32(src.Pix[%si+2]) * 0x101\n"+
+ "%sa%s := uint32(src.Pix[%si+3]) * 0x101\n",
+ lhs, pixOffset("src", args[0], args[1], "*4", "*src.Stride"),
+ lhs, tmp, lhs,
+ lhs, tmp, lhs,
+ lhs, tmp, lhs,
+ lhs, tmp, lhs,
+ )
+ case "*image.YCbCr":
+ fmt.Fprintf(buf, ""+
+ "%si := %s\n"+
+ "%sj := %s\n"+
+ "%s\n",
+ lhs, pixOffset("src", args[0], args[1], "", "*src.YStride"),
+ lhs, cOffset(args[0], args[1], d.sratio),
+ ycbcrToRGB(lhs, tmp),
+ )
+ }
+
+ if dollar == "srcf" {
+ switch d.sType {
+ default:
+ fmt.Fprintf(buf, ""+
+ "%sr %s float64(%sru)%s\n"+
+ "%sg %s float64(%sgu)%s\n"+
+ "%sb %s float64(%sbu)%s\n"+
+ "%sa %s float64(%sau)%s\n",
+ lhs, eqOp, lhs, extra,
+ lhs, eqOp, lhs, extra,
+ lhs, eqOp, lhs, extra,
+ lhs, eqOp, lhs, extra,
+ )
+ case "*image.Gray":
+ fmt.Fprintf(buf, ""+
+ "%sr %s float64(%sru)%s\n",
+ lhs, eqOp, lhs, extra,
+ )
+ case "*image.YCbCr":
+ fmt.Fprintf(buf, ""+
+ "%sr %s float64(%sru)%s\n"+
+ "%sg %s float64(%sgu)%s\n"+
+ "%sb %s float64(%sbu)%s\n",
+ lhs, eqOp, lhs, extra,
+ lhs, eqOp, lhs, extra,
+ lhs, eqOp, lhs, extra,
+ )
+ }
+ }
+
+ return strings.TrimSpace(buf.String())
+
+ case "tweakD":
+ if d.dType == "*image.RGBA" {
+ return "d += dst.Stride"
+ }
+ return ";"
+
+ case "tweakDx":
+ if d.dType == "*image.RGBA" {
+ return strings.Replace(prefix, "dx++", "dx, d = dx+1, d+4", 1)
+ }
+ return prefix
+
+ case "tweakDy":
+ if d.dType == "*image.RGBA" {
+ return strings.Replace(prefix, "for dy, s", "for _, s", 1)
+ }
+ return prefix
+
+ case "tweakP":
+ switch d.sType {
+ case "*image.Gray":
+ if strings.HasPrefix(strings.TrimSpace(prefix), "pa * ") {
+ return "1,"
+ }
+ return "pr,"
+ case "*image.YCbCr":
+ if strings.HasPrefix(strings.TrimSpace(prefix), "pa * ") {
+ return "1,"
+ }
+ }
+ return prefix
+
+ case "tweakPr":
+ if d.sType == "*image.Gray" {
+ return "pr *= s.invTotalWeightFFFF"
+ }
+ return ";"
+
+ case "tweakVarP":
+ switch d.sType {
+ case "*image.Gray":
+ return strings.Replace(prefix, "var pr, pg, pb, pa", "var pr", 1)
+ case "*image.YCbCr":
+ return strings.Replace(prefix, "var pr, pg, pb, pa", "var pr, pg, pb", 1)
+ }
+ return prefix
+ }
+ return ""
+}
+
+func expnSwitch(op, dType string, expandBoth bool, template string) string {
+ if op == "" && dType != "anyDType" {
+ lines := []string{"switch op {"}
+ for _, op = range ops {
+ lines = append(lines,
+ fmt.Sprintf("case %s:", op),
+ expnSwitch(op, dType, expandBoth, template),
+ )
+ }
+ lines = append(lines, "}")
+ return strings.Join(lines, "\n")
+ }
+
+ switchVar := "dst"
+ if dType != "" {
+ switchVar = "src"
+ }
+ lines := []string{fmt.Sprintf("switch %s := %s.(type) {", switchVar, switchVar)}
+
+ fallback, values := "Image", dTypes
+ if dType != "" {
+ fallback, values = "image.Image", sTypesForDType[dType]
+ }
+ for _, v := range values {
+ if dType != "" {
+ // v is the sType. Skip those always-opaque sTypes, where Over is
+ // equivalent to Src.
+ if op == "Over" && alwaysOpaque[v] {
+ continue
+ }
+ }
+
+ if v == fallback {
+ lines = append(lines, "default:")
+ } else {
+ lines = append(lines, fmt.Sprintf("case %s:", v))
+ }
+
+ if dType != "" {
+ if v == "*image.YCbCr" {
+ lines = append(lines, expnSwitchYCbCr(op, dType, template))
+ } else {
+ lines = append(lines, expnLine(template, &data{dType: dType, sType: v, op: op}))
+ }
+ } else if !expandBoth {
+ lines = append(lines, expnLine(template, &data{dType: v, op: op}))
+ } else {
+ lines = append(lines, expnSwitch(op, v, false, template))
+ }
+ }
+
+ lines = append(lines, "}")
+ return strings.Join(lines, "\n")
+}
+
+func expnSwitchYCbCr(op, dType, template string) string {
+ lines := []string{
+ "switch src.SubsampleRatio {",
+ "default:",
+ expnLine(template, &data{dType: dType, sType: "image.Image", op: op}),
+ }
+ for _, sratio := range subsampleRatios {
+ lines = append(lines,
+ fmt.Sprintf("case image.YCbCrSubsampleRatio%s:", sratio),
+ expnLine(template, &data{dType: dType, sType: "*image.YCbCr", sratio: sratio, op: op}),
+ )
+ }
+ lines = append(lines, "}")
+ return strings.Join(lines, "\n")
+}
+
+func argf(args []string, s string) string {
+ if len(args) > 9 {
+ panic("too many args")
+ }
+ for i, a := range args {
+ old := fmt.Sprintf("$%d", i)
+ s = strings.Replace(s, old, a, -1)
+ }
+ return s
+}
+
+func pixOffset(m, x, y, xstride, ystride string) string {
+ return fmt.Sprintf("(%s-%s.Rect.Min.Y)%s + (%s-%s.Rect.Min.X)%s", y, m, ystride, x, m, xstride)
+}
+
+func cOffset(x, y, sratio string) string {
+ switch sratio {
+ case "444":
+ return fmt.Sprintf("( %s - src.Rect.Min.Y )*src.CStride + ( %s - src.Rect.Min.X )", y, x)
+ case "422":
+ return fmt.Sprintf("( %s - src.Rect.Min.Y )*src.CStride + ((%s)/2 - src.Rect.Min.X/2)", y, x)
+ case "420":
+ return fmt.Sprintf("((%s)/2 - src.Rect.Min.Y/2)*src.CStride + ((%s)/2 - src.Rect.Min.X/2)", y, x)
+ case "440":
+ return fmt.Sprintf("((%s)/2 - src.Rect.Min.Y/2)*src.CStride + ( %s - src.Rect.Min.X )", y, x)
+ }
+ return fmt.Sprintf("unsupported sratio %q", sratio)
+}
+
+func ycbcrToRGB(lhs, tmp string) string {
+ s := `
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ $yy1 := int(src.Y[$i]) * 0x10101
+ $cb1 := int(src.Cb[$j]) - 128
+ $cr1 := int(src.Cr[$j]) - 128
+ $r@ := ($yy1 + 91881*$cr1) >> 8
+ $g@ := ($yy1 - 22554*$cb1 - 46802*$cr1) >> 8
+ $b@ := ($yy1 + 116130*$cb1) >> 8
+ if $r@ < 0 {
+ $r@ = 0
+ } else if $r@ > 0xffff {
+ $r@ = 0xffff
+ }
+ if $g@ < 0 {
+ $g@ = 0
+ } else if $g@ > 0xffff {
+ $g@ = 0xffff
+ }
+ if $b@ < 0 {
+ $b@ = 0
+ } else if $b@ > 0xffff {
+ $b@ = 0xffff
+ }
+ `
+ s = strings.Replace(s, "$", lhs, -1)
+ s = strings.Replace(s, "@", tmp, -1)
+ return s
+}
+
+func split(s, sep string) (string, string) {
+ if i := strings.Index(s, sep); i >= 0 {
+ return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):])
+ }
+ return "", ""
+}
+
+func splitEq(s string) (lhs, eqOp string) {
+ s = strings.TrimSpace(s)
+ if lhs, _ = split(s, ":="); lhs != "" {
+ return lhs, ":="
+ }
+ if lhs, _ = split(s, "+="); lhs != "" {
+ return lhs, "+="
+ }
+ return "", ""
+}
+
+func splitArgs(s string) (args []string, extra string) {
+ s = strings.TrimSpace(s)
+ if s == "" || s[0] != '[' {
+ return nil, ""
+ }
+ s = s[1:]
+
+ i := strings.IndexByte(s, ']')
+ if i < 0 {
+ return nil, ""
+ }
+ args, extra = strings.Split(s[:i], ","), s[i+1:]
+ for i := range args {
+ args[i] = strings.TrimSpace(args[i])
+ }
+ return args, extra
+}
+
+func relName(s string) string {
+ if i := strings.LastIndex(s, "."); i >= 0 {
+ return s[i+1:]
+ }
+ return s
+}
+
+const (
+ codeRoot = `
+ func (z $receiver) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ // Try to simplify a Scale to a Copy when DstMask is not specified.
+ // If DstMask is not nil, Copy will call Scale back with same dr and sr, and cause stack overflow.
+ if dr.Size() == sr.Size() && (opts == nil || opts.DstMask == nil) {
+ Copy(dst, dr.Min, src, sr, op, opts)
+ return
+ }
+
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
+ switch op {
+ case Over:
+ z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
+ case Src:
+ z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
+ }
+ } else if _, ok := src.(*image.Uniform); ok {
+ Draw(dst, dr, src, src.Bounds().Min, op)
+ } else {
+ $switch z.scale_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, src, sr, &o)
+ }
+ }
+
+ func (z $receiver) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ // Try to simplify a Transform to a Copy.
+ if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 {
+ dx := int(s2d[2])
+ dy := int(s2d[5])
+ if float64(dx) == s2d[2] && float64(dy) == s2d[5] {
+ Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts)
+ return
+ }
+ }
+
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ dr := transformRect(&s2d, &sr)
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+
+ d2s := invert(&s2d)
+ // bias is a translation of the mapping from dst coordinates to src
+ // coordinates such that the latter temporarily have non-negative X
+ // and Y coordinates. This allows us to write int(f) instead of
+ // int(math.Floor(f)), since "round to zero" and "round down" are
+ // equivalent when f >= 0, but the former is much cheaper. The X--
+ // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
+ // adjustment.
+ bias := transformRect(&d2s, &adr).Min
+ bias.X--
+ bias.Y--
+ d2s[2] -= float64(bias.X)
+ d2s[5] -= float64(bias.Y)
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
+ switch op {
+ case Over:
+ z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case Src:
+ z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ } else if u, ok := src.(*image.Uniform); ok {
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
+ } else {
+ $switch z.transform_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ }
+ `
+
+ codeNNScaleLeaf = `
+ func (nnInterpolator) scale_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, src $sType, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ $preOuter
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ $preInner
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ p := $srcu[sr.Min.X + int(sx), sr.Min.Y + int(sy)]
+ $outputu[dr.Min.X + int(dx), dr.Min.Y + int(dy), p]
+ }
+ }
+ }
+ `
+
+ codeNNTransformLeaf = `
+ func (nnInterpolator) transform_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle, bias image.Point, opts *Options) {
+ $preOuter
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y + int(dy)) + 0.5
+ $preInner
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
+ dxf := float64(dr.Min.X + int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf + d2s[1]*dyf + d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf + d2s[4]*dyf + d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ p := $srcu[sx0, sy0]
+ $outputu[dr.Min.X + int(dx), dr.Min.Y + int(dy), p]
+ }
+ }
+ }
+ `
+
+ codeABLScaleLeaf = `
+ func (ablInterpolator) scale_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, src $sType, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw - 1, sh - 1
+ $preOuter
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ $preInner
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00 := $srcf[sr.Min.X + int(sx0), sr.Min.Y + int(sy0)]
+ s10 := $srcf[sr.Min.X + int(sx1), sr.Min.Y + int(sy0)]
+ $blend[xFrac1, s00, xFrac0, s10]
+ s01 := $srcf[sr.Min.X + int(sx0), sr.Min.Y + int(sy1)]
+ s11 := $srcf[sr.Min.X + int(sx1), sr.Min.Y + int(sy1)]
+ $blend[xFrac1, s01, xFrac0, s11]
+ $blend[yFrac1, s10, yFrac0, s11]
+ $convFtou[p, s11]
+ $outputu[dr.Min.X + int(dx), dr.Min.Y + int(dy), p]
+ }
+ }
+ }
+ `
+
+ codeABLTransformLeaf = `
+ func (ablInterpolator) transform_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle, bias image.Point, opts *Options) {
+ $preOuter
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y + int(dy)) + 0.5
+ $preInner
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
+ dxf := float64(dr.Min.X + int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00 := $srcf[sx0, sy0]
+ s10 := $srcf[sx1, sy0]
+ $blend[xFrac1, s00, xFrac0, s10]
+ s01 := $srcf[sx0, sy1]
+ s11 := $srcf[sx1, sy1]
+ $blend[xFrac1, s01, xFrac0, s11]
+ $blend[yFrac1, s10, yFrac0, s11]
+ $convFtou[p, s11]
+ $outputu[dr.Min.X + int(dx), dr.Min.Y + int(dy), p]
+ }
+ }
+ }
+ `
+
+ codeKernelRoot = `
+ func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ if z.dw != int32(dr.Dx()) || z.dh != int32(dr.Dy()) || z.sw != int32(sr.Dx()) || z.sh != int32(sr.Dy()) {
+ z.kernel.Scale(dst, dr, src, sr, op, opts)
+ return
+ }
+
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+
+ if _, ok := src.(*image.Uniform); ok && o.DstMask == nil && o.SrcMask == nil && sr.In(src.Bounds()) {
+ Draw(dst, dr, src, src.Bounds().Min, op)
+ return
+ }
+
+ // Create a temporary buffer:
+ // scaleX distributes the source image's columns over the temporary image.
+ // scaleY distributes the temporary image's rows over the destination image.
+ var tmp [][4]float64
+ if z.pool.New != nil {
+ tmpp := z.pool.Get().(*[][4]float64)
+ defer z.pool.Put(tmpp)
+ tmp = *tmpp
+ } else {
+ tmp = z.makeTmpBuf()
+ }
+
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.SrcMask != nil || !sr.In(src.Bounds()) {
+ z.scaleX_Image(tmp, src, sr, &o)
+ } else {
+ $switchS z.scaleX_$sTypeRN$sratio(tmp, src, sr, &o)
+ }
+
+ if o.DstMask != nil {
+ switch op {
+ case Over:
+ z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
+ case Src:
+ z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
+ }
+ } else {
+ $switchD z.scaleY_$dTypeRN_$op(dst, dr, adr, tmp, &o)
+ }
+ }
+
+ func (q *Kernel) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ dr := transformRect(&s2d, &sr)
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+ d2s := invert(&s2d)
+ // bias is a translation of the mapping from dst coordinates to src
+ // coordinates such that the latter temporarily have non-negative X
+ // and Y coordinates. This allows us to write int(f) instead of
+ // int(math.Floor(f)), since "round to zero" and "round down" are
+ // equivalent when f >= 0, but the former is much cheaper. The X--
+ // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
+ // adjustment.
+ bias := transformRect(&d2s, &adr).Min
+ bias.X--
+ bias.Y--
+ d2s[2] -= float64(bias.X)
+ d2s[5] -= float64(bias.Y)
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+
+ if u, ok := src.(*image.Uniform); ok && o.DstMask != nil && o.SrcMask != nil && sr.In(src.Bounds()) {
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
+ return
+ }
+
+ xscale := abs(d2s[0])
+ if s := abs(d2s[1]); xscale < s {
+ xscale = s
+ }
+ yscale := abs(d2s[3])
+ if s := abs(d2s[4]); yscale < s {
+ yscale = s
+ }
+
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
+ switch op {
+ case Over:
+ q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case Src:
+ q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ }
+ } else {
+ $switch q.transform_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ }
+ }
+ `
+
+ codeKernelScaleLeafX = `
+ func (z *kernelScaler) scaleX_$sTypeRN$sratio(tmp [][4]float64, src $sType, sr image.Rectangle, opts *Options) {
+ t := 0
+ $preKernelOuter
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb, pa float64 $tweakVarP
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ p += $srcf[sr.Min.X + int(c.coord), sr.Min.Y + int(y)] * c.weight
+ }
+ $tweakPr
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF, $tweakP
+ pg * s.invTotalWeightFFFF, $tweakP
+ pb * s.invTotalWeightFFFF, $tweakP
+ pa * s.invTotalWeightFFFF, $tweakP
+ }
+ t++
+ }
+ }
+ }
+ `
+
+ codeKernelScaleLeafY = `
+ func (z *kernelScaler) scaleY_$dTypeRN_$op(dst $dType, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
+ $preOuter
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ $preKernelInner
+ for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] { $tweakDy
+ var pr, pg, pb, pa float64
+ for _, c := range z.vertical.contribs[s.i:s.j] {
+ p := &tmp[c.coord*z.dw+dx]
+ pr += p[0] * c.weight
+ pg += p[1] * c.weight
+ pb += p[2] * c.weight
+ pa += p[3] * c.weight
+ }
+ $clampToAlpha
+ $outputf[dr.Min.X + int(dx), dr.Min.Y + int(adr.Min.Y + dy), ftou, p, s.invTotalWeight]
+ $tweakD
+ }
+ }
+ }
+ `
+
+ codeKernelTransformLeaf = `
+ func (q *Kernel) transform_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1 + 2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1 + 2*int(math.Ceil(yHalfWidth)))
+
+ $preOuter
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y + int(dy)) + 0.5
+ $preInner
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
+ dxf := float64(dr.Min.X + int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx - ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky - iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb, pa float64 $tweakVarP
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky - iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx - ix] * yWeight; w != 0 {
+ p += $srcf[kx, ky] * w
+ }
+ }
+ }
+ }
+ $clampToAlpha
+ $outputf[dr.Min.X + int(dx), dr.Min.Y + int(dy), fffftou, p, 1]
+ }
+ }
+ }
+ `
+)
diff --git a/vendor/golang.org/x/image/draw/go1_8.go b/vendor/golang.org/x/image/draw/go1_8.go
new file mode 100644
index 0000000..ec192b7
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/go1_8.go
@@ -0,0 +1,49 @@
+// Copyright 2015 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.9,!go1.8.typealias
+
+package draw
+
+import (
+ "image"
+ "image/color"
+ "image/draw"
+)
+
+// Drawer contains the Draw method.
+type Drawer interface {
+ // Draw aligns r.Min in dst with sp in src and then replaces the
+ // rectangle r in dst with the result of drawing src on dst.
+ Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
+}
+
+// Image is an image.Image with a Set method to change a single pixel.
+type Image interface {
+ image.Image
+ Set(x, y int, c color.Color)
+}
+
+// Op is a Porter-Duff compositing operator.
+type Op int
+
+const (
+ // Over specifies ``(src in mask) over dst''.
+ Over Op = Op(draw.Over)
+ // Src specifies ``src in mask''.
+ Src Op = Op(draw.Src)
+)
+
+// Draw implements the Drawer interface by calling the Draw function with
+// this Op.
+func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
+ (draw.Op(op)).Draw(dst, r, src, sp)
+}
+
+// Quantizer produces a palette for an image.
+type Quantizer interface {
+ // Quantize appends up to cap(p) - len(p) colors to p and returns the
+ // updated palette suitable for converting m to a paletted image.
+ Quantize(p color.Palette, m image.Image) color.Palette
+}
diff --git a/vendor/golang.org/x/image/draw/go1_9.go b/vendor/golang.org/x/image/draw/go1_9.go
new file mode 100644
index 0000000..fc548e9
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/go1_9.go
@@ -0,0 +1,57 @@
+// 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.
+
+// +build go1.9 go1.8.typealias
+
+package draw
+
+import (
+ "image/draw"
+)
+
+// We use type aliases (new in Go 1.9) for the exported names from the standard
+// library's image/draw package. This is not merely syntactic sugar for
+//
+// type Drawer draw.Drawer
+//
+// as aliasing means that the types in this package, such as draw.Image and
+// draw.Op, are identical to the corresponding draw.Image and draw.Op types in
+// the standard library. In comparison, prior to Go 1.9, the code in go1_8.go
+// defines new types that mimic the old but are different types.
+//
+// The package documentation, in draw.go, explicitly gives the intent of this
+// package:
+//
+// This package is a superset of and a drop-in replacement for the
+// image/draw package in the standard library.
+//
+// Drop-in replacement means that I can replace all of my "image/draw" imports
+// with "golang.org/x/image/draw", to access additional features in this
+// package, and no further changes are required. That's mostly true, but not
+// completely true unless we use type aliases.
+//
+// Without type aliases, users might need to import both "image/draw" and
+// "golang.org/x/image/draw" in order to convert from two conceptually
+// equivalent but different (from the compiler's point of view) types, such as
+// from one draw.Op type to another draw.Op type, to satisfy some other
+// interface or function signature.
+
+// Drawer contains the Draw method.
+type Drawer = draw.Drawer
+
+// Image is an image.Image with a Set method to change a single pixel.
+type Image = draw.Image
+
+// Op is a Porter-Duff compositing operator.
+type Op = draw.Op
+
+const (
+ // Over specifies ``(src in mask) over dst''.
+ Over Op = draw.Over
+ // Src specifies ``src in mask''.
+ Src Op = draw.Src
+)
+
+// Quantizer produces a palette for an image.
+type Quantizer = draw.Quantizer
diff --git a/vendor/golang.org/x/image/draw/impl.go b/vendor/golang.org/x/image/draw/impl.go
new file mode 100644
index 0000000..75498ad
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/impl.go
@@ -0,0 +1,6670 @@
+// generated by "go run gen.go". DO NOT EDIT.
+
+package draw
+
+import (
+ "image"
+ "image/color"
+ "math"
+
+ "golang.org/x/image/math/f64"
+)
+
+func (z nnInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ // Try to simplify a Scale to a Copy when DstMask is not specified.
+ // If DstMask is not nil, Copy will call Scale back with same dr and sr, and cause stack overflow.
+ if dr.Size() == sr.Size() && (opts == nil || opts.DstMask == nil) {
+ Copy(dst, dr.Min, src, sr, op, opts)
+ return
+ }
+
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
+ switch op {
+ case Over:
+ z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
+ case Src:
+ z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
+ }
+ } else if _, ok := src.(*image.Uniform); ok {
+ Draw(dst, dr, src, src.Bounds().Min, op)
+ } else {
+ switch op {
+ case Over:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.NRGBA:
+ z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr, &o)
+ case *image.RGBA:
+ z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr, &o)
+ default:
+ z.scale_RGBA_Image_Over(dst, dr, adr, src, sr, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
+ }
+ }
+ case Src:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.Gray:
+ z.scale_RGBA_Gray_Src(dst, dr, adr, src, sr, &o)
+ case *image.NRGBA:
+ z.scale_RGBA_NRGBA_Src(dst, dr, adr, src, sr, &o)
+ case *image.RGBA:
+ z.scale_RGBA_RGBA_Src(dst, dr, adr, src, sr, &o)
+ case *image.YCbCr:
+ switch src.SubsampleRatio {
+ default:
+ z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
+ case image.YCbCrSubsampleRatio444:
+ z.scale_RGBA_YCbCr444_Src(dst, dr, adr, src, sr, &o)
+ case image.YCbCrSubsampleRatio422:
+ z.scale_RGBA_YCbCr422_Src(dst, dr, adr, src, sr, &o)
+ case image.YCbCrSubsampleRatio420:
+ z.scale_RGBA_YCbCr420_Src(dst, dr, adr, src, sr, &o)
+ case image.YCbCrSubsampleRatio440:
+ z.scale_RGBA_YCbCr440_Src(dst, dr, adr, src, sr, &o)
+ }
+ default:
+ z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
+ }
+ }
+ }
+ }
+}
+
+func (z nnInterpolator) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ // Try to simplify a Transform to a Copy.
+ if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 {
+ dx := int(s2d[2])
+ dy := int(s2d[5])
+ if float64(dx) == s2d[2] && float64(dy) == s2d[5] {
+ Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts)
+ return
+ }
+ }
+
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ dr := transformRect(&s2d, &sr)
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+
+ d2s := invert(&s2d)
+ // bias is a translation of the mapping from dst coordinates to src
+ // coordinates such that the latter temporarily have non-negative X
+ // and Y coordinates. This allows us to write int(f) instead of
+ // int(math.Floor(f)), since "round to zero" and "round down" are
+ // equivalent when f >= 0, but the former is much cheaper. The X--
+ // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
+ // adjustment.
+ bias := transformRect(&d2s, &adr).Min
+ bias.X--
+ bias.Y--
+ d2s[2] -= float64(bias.X)
+ d2s[5] -= float64(bias.Y)
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
+ switch op {
+ case Over:
+ z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case Src:
+ z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ } else if u, ok := src.(*image.Uniform); ok {
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
+ } else {
+ switch op {
+ case Over:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.NRGBA:
+ z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case *image.RGBA:
+ z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ default:
+ z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ }
+ case Src:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.Gray:
+ z.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case *image.NRGBA:
+ z.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case *image.RGBA:
+ z.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case *image.YCbCr:
+ switch src.SubsampleRatio {
+ default:
+ z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case image.YCbCrSubsampleRatio444:
+ z.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case image.YCbCrSubsampleRatio422:
+ z.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case image.YCbCrSubsampleRatio420:
+ z.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case image.YCbCrSubsampleRatio440:
+ z.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ default:
+ z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ }
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx) - src.Rect.Min.X)
+ pr := uint32(src.Pix[pi]) * 0x101
+ out := uint8(pr >> 8)
+ dst.Pix[d+0] = out
+ dst.Pix[d+1] = out
+ dst.Pix[d+2] = out
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
+ pa := uint32(src.Pix[pi+3]) * 0x101
+ pr := uint32(src.Pix[pi+0]) * pa / 0xff
+ pg := uint32(src.Pix[pi+1]) * pa / 0xff
+ pb := uint32(src.Pix[pi+2]) * pa / 0xff
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
+ pa := uint32(src.Pix[pi+3]) * 0x101
+ pr := uint32(src.Pix[pi+0]) * pa / 0xff
+ pg := uint32(src.Pix[pi+1]) * pa / 0xff
+ pb := uint32(src.Pix[pi+2]) * pa / 0xff
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
+ pr := uint32(src.Pix[pi+0]) * 0x101
+ pg := uint32(src.Pix[pi+1]) * 0x101
+ pb := uint32(src.Pix[pi+2]) * 0x101
+ pa := uint32(src.Pix[pi+3]) * 0x101
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
+ pr := uint32(src.Pix[pi+0]) * 0x101
+ pg := uint32(src.Pix[pi+1]) * 0x101
+ pb := uint32(src.Pix[pi+2]) * 0x101
+ pa := uint32(src.Pix[pi+3]) * 0x101
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
+ pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pr := (pyy1 + 91881*pcr1) >> 8
+ pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pb := (pyy1 + 116130*pcb1) >> 8
+ if pr < 0 {
+ pr = 0
+ } else if pr > 0xffff {
+ pr = 0xffff
+ }
+ if pg < 0 {
+ pg = 0
+ } else if pg > 0xffff {
+ pg = 0xffff
+ }
+ if pb < 0 {
+ pb = 0
+ } else if pb > 0xffff {
+ pb = 0xffff
+ }
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
+ pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pr := (pyy1 + 91881*pcr1) >> 8
+ pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pb := (pyy1 + 116130*pcb1) >> 8
+ if pr < 0 {
+ pr = 0
+ } else if pr > 0xffff {
+ pr = 0xffff
+ }
+ if pg < 0 {
+ pg = 0
+ } else if pg > 0xffff {
+ pg = 0xffff
+ }
+ if pb < 0 {
+ pb = 0
+ } else if pb > 0xffff {
+ pb = 0xffff
+ }
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
+ pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pr := (pyy1 + 91881*pcr1) >> 8
+ pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pb := (pyy1 + 116130*pcb1) >> 8
+ if pr < 0 {
+ pr = 0
+ } else if pr > 0xffff {
+ pr = 0xffff
+ }
+ if pg < 0 {
+ pg = 0
+ } else if pg > 0xffff {
+ pg = 0xffff
+ }
+ if pb < 0 {
+ pb = 0
+ } else if pb > 0xffff {
+ pb = 0xffff
+ }
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
+ pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pr := (pyy1 + 91881*pcr1) >> 8
+ pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pb := (pyy1 + 116130*pcb1) >> 8
+ if pr < 0 {
+ pr = 0
+ } else if pr > 0xffff {
+ pr = 0xffff
+ }
+ if pg < 0 {
+ pg = 0
+ } else if pg > 0xffff {
+ pg = 0xffff
+ }
+ if pb < 0 {
+ pb = 0
+ } else if pb > 0xffff {
+ pb = 0xffff
+ }
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ }
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ if dstMask != nil {
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ }
+ pa1 := 0xffff - pa
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+}
+
+func (nnInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
+ dw2 := uint64(dr.Dx()) * 2
+ dh2 := uint64(dr.Dy()) * 2
+ sw := uint64(sr.Dx())
+ sh := uint64(sr.Dy())
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (2*uint64(dy) + 1) * sh / dh2
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ sx := (2*uint64(dx) + 1) * sw / dw2
+ pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ }
+ if dstMask != nil {
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ pa1 := 0xffff - ma
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ } else {
+ dstColorRGBA64.R = uint16(pr)
+ dstColorRGBA64.G = uint16(pg)
+ dstColorRGBA64.B = uint16(pb)
+ dstColorRGBA64.A = uint16(pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
+ pr := uint32(src.Pix[pi]) * 0x101
+ out := uint8(pr >> 8)
+ dst.Pix[d+0] = out
+ dst.Pix[d+1] = out
+ dst.Pix[d+2] = out
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ pa := uint32(src.Pix[pi+3]) * 0x101
+ pr := uint32(src.Pix[pi+0]) * pa / 0xff
+ pg := uint32(src.Pix[pi+1]) * pa / 0xff
+ pb := uint32(src.Pix[pi+2]) * pa / 0xff
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ pa := uint32(src.Pix[pi+3]) * 0x101
+ pr := uint32(src.Pix[pi+0]) * pa / 0xff
+ pg := uint32(src.Pix[pi+1]) * pa / 0xff
+ pb := uint32(src.Pix[pi+2]) * pa / 0xff
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ pr := uint32(src.Pix[pi+0]) * 0x101
+ pg := uint32(src.Pix[pi+1]) * 0x101
+ pb := uint32(src.Pix[pi+2]) * 0x101
+ pa := uint32(src.Pix[pi+3]) * 0x101
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ pr := uint32(src.Pix[pi+0]) * 0x101
+ pg := uint32(src.Pix[pi+1]) * 0x101
+ pb := uint32(src.Pix[pi+2]) * 0x101
+ pa := uint32(src.Pix[pi+3]) * 0x101
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ pj := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pr := (pyy1 + 91881*pcr1) >> 8
+ pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pb := (pyy1 + 116130*pcb1) >> 8
+ if pr < 0 {
+ pr = 0
+ } else if pr > 0xffff {
+ pr = 0xffff
+ }
+ if pg < 0 {
+ pg = 0
+ } else if pg > 0xffff {
+ pg = 0xffff
+ }
+ if pb < 0 {
+ pb = 0
+ } else if pb > 0xffff {
+ pb = 0xffff
+ }
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ pj := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pr := (pyy1 + 91881*pcr1) >> 8
+ pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pb := (pyy1 + 116130*pcb1) >> 8
+ if pr < 0 {
+ pr = 0
+ } else if pr > 0xffff {
+ pr = 0xffff
+ }
+ if pg < 0 {
+ pg = 0
+ } else if pg > 0xffff {
+ pg = 0xffff
+ }
+ if pb < 0 {
+ pb = 0
+ } else if pb > 0xffff {
+ pb = 0xffff
+ }
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pr := (pyy1 + 91881*pcr1) >> 8
+ pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pb := (pyy1 + 116130*pcb1) >> 8
+ if pr < 0 {
+ pr = 0
+ } else if pr > 0xffff {
+ pr = 0xffff
+ }
+ if pg < 0 {
+ pg = 0
+ } else if pg > 0xffff {
+ pg = 0xffff
+ }
+ if pb < 0 {
+ pb = 0
+ } else if pb > 0xffff {
+ pb = 0xffff
+ }
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pr := (pyy1 + 91881*pcr1) >> 8
+ pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pb := (pyy1 + 116130*pcb1) >> 8
+ if pr < 0 {
+ pr = 0
+ } else if pr > 0xffff {
+ pr = 0xffff
+ }
+ if pg < 0 {
+ pg = 0
+ } else if pg > 0xffff {
+ pg = 0xffff
+ }
+ if pb < 0 {
+ pb = 0
+ } else if pb > 0xffff {
+ pb = 0xffff
+ }
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (nnInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ }
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ if dstMask != nil {
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ }
+ pa1 := 0xffff - pa
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+}
+
+func (nnInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ }
+ if dstMask != nil {
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ pa1 := 0xffff - ma
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ } else {
+ dstColorRGBA64.R = uint16(pr)
+ dstColorRGBA64.G = uint16(pg)
+ dstColorRGBA64.B = uint16(pb)
+ dstColorRGBA64.A = uint16(pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+ }
+}
+
+func (z ablInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ // Try to simplify a Scale to a Copy when DstMask is not specified.
+ // If DstMask is not nil, Copy will call Scale back with same dr and sr, and cause stack overflow.
+ if dr.Size() == sr.Size() && (opts == nil || opts.DstMask == nil) {
+ Copy(dst, dr.Min, src, sr, op, opts)
+ return
+ }
+
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
+ switch op {
+ case Over:
+ z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
+ case Src:
+ z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
+ }
+ } else if _, ok := src.(*image.Uniform); ok {
+ Draw(dst, dr, src, src.Bounds().Min, op)
+ } else {
+ switch op {
+ case Over:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.NRGBA:
+ z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr, &o)
+ case *image.RGBA:
+ z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr, &o)
+ default:
+ z.scale_RGBA_Image_Over(dst, dr, adr, src, sr, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
+ }
+ }
+ case Src:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.Gray:
+ z.scale_RGBA_Gray_Src(dst, dr, adr, src, sr, &o)
+ case *image.NRGBA:
+ z.scale_RGBA_NRGBA_Src(dst, dr, adr, src, sr, &o)
+ case *image.RGBA:
+ z.scale_RGBA_RGBA_Src(dst, dr, adr, src, sr, &o)
+ case *image.YCbCr:
+ switch src.SubsampleRatio {
+ default:
+ z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
+ case image.YCbCrSubsampleRatio444:
+ z.scale_RGBA_YCbCr444_Src(dst, dr, adr, src, sr, &o)
+ case image.YCbCrSubsampleRatio422:
+ z.scale_RGBA_YCbCr422_Src(dst, dr, adr, src, sr, &o)
+ case image.YCbCrSubsampleRatio420:
+ z.scale_RGBA_YCbCr420_Src(dst, dr, adr, src, sr, &o)
+ case image.YCbCrSubsampleRatio440:
+ z.scale_RGBA_YCbCr440_Src(dst, dr, adr, src, sr, &o)
+ }
+ default:
+ z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
+ }
+ }
+ }
+ }
+}
+
+func (z ablInterpolator) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ // Try to simplify a Transform to a Copy.
+ if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 {
+ dx := int(s2d[2])
+ dy := int(s2d[5])
+ if float64(dx) == s2d[2] && float64(dy) == s2d[5] {
+ Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts)
+ return
+ }
+ }
+
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ dr := transformRect(&s2d, &sr)
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+
+ d2s := invert(&s2d)
+ // bias is a translation of the mapping from dst coordinates to src
+ // coordinates such that the latter temporarily have non-negative X
+ // and Y coordinates. This allows us to write int(f) instead of
+ // int(math.Floor(f)), since "round to zero" and "round down" are
+ // equivalent when f >= 0, but the former is much cheaper. The X--
+ // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
+ // adjustment.
+ bias := transformRect(&d2s, &adr).Min
+ bias.X--
+ bias.Y--
+ d2s[2] -= float64(bias.X)
+ d2s[5] -= float64(bias.Y)
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
+ switch op {
+ case Over:
+ z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case Src:
+ z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ } else if u, ok := src.(*image.Uniform); ok {
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
+ } else {
+ switch op {
+ case Over:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.NRGBA:
+ z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case *image.RGBA:
+ z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ default:
+ z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ }
+ case Src:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.Gray:
+ z.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case *image.NRGBA:
+ z.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case *image.RGBA:
+ z.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case *image.YCbCr:
+ switch src.SubsampleRatio {
+ default:
+ z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case image.YCbCrSubsampleRatio444:
+ z.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case image.YCbCrSubsampleRatio422:
+ z.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case image.YCbCrSubsampleRatio420:
+ z.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ case image.YCbCrSubsampleRatio440:
+ z.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ default:
+ z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
+ }
+ }
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s00ru := uint32(src.Pix[s00i]) * 0x101
+ s00r := float64(s00ru)
+ s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s10ru := uint32(src.Pix[s10i]) * 0x101
+ s10r := float64(s10ru)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s01ru := uint32(src.Pix[s01i]) * 0x101
+ s01r := float64(s01ru)
+ s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s11ru := uint32(src.Pix[s11i]) * 0x101
+ s11r := float64(s11ru)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11r = yFrac1*s10r + yFrac0*s11r
+ pr := uint32(s11r)
+ out := uint8(pr >> 8)
+ dst.Pix[d+0] = out
+ dst.Pix[d+1] = out
+ dst.Pix[d+2] = out
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
+ s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
+ s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
+ s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
+ s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
+ s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
+ s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
+ s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
+ s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
+ s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
+ s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
+ s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
+ s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
+ s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
+ s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
+ s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
+ s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
+ s00ru := uint32(src.Pix[s00i+0]) * 0x101
+ s00gu := uint32(src.Pix[s00i+1]) * 0x101
+ s00bu := uint32(src.Pix[s00i+2]) * 0x101
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
+ s10ru := uint32(src.Pix[s10i+0]) * 0x101
+ s10gu := uint32(src.Pix[s10i+1]) * 0x101
+ s10bu := uint32(src.Pix[s10i+2]) * 0x101
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
+ s01ru := uint32(src.Pix[s01i+0]) * 0x101
+ s01gu := uint32(src.Pix[s01i+1]) * 0x101
+ s01bu := uint32(src.Pix[s01i+2]) * 0x101
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
+ s11ru := uint32(src.Pix[s11i+0]) * 0x101
+ s11gu := uint32(src.Pix[s11i+1]) * 0x101
+ s11bu := uint32(src.Pix[s11i+2]) * 0x101
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
+ s00ru := uint32(src.Pix[s00i+0]) * 0x101
+ s00gu := uint32(src.Pix[s00i+1]) * 0x101
+ s00bu := uint32(src.Pix[s00i+2]) * 0x101
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
+ s10ru := uint32(src.Pix[s10i+0]) * 0x101
+ s10gu := uint32(src.Pix[s10i+1]) * 0x101
+ s10bu := uint32(src.Pix[s10i+2]) * 0x101
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
+ s01ru := uint32(src.Pix[s01i+0]) * 0x101
+ s01gu := uint32(src.Pix[s01i+1]) * 0x101
+ s01bu := uint32(src.Pix[s01i+2]) * 0x101
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
+ s11ru := uint32(src.Pix[s11i+0]) * 0x101
+ s11gu := uint32(src.Pix[s11i+1]) * 0x101
+ s11bu := uint32(src.Pix[s11i+2]) * 0x101
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i]) * 0x10101
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
+ }
+
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i]) * 0x10101
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i]) * 0x10101
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i]) * 0x10101
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
+ }
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
+ }
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
+ }
+
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i]) * 0x10101
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
+ }
+
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i]) * 0x10101
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i]) * 0x10101
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i]) * 0x10101
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
+ }
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
+ }
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
+ }
+
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i]) * 0x10101
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
+ }
+
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i]) * 0x10101
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i]) * 0x10101
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i]) * 0x10101
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
+ }
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
+ }
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
+ }
+
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i]) * 0x10101
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
+ }
+
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i]) * 0x10101
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+ s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i]) * 0x10101
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+ s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i]) * 0x10101
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
+ }
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
+ }
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
+ }
+
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA()
+ s00ru = s00ru * ma / 0xffff
+ s00gu = s00gu * ma / 0xffff
+ s00bu = s00bu * ma / 0xffff
+ s00au = s00au * ma / 0xffff
+ }
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA()
+ s10ru = s10ru * ma / 0xffff
+ s10gu = s10gu * ma / 0xffff
+ s10bu = s10bu * ma / 0xffff
+ s10au = s10au * ma / 0xffff
+ }
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA()
+ s01ru = s01ru * ma / 0xffff
+ s01gu = s01gu * ma / 0xffff
+ s01bu = s01bu * ma / 0xffff
+ s01au = s01au * ma / 0xffff
+ }
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA()
+ s11ru = s11ru * ma / 0xffff
+ s11gu = s11gu * ma / 0xffff
+ s11bu = s11bu * ma / 0xffff
+ s11au = s11au * ma / 0xffff
+ }
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ if dstMask != nil {
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ }
+ pa1 := 0xffff - pa
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+}
+
+func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
+ sw := int32(sr.Dx())
+ sh := int32(sr.Dy())
+ yscale := float64(sh) / float64(dr.Dy())
+ xscale := float64(sw) / float64(dr.Dx())
+ swMinus1, shMinus1 := sw-1, sh-1
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ sy := (float64(dy)+0.5)*yscale - 0.5
+ // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
+ // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
+ // sx, below.
+ sy0 := int32(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy1 := sy0 + 1
+ if sy < 0 {
+ sy0, sy1 = 0, 0
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 > shMinus1 {
+ sy0, sy1 = shMinus1, shMinus1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ sx := (float64(dx)+0.5)*xscale - 0.5
+ sx0 := int32(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx1 := sx0 + 1
+ if sx < 0 {
+ sx0, sx1 = 0, 0
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 > swMinus1 {
+ sx0, sx1 = swMinus1, swMinus1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA()
+ s00ru = s00ru * ma / 0xffff
+ s00gu = s00gu * ma / 0xffff
+ s00bu = s00bu * ma / 0xffff
+ s00au = s00au * ma / 0xffff
+ }
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA()
+ s10ru = s10ru * ma / 0xffff
+ s10gu = s10gu * ma / 0xffff
+ s10bu = s10bu * ma / 0xffff
+ s10au = s10au * ma / 0xffff
+ }
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA()
+ s01ru = s01ru * ma / 0xffff
+ s01gu = s01gu * ma / 0xffff
+ s01bu = s01bu * ma / 0xffff
+ s01au = s01au * ma / 0xffff
+ }
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA()
+ s11ru = s11ru * ma / 0xffff
+ s11gu = s11gu * ma / 0xffff
+ s11bu = s11bu * ma / 0xffff
+ s11au = s11au * ma / 0xffff
+ }
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ if dstMask != nil {
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ pa1 := 0xffff - ma
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ } else {
+ dstColorRGBA64.R = uint16(pr)
+ dstColorRGBA64.G = uint16(pg)
+ dstColorRGBA64.B = uint16(pb)
+ dstColorRGBA64.A = uint16(pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
+ s00ru := uint32(src.Pix[s00i]) * 0x101
+ s00r := float64(s00ru)
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
+ s10ru := uint32(src.Pix[s10i]) * 0x101
+ s10r := float64(s10ru)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
+ s01ru := uint32(src.Pix[s01i]) * 0x101
+ s01r := float64(s01ru)
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
+ s11ru := uint32(src.Pix[s11i]) * 0x101
+ s11r := float64(s11ru)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11r = yFrac1*s10r + yFrac0*s11r
+ pr := uint32(s11r)
+ out := uint8(pr >> 8)
+ dst.Pix[d+0] = out
+ dst.Pix[d+1] = out
+ dst.Pix[d+2] = out
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
+ s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
+ s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
+ s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
+ s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
+ s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
+ s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
+ s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
+ s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
+ s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
+ s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
+ s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
+ s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
+ s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
+ s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
+ s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
+ s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s00ru := uint32(src.Pix[s00i+0]) * 0x101
+ s00gu := uint32(src.Pix[s00i+1]) * 0x101
+ s00bu := uint32(src.Pix[s00i+2]) * 0x101
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s10ru := uint32(src.Pix[s10i+0]) * 0x101
+ s10gu := uint32(src.Pix[s10i+1]) * 0x101
+ s10bu := uint32(src.Pix[s10i+2]) * 0x101
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s01ru := uint32(src.Pix[s01i+0]) * 0x101
+ s01gu := uint32(src.Pix[s01i+1]) * 0x101
+ s01bu := uint32(src.Pix[s01i+2]) * 0x101
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s11ru := uint32(src.Pix[s11i+0]) * 0x101
+ s11gu := uint32(src.Pix[s11i+1]) * 0x101
+ s11bu := uint32(src.Pix[s11i+2]) * 0x101
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s00ru := uint32(src.Pix[s00i+0]) * 0x101
+ s00gu := uint32(src.Pix[s00i+1]) * 0x101
+ s00bu := uint32(src.Pix[s00i+2]) * 0x101
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s10ru := uint32(src.Pix[s10i+0]) * 0x101
+ s10gu := uint32(src.Pix[s10i+1]) * 0x101
+ s10bu := uint32(src.Pix[s10i+2]) * 0x101
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s01ru := uint32(src.Pix[s01i+0]) * 0x101
+ s01gu := uint32(src.Pix[s01i+1]) * 0x101
+ s01bu := uint32(src.Pix[s01i+2]) * 0x101
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s11ru := uint32(src.Pix[s11i+0]) * 0x101
+ s11gu := uint32(src.Pix[s11i+1]) * 0x101
+ s11bu := uint32(src.Pix[s11i+2]) * 0x101
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i]) * 0x10101
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
+ }
+
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i]) * 0x10101
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i]) * 0x10101
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i]) * 0x10101
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
+ }
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
+ }
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
+ }
+
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i]) * 0x10101
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
+ }
+
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i]) * 0x10101
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i]) * 0x10101
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i]) * 0x10101
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
+ }
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
+ }
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
+ }
+
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i]) * 0x10101
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
+ }
+
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i]) * 0x10101
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i]) * 0x10101
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i]) * 0x10101
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
+ }
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
+ }
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
+ }
+
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i]) * 0x10101
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
+ }
+
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i]) * 0x10101
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i]) * 0x10101
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i]) * 0x10101
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
+ }
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
+ }
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
+ }
+
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ pa1 := (0xffff - pa) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ dst.Pix[d+0] = uint8(pr >> 8)
+ dst.Pix[d+1] = uint8(pg >> 8)
+ dst.Pix[d+2] = uint8(pb >> 8)
+ dst.Pix[d+3] = uint8(pa >> 8)
+ }
+ }
+}
+
+func (ablInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
+ s00ru = s00ru * ma / 0xffff
+ s00gu = s00gu * ma / 0xffff
+ s00bu = s00bu * ma / 0xffff
+ s00au = s00au * ma / 0xffff
+ }
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA()
+ s10ru = s10ru * ma / 0xffff
+ s10gu = s10gu * ma / 0xffff
+ s10bu = s10bu * ma / 0xffff
+ s10au = s10au * ma / 0xffff
+ }
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA()
+ s01ru = s01ru * ma / 0xffff
+ s01gu = s01gu * ma / 0xffff
+ s01bu = s01bu * ma / 0xffff
+ s01au = s01au * ma / 0xffff
+ }
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA()
+ s11ru = s11ru * ma / 0xffff
+ s11gu = s11gu * ma / 0xffff
+ s11bu = s11bu * ma / 0xffff
+ s11au = s11au * ma / 0xffff
+ }
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ if dstMask != nil {
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ }
+ pa1 := 0xffff - pa
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+}
+
+func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
+ s00ru = s00ru * ma / 0xffff
+ s00gu = s00gu * ma / 0xffff
+ s00bu = s00bu * ma / 0xffff
+ s00au = s00au * ma / 0xffff
+ }
+ s00r := float64(s00ru)
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA()
+ s10ru = s10ru * ma / 0xffff
+ s10gu = s10gu * ma / 0xffff
+ s10bu = s10bu * ma / 0xffff
+ s10au = s10au * ma / 0xffff
+ }
+ s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA()
+ s01ru = s01ru * ma / 0xffff
+ s01gu = s01gu * ma / 0xffff
+ s01bu = s01bu * ma / 0xffff
+ s01au = s01au * ma / 0xffff
+ }
+ s01r := float64(s01ru)
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA()
+ s11ru = s11ru * ma / 0xffff
+ s11gu = s11gu * ma / 0xffff
+ s11bu = s11bu * ma / 0xffff
+ s11au = s11au * ma / 0xffff
+ }
+ s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
+ s11r = yFrac1*s10r + yFrac0*s11r
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ pr := uint32(s11r)
+ pg := uint32(s11g)
+ pb := uint32(s11b)
+ pa := uint32(s11a)
+ if dstMask != nil {
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr = pr * ma / 0xffff
+ pg = pg * ma / 0xffff
+ pb = pb * ma / 0xffff
+ pa = pa * ma / 0xffff
+ pa1 := 0xffff - ma
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ } else {
+ dstColorRGBA64.R = uint16(pr)
+ dstColorRGBA64.G = uint16(pg)
+ dstColorRGBA64.B = uint16(pb)
+ dstColorRGBA64.A = uint16(pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+ }
+}
+
+func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ if z.dw != int32(dr.Dx()) || z.dh != int32(dr.Dy()) || z.sw != int32(sr.Dx()) || z.sh != int32(sr.Dy()) {
+ z.kernel.Scale(dst, dr, src, sr, op, opts)
+ return
+ }
+
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+
+ if _, ok := src.(*image.Uniform); ok && o.DstMask == nil && o.SrcMask == nil && sr.In(src.Bounds()) {
+ Draw(dst, dr, src, src.Bounds().Min, op)
+ return
+ }
+
+ // Create a temporary buffer:
+ // scaleX distributes the source image's columns over the temporary image.
+ // scaleY distributes the temporary image's rows over the destination image.
+ var tmp [][4]float64
+ if z.pool.New != nil {
+ tmpp := z.pool.Get().(*[][4]float64)
+ defer z.pool.Put(tmpp)
+ tmp = *tmpp
+ } else {
+ tmp = z.makeTmpBuf()
+ }
+
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.SrcMask != nil || !sr.In(src.Bounds()) {
+ z.scaleX_Image(tmp, src, sr, &o)
+ } else {
+ switch src := src.(type) {
+ case *image.Gray:
+ z.scaleX_Gray(tmp, src, sr, &o)
+ case *image.NRGBA:
+ z.scaleX_NRGBA(tmp, src, sr, &o)
+ case *image.RGBA:
+ z.scaleX_RGBA(tmp, src, sr, &o)
+ case *image.YCbCr:
+ switch src.SubsampleRatio {
+ default:
+ z.scaleX_Image(tmp, src, sr, &o)
+ case image.YCbCrSubsampleRatio444:
+ z.scaleX_YCbCr444(tmp, src, sr, &o)
+ case image.YCbCrSubsampleRatio422:
+ z.scaleX_YCbCr422(tmp, src, sr, &o)
+ case image.YCbCrSubsampleRatio420:
+ z.scaleX_YCbCr420(tmp, src, sr, &o)
+ case image.YCbCrSubsampleRatio440:
+ z.scaleX_YCbCr440(tmp, src, sr, &o)
+ }
+ default:
+ z.scaleX_Image(tmp, src, sr, &o)
+ }
+ }
+
+ if o.DstMask != nil {
+ switch op {
+ case Over:
+ z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
+ case Src:
+ z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
+ }
+ } else {
+ switch op {
+ case Over:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ z.scaleY_RGBA_Over(dst, dr, adr, tmp, &o)
+ default:
+ z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
+ }
+ case Src:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ z.scaleY_RGBA_Src(dst, dr, adr, tmp, &o)
+ default:
+ z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
+ }
+ }
+ }
+}
+
+func (q *Kernel) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+
+ dr := transformRect(&s2d, &sr)
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ if op == Over && o.SrcMask == nil && opaque(src) {
+ op = Src
+ }
+ d2s := invert(&s2d)
+ // bias is a translation of the mapping from dst coordinates to src
+ // coordinates such that the latter temporarily have non-negative X
+ // and Y coordinates. This allows us to write int(f) instead of
+ // int(math.Floor(f)), since "round to zero" and "round down" are
+ // equivalent when f >= 0, but the former is much cheaper. The X--
+ // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
+ // adjustment.
+ bias := transformRect(&d2s, &adr).Min
+ bias.X--
+ bias.Y--
+ d2s[2] -= float64(bias.X)
+ d2s[5] -= float64(bias.Y)
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
+
+ if u, ok := src.(*image.Uniform); ok && o.DstMask != nil && o.SrcMask != nil && sr.In(src.Bounds()) {
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
+ return
+ }
+
+ xscale := abs(d2s[0])
+ if s := abs(d2s[1]); xscale < s {
+ xscale = s
+ }
+ yscale := abs(d2s[3])
+ if s := abs(d2s[4]); yscale < s {
+ yscale = s
+ }
+
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ //
+ // Similarly, the fast paths assume that the masks are nil.
+ if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
+ switch op {
+ case Over:
+ q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case Src:
+ q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ }
+ } else {
+ switch op {
+ case Over:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.NRGBA:
+ q.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case *image.RGBA:
+ q.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ default:
+ q.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ }
+ }
+ case Src:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.Gray:
+ q.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case *image.NRGBA:
+ q.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case *image.RGBA:
+ q.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case *image.YCbCr:
+ switch src.SubsampleRatio {
+ default:
+ q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case image.YCbCrSubsampleRatio444:
+ q.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case image.YCbCrSubsampleRatio422:
+ q.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case image.YCbCrSubsampleRatio420:
+ q.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ case image.YCbCrSubsampleRatio440:
+ q.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ }
+ default:
+ q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
+ }
+ }
+ }
+ }
+}
+
+func (z *kernelScaler) scaleX_Gray(tmp [][4]float64, src *image.Gray, sr image.Rectangle, opts *Options) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ pru := uint32(src.Pix[pi]) * 0x101
+ pr += float64(pru) * c.weight
+ }
+ pr *= s.invTotalWeightFFFF
+ tmp[t] = [4]float64{
+ pr,
+ pr,
+ pr,
+ 1,
+ }
+ t++
+ }
+ }
+}
+
+func (z *kernelScaler) scaleX_NRGBA(tmp [][4]float64, src *image.NRGBA, sr image.Rectangle, opts *Options) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb, pa float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pru := uint32(src.Pix[pi+0]) * pau / 0xff
+ pgu := uint32(src.Pix[pi+1]) * pau / 0xff
+ pbu := uint32(src.Pix[pi+2]) * pau / 0xff
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ pa += float64(pau) * c.weight
+ }
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ pa * s.invTotalWeightFFFF,
+ }
+ t++
+ }
+ }
+}
+
+func (z *kernelScaler) scaleX_RGBA(tmp [][4]float64, src *image.RGBA, sr image.Rectangle, opts *Options) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb, pa float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
+ pru := uint32(src.Pix[pi+0]) * 0x101
+ pgu := uint32(src.Pix[pi+1]) * 0x101
+ pbu := uint32(src.Pix[pi+2]) * 0x101
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ pa += float64(pau) * c.weight
+ }
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ pa * s.invTotalWeightFFFF,
+ }
+ t++
+ }
+ }
+}
+
+func (z *kernelScaler) scaleX_YCbCr444(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
+
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ }
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ 1,
+ }
+ t++
+ }
+ }
+}
+
+func (z *kernelScaler) scaleX_YCbCr422(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
+
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ }
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ 1,
+ }
+ t++
+ }
+ }
+}
+
+func (z *kernelScaler) scaleX_YCbCr420(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
+
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ }
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ 1,
+ }
+ t++
+ }
+ }
+}
+
+func (z *kernelScaler) scaleX_YCbCr440(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
+
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ }
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ 1,
+ }
+ t++
+ }
+ }
+}
+
+func (z *kernelScaler) scaleX_Image(tmp [][4]float64, src image.Image, sr image.Rectangle, opts *Options) {
+ t := 0
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb, pa float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pru, pgu, pbu, pau := src.At(sr.Min.X+int(c.coord), sr.Min.Y+int(y)).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(c.coord), smp.Y+sr.Min.Y+int(y)).RGBA()
+ pru = pru * ma / 0xffff
+ pgu = pgu * ma / 0xffff
+ pbu = pbu * ma / 0xffff
+ pau = pau * ma / 0xffff
+ }
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ pa += float64(pau) * c.weight
+ }
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ pa * s.invTotalWeightFFFF,
+ }
+ t++
+ }
+ }
+}
+
+func (z *kernelScaler) scaleY_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
+ for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
+ var pr, pg, pb, pa float64
+ for _, c := range z.vertical.contribs[s.i:s.j] {
+ p := &tmp[c.coord*z.dw+dx]
+ pr += p[0] * c.weight
+ pg += p[1] * c.weight
+ pb += p[2] * c.weight
+ pa += p[3] * c.weight
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ pr0 := uint32(ftou(pr * s.invTotalWeight))
+ pg0 := uint32(ftou(pg * s.invTotalWeight))
+ pb0 := uint32(ftou(pb * s.invTotalWeight))
+ pa0 := uint32(ftou(pa * s.invTotalWeight))
+ pa1 := (0xffff - uint32(pa0)) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
+ d += dst.Stride
+ }
+ }
+}
+
+func (z *kernelScaler) scaleY_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
+ for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
+ var pr, pg, pb, pa float64
+ for _, c := range z.vertical.contribs[s.i:s.j] {
+ p := &tmp[c.coord*z.dw+dx]
+ pr += p[0] * c.weight
+ pg += p[1] * c.weight
+ pb += p[2] * c.weight
+ pa += p[3] * c.weight
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ dst.Pix[d+0] = uint8(ftou(pr*s.invTotalWeight) >> 8)
+ dst.Pix[d+1] = uint8(ftou(pg*s.invTotalWeight) >> 8)
+ dst.Pix[d+2] = uint8(ftou(pb*s.invTotalWeight) >> 8)
+ dst.Pix[d+3] = uint8(ftou(pa*s.invTotalWeight) >> 8)
+ d += dst.Stride
+ }
+ }
+}
+
+func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
+ var pr, pg, pb, pa float64
+ for _, c := range z.vertical.contribs[s.i:s.j] {
+ p := &tmp[c.coord*z.dw+dx]
+ pr += p[0] * c.weight
+ pg += p[1] * c.weight
+ pb += p[2] * c.weight
+ pa += p[3] * c.weight
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
+ pr0 := uint32(ftou(pr * s.invTotalWeight))
+ pg0 := uint32(ftou(pg * s.invTotalWeight))
+ pb0 := uint32(ftou(pb * s.invTotalWeight))
+ pa0 := uint32(ftou(pa * s.invTotalWeight))
+ if dstMask != nil {
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
+ pr0 = pr0 * ma / 0xffff
+ pg0 = pg0 * ma / 0xffff
+ pb0 = pb0 * ma / 0xffff
+ pa0 = pa0 * ma / 0xffff
+ }
+ pa1 := 0xffff - pa0
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb0)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa0)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
+ }
+ }
+}
+
+func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
+ var pr, pg, pb, pa float64
+ for _, c := range z.vertical.contribs[s.i:s.j] {
+ p := &tmp[c.coord*z.dw+dx]
+ pr += p[0] * c.weight
+ pg += p[1] * c.weight
+ pb += p[2] * c.weight
+ pa += p[3] * c.weight
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ if dstMask != nil {
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
+ pr := uint32(ftou(pr*s.invTotalWeight)) * ma / 0xffff
+ pg := uint32(ftou(pg*s.invTotalWeight)) * ma / 0xffff
+ pb := uint32(ftou(pb*s.invTotalWeight)) * ma / 0xffff
+ pa := uint32(ftou(pa*s.invTotalWeight)) * ma / 0xffff
+ pa1 := 0xffff - ma
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
+ } else {
+ dstColorRGBA64.R = ftou(pr * s.invTotalWeight)
+ dstColorRGBA64.G = ftou(pg * s.invTotalWeight)
+ dstColorRGBA64.B = ftou(pb * s.invTotalWeight)
+ dstColorRGBA64.A = ftou(pa * s.invTotalWeight)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
+ }
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx - src.Rect.Min.X)
+ pru := uint32(src.Pix[pi]) * 0x101
+ pr += float64(pru) * w
+ }
+ }
+ }
+ }
+ out := uint8(fffftou(pr) >> 8)
+ dst.Pix[d+0] = out
+ dst.Pix[d+1] = out
+ dst.Pix[d+2] = out
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb, pa float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pru := uint32(src.Pix[pi+0]) * pau / 0xff
+ pgu := uint32(src.Pix[pi+1]) * pau / 0xff
+ pbu := uint32(src.Pix[pi+2]) * pau / 0xff
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ pa += float64(pau) * w
+ }
+ }
+ }
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ pr0 := uint32(fffftou(pr))
+ pg0 := uint32(fffftou(pg))
+ pb0 := uint32(fffftou(pb))
+ pa0 := uint32(fffftou(pa))
+ pa1 := (0xffff - uint32(pa0)) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb, pa float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pru := uint32(src.Pix[pi+0]) * pau / 0xff
+ pgu := uint32(src.Pix[pi+1]) * pau / 0xff
+ pbu := uint32(src.Pix[pi+2]) * pau / 0xff
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ pa += float64(pau) * w
+ }
+ }
+ }
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
+ dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
+ dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
+ dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb, pa float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
+ pru := uint32(src.Pix[pi+0]) * 0x101
+ pgu := uint32(src.Pix[pi+1]) * 0x101
+ pbu := uint32(src.Pix[pi+2]) * 0x101
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ pa += float64(pau) * w
+ }
+ }
+ }
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ pr0 := uint32(fffftou(pr))
+ pg0 := uint32(fffftou(pg))
+ pb0 := uint32(fffftou(pb))
+ pa0 := uint32(fffftou(pa))
+ pa1 := (0xffff - uint32(pa0)) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb, pa float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
+ pru := uint32(src.Pix[pi+0]) * 0x101
+ pgu := uint32(src.Pix[pi+1]) * 0x101
+ pbu := uint32(src.Pix[pi+2]) * 0x101
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ pa += float64(pau) * w
+ }
+ }
+ }
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
+ dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
+ dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
+ dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
+ pj := (ky-src.Rect.Min.Y)*src.CStride + (kx - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
+
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ }
+ }
+ }
+ }
+ dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
+ dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
+ dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
+ pj := (ky-src.Rect.Min.Y)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
+
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ }
+ }
+ }
+ }
+ dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
+ dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
+ dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
+ pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
+
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ }
+ }
+ }
+ }
+ dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
+ dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
+ dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
+ pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + (kx - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi]) * 0x10101
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
+
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ }
+ }
+ }
+ }
+ dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
+ dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
+ dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb, pa float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ pa += float64(pau) * w
+ }
+ }
+ }
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ pr0 := uint32(fffftou(pr))
+ pg0 := uint32(fffftou(pg))
+ pb0 := uint32(fffftou(pb))
+ pa0 := uint32(fffftou(pa))
+ pa1 := (0xffff - uint32(pa0)) * 0x101
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
+ }
+ }
+}
+
+func (q *Kernel) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb, pa float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ pa += float64(pau) * w
+ }
+ }
+ }
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
+ dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
+ dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
+ dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
+ }
+ }
+}
+
+func (q *Kernel) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb, pa float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA()
+ pru = pru * ma / 0xffff
+ pgu = pgu * ma / 0xffff
+ pbu = pbu * ma / 0xffff
+ pau = pau * ma / 0xffff
+ }
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ pa += float64(pau) * w
+ }
+ }
+ }
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ pr0 := uint32(fffftou(pr))
+ pg0 := uint32(fffftou(pg))
+ pb0 := uint32(fffftou(pb))
+ pa0 := uint32(fffftou(pa))
+ if dstMask != nil {
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr0 = pr0 * ma / 0xffff
+ pg0 = pg0 * ma / 0xffff
+ pb0 = pb0 * ma / 0xffff
+ pa0 = pa0 * ma / 0xffff
+ }
+ pa1 := 0xffff - pa0
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb0)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa0)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+}
+
+func (q *Kernel) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ xHalfWidth, xKernelArgScale := q.Support, 1.0
+ if xscale > 1 {
+ xHalfWidth *= xscale
+ xKernelArgScale = 1 / xscale
+ }
+ yHalfWidth, yKernelArgScale := q.Support, 1.0
+ if yscale > 1 {
+ yHalfWidth *= yscale
+ yKernelArgScale = 1 / yscale
+ }
+
+ xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
+ yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+
+ srcMask, smp := opts.SrcMask, opts.SrcMaskP
+ dstMask, dmp := opts.DstMask, opts.DstMaskP
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ // TODO: adjust the bias so that we can use int(f) instead
+ // of math.Floor(f) and math.Ceil(f).
+ sx += float64(bias.X)
+ sx -= 0.5
+ ix := int(math.Floor(sx - xHalfWidth))
+ if ix < sr.Min.X {
+ ix = sr.Min.X
+ }
+ jx := int(math.Ceil(sx + xHalfWidth))
+ if jx > sr.Max.X {
+ jx = sr.Max.X
+ }
+
+ totalXWeight := 0.0
+ for kx := ix; kx < jx; kx++ {
+ xWeight := 0.0
+ if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
+ xWeight = q.At(t)
+ }
+ xWeights[kx-ix] = xWeight
+ totalXWeight += xWeight
+ }
+ for x := range xWeights[:jx-ix] {
+ xWeights[x] /= totalXWeight
+ }
+
+ sy += float64(bias.Y)
+ sy -= 0.5
+ iy := int(math.Floor(sy - yHalfWidth))
+ if iy < sr.Min.Y {
+ iy = sr.Min.Y
+ }
+ jy := int(math.Ceil(sy + yHalfWidth))
+ if jy > sr.Max.Y {
+ jy = sr.Max.Y
+ }
+
+ totalYWeight := 0.0
+ for ky := iy; ky < jy; ky++ {
+ yWeight := 0.0
+ if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
+ yWeight = q.At(t)
+ }
+ yWeights[ky-iy] = yWeight
+ totalYWeight += yWeight
+ }
+ for y := range yWeights[:jy-iy] {
+ yWeights[y] /= totalYWeight
+ }
+
+ var pr, pg, pb, pa float64
+ for ky := iy; ky < jy; ky++ {
+ if yWeight := yWeights[ky-iy]; yWeight != 0 {
+ for kx := ix; kx < jx; kx++ {
+ if w := xWeights[kx-ix] * yWeight; w != 0 {
+ pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
+ if srcMask != nil {
+ _, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA()
+ pru = pru * ma / 0xffff
+ pgu = pgu * ma / 0xffff
+ pbu = pbu * ma / 0xffff
+ pau = pau * ma / 0xffff
+ }
+ pr += float64(pru) * w
+ pg += float64(pgu) * w
+ pb += float64(pbu) * w
+ pa += float64(pau) * w
+ }
+ }
+ }
+ }
+
+ if pr > pa {
+ pr = pa
+ }
+ if pg > pa {
+ pg = pa
+ }
+ if pb > pa {
+ pb = pa
+ }
+
+ if dstMask != nil {
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
+ pr := uint32(fffftou(pr)) * ma / 0xffff
+ pg := uint32(fffftou(pg)) * ma / 0xffff
+ pb := uint32(fffftou(pb)) * ma / 0xffff
+ pa := uint32(fffftou(pa)) * ma / 0xffff
+ pa1 := 0xffff - ma
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ } else {
+ dstColorRGBA64.R = fffftou(pr)
+ dstColorRGBA64.G = fffftou(pg)
+ dstColorRGBA64.B = fffftou(pb)
+ dstColorRGBA64.A = fffftou(pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+ }
+}
diff --git a/vendor/golang.org/x/image/draw/scale.go b/vendor/golang.org/x/image/draw/scale.go
new file mode 100644
index 0000000..98ab404
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/scale.go
@@ -0,0 +1,527 @@
+// Copyright 2015 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.
+
+//go:generate go run gen.go
+
+package draw
+
+import (
+ "image"
+ "image/color"
+ "math"
+ "sync"
+
+ "golang.org/x/image/math/f64"
+)
+
+// Copy copies the part of the source image defined by src and sr and writes
+// the result of a Porter-Duff composition to the part of the destination image
+// defined by dst and the translation of sr so that sr.Min translates to dp.
+func Copy(dst Image, dp image.Point, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ var o Options
+ if opts != nil {
+ o = *opts
+ }
+ dr := sr.Add(dp.Sub(sr.Min))
+ if o.DstMask == nil {
+ DrawMask(dst, dr, src, sr.Min, o.SrcMask, o.SrcMaskP.Add(sr.Min), op)
+ } else {
+ NearestNeighbor.Scale(dst, dr, src, sr, op, opts)
+ }
+}
+
+// Scaler scales the part of the source image defined by src and sr and writes
+// the result of a Porter-Duff composition to the part of the destination image
+// defined by dst and dr.
+//
+// A Scaler is safe to use concurrently.
+type Scaler interface {
+ Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options)
+}
+
+// Transformer transforms the part of the source image defined by src and sr
+// and writes the result of a Porter-Duff composition to the part of the
+// destination image defined by dst and the affine transform m applied to sr.
+//
+// For example, if m is the matrix
+//
+// m00 m01 m02
+// m10 m11 m12
+//
+// then the src-space point (sx, sy) maps to the dst-space point
+// (m00*sx + m01*sy + m02, m10*sx + m11*sy + m12).
+//
+// A Transformer is safe to use concurrently.
+type Transformer interface {
+ Transform(dst Image, m f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options)
+}
+
+// Options are optional parameters to Copy, Scale and Transform.
+//
+// A nil *Options means to use the default (zero) values of each field.
+type Options struct {
+ // Masks limit what parts of the dst image are drawn to and what parts of
+ // the src image are drawn from.
+ //
+ // A dst or src mask image having a zero alpha (transparent) pixel value in
+ // the respective coordinate space means that that dst pixel is entirely
+ // unaffected or that src pixel is considered transparent black. A full
+ // alpha (opaque) value means that the dst pixel is maximally affected or
+ // the src pixel contributes maximally. The default values, nil, are
+ // equivalent to fully opaque, infinitely large mask images.
+ //
+ // The DstMask is otherwise known as a clip mask, and its pixels map 1:1 to
+ // the dst image's pixels. DstMaskP in DstMask space corresponds to
+ // image.Point{X:0, Y:0} in dst space. For example, when limiting
+ // repainting to a 'dirty rectangle', use that image.Rectangle and a zero
+ // image.Point as the DstMask and DstMaskP.
+ //
+ // The SrcMask's pixels map 1:1 to the src image's pixels. SrcMaskP in
+ // SrcMask space corresponds to image.Point{X:0, Y:0} in src space. For
+ // example, when drawing font glyphs in a uniform color, use an
+ // *image.Uniform as the src, and use the glyph atlas image and the
+ // per-glyph offset as SrcMask and SrcMaskP:
+ // Copy(dst, dp, image.NewUniform(color), image.Rect(0, 0, glyphWidth, glyphHeight), &Options{
+ // SrcMask: glyphAtlas,
+ // SrcMaskP: glyphOffset,
+ // })
+ DstMask image.Image
+ DstMaskP image.Point
+ SrcMask image.Image
+ SrcMaskP image.Point
+
+ // TODO: a smooth vs sharp edges option, for arbitrary rotations?
+}
+
+// Interpolator is an interpolation algorithm, when dst and src pixels don't
+// have a 1:1 correspondence.
+//
+// Of the interpolators provided by this package:
+// - NearestNeighbor is fast but usually looks worst.
+// - CatmullRom is slow but usually looks best.
+// - ApproxBiLinear has reasonable speed and quality.
+//
+// The time taken depends on the size of dr. For kernel interpolators, the
+// speed also depends on the size of sr, and so are often slower than
+// non-kernel interpolators, especially when scaling down.
+type Interpolator interface {
+ Scaler
+ Transformer
+}
+
+// Kernel is an interpolator that blends source pixels weighted by a symmetric
+// kernel function.
+type Kernel struct {
+ // Support is the kernel support and must be >= 0. At(t) is assumed to be
+ // zero when t >= Support.
+ Support float64
+ // At is the kernel function. It will only be called with t in the
+ // range [0, Support).
+ At func(t float64) float64
+}
+
+// Scale implements the Scaler interface.
+func (q *Kernel) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
+ q.newScaler(dr.Dx(), dr.Dy(), sr.Dx(), sr.Dy(), false).Scale(dst, dr, src, sr, op, opts)
+}
+
+// NewScaler returns a Scaler that is optimized for scaling multiple times with
+// the same fixed destination and source width and height.
+func (q *Kernel) NewScaler(dw, dh, sw, sh int) Scaler {
+ return q.newScaler(dw, dh, sw, sh, true)
+}
+
+func (q *Kernel) newScaler(dw, dh, sw, sh int, usePool bool) Scaler {
+ z := &kernelScaler{
+ kernel: q,
+ dw: int32(dw),
+ dh: int32(dh),
+ sw: int32(sw),
+ sh: int32(sh),
+ horizontal: newDistrib(q, int32(dw), int32(sw)),
+ vertical: newDistrib(q, int32(dh), int32(sh)),
+ }
+ if usePool {
+ z.pool.New = func() interface{} {
+ tmp := z.makeTmpBuf()
+ return &tmp
+ }
+ }
+ return z
+}
+
+var (
+ // NearestNeighbor is the nearest neighbor interpolator. It is very fast,
+ // but usually gives very low quality results. When scaling up, the result
+ // will look 'blocky'.
+ NearestNeighbor = Interpolator(nnInterpolator{})
+
+ // ApproxBiLinear is a mixture of the nearest neighbor and bi-linear
+ // interpolators. It is fast, but usually gives medium quality results.
+ //
+ // It implements bi-linear interpolation when upscaling and a bi-linear
+ // blend of the 4 nearest neighbor pixels when downscaling. This yields
+ // nicer quality than nearest neighbor interpolation when upscaling, but
+ // the time taken is independent of the number of source pixels, unlike the
+ // bi-linear interpolator. When downscaling a large image, the performance
+ // difference can be significant.
+ ApproxBiLinear = Interpolator(ablInterpolator{})
+
+ // BiLinear is the tent kernel. It is slow, but usually gives high quality
+ // results.
+ BiLinear = &Kernel{1, func(t float64) float64 {
+ return 1 - t
+ }}
+
+ // CatmullRom is the Catmull-Rom kernel. It is very slow, but usually gives
+ // very high quality results.
+ //
+ // It is an instance of the more general cubic BC-spline kernel with parameters
+ // B=0 and C=0.5. See Mitchell and Netravali, "Reconstruction Filters in
+ // Computer Graphics", Computer Graphics, Vol. 22, No. 4, pp. 221-228.
+ CatmullRom = &Kernel{2, func(t float64) float64 {
+ if t < 1 {
+ return (1.5*t-2.5)*t*t + 1
+ }
+ return ((-0.5*t+2.5)*t-4)*t + 2
+ }}
+
+ // TODO: a Kaiser-Bessel kernel?
+)
+
+type nnInterpolator struct{}
+
+type ablInterpolator struct{}
+
+type kernelScaler struct {
+ kernel *Kernel
+ dw, dh, sw, sh int32
+ horizontal, vertical distrib
+ pool sync.Pool
+}
+
+func (z *kernelScaler) makeTmpBuf() [][4]float64 {
+ return make([][4]float64, z.dw*z.sh)
+}
+
+// source is a range of contribs, their inverse total weight, and that ITW
+// divided by 0xffff.
+type source struct {
+ i, j int32
+ invTotalWeight float64
+ invTotalWeightFFFF float64
+}
+
+// contrib is the weight of a column or row.
+type contrib struct {
+ coord int32
+ weight float64
+}
+
+// distrib measures how source pixels are distributed over destination pixels.
+type distrib struct {
+ // sources are what contribs each column or row in the source image owns,
+ // and the total weight of those contribs.
+ sources []source
+ // contribs are the contributions indexed by sources[s].i and sources[s].j.
+ contribs []contrib
+}
+
+// newDistrib returns a distrib that distributes sw source columns (or rows)
+// over dw destination columns (or rows).
+func newDistrib(q *Kernel, dw, sw int32) distrib {
+ scale := float64(sw) / float64(dw)
+ halfWidth, kernelArgScale := q.Support, 1.0
+ // When shrinking, broaden the effective kernel support so that we still
+ // visit every source pixel.
+ if scale > 1 {
+ halfWidth *= scale
+ kernelArgScale = 1 / scale
+ }
+
+ // Make the sources slice, one source for each column or row, and temporarily
+ // appropriate its elements' fields so that invTotalWeight is the scaled
+ // coordinate of the source column or row, and i and j are the lower and
+ // upper bounds of the range of destination columns or rows affected by the
+ // source column or row.
+ n, sources := int32(0), make([]source, dw)
+ for x := range sources {
+ center := (float64(x)+0.5)*scale - 0.5
+ i := int32(math.Floor(center - halfWidth))
+ if i < 0 {
+ i = 0
+ }
+ j := int32(math.Ceil(center + halfWidth))
+ if j > sw {
+ j = sw
+ if j < i {
+ j = i
+ }
+ }
+ sources[x] = source{i: i, j: j, invTotalWeight: center}
+ n += j - i
+ }
+
+ contribs := make([]contrib, 0, n)
+ for k, b := range sources {
+ totalWeight := 0.0
+ l := int32(len(contribs))
+ for coord := b.i; coord < b.j; coord++ {
+ t := abs((b.invTotalWeight - float64(coord)) * kernelArgScale)
+ if t >= q.Support {
+ continue
+ }
+ weight := q.At(t)
+ if weight == 0 {
+ continue
+ }
+ totalWeight += weight
+ contribs = append(contribs, contrib{coord, weight})
+ }
+ totalWeight = 1 / totalWeight
+ sources[k] = source{
+ i: l,
+ j: int32(len(contribs)),
+ invTotalWeight: totalWeight,
+ invTotalWeightFFFF: totalWeight / 0xffff,
+ }
+ }
+
+ return distrib{sources, contribs}
+}
+
+// abs is like math.Abs, but it doesn't care about negative zero, infinities or
+// NaNs.
+func abs(f float64) float64 {
+ if f < 0 {
+ f = -f
+ }
+ return f
+}
+
+// ftou converts the range [0.0, 1.0] to [0, 0xffff].
+func ftou(f float64) uint16 {
+ i := int32(0xffff*f + 0.5)
+ if i > 0xffff {
+ return 0xffff
+ }
+ if i > 0 {
+ return uint16(i)
+ }
+ return 0
+}
+
+// fffftou converts the range [0.0, 65535.0] to [0, 0xffff].
+func fffftou(f float64) uint16 {
+ i := int32(f + 0.5)
+ if i > 0xffff {
+ return 0xffff
+ }
+ if i > 0 {
+ return uint16(i)
+ }
+ return 0
+}
+
+// invert returns the inverse of m.
+//
+// TODO: move this into the f64 package, once we work out the convention for
+// matrix methods in that package: do they modify the receiver, take a dst
+// pointer argument, or return a new value?
+func invert(m *f64.Aff3) f64.Aff3 {
+ m00 := +m[3*1+1]
+ m01 := -m[3*0+1]
+ m02 := +m[3*1+2]*m[3*0+1] - m[3*1+1]*m[3*0+2]
+ m10 := -m[3*1+0]
+ m11 := +m[3*0+0]
+ m12 := +m[3*1+0]*m[3*0+2] - m[3*1+2]*m[3*0+0]
+
+ det := m00*m11 - m10*m01
+
+ return f64.Aff3{
+ m00 / det,
+ m01 / det,
+ m02 / det,
+ m10 / det,
+ m11 / det,
+ m12 / det,
+ }
+}
+
+func matMul(p, q *f64.Aff3) f64.Aff3 {
+ return f64.Aff3{
+ p[3*0+0]*q[3*0+0] + p[3*0+1]*q[3*1+0],
+ p[3*0+0]*q[3*0+1] + p[3*0+1]*q[3*1+1],
+ p[3*0+0]*q[3*0+2] + p[3*0+1]*q[3*1+2] + p[3*0+2],
+ p[3*1+0]*q[3*0+0] + p[3*1+1]*q[3*1+0],
+ p[3*1+0]*q[3*0+1] + p[3*1+1]*q[3*1+1],
+ p[3*1+0]*q[3*0+2] + p[3*1+1]*q[3*1+2] + p[3*1+2],
+ }
+}
+
+// transformRect returns a rectangle dr that contains sr transformed by s2d.
+func transformRect(s2d *f64.Aff3, sr *image.Rectangle) (dr image.Rectangle) {
+ ps := [...]image.Point{
+ {sr.Min.X, sr.Min.Y},
+ {sr.Max.X, sr.Min.Y},
+ {sr.Min.X, sr.Max.Y},
+ {sr.Max.X, sr.Max.Y},
+ }
+ for i, p := range ps {
+ sxf := float64(p.X)
+ syf := float64(p.Y)
+ dx := int(math.Floor(s2d[0]*sxf + s2d[1]*syf + s2d[2]))
+ dy := int(math.Floor(s2d[3]*sxf + s2d[4]*syf + s2d[5]))
+
+ // The +1 adjustments below are because an image.Rectangle is inclusive
+ // on the low end but exclusive on the high end.
+
+ if i == 0 {
+ dr = image.Rectangle{
+ Min: image.Point{dx + 0, dy + 0},
+ Max: image.Point{dx + 1, dy + 1},
+ }
+ continue
+ }
+
+ if dr.Min.X > dx {
+ dr.Min.X = dx
+ }
+ dx++
+ if dr.Max.X < dx {
+ dr.Max.X = dx
+ }
+
+ if dr.Min.Y > dy {
+ dr.Min.Y = dy
+ }
+ dy++
+ if dr.Max.Y < dy {
+ dr.Max.Y = dy
+ }
+ }
+ return dr
+}
+
+func clipAffectedDestRect(adr image.Rectangle, dstMask image.Image, dstMaskP image.Point) (image.Rectangle, image.Image) {
+ if dstMask == nil {
+ return adr, nil
+ }
+ // TODO: enable this fast path once Go 1.5 is released, where an
+ // image.Rectangle implements image.Image.
+ // if r, ok := dstMask.(image.Rectangle); ok {
+ // return adr.Intersect(r.Sub(dstMaskP)), nil
+ // }
+ // TODO: clip to dstMask.Bounds() if the color model implies that out-of-bounds means 0 alpha?
+ return adr, dstMask
+}
+
+func transform_Uniform(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Uniform, sr image.Rectangle, bias image.Point, op Op) {
+ switch op {
+ case Over:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ pr, pg, pb, pa := src.C.RGBA()
+ pa1 := (0xffff - pa) * 0x101
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := dst.PixOffset(dr.Min.X+adr.Min.X, dr.Min.Y+int(dy))
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
+ dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
+ dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
+ dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
+ }
+ }
+
+ default:
+ pr, pg, pb, pa := src.C.RGBA()
+ pa1 := 0xffff - pa
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
+ dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
+ dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
+ dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
+ dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+ }
+
+ case Src:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ pr, pg, pb, pa := src.C.RGBA()
+ pr8 := uint8(pr >> 8)
+ pg8 := uint8(pg >> 8)
+ pb8 := uint8(pb >> 8)
+ pa8 := uint8(pa >> 8)
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := dst.PixOffset(dr.Min.X+adr.Min.X, dr.Min.Y+int(dy))
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ dst.Pix[d+0] = pr8
+ dst.Pix[d+1] = pg8
+ dst.Pix[d+2] = pb8
+ dst.Pix[d+3] = pa8
+ }
+ }
+
+ default:
+ pr, pg, pb, pa := src.C.RGBA()
+ dstColorRGBA64 := &color.RGBA64{
+ uint16(pr),
+ uint16(pg),
+ uint16(pb),
+ uint16(pa),
+ }
+ dstColor := color.Color(dstColorRGBA64)
+
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
+ sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
+ if !(image.Point{sx0, sy0}).In(sr) {
+ continue
+ }
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ }
+ }
+ }
+ }
+}
+
+func opaque(m image.Image) bool {
+ o, ok := m.(interface {
+ Opaque() bool
+ })
+ return ok && o.Opaque()
+}
diff --git a/vendor/golang.org/x/image/draw/scale_test.go b/vendor/golang.org/x/image/draw/scale_test.go
new file mode 100644
index 0000000..ea41940
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/scale_test.go
@@ -0,0 +1,742 @@
+// Copyright 2015 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 draw
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "image"
+ "image/color"
+ "image/png"
+ "math/rand"
+ "os"
+ "reflect"
+ "testing"
+
+ "golang.org/x/image/math/f64"
+
+ _ "image/jpeg"
+)
+
+var genGoldenFiles = flag.Bool("gen_golden_files", false, "whether to generate the TestXxx golden files.")
+
+var transformMatrix = func(scale, tx, ty float64) f64.Aff3 {
+ const cos30, sin30 = 0.866025404, 0.5
+ return f64.Aff3{
+ +scale * cos30, -scale * sin30, tx,
+ +scale * sin30, +scale * cos30, ty,
+ }
+}
+
+func encode(filename string, m image.Image) error {
+ f, err := os.Create(filename)
+ if err != nil {
+ return fmt.Errorf("Create: %v", err)
+ }
+ defer f.Close()
+ if err := png.Encode(f, m); err != nil {
+ return fmt.Errorf("Encode: %v", err)
+ }
+ return nil
+}
+
+// testInterp tests that interpolating the source image gives the exact
+// destination image. This is to ensure that any refactoring or optimization of
+// the interpolation code doesn't change the behavior. Changing the actual
+// algorithm or kernel used by any particular quality setting will obviously
+// change the resultant pixels. In such a case, use the gen_golden_files flag
+// to regenerate the golden files.
+func testInterp(t *testing.T, w int, h int, direction, prefix, suffix string) {
+ f, err := os.Open("../testdata/" + prefix + suffix)
+ if err != nil {
+ t.Fatalf("Open: %v", err)
+ }
+ defer f.Close()
+ src, _, err := image.Decode(f)
+ if err != nil {
+ t.Fatalf("Decode: %v", err)
+ }
+
+ op, scale := Src, 3.75
+ if prefix == "tux" {
+ op, scale = Over, 0.125
+ }
+ green := image.NewUniform(color.RGBA{0x00, 0x22, 0x11, 0xff})
+
+ testCases := map[string]Interpolator{
+ "nn": NearestNeighbor,
+ "ab": ApproxBiLinear,
+ "bl": BiLinear,
+ "cr": CatmullRom,
+ }
+ for name, q := range testCases {
+ goldenFilename := fmt.Sprintf("../testdata/%s-%s-%s.png", prefix, direction, name)
+
+ got := image.NewRGBA(image.Rect(0, 0, w, h))
+ Copy(got, image.Point{}, green, got.Bounds(), Src, nil)
+ if direction == "rotate" {
+ q.Transform(got, transformMatrix(scale, 40, 10), src, src.Bounds(), op, nil)
+ } else {
+ q.Scale(got, got.Bounds(), src, src.Bounds(), op, nil)
+ }
+
+ if *genGoldenFiles {
+ if err := encode(goldenFilename, got); err != nil {
+ t.Error(err)
+ }
+ continue
+ }
+
+ g, err := os.Open(goldenFilename)
+ if err != nil {
+ t.Errorf("Open: %v", err)
+ continue
+ }
+ defer g.Close()
+ wantRaw, err := png.Decode(g)
+ if err != nil {
+ t.Errorf("Decode: %v", err)
+ continue
+ }
+ // convert wantRaw to RGBA.
+ want, ok := wantRaw.(*image.RGBA)
+ if !ok {
+ b := wantRaw.Bounds()
+ want = image.NewRGBA(b)
+ Draw(want, b, wantRaw, b.Min, Src)
+ }
+
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("%s: actual image differs from golden image", goldenFilename)
+ continue
+ }
+ }
+}
+
+func TestScaleDown(t *testing.T) { testInterp(t, 100, 100, "down", "go-turns-two", "-280x360.jpeg") }
+func TestScaleUp(t *testing.T) { testInterp(t, 75, 100, "up", "go-turns-two", "-14x18.png") }
+func TestTformSrc(t *testing.T) { testInterp(t, 100, 100, "rotate", "go-turns-two", "-14x18.png") }
+func TestTformOver(t *testing.T) { testInterp(t, 100, 100, "rotate", "tux", ".png") }
+
+// TestSimpleTransforms tests Scale and Transform calls that simplify to Copy
+// or Scale calls.
+func TestSimpleTransforms(t *testing.T) {
+ f, err := os.Open("../testdata/testpattern.png") // A 100x100 image.
+ if err != nil {
+ t.Fatalf("Open: %v", err)
+ }
+ defer f.Close()
+ src, _, err := image.Decode(f)
+ if err != nil {
+ t.Fatalf("Decode: %v", err)
+ }
+
+ dst0 := image.NewRGBA(image.Rect(0, 0, 120, 150))
+ dst1 := image.NewRGBA(image.Rect(0, 0, 120, 150))
+ for _, op := range []string{"scale/copy", "tform/copy", "tform/scale"} {
+ for _, epsilon := range []float64{0, 1e-50, 1e-1} {
+ Copy(dst0, image.Point{}, image.Transparent, dst0.Bounds(), Src, nil)
+ Copy(dst1, image.Point{}, image.Transparent, dst1.Bounds(), Src, nil)
+
+ switch op {
+ case "scale/copy":
+ dr := image.Rect(10, 30, 10+100, 30+100)
+ if epsilon > 1e-10 {
+ dr.Max.X++
+ }
+ Copy(dst0, image.Point{10, 30}, src, src.Bounds(), Src, nil)
+ ApproxBiLinear.Scale(dst1, dr, src, src.Bounds(), Src, nil)
+ case "tform/copy":
+ Copy(dst0, image.Point{10, 30}, src, src.Bounds(), Src, nil)
+ ApproxBiLinear.Transform(dst1, f64.Aff3{
+ 1, 0 + epsilon, 10,
+ 0, 1, 30,
+ }, src, src.Bounds(), Src, nil)
+ case "tform/scale":
+ ApproxBiLinear.Scale(dst0, image.Rect(10, 50, 10+50, 50+50), src, src.Bounds(), Src, nil)
+ ApproxBiLinear.Transform(dst1, f64.Aff3{
+ 0.5, 0.0 + epsilon, 10,
+ 0.0, 0.5, 50,
+ }, src, src.Bounds(), Src, nil)
+ }
+
+ differ := !bytes.Equal(dst0.Pix, dst1.Pix)
+ if epsilon > 1e-10 {
+ if !differ {
+ t.Errorf("%s yielded same pixels, want different pixels: epsilon=%v", op, epsilon)
+ }
+ } else {
+ if differ {
+ t.Errorf("%s yielded different pixels, want same pixels: epsilon=%v", op, epsilon)
+ }
+ }
+ }
+ }
+}
+
+func BenchmarkSimpleScaleCopy(b *testing.B) {
+ dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
+ src := image.NewRGBA(image.Rect(0, 0, 400, 300))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ ApproxBiLinear.Scale(dst, image.Rect(10, 20, 10+400, 20+300), src, src.Bounds(), Src, nil)
+ }
+}
+
+func BenchmarkSimpleTransformCopy(b *testing.B) {
+ dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
+ src := image.NewRGBA(image.Rect(0, 0, 400, 300))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ ApproxBiLinear.Transform(dst, f64.Aff3{
+ 1, 0, 10,
+ 0, 1, 20,
+ }, src, src.Bounds(), Src, nil)
+ }
+}
+
+func BenchmarkSimpleTransformScale(b *testing.B) {
+ dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
+ src := image.NewRGBA(image.Rect(0, 0, 400, 300))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ ApproxBiLinear.Transform(dst, f64.Aff3{
+ 0.5, 0.0, 10,
+ 0.0, 0.5, 20,
+ }, src, src.Bounds(), Src, nil)
+ }
+}
+
+func TestOps(t *testing.T) {
+ blue := image.NewUniform(color.RGBA{0x00, 0x00, 0xff, 0xff})
+ testCases := map[Op]color.RGBA{
+ Over: color.RGBA{0x7f, 0x00, 0x80, 0xff},
+ Src: color.RGBA{0x7f, 0x00, 0x00, 0x7f},
+ }
+ for op, want := range testCases {
+ dst := image.NewRGBA(image.Rect(0, 0, 2, 2))
+ Copy(dst, image.Point{}, blue, dst.Bounds(), Src, nil)
+
+ src := image.NewRGBA(image.Rect(0, 0, 1, 1))
+ src.SetRGBA(0, 0, color.RGBA{0x7f, 0x00, 0x00, 0x7f})
+
+ NearestNeighbor.Scale(dst, dst.Bounds(), src, src.Bounds(), op, nil)
+
+ if got := dst.RGBAAt(0, 0); got != want {
+ t.Errorf("op=%v: got %v, want %v", op, got, want)
+ }
+ }
+}
+
+// TestNegativeWeights tests that scaling by a kernel that produces negative
+// weights, such as the Catmull-Rom kernel, doesn't produce an invalid color
+// according to Go's alpha-premultiplied model.
+func TestNegativeWeights(t *testing.T) {
+ check := func(m *image.RGBA) error {
+ b := m.Bounds()
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ if c := m.RGBAAt(x, y); c.R > c.A || c.G > c.A || c.B > c.A {
+ return fmt.Errorf("invalid color.RGBA at (%d, %d): %v", x, y, c)
+ }
+ }
+ }
+ return nil
+ }
+
+ src := image.NewRGBA(image.Rect(0, 0, 16, 16))
+ for y := 0; y < 16; y++ {
+ for x := 0; x < 16; x++ {
+ a := y * 0x11
+ src.Set(x, y, color.RGBA{
+ R: uint8(x * 0x11 * a / 0xff),
+ A: uint8(a),
+ })
+ }
+ }
+ if err := check(src); err != nil {
+ t.Fatalf("src image: %v", err)
+ }
+
+ dst := image.NewRGBA(image.Rect(0, 0, 32, 32))
+ CatmullRom.Scale(dst, dst.Bounds(), src, src.Bounds(), Over, nil)
+ if err := check(dst); err != nil {
+ t.Fatalf("dst image: %v", err)
+ }
+}
+
+func fillPix(r *rand.Rand, pixs ...[]byte) {
+ for _, pix := range pixs {
+ for i := range pix {
+ pix[i] = uint8(r.Intn(256))
+ }
+ }
+}
+
+func TestInterpClipCommute(t *testing.T) {
+ src := image.NewNRGBA(image.Rect(0, 0, 20, 20))
+ fillPix(rand.New(rand.NewSource(0)), src.Pix)
+
+ outer := image.Rect(1, 1, 8, 5)
+ inner := image.Rect(2, 3, 6, 5)
+ qs := []Interpolator{
+ NearestNeighbor,
+ ApproxBiLinear,
+ CatmullRom,
+ }
+ for _, transform := range []bool{false, true} {
+ for _, q := range qs {
+ dst0 := image.NewRGBA(image.Rect(1, 1, 10, 10))
+ dst1 := image.NewRGBA(image.Rect(1, 1, 10, 10))
+ for i := range dst0.Pix {
+ dst0.Pix[i] = uint8(i / 4)
+ dst1.Pix[i] = uint8(i / 4)
+ }
+
+ var interp func(dst *image.RGBA)
+ if transform {
+ interp = func(dst *image.RGBA) {
+ q.Transform(dst, transformMatrix(3.75, 2, 1), src, src.Bounds(), Over, nil)
+ }
+ } else {
+ interp = func(dst *image.RGBA) {
+ q.Scale(dst, outer, src, src.Bounds(), Over, nil)
+ }
+ }
+
+ // Interpolate then clip.
+ interp(dst0)
+ dst0 = dst0.SubImage(inner).(*image.RGBA)
+
+ // Clip then interpolate.
+ dst1 = dst1.SubImage(inner).(*image.RGBA)
+ interp(dst1)
+
+ loop:
+ for y := inner.Min.Y; y < inner.Max.Y; y++ {
+ for x := inner.Min.X; x < inner.Max.X; x++ {
+ if c0, c1 := dst0.RGBAAt(x, y), dst1.RGBAAt(x, y); c0 != c1 {
+ t.Errorf("q=%T: at (%d, %d): c0=%v, c1=%v", q, x, y, c0, c1)
+ break loop
+ }
+ }
+ }
+ }
+ }
+}
+
+// translatedImage is an image m translated by t.
+type translatedImage struct {
+ m image.Image
+ t image.Point
+}
+
+func (t *translatedImage) At(x, y int) color.Color { return t.m.At(x-t.t.X, y-t.t.Y) }
+func (t *translatedImage) Bounds() image.Rectangle { return t.m.Bounds().Add(t.t) }
+func (t *translatedImage) ColorModel() color.Model { return t.m.ColorModel() }
+
+// TestSrcTranslationInvariance tests that Scale and Transform are invariant
+// under src translations. Specifically, when some source pixels are not in the
+// bottom-right quadrant of src coordinate space, we consistently round down,
+// not round towards zero.
+func TestSrcTranslationInvariance(t *testing.T) {
+ f, err := os.Open("../testdata/testpattern.png")
+ if err != nil {
+ t.Fatalf("Open: %v", err)
+ }
+ defer f.Close()
+ src, _, err := image.Decode(f)
+ if err != nil {
+ t.Fatalf("Decode: %v", err)
+ }
+ sr := image.Rect(2, 3, 16, 12)
+ if !sr.In(src.Bounds()) {
+ t.Fatalf("src bounds too small: got %v", src.Bounds())
+ }
+ qs := []Interpolator{
+ NearestNeighbor,
+ ApproxBiLinear,
+ CatmullRom,
+ }
+ deltas := []image.Point{
+ {+0, +0},
+ {+0, +5},
+ {+0, -5},
+ {+5, +0},
+ {-5, +0},
+ {+8, +8},
+ {+8, -8},
+ {-8, +8},
+ {-8, -8},
+ }
+ m00 := transformMatrix(3.75, 0, 0)
+
+ for _, transform := range []bool{false, true} {
+ for _, q := range qs {
+ want := image.NewRGBA(image.Rect(0, 0, 20, 20))
+ if transform {
+ q.Transform(want, m00, src, sr, Over, nil)
+ } else {
+ q.Scale(want, want.Bounds(), src, sr, Over, nil)
+ }
+ for _, delta := range deltas {
+ tsrc := &translatedImage{src, delta}
+ got := image.NewRGBA(image.Rect(0, 0, 20, 20))
+ if transform {
+ m := matMul(&m00, &f64.Aff3{
+ 1, 0, -float64(delta.X),
+ 0, 1, -float64(delta.Y),
+ })
+ q.Transform(got, m, tsrc, sr.Add(delta), Over, nil)
+ } else {
+ q.Scale(got, got.Bounds(), tsrc, sr.Add(delta), Over, nil)
+ }
+ if !bytes.Equal(got.Pix, want.Pix) {
+ t.Errorf("pix differ for delta=%v, transform=%t, q=%T", delta, transform, q)
+ }
+ }
+ }
+ }
+}
+
+func TestSrcMask(t *testing.T) {
+ srcMask := image.NewRGBA(image.Rect(0, 0, 23, 1))
+ srcMask.SetRGBA(19, 0, color.RGBA{0x00, 0x00, 0x00, 0x7f})
+ srcMask.SetRGBA(20, 0, color.RGBA{0x00, 0x00, 0x00, 0xff})
+ srcMask.SetRGBA(21, 0, color.RGBA{0x00, 0x00, 0x00, 0x3f})
+ srcMask.SetRGBA(22, 0, color.RGBA{0x00, 0x00, 0x00, 0x00})
+ red := image.NewUniform(color.RGBA{0xff, 0x00, 0x00, 0xff})
+ blue := image.NewUniform(color.RGBA{0x00, 0x00, 0xff, 0xff})
+ dst := image.NewRGBA(image.Rect(0, 0, 6, 1))
+ Copy(dst, image.Point{}, blue, dst.Bounds(), Src, nil)
+ NearestNeighbor.Scale(dst, dst.Bounds(), red, image.Rect(0, 0, 3, 1), Over, &Options{
+ SrcMask: srcMask,
+ SrcMaskP: image.Point{20, 0},
+ })
+ got := [6]color.RGBA{
+ dst.RGBAAt(0, 0),
+ dst.RGBAAt(1, 0),
+ dst.RGBAAt(2, 0),
+ dst.RGBAAt(3, 0),
+ dst.RGBAAt(4, 0),
+ dst.RGBAAt(5, 0),
+ }
+ want := [6]color.RGBA{
+ {0xff, 0x00, 0x00, 0xff},
+ {0xff, 0x00, 0x00, 0xff},
+ {0x3f, 0x00, 0xc0, 0xff},
+ {0x3f, 0x00, 0xc0, 0xff},
+ {0x00, 0x00, 0xff, 0xff},
+ {0x00, 0x00, 0xff, 0xff},
+ }
+ if got != want {
+ t.Errorf("\ngot %v\nwant %v", got, want)
+ }
+}
+
+func TestDstMask(t *testing.T) {
+ dstMask := image.NewRGBA(image.Rect(0, 0, 23, 1))
+ dstMask.SetRGBA(19, 0, color.RGBA{0x00, 0x00, 0x00, 0x7f})
+ dstMask.SetRGBA(20, 0, color.RGBA{0x00, 0x00, 0x00, 0xff})
+ dstMask.SetRGBA(21, 0, color.RGBA{0x00, 0x00, 0x00, 0x3f})
+ dstMask.SetRGBA(22, 0, color.RGBA{0x00, 0x00, 0x00, 0x00})
+ red := image.NewRGBA(image.Rect(0, 0, 1, 1))
+ red.SetRGBA(0, 0, color.RGBA{0xff, 0x00, 0x00, 0xff})
+ blue := image.NewUniform(color.RGBA{0x00, 0x00, 0xff, 0xff})
+ qs := []Interpolator{
+ NearestNeighbor,
+ ApproxBiLinear,
+ CatmullRom,
+ }
+ for _, q := range qs {
+ dst := image.NewRGBA(image.Rect(0, 0, 3, 1))
+ Copy(dst, image.Point{}, blue, dst.Bounds(), Src, nil)
+ q.Scale(dst, dst.Bounds(), red, red.Bounds(), Over, &Options{
+ DstMask: dstMask,
+ DstMaskP: image.Point{20, 0},
+ })
+ got := [3]color.RGBA{
+ dst.RGBAAt(0, 0),
+ dst.RGBAAt(1, 0),
+ dst.RGBAAt(2, 0),
+ }
+ want := [3]color.RGBA{
+ {0xff, 0x00, 0x00, 0xff},
+ {0x3f, 0x00, 0xc0, 0xff},
+ {0x00, 0x00, 0xff, 0xff},
+ }
+ if got != want {
+ t.Errorf("q=%T:\ngot %v\nwant %v", q, got, want)
+ }
+ }
+}
+
+func TestRectDstMask(t *testing.T) {
+ f, err := os.Open("../testdata/testpattern.png")
+ if err != nil {
+ t.Fatalf("Open: %v", err)
+ }
+ defer f.Close()
+ src, _, err := image.Decode(f)
+ if err != nil {
+ t.Fatalf("Decode: %v", err)
+ }
+ m00 := transformMatrix(1, 0, 0)
+
+ bounds := image.Rect(0, 0, 50, 50)
+ dstOutside := image.NewRGBA(bounds)
+ for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
+ for x := bounds.Min.X; x < bounds.Max.X; x++ {
+ dstOutside.SetRGBA(x, y, color.RGBA{uint8(5 * x), uint8(5 * y), 0x00, 0xff})
+ }
+ }
+
+ mk := func(q Transformer, dstMask image.Image, dstMaskP image.Point) *image.RGBA {
+ m := image.NewRGBA(bounds)
+ Copy(m, bounds.Min, dstOutside, bounds, Src, nil)
+ q.Transform(m, m00, src, src.Bounds(), Over, &Options{
+ DstMask: dstMask,
+ DstMaskP: dstMaskP,
+ })
+ return m
+ }
+
+ qs := []Interpolator{
+ NearestNeighbor,
+ ApproxBiLinear,
+ CatmullRom,
+ }
+ dstMaskPs := []image.Point{
+ {0, 0},
+ {5, 7},
+ {-3, 0},
+ }
+ rect := image.Rect(10, 10, 30, 40)
+ for _, q := range qs {
+ for _, dstMaskP := range dstMaskPs {
+ dstInside := mk(q, nil, image.Point{})
+ for _, wrap := range []bool{false, true} {
+ // TODO: replace "rectImage(rect)" with "rect" once Go 1.5 is
+ // released, where an image.Rectangle implements image.Image.
+ dstMask := image.Image(rectImage(rect))
+ if wrap {
+ dstMask = srcWrapper{dstMask}
+ }
+ dst := mk(q, dstMask, dstMaskP)
+
+ nError := 0
+ loop:
+ for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
+ for x := bounds.Min.X; x < bounds.Max.X; x++ {
+ which := dstOutside
+ if (image.Point{x, y}).Add(dstMaskP).In(rect) {
+ which = dstInside
+ }
+ if got, want := dst.RGBAAt(x, y), which.RGBAAt(x, y); got != want {
+ if nError == 10 {
+ t.Errorf("q=%T dmp=%v wrap=%v: ...and more errors", q, dstMaskP, wrap)
+ break loop
+ }
+ nError++
+ t.Errorf("q=%T dmp=%v wrap=%v: x=%3d y=%3d: got %v, want %v",
+ q, dstMaskP, wrap, x, y, got, want)
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+func TestDstMaskSameSizeCopy(t *testing.T) {
+ bounds := image.Rect(0, 0, 42, 42)
+ src := image.Opaque
+ dst := image.NewRGBA(bounds)
+ mask := image.NewRGBA(bounds)
+
+ Copy(dst, image.ZP, src, bounds, Src, &Options{
+ DstMask: mask,
+ })
+}
+
+// TODO: delete this wrapper type once Go 1.5 is released, where an
+// image.Rectangle implements image.Image.
+type rectImage image.Rectangle
+
+func (r rectImage) ColorModel() color.Model { return color.Alpha16Model }
+func (r rectImage) Bounds() image.Rectangle { return image.Rectangle(r) }
+func (r rectImage) At(x, y int) color.Color {
+ if (image.Point{x, y}).In(image.Rectangle(r)) {
+ return color.Opaque
+ }
+ return color.Transparent
+}
+
+// The fooWrapper types wrap the dst or src image to avoid triggering the
+// type-specific fast path implementations.
+type (
+ dstWrapper struct{ Image }
+ srcWrapper struct{ image.Image }
+)
+
+func srcGray(boundsHint image.Rectangle) (image.Image, error) {
+ m := image.NewGray(boundsHint)
+ fillPix(rand.New(rand.NewSource(0)), m.Pix)
+ return m, nil
+}
+
+func srcNRGBA(boundsHint image.Rectangle) (image.Image, error) {
+ m := image.NewNRGBA(boundsHint)
+ fillPix(rand.New(rand.NewSource(1)), m.Pix)
+ return m, nil
+}
+
+func srcRGBA(boundsHint image.Rectangle) (image.Image, error) {
+ m := image.NewRGBA(boundsHint)
+ fillPix(rand.New(rand.NewSource(2)), m.Pix)
+ // RGBA is alpha-premultiplied, so the R, G and B values should
+ // be <= the A values.
+ for i := 0; i < len(m.Pix); i += 4 {
+ m.Pix[i+0] = uint8(uint32(m.Pix[i+0]) * uint32(m.Pix[i+3]) / 0xff)
+ m.Pix[i+1] = uint8(uint32(m.Pix[i+1]) * uint32(m.Pix[i+3]) / 0xff)
+ m.Pix[i+2] = uint8(uint32(m.Pix[i+2]) * uint32(m.Pix[i+3]) / 0xff)
+ }
+ return m, nil
+}
+
+func srcUnif(boundsHint image.Rectangle) (image.Image, error) {
+ return image.NewUniform(color.RGBA64{0x1234, 0x5555, 0x9181, 0xbeef}), nil
+}
+
+func srcYCbCr(boundsHint image.Rectangle) (image.Image, error) {
+ m := image.NewYCbCr(boundsHint, image.YCbCrSubsampleRatio420)
+ fillPix(rand.New(rand.NewSource(3)), m.Y, m.Cb, m.Cr)
+ return m, nil
+}
+
+func srcLarge(boundsHint image.Rectangle) (image.Image, error) {
+ // 3072 x 2304 is over 7 million pixels at 4:3, comparable to a
+ // 2015 smart-phone camera's output.
+ return srcYCbCr(image.Rect(0, 0, 3072, 2304))
+}
+
+func srcTux(boundsHint image.Rectangle) (image.Image, error) {
+ // tux.png is a 386 x 395 image.
+ f, err := os.Open("../testdata/tux.png")
+ if err != nil {
+ return nil, fmt.Errorf("Open: %v", err)
+ }
+ defer f.Close()
+ src, err := png.Decode(f)
+ if err != nil {
+ return nil, fmt.Errorf("Decode: %v", err)
+ }
+ return src, nil
+}
+
+func benchScale(b *testing.B, w int, h int, op Op, srcf func(image.Rectangle) (image.Image, error), q Interpolator) {
+ dst := image.NewRGBA(image.Rect(0, 0, w, h))
+ src, err := srcf(image.Rect(0, 0, 1024, 768))
+ if err != nil {
+ b.Fatal(err)
+ }
+ dr, sr := dst.Bounds(), src.Bounds()
+ scaler := Scaler(q)
+ if n, ok := q.(interface {
+ NewScaler(int, int, int, int) Scaler
+ }); ok {
+ scaler = n.NewScaler(dr.Dx(), dr.Dy(), sr.Dx(), sr.Dy())
+ }
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ scaler.Scale(dst, dr, src, sr, op, nil)
+ }
+}
+
+func benchTform(b *testing.B, w int, h int, op Op, srcf func(image.Rectangle) (image.Image, error), q Interpolator) {
+ dst := image.NewRGBA(image.Rect(0, 0, w, h))
+ src, err := srcf(image.Rect(0, 0, 1024, 768))
+ if err != nil {
+ b.Fatal(err)
+ }
+ sr := src.Bounds()
+ m := transformMatrix(3.75, 40, 10)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ q.Transform(dst, m, src, sr, op, nil)
+ }
+}
+
+func BenchmarkScaleNNLargeDown(b *testing.B) { benchScale(b, 200, 150, Src, srcLarge, NearestNeighbor) }
+func BenchmarkScaleABLargeDown(b *testing.B) { benchScale(b, 200, 150, Src, srcLarge, ApproxBiLinear) }
+func BenchmarkScaleBLLargeDown(b *testing.B) { benchScale(b, 200, 150, Src, srcLarge, BiLinear) }
+func BenchmarkScaleCRLargeDown(b *testing.B) { benchScale(b, 200, 150, Src, srcLarge, CatmullRom) }
+
+func BenchmarkScaleNNDown(b *testing.B) { benchScale(b, 120, 80, Src, srcTux, NearestNeighbor) }
+func BenchmarkScaleABDown(b *testing.B) { benchScale(b, 120, 80, Src, srcTux, ApproxBiLinear) }
+func BenchmarkScaleBLDown(b *testing.B) { benchScale(b, 120, 80, Src, srcTux, BiLinear) }
+func BenchmarkScaleCRDown(b *testing.B) { benchScale(b, 120, 80, Src, srcTux, CatmullRom) }
+
+func BenchmarkScaleNNUp(b *testing.B) { benchScale(b, 800, 600, Src, srcTux, NearestNeighbor) }
+func BenchmarkScaleABUp(b *testing.B) { benchScale(b, 800, 600, Src, srcTux, ApproxBiLinear) }
+func BenchmarkScaleBLUp(b *testing.B) { benchScale(b, 800, 600, Src, srcTux, BiLinear) }
+func BenchmarkScaleCRUp(b *testing.B) { benchScale(b, 800, 600, Src, srcTux, CatmullRom) }
+
+func BenchmarkScaleNNSrcRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcRGBA, NearestNeighbor) }
+func BenchmarkScaleNNSrcUnif(b *testing.B) { benchScale(b, 200, 150, Src, srcUnif, NearestNeighbor) }
+
+func BenchmarkScaleNNOverRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcRGBA, NearestNeighbor) }
+func BenchmarkScaleNNOverUnif(b *testing.B) { benchScale(b, 200, 150, Over, srcUnif, NearestNeighbor) }
+
+func BenchmarkTformNNSrcRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcRGBA, NearestNeighbor) }
+func BenchmarkTformNNSrcUnif(b *testing.B) { benchTform(b, 200, 150, Src, srcUnif, NearestNeighbor) }
+
+func BenchmarkTformNNOverRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcRGBA, NearestNeighbor) }
+func BenchmarkTformNNOverUnif(b *testing.B) { benchTform(b, 200, 150, Over, srcUnif, NearestNeighbor) }
+
+func BenchmarkScaleABSrcGray(b *testing.B) { benchScale(b, 200, 150, Src, srcGray, ApproxBiLinear) }
+func BenchmarkScaleABSrcNRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcNRGBA, ApproxBiLinear) }
+func BenchmarkScaleABSrcRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcRGBA, ApproxBiLinear) }
+func BenchmarkScaleABSrcYCbCr(b *testing.B) { benchScale(b, 200, 150, Src, srcYCbCr, ApproxBiLinear) }
+
+func BenchmarkScaleABOverGray(b *testing.B) { benchScale(b, 200, 150, Over, srcGray, ApproxBiLinear) }
+func BenchmarkScaleABOverNRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcNRGBA, ApproxBiLinear) }
+func BenchmarkScaleABOverRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcRGBA, ApproxBiLinear) }
+func BenchmarkScaleABOverYCbCr(b *testing.B) { benchScale(b, 200, 150, Over, srcYCbCr, ApproxBiLinear) }
+
+func BenchmarkTformABSrcGray(b *testing.B) { benchTform(b, 200, 150, Src, srcGray, ApproxBiLinear) }
+func BenchmarkTformABSrcNRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcNRGBA, ApproxBiLinear) }
+func BenchmarkTformABSrcRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcRGBA, ApproxBiLinear) }
+func BenchmarkTformABSrcYCbCr(b *testing.B) { benchTform(b, 200, 150, Src, srcYCbCr, ApproxBiLinear) }
+
+func BenchmarkTformABOverGray(b *testing.B) { benchTform(b, 200, 150, Over, srcGray, ApproxBiLinear) }
+func BenchmarkTformABOverNRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcNRGBA, ApproxBiLinear) }
+func BenchmarkTformABOverRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcRGBA, ApproxBiLinear) }
+func BenchmarkTformABOverYCbCr(b *testing.B) { benchTform(b, 200, 150, Over, srcYCbCr, ApproxBiLinear) }
+
+func BenchmarkScaleCRSrcGray(b *testing.B) { benchScale(b, 200, 150, Src, srcGray, CatmullRom) }
+func BenchmarkScaleCRSrcNRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcNRGBA, CatmullRom) }
+func BenchmarkScaleCRSrcRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcRGBA, CatmullRom) }
+func BenchmarkScaleCRSrcYCbCr(b *testing.B) { benchScale(b, 200, 150, Src, srcYCbCr, CatmullRom) }
+
+func BenchmarkScaleCROverGray(b *testing.B) { benchScale(b, 200, 150, Over, srcGray, CatmullRom) }
+func BenchmarkScaleCROverNRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcNRGBA, CatmullRom) }
+func BenchmarkScaleCROverRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcRGBA, CatmullRom) }
+func BenchmarkScaleCROverYCbCr(b *testing.B) { benchScale(b, 200, 150, Over, srcYCbCr, CatmullRom) }
+
+func BenchmarkTformCRSrcGray(b *testing.B) { benchTform(b, 200, 150, Src, srcGray, CatmullRom) }
+func BenchmarkTformCRSrcNRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcNRGBA, CatmullRom) }
+func BenchmarkTformCRSrcRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcRGBA, CatmullRom) }
+func BenchmarkTformCRSrcYCbCr(b *testing.B) { benchTform(b, 200, 150, Src, srcYCbCr, CatmullRom) }
+
+func BenchmarkTformCROverGray(b *testing.B) { benchTform(b, 200, 150, Over, srcGray, CatmullRom) }
+func BenchmarkTformCROverNRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcNRGBA, CatmullRom) }
+func BenchmarkTformCROverRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcRGBA, CatmullRom) }
+func BenchmarkTformCROverYCbCr(b *testing.B) { benchTform(b, 200, 150, Over, srcYCbCr, CatmullRom) }
diff --git a/vendor/golang.org/x/image/draw/stdlib_test.go b/vendor/golang.org/x/image/draw/stdlib_test.go
new file mode 100644
index 0000000..9015bfd
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/stdlib_test.go
@@ -0,0 +1,96 @@
+// Copyright 2015 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.9
+
+package draw
+
+// This file contains tests that depend on the exact behavior of the
+// image/color package in the standard library. The color conversion formula
+// from YCbCr to RGBA changed between Go 1.4 and Go 1.5, and between Go 1.8 and
+// Go 1.9, so this file's tests are only enabled for Go 1.9 and above.
+
+import (
+ "bytes"
+ "image"
+ "image/color"
+ "testing"
+)
+
+// TestFastPaths tests that the fast path implementations produce identical
+// results to the generic implementation.
+func TestFastPaths(t *testing.T) {
+ drs := []image.Rectangle{
+ image.Rect(0, 0, 10, 10), // The dst bounds.
+ image.Rect(3, 4, 8, 6), // A strict subset of the dst bounds.
+ image.Rect(-3, -5, 2, 4), // Partial out-of-bounds #0.
+ image.Rect(4, -2, 6, 12), // Partial out-of-bounds #1.
+ image.Rect(12, 14, 23, 45), // Complete out-of-bounds.
+ image.Rect(5, 5, 5, 5), // Empty.
+ }
+ srs := []image.Rectangle{
+ image.Rect(0, 0, 12, 9), // The src bounds.
+ image.Rect(2, 2, 10, 8), // A strict subset of the src bounds.
+ image.Rect(10, 5, 20, 20), // Partial out-of-bounds #0.
+ image.Rect(-40, 0, 40, 8), // Partial out-of-bounds #1.
+ image.Rect(-8, -8, -4, -4), // Complete out-of-bounds.
+ image.Rect(5, 5, 5, 5), // Empty.
+ }
+ srcfs := []func(image.Rectangle) (image.Image, error){
+ srcGray,
+ srcNRGBA,
+ srcRGBA,
+ srcUnif,
+ srcYCbCr,
+ }
+ var srcs []image.Image
+ for _, srcf := range srcfs {
+ src, err := srcf(srs[0])
+ if err != nil {
+ t.Fatal(err)
+ }
+ srcs = append(srcs, src)
+ }
+ qs := []Interpolator{
+ NearestNeighbor,
+ ApproxBiLinear,
+ CatmullRom,
+ }
+ ops := []Op{
+ Over,
+ Src,
+ }
+ blue := image.NewUniform(color.RGBA{0x11, 0x22, 0x44, 0x7f})
+
+ for _, dr := range drs {
+ for _, src := range srcs {
+ for _, sr := range srs {
+ for _, transform := range []bool{false, true} {
+ for _, q := range qs {
+ for _, op := range ops {
+ dst0 := image.NewRGBA(drs[0])
+ dst1 := image.NewRGBA(drs[0])
+ Draw(dst0, dst0.Bounds(), blue, image.Point{}, Src)
+ Draw(dstWrapper{dst1}, dst1.Bounds(), srcWrapper{blue}, image.Point{}, Src)
+
+ if transform {
+ m := transformMatrix(3.75, 2, 1)
+ q.Transform(dst0, m, src, sr, op, nil)
+ q.Transform(dstWrapper{dst1}, m, srcWrapper{src}, sr, op, nil)
+ } else {
+ q.Scale(dst0, dr, src, sr, op, nil)
+ q.Scale(dstWrapper{dst1}, dr, srcWrapper{src}, sr, op, nil)
+ }
+
+ if !bytes.Equal(dst0.Pix, dst1.Pix) {
+ t.Errorf("pix differ for dr=%v, src=%T, sr=%v, transform=%t, q=%T",
+ dr, src, sr, transform, q)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/golang.org/x/image/math/f64/f64.go b/vendor/golang.org/x/image/math/f64/f64.go
new file mode 100644
index 0000000..a1f7fc0
--- /dev/null
+++ b/vendor/golang.org/x/image/math/f64/f64.go
@@ -0,0 +1,37 @@
+// Copyright 2015 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 f64 implements float64 vector and matrix types.
+package f64 // import "golang.org/x/image/math/f64"
+
+// Vec2 is a 2-element vector.
+type Vec2 [2]float64
+
+// Vec3 is a 3-element vector.
+type Vec3 [3]float64
+
+// Vec4 is a 4-element vector.
+type Vec4 [4]float64
+
+// Mat3 is a 3x3 matrix in row major order.
+//
+// m[3*r + c] is the element in the r'th row and c'th column.
+type Mat3 [9]float64
+
+// Mat4 is a 4x4 matrix in row major order.
+//
+// m[4*r + c] is the element in the r'th row and c'th column.
+type Mat4 [16]float64
+
+// Aff3 is a 3x3 affine transformation matrix in row major order, where the
+// bottom row is implicitly [0 0 1].
+//
+// m[3*r + c] is the element in the r'th row and c'th column.
+type Aff3 [6]float64
+
+// Aff4 is a 4x4 affine transformation matrix in row major order, where the
+// bottom row is implicitly [0 0 0 1].
+//
+// m[4*r + c] is the element in the r'th row and c'th column.
+type Aff4 [12]float64
diff --git a/vendor/golang.org/x/image/riff/example_test.go b/vendor/golang.org/x/image/riff/example_test.go
new file mode 100644
index 0000000..93c72b0
--- /dev/null
+++ b/vendor/golang.org/x/image/riff/example_test.go
@@ -0,0 +1,113 @@
+// 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 riff_test
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "strings"
+
+ "golang.org/x/image/riff"
+)
+
+func ExampleReader() {
+ formType, r, err := riff.NewReader(strings.NewReader(data))
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Printf("RIFF(%s)\n", formType)
+ if err := dump(r, ".\t"); err != nil {
+ log.Fatal(err)
+ }
+ // Output:
+ // RIFF(ROOT)
+ // . ZERO ""
+ // . ONE "a"
+ // . LIST(META)
+ // . . LIST(GOOD)
+ // . . . ONE "a"
+ // . . . FIVE "klmno"
+ // . . ZERO ""
+ // . . LIST(BAD )
+ // . . . THRE "def"
+ // . TWO "bc"
+ // . LIST(UGLY)
+ // . . FOUR "ghij"
+ // . . SIX "pqrstu"
+}
+
+func dump(r *riff.Reader, indent string) error {
+ for {
+ chunkID, chunkLen, chunkData, err := r.Next()
+ if err == io.EOF {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ if chunkID == riff.LIST {
+ listType, list, err := riff.NewListReader(chunkLen, chunkData)
+ if err != nil {
+ return err
+ }
+ fmt.Printf("%sLIST(%s)\n", indent, listType)
+ if err := dump(list, indent+".\t"); err != nil {
+ return err
+ }
+ continue
+ }
+ b, err := ioutil.ReadAll(chunkData)
+ if err != nil {
+ return err
+ }
+ fmt.Printf("%s%s %q\n", indent, chunkID, b)
+ }
+}
+
+func encodeU32(u uint32) string {
+ return string([]byte{
+ byte(u >> 0),
+ byte(u >> 8),
+ byte(u >> 16),
+ byte(u >> 24),
+ })
+}
+
+func encode(chunkID, contents string) string {
+ n := len(contents)
+ if n&1 == 1 {
+ contents += "\x00"
+ }
+ return chunkID + encodeU32(uint32(n)) + contents
+}
+
+func encodeMulti(typ0, typ1 string, chunks ...string) string {
+ n := 4
+ for _, c := range chunks {
+ n += len(c)
+ }
+ s := typ0 + encodeU32(uint32(n)) + typ1
+ for _, c := range chunks {
+ s += c
+ }
+ return s
+}
+
+var (
+ d0 = encode("ZERO", "")
+ d1 = encode("ONE ", "a")
+ d2 = encode("TWO ", "bc")
+ d3 = encode("THRE", "def")
+ d4 = encode("FOUR", "ghij")
+ d5 = encode("FIVE", "klmno")
+ d6 = encode("SIX ", "pqrstu")
+ l0 = encodeMulti("LIST", "GOOD", d1, d5)
+ l1 = encodeMulti("LIST", "BAD ", d3)
+ l2 = encodeMulti("LIST", "UGLY", d4, d6)
+ l01 = encodeMulti("LIST", "META", l0, d0, l1)
+ data = encodeMulti("RIFF", "ROOT", d0, d1, l01, d2, l2)
+)
diff --git a/vendor/golang.org/x/image/riff/riff.go b/vendor/golang.org/x/image/riff/riff.go
new file mode 100644
index 0000000..38dc0e5
--- /dev/null
+++ b/vendor/golang.org/x/image/riff/riff.go
@@ -0,0 +1,193 @@
+// 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 riff implements the Resource Interchange File Format, used by media
+// formats such as AVI, WAVE and WEBP.
+//
+// A RIFF stream contains a sequence of chunks. Each chunk consists of an 8-byte
+// header (containing a 4-byte chunk type and a 4-byte chunk length), the chunk
+// data (presented as an io.Reader), and some padding bytes.
+//
+// A detailed description of the format is at
+// http://www.tactilemedia.com/info/MCI_Control_Info.html
+package riff // import "golang.org/x/image/riff"
+
+import (
+ "errors"
+ "io"
+ "io/ioutil"
+ "math"
+)
+
+var (
+ errMissingPaddingByte = errors.New("riff: missing padding byte")
+ errMissingRIFFChunkHeader = errors.New("riff: missing RIFF chunk header")
+ errListSubchunkTooLong = errors.New("riff: list subchunk too long")
+ errShortChunkData = errors.New("riff: short chunk data")
+ errShortChunkHeader = errors.New("riff: short chunk header")
+ errStaleReader = errors.New("riff: stale reader")
+)
+
+// u32 decodes the first four bytes of b as a little-endian integer.
+func u32(b []byte) uint32 {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+const chunkHeaderSize = 8
+
+// FourCC is a four character code.
+type FourCC [4]byte
+
+// LIST is the "LIST" FourCC.
+var LIST = FourCC{'L', 'I', 'S', 'T'}
+
+// NewReader returns the RIFF stream's form type, such as "AVI " or "WAVE", and
+// its chunks as a *Reader.
+func NewReader(r io.Reader) (formType FourCC, data *Reader, err error) {
+ var buf [chunkHeaderSize]byte
+ if _, err := io.ReadFull(r, buf[:]); err != nil {
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
+ err = errMissingRIFFChunkHeader
+ }
+ return FourCC{}, nil, err
+ }
+ if buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F' {
+ return FourCC{}, nil, errMissingRIFFChunkHeader
+ }
+ return NewListReader(u32(buf[4:]), r)
+}
+
+// NewListReader returns a LIST chunk's list type, such as "movi" or "wavl",
+// and its chunks as a *Reader.
+func NewListReader(chunkLen uint32, chunkData io.Reader) (listType FourCC, data *Reader, err error) {
+ if chunkLen < 4 {
+ return FourCC{}, nil, errShortChunkData
+ }
+ z := &Reader{r: chunkData}
+ if _, err := io.ReadFull(chunkData, z.buf[:4]); err != nil {
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
+ err = errShortChunkData
+ }
+ return FourCC{}, nil, err
+ }
+ z.totalLen = chunkLen - 4
+ return FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}, z, nil
+}
+
+// Reader reads chunks from an underlying io.Reader.
+type Reader struct {
+ r io.Reader
+ err error
+
+ totalLen uint32
+ chunkLen uint32
+
+ chunkReader *chunkReader
+ buf [chunkHeaderSize]byte
+ padded bool
+}
+
+// Next returns the next chunk's ID, length and data. It returns io.EOF if there
+// are no more chunks. The io.Reader returned becomes stale after the next Next
+// call, and should no longer be used.
+//
+// It is valid to call Next even if all of the previous chunk's data has not
+// been read.
+func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, err error) {
+ if z.err != nil {
+ return FourCC{}, 0, nil, z.err
+ }
+
+ // Drain the rest of the previous chunk.
+ if z.chunkLen != 0 {
+ want := z.chunkLen
+ var got int64
+ got, z.err = io.Copy(ioutil.Discard, z.chunkReader)
+ if z.err == nil && uint32(got) != want {
+ z.err = errShortChunkData
+ }
+ if z.err != nil {
+ return FourCC{}, 0, nil, z.err
+ }
+ }
+ z.chunkReader = nil
+ if z.padded {
+ if z.totalLen == 0 {
+ z.err = errListSubchunkTooLong
+ return FourCC{}, 0, nil, z.err
+ }
+ z.totalLen--
+ _, z.err = io.ReadFull(z.r, z.buf[:1])
+ if z.err != nil {
+ if z.err == io.EOF {
+ z.err = errMissingPaddingByte
+ }
+ return FourCC{}, 0, nil, z.err
+ }
+ }
+
+ // We are done if we have no more data.
+ if z.totalLen == 0 {
+ z.err = io.EOF
+ return FourCC{}, 0, nil, z.err
+ }
+
+ // Read the next chunk header.
+ if z.totalLen < chunkHeaderSize {
+ z.err = errShortChunkHeader
+ return FourCC{}, 0, nil, z.err
+ }
+ z.totalLen -= chunkHeaderSize
+ if _, z.err = io.ReadFull(z.r, z.buf[:chunkHeaderSize]); z.err != nil {
+ if z.err == io.EOF || z.err == io.ErrUnexpectedEOF {
+ z.err = errShortChunkHeader
+ }
+ return FourCC{}, 0, nil, z.err
+ }
+ chunkID = FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}
+ z.chunkLen = u32(z.buf[4:])
+ if z.chunkLen > z.totalLen {
+ z.err = errListSubchunkTooLong
+ return FourCC{}, 0, nil, z.err
+ }
+ z.padded = z.chunkLen&1 == 1
+ z.chunkReader = &chunkReader{z}
+ return chunkID, z.chunkLen, z.chunkReader, nil
+}
+
+type chunkReader struct {
+ z *Reader
+}
+
+func (c *chunkReader) Read(p []byte) (int, error) {
+ if c != c.z.chunkReader {
+ return 0, errStaleReader
+ }
+ z := c.z
+ if z.err != nil {
+ if z.err == io.EOF {
+ return 0, errStaleReader
+ }
+ return 0, z.err
+ }
+
+ n := int(z.chunkLen)
+ if n == 0 {
+ return 0, io.EOF
+ }
+ if n < 0 {
+ // Converting uint32 to int overflowed.
+ n = math.MaxInt32
+ }
+ if n > len(p) {
+ n = len(p)
+ }
+ n, err := z.r.Read(p[:n])
+ z.totalLen -= uint32(n)
+ z.chunkLen -= uint32(n)
+ if err != io.EOF {
+ z.err = err
+ }
+ return n, err
+}
diff --git a/vendor/golang.org/x/image/riff/riff_test.go b/vendor/golang.org/x/image/riff/riff_test.go
new file mode 100644
index 0000000..567e938
--- /dev/null
+++ b/vendor/golang.org/x/image/riff/riff_test.go
@@ -0,0 +1,69 @@
+// 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 riff
+
+import (
+ "bytes"
+ "testing"
+)
+
+func encodeU32(u uint32) []byte {
+ return []byte{
+ byte(u >> 0),
+ byte(u >> 8),
+ byte(u >> 16),
+ byte(u >> 24),
+ }
+}
+
+func TestShortChunks(t *testing.T) {
+ // s is a RIFF(ABCD) with allegedly 256 bytes of data (excluding the
+ // leading 8-byte "RIFF\x00\x01\x00\x00"). The first chunk of that ABCD
+ // list is an abcd chunk of length m followed by n zeroes.
+ for _, m := range []uint32{0, 8, 15, 200, 300} {
+ for _, n := range []int{0, 1, 2, 7} {
+ s := []byte("RIFF\x00\x01\x00\x00ABCDabcd")
+ s = append(s, encodeU32(m)...)
+ s = append(s, make([]byte, n)...)
+ _, r, err := NewReader(bytes.NewReader(s))
+ if err != nil {
+ t.Errorf("m=%d, n=%d: NewReader: %v", m, n, err)
+ continue
+ }
+
+ _, _, _, err0 := r.Next()
+ // The total "ABCD" list length is 256 bytes, of which the first 12
+ // bytes are "ABCDabcd" plus the 4-byte encoding of m. If the
+ // "abcd" subchunk length (m) plus those 12 bytes is greater than
+ // the total list length, we have an invalid RIFF, and we expect an
+ // errListSubchunkTooLong error.
+ if m+12 > 256 {
+ if err0 != errListSubchunkTooLong {
+ t.Errorf("m=%d, n=%d: Next #0: got %v, want %v", m, n, err0, errListSubchunkTooLong)
+ }
+ continue
+ }
+ // Otherwise, we expect a nil error.
+ if err0 != nil {
+ t.Errorf("m=%d, n=%d: Next #0: %v", m, n, err0)
+ continue
+ }
+
+ _, _, _, err1 := r.Next()
+ // If m > 0, then m > n, so that "abcd" subchunk doesn't have m
+ // bytes of data. If m == 0, then that "abcd" subchunk is OK in
+ // that it has 0 extra bytes of data, but the next subchunk (8 byte
+ // header plus body) is missing, as we only have n < 8 more bytes.
+ want := errShortChunkData
+ if m == 0 {
+ want = errShortChunkHeader
+ }
+ if err1 != want {
+ t.Errorf("m=%d, n=%d: Next #1: got %v, want %v", m, n, err1, want)
+ continue
+ }
+ }
+ }
+}
diff --git a/vendor/golang.org/x/image/vp8/decode.go b/vendor/golang.org/x/image/vp8/decode.go
new file mode 100644
index 0000000..1bb5028
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/decode.go
@@ -0,0 +1,403 @@
+// 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.
+
+// Package vp8 implements a decoder for the VP8 lossy image format.
+//
+// The VP8 specification is RFC 6386.
+package vp8 // import "golang.org/x/image/vp8"
+
+// This file implements the top-level decoding algorithm.
+
+import (
+ "errors"
+ "image"
+ "io"
+)
+
+// limitReader wraps an io.Reader to read at most n bytes from it.
+type limitReader struct {
+ r io.Reader
+ n int
+}
+
+// ReadFull reads exactly len(p) bytes into p.
+func (r *limitReader) ReadFull(p []byte) error {
+ if len(p) > r.n {
+ return io.ErrUnexpectedEOF
+ }
+ n, err := io.ReadFull(r.r, p)
+ r.n -= n
+ return err
+}
+
+// FrameHeader is a frame header, as specified in section 9.1.
+type FrameHeader struct {
+ KeyFrame bool
+ VersionNumber uint8
+ ShowFrame bool
+ FirstPartitionLen uint32
+ Width int
+ Height int
+ XScale uint8
+ YScale uint8
+}
+
+const (
+ nSegment = 4
+ nSegmentProb = 3
+)
+
+// segmentHeader holds segment-related header information.
+type segmentHeader struct {
+ useSegment bool
+ updateMap bool
+ relativeDelta bool
+ quantizer [nSegment]int8
+ filterStrength [nSegment]int8
+ prob [nSegmentProb]uint8
+}
+
+const (
+ nRefLFDelta = 4
+ nModeLFDelta = 4
+)
+
+// filterHeader holds filter-related header information.
+type filterHeader struct {
+ simple bool
+ level int8
+ sharpness uint8
+ useLFDelta bool
+ refLFDelta [nRefLFDelta]int8
+ modeLFDelta [nModeLFDelta]int8
+ perSegmentLevel [nSegment]int8
+}
+
+// mb is the per-macroblock decode state. A decoder maintains mbw+1 of these
+// as it is decoding macroblocks left-to-right and top-to-bottom: mbw for the
+// macroblocks in the row above, and one for the macroblock to the left.
+type mb struct {
+ // pred is the predictor mode for the 4 bottom or right 4x4 luma regions.
+ pred [4]uint8
+ // nzMask is a mask of 8 bits: 4 for the bottom or right 4x4 luma regions,
+ // and 2 + 2 for the bottom or right 4x4 chroma regions. A 1 bit indicates
+ // that that region has non-zero coefficients.
+ nzMask uint8
+ // nzY16 is a 0/1 value that is 1 if the macroblock used Y16 prediction and
+ // had non-zero coefficients.
+ nzY16 uint8
+}
+
+// Decoder decodes VP8 bitstreams into frames. Decoding one frame consists of
+// calling Init, DecodeFrameHeader and then DecodeFrame in that order.
+// A Decoder can be re-used to decode multiple frames.
+type Decoder struct {
+ // r is the input bitsream.
+ r limitReader
+ // scratch is a scratch buffer.
+ scratch [8]byte
+ // img is the YCbCr image to decode into.
+ img *image.YCbCr
+ // mbw and mbh are the number of 16x16 macroblocks wide and high the image is.
+ mbw, mbh int
+ // frameHeader is the frame header. When decoding multiple frames,
+ // frames that aren't key frames will inherit the Width, Height,
+ // XScale and YScale of the most recent key frame.
+ frameHeader FrameHeader
+ // Other headers.
+ segmentHeader segmentHeader
+ filterHeader filterHeader
+ // The image data is divided into a number of independent partitions.
+ // There is 1 "first partition" and between 1 and 8 "other partitions"
+ // for coefficient data.
+ fp partition
+ op [8]partition
+ nOP int
+ // Quantization factors.
+ quant [nSegment]quant
+ // DCT/WHT coefficient decoding probabilities.
+ tokenProb [nPlane][nBand][nContext][nProb]uint8
+ useSkipProb bool
+ skipProb uint8
+ // Loop filter parameters.
+ filterParams [nSegment][2]filterParam
+ perMBFilterParams []filterParam
+
+ // The eight fields below relate to the current macroblock being decoded.
+ //
+ // Segment-based adjustments.
+ segment int
+ // Per-macroblock state for the macroblock immediately left of and those
+ // macroblocks immediately above the current macroblock.
+ leftMB mb
+ upMB []mb
+ // Bitmasks for which 4x4 regions of coeff contain non-zero coefficients.
+ nzDCMask, nzACMask uint32
+ // Predictor modes.
+ usePredY16 bool // The libwebp C code calls this !is_i4x4_.
+ predY16 uint8
+ predC8 uint8
+ predY4 [4][4]uint8
+
+ // The two fields below form a workspace for reconstructing a macroblock.
+ // Their specific sizes are documented in reconstruct.go.
+ coeff [1*16*16 + 2*8*8 + 1*4*4]int16
+ ybr [1 + 16 + 1 + 8][32]uint8
+}
+
+// NewDecoder returns a new Decoder.
+func NewDecoder() *Decoder {
+ return &Decoder{}
+}
+
+// Init initializes the decoder to read at most n bytes from r.
+func (d *Decoder) Init(r io.Reader, n int) {
+ d.r = limitReader{r, n}
+}
+
+// DecodeFrameHeader decodes the frame header.
+func (d *Decoder) DecodeFrameHeader() (fh FrameHeader, err error) {
+ // All frame headers are at least 3 bytes long.
+ b := d.scratch[:3]
+ if err = d.r.ReadFull(b); err != nil {
+ return
+ }
+ d.frameHeader.KeyFrame = (b[0] & 1) == 0
+ d.frameHeader.VersionNumber = (b[0] >> 1) & 7
+ d.frameHeader.ShowFrame = (b[0]>>4)&1 == 1
+ d.frameHeader.FirstPartitionLen = uint32(b[0])>>5 | uint32(b[1])<<3 | uint32(b[2])<<11
+ if !d.frameHeader.KeyFrame {
+ return d.frameHeader, nil
+ }
+ // Frame headers for key frames are an additional 7 bytes long.
+ b = d.scratch[:7]
+ if err = d.r.ReadFull(b); err != nil {
+ return
+ }
+ // Check the magic sync code.
+ if b[0] != 0x9d || b[1] != 0x01 || b[2] != 0x2a {
+ err = errors.New("vp8: invalid format")
+ return
+ }
+ d.frameHeader.Width = int(b[4]&0x3f)<<8 | int(b[3])
+ d.frameHeader.Height = int(b[6]&0x3f)<<8 | int(b[5])
+ d.frameHeader.XScale = b[4] >> 6
+ d.frameHeader.YScale = b[6] >> 6
+ d.mbw = (d.frameHeader.Width + 0x0f) >> 4
+ d.mbh = (d.frameHeader.Height + 0x0f) >> 4
+ d.segmentHeader = segmentHeader{
+ prob: [3]uint8{0xff, 0xff, 0xff},
+ }
+ d.tokenProb = defaultTokenProb
+ d.segment = 0
+ return d.frameHeader, nil
+}
+
+// ensureImg ensures that d.img is large enough to hold the decoded frame.
+func (d *Decoder) ensureImg() {
+ if d.img != nil {
+ p0, p1 := d.img.Rect.Min, d.img.Rect.Max
+ if p0.X == 0 && p0.Y == 0 && p1.X >= 16*d.mbw && p1.Y >= 16*d.mbh {
+ return
+ }
+ }
+ m := image.NewYCbCr(image.Rect(0, 0, 16*d.mbw, 16*d.mbh), image.YCbCrSubsampleRatio420)
+ d.img = m.SubImage(image.Rect(0, 0, d.frameHeader.Width, d.frameHeader.Height)).(*image.YCbCr)
+ d.perMBFilterParams = make([]filterParam, d.mbw*d.mbh)
+ d.upMB = make([]mb, d.mbw)
+}
+
+// parseSegmentHeader parses the segment header, as specified in section 9.3.
+func (d *Decoder) parseSegmentHeader() {
+ d.segmentHeader.useSegment = d.fp.readBit(uniformProb)
+ if !d.segmentHeader.useSegment {
+ d.segmentHeader.updateMap = false
+ return
+ }
+ d.segmentHeader.updateMap = d.fp.readBit(uniformProb)
+ if d.fp.readBit(uniformProb) {
+ d.segmentHeader.relativeDelta = !d.fp.readBit(uniformProb)
+ for i := range d.segmentHeader.quantizer {
+ d.segmentHeader.quantizer[i] = int8(d.fp.readOptionalInt(uniformProb, 7))
+ }
+ for i := range d.segmentHeader.filterStrength {
+ d.segmentHeader.filterStrength[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
+ }
+ }
+ if !d.segmentHeader.updateMap {
+ return
+ }
+ for i := range d.segmentHeader.prob {
+ if d.fp.readBit(uniformProb) {
+ d.segmentHeader.prob[i] = uint8(d.fp.readUint(uniformProb, 8))
+ } else {
+ d.segmentHeader.prob[i] = 0xff
+ }
+ }
+}
+
+// parseFilterHeader parses the filter header, as specified in section 9.4.
+func (d *Decoder) parseFilterHeader() {
+ d.filterHeader.simple = d.fp.readBit(uniformProb)
+ d.filterHeader.level = int8(d.fp.readUint(uniformProb, 6))
+ d.filterHeader.sharpness = uint8(d.fp.readUint(uniformProb, 3))
+ d.filterHeader.useLFDelta = d.fp.readBit(uniformProb)
+ if d.filterHeader.useLFDelta && d.fp.readBit(uniformProb) {
+ for i := range d.filterHeader.refLFDelta {
+ d.filterHeader.refLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
+ }
+ for i := range d.filterHeader.modeLFDelta {
+ d.filterHeader.modeLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
+ }
+ }
+ if d.filterHeader.level == 0 {
+ return
+ }
+ if d.segmentHeader.useSegment {
+ for i := range d.filterHeader.perSegmentLevel {
+ strength := d.segmentHeader.filterStrength[i]
+ if d.segmentHeader.relativeDelta {
+ strength += d.filterHeader.level
+ }
+ d.filterHeader.perSegmentLevel[i] = strength
+ }
+ } else {
+ d.filterHeader.perSegmentLevel[0] = d.filterHeader.level
+ }
+ d.computeFilterParams()
+}
+
+// parseOtherPartitions parses the other partitions, as specified in section 9.5.
+func (d *Decoder) parseOtherPartitions() error {
+ const maxNOP = 1 << 3
+ var partLens [maxNOP]int
+ d.nOP = 1 << d.fp.readUint(uniformProb, 2)
+
+ // The final partition length is implied by the the remaining chunk data
+ // (d.r.n) and the other d.nOP-1 partition lengths. Those d.nOP-1 partition
+ // lengths are stored as 24-bit uints, i.e. up to 16 MiB per partition.
+ n := 3 * (d.nOP - 1)
+ partLens[d.nOP-1] = d.r.n - n
+ if partLens[d.nOP-1] < 0 {
+ return io.ErrUnexpectedEOF
+ }
+ if n > 0 {
+ buf := make([]byte, n)
+ if err := d.r.ReadFull(buf); err != nil {
+ return err
+ }
+ for i := 0; i < d.nOP-1; i++ {
+ pl := int(buf[3*i+0]) | int(buf[3*i+1])<<8 | int(buf[3*i+2])<<16
+ if pl > partLens[d.nOP-1] {
+ return io.ErrUnexpectedEOF
+ }
+ partLens[i] = pl
+ partLens[d.nOP-1] -= pl
+ }
+ }
+
+ // We check if the final partition length can also fit into a 24-bit uint.
+ // Strictly speaking, this isn't part of the spec, but it guards against a
+ // malicious WEBP image that is too large to ReadFull the encoded DCT
+ // coefficients into memory, whether that's because the actual WEBP file is
+ // too large, or whether its RIFF metadata lists too large a chunk.
+ if 1<<24 <= partLens[d.nOP-1] {
+ return errors.New("vp8: too much data to decode")
+ }
+
+ buf := make([]byte, d.r.n)
+ if err := d.r.ReadFull(buf); err != nil {
+ return err
+ }
+ for i, pl := range partLens {
+ if i == d.nOP {
+ break
+ }
+ d.op[i].init(buf[:pl])
+ buf = buf[pl:]
+ }
+ return nil
+}
+
+// parseOtherHeaders parses header information other than the frame header.
+func (d *Decoder) parseOtherHeaders() error {
+ // Initialize and parse the first partition.
+ firstPartition := make([]byte, d.frameHeader.FirstPartitionLen)
+ if err := d.r.ReadFull(firstPartition); err != nil {
+ return err
+ }
+ d.fp.init(firstPartition)
+ if d.frameHeader.KeyFrame {
+ // Read and ignore the color space and pixel clamp values. They are
+ // specified in section 9.2, but are unimplemented.
+ d.fp.readBit(uniformProb)
+ d.fp.readBit(uniformProb)
+ }
+ d.parseSegmentHeader()
+ d.parseFilterHeader()
+ if err := d.parseOtherPartitions(); err != nil {
+ return err
+ }
+ d.parseQuant()
+ if !d.frameHeader.KeyFrame {
+ // Golden and AltRef frames are specified in section 9.7.
+ // TODO(nigeltao): implement. Note that they are only used for video, not still images.
+ return errors.New("vp8: Golden / AltRef frames are not implemented")
+ }
+ // Read and ignore the refreshLastFrameBuffer bit, specified in section 9.8.
+ // It applies only to video, and not still images.
+ d.fp.readBit(uniformProb)
+ d.parseTokenProb()
+ d.useSkipProb = d.fp.readBit(uniformProb)
+ if d.useSkipProb {
+ d.skipProb = uint8(d.fp.readUint(uniformProb, 8))
+ }
+ if d.fp.unexpectedEOF {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+// DecodeFrame decodes the frame and returns it as an YCbCr image.
+// The image's contents are valid up until the next call to Decoder.Init.
+func (d *Decoder) DecodeFrame() (*image.YCbCr, error) {
+ d.ensureImg()
+ if err := d.parseOtherHeaders(); err != nil {
+ return nil, err
+ }
+ // Reconstruct the rows.
+ for mbx := 0; mbx < d.mbw; mbx++ {
+ d.upMB[mbx] = mb{}
+ }
+ for mby := 0; mby < d.mbh; mby++ {
+ d.leftMB = mb{}
+ for mbx := 0; mbx < d.mbw; mbx++ {
+ skip := d.reconstruct(mbx, mby)
+ fs := d.filterParams[d.segment][btou(!d.usePredY16)]
+ fs.inner = fs.inner || !skip
+ d.perMBFilterParams[d.mbw*mby+mbx] = fs
+ }
+ }
+ if d.fp.unexpectedEOF {
+ return nil, io.ErrUnexpectedEOF
+ }
+ for i := 0; i < d.nOP; i++ {
+ if d.op[i].unexpectedEOF {
+ return nil, io.ErrUnexpectedEOF
+ }
+ }
+ // Apply the loop filter.
+ //
+ // Even if we are using per-segment levels, section 15 says that "loop
+ // filtering must be skipped entirely if loop_filter_level at either the
+ // frame header level or macroblock override level is 0".
+ if d.filterHeader.level != 0 {
+ if d.filterHeader.simple {
+ d.simpleFilter()
+ } else {
+ d.normalFilter()
+ }
+ }
+ return d.img, nil
+}
diff --git a/vendor/golang.org/x/image/vp8/filter.go b/vendor/golang.org/x/image/vp8/filter.go
new file mode 100644
index 0000000..e34a811
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/filter.go
@@ -0,0 +1,273 @@
+// 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 vp8
+
+// filter2 modifies a 2-pixel wide or 2-pixel high band along an edge.
+func filter2(pix []byte, level, index, iStep, jStep int) {
+ for n := 16; n > 0; n, index = n-1, index+iStep {
+ p1 := int(pix[index-2*jStep])
+ p0 := int(pix[index-1*jStep])
+ q0 := int(pix[index+0*jStep])
+ q1 := int(pix[index+1*jStep])
+ if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
+ continue
+ }
+ a := 3*(q0-p0) + clamp127(p1-q1)
+ a1 := clamp15((a + 4) >> 3)
+ a2 := clamp15((a + 3) >> 3)
+ pix[index-1*jStep] = clamp255(p0 + a2)
+ pix[index+0*jStep] = clamp255(q0 - a1)
+ }
+}
+
+// filter246 modifies a 2-, 4- or 6-pixel wide or high band along an edge.
+func filter246(pix []byte, n, level, ilevel, hlevel, index, iStep, jStep int, fourNotSix bool) {
+ for ; n > 0; n, index = n-1, index+iStep {
+ p3 := int(pix[index-4*jStep])
+ p2 := int(pix[index-3*jStep])
+ p1 := int(pix[index-2*jStep])
+ p0 := int(pix[index-1*jStep])
+ q0 := int(pix[index+0*jStep])
+ q1 := int(pix[index+1*jStep])
+ q2 := int(pix[index+2*jStep])
+ q3 := int(pix[index+3*jStep])
+ if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
+ continue
+ }
+ if abs(p3-p2) > ilevel ||
+ abs(p2-p1) > ilevel ||
+ abs(p1-p0) > ilevel ||
+ abs(q1-q0) > ilevel ||
+ abs(q2-q1) > ilevel ||
+ abs(q3-q2) > ilevel {
+ continue
+ }
+ if abs(p1-p0) > hlevel || abs(q1-q0) > hlevel {
+ // Filter 2 pixels.
+ a := 3*(q0-p0) + clamp127(p1-q1)
+ a1 := clamp15((a + 4) >> 3)
+ a2 := clamp15((a + 3) >> 3)
+ pix[index-1*jStep] = clamp255(p0 + a2)
+ pix[index+0*jStep] = clamp255(q0 - a1)
+ } else if fourNotSix {
+ // Filter 4 pixels.
+ a := 3 * (q0 - p0)
+ a1 := clamp15((a + 4) >> 3)
+ a2 := clamp15((a + 3) >> 3)
+ a3 := (a1 + 1) >> 1
+ pix[index-2*jStep] = clamp255(p1 + a3)
+ pix[index-1*jStep] = clamp255(p0 + a2)
+ pix[index+0*jStep] = clamp255(q0 - a1)
+ pix[index+1*jStep] = clamp255(q1 - a3)
+ } else {
+ // Filter 6 pixels.
+ a := clamp127(3*(q0-p0) + clamp127(p1-q1))
+ a1 := (27*a + 63) >> 7
+ a2 := (18*a + 63) >> 7
+ a3 := (9*a + 63) >> 7
+ pix[index-3*jStep] = clamp255(p2 + a3)
+ pix[index-2*jStep] = clamp255(p1 + a2)
+ pix[index-1*jStep] = clamp255(p0 + a1)
+ pix[index+0*jStep] = clamp255(q0 - a1)
+ pix[index+1*jStep] = clamp255(q1 - a2)
+ pix[index+2*jStep] = clamp255(q2 - a3)
+ }
+ }
+}
+
+// simpleFilter implements the simple filter, as specified in section 15.2.
+func (d *Decoder) simpleFilter() {
+ for mby := 0; mby < d.mbh; mby++ {
+ for mbx := 0; mbx < d.mbw; mbx++ {
+ f := d.perMBFilterParams[d.mbw*mby+mbx]
+ if f.level == 0 {
+ continue
+ }
+ l := int(f.level)
+ yIndex := (mby*d.img.YStride + mbx) * 16
+ if mbx > 0 {
+ filter2(d.img.Y, l+4, yIndex, d.img.YStride, 1)
+ }
+ if f.inner {
+ filter2(d.img.Y, l, yIndex+0x4, d.img.YStride, 1)
+ filter2(d.img.Y, l, yIndex+0x8, d.img.YStride, 1)
+ filter2(d.img.Y, l, yIndex+0xc, d.img.YStride, 1)
+ }
+ if mby > 0 {
+ filter2(d.img.Y, l+4, yIndex, 1, d.img.YStride)
+ }
+ if f.inner {
+ filter2(d.img.Y, l, yIndex+d.img.YStride*0x4, 1, d.img.YStride)
+ filter2(d.img.Y, l, yIndex+d.img.YStride*0x8, 1, d.img.YStride)
+ filter2(d.img.Y, l, yIndex+d.img.YStride*0xc, 1, d.img.YStride)
+ }
+ }
+ }
+}
+
+// normalFilter implements the normal filter, as specified in section 15.3.
+func (d *Decoder) normalFilter() {
+ for mby := 0; mby < d.mbh; mby++ {
+ for mbx := 0; mbx < d.mbw; mbx++ {
+ f := d.perMBFilterParams[d.mbw*mby+mbx]
+ if f.level == 0 {
+ continue
+ }
+ l, il, hl := int(f.level), int(f.ilevel), int(f.hlevel)
+ yIndex := (mby*d.img.YStride + mbx) * 16
+ cIndex := (mby*d.img.CStride + mbx) * 8
+ if mbx > 0 {
+ filter246(d.img.Y, 16, l+4, il, hl, yIndex, d.img.YStride, 1, false)
+ filter246(d.img.Cb, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
+ filter246(d.img.Cr, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
+ }
+ if f.inner {
+ filter246(d.img.Y, 16, l, il, hl, yIndex+0x4, d.img.YStride, 1, true)
+ filter246(d.img.Y, 16, l, il, hl, yIndex+0x8, d.img.YStride, 1, true)
+ filter246(d.img.Y, 16, l, il, hl, yIndex+0xc, d.img.YStride, 1, true)
+ filter246(d.img.Cb, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
+ filter246(d.img.Cr, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
+ }
+ if mby > 0 {
+ filter246(d.img.Y, 16, l+4, il, hl, yIndex, 1, d.img.YStride, false)
+ filter246(d.img.Cb, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
+ filter246(d.img.Cr, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
+ }
+ if f.inner {
+ filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x4, 1, d.img.YStride, true)
+ filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x8, 1, d.img.YStride, true)
+ filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0xc, 1, d.img.YStride, true)
+ filter246(d.img.Cb, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
+ filter246(d.img.Cr, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
+ }
+ }
+ }
+}
+
+// filterParam holds the loop filter parameters for a macroblock.
+type filterParam struct {
+ // The first three fields are thresholds used by the loop filter to smooth
+ // over the edges and interior of a macroblock. level is used by both the
+ // simple and normal filters. The inner level and high edge variance level
+ // are only used by the normal filter.
+ level, ilevel, hlevel uint8
+ // inner is whether the inner loop filter cannot be optimized out as a
+ // no-op for this particular macroblock.
+ inner bool
+}
+
+// computeFilterParams computes the loop filter parameters, as specified in
+// section 15.4.
+func (d *Decoder) computeFilterParams() {
+ for i := range d.filterParams {
+ baseLevel := d.filterHeader.level
+ if d.segmentHeader.useSegment {
+ baseLevel = d.segmentHeader.filterStrength[i]
+ if d.segmentHeader.relativeDelta {
+ baseLevel += d.filterHeader.level
+ }
+ }
+
+ for j := range d.filterParams[i] {
+ p := &d.filterParams[i][j]
+ p.inner = j != 0
+ level := baseLevel
+ if d.filterHeader.useLFDelta {
+ // The libwebp C code has a "TODO: only CURRENT is handled for now."
+ level += d.filterHeader.refLFDelta[0]
+ if j != 0 {
+ level += d.filterHeader.modeLFDelta[0]
+ }
+ }
+ if level <= 0 {
+ p.level = 0
+ continue
+ }
+ if level > 63 {
+ level = 63
+ }
+ ilevel := level
+ if d.filterHeader.sharpness > 0 {
+ if d.filterHeader.sharpness > 4 {
+ ilevel >>= 2
+ } else {
+ ilevel >>= 1
+ }
+ if x := int8(9 - d.filterHeader.sharpness); ilevel > x {
+ ilevel = x
+ }
+ }
+ if ilevel < 1 {
+ ilevel = 1
+ }
+ p.ilevel = uint8(ilevel)
+ p.level = uint8(2*level + ilevel)
+ if d.frameHeader.KeyFrame {
+ if level < 15 {
+ p.hlevel = 0
+ } else if level < 40 {
+ p.hlevel = 1
+ } else {
+ p.hlevel = 2
+ }
+ } else {
+ if level < 15 {
+ p.hlevel = 0
+ } else if level < 20 {
+ p.hlevel = 1
+ } else if level < 40 {
+ p.hlevel = 2
+ } else {
+ p.hlevel = 3
+ }
+ }
+ }
+ }
+}
+
+// intSize is either 32 or 64.
+const intSize = 32 << (^uint(0) >> 63)
+
+func abs(x int) int {
+ // m := -1 if x < 0. m := 0 otherwise.
+ m := x >> (intSize - 1)
+
+ // In two's complement representation, the negative number
+ // of any number (except the smallest one) can be computed
+ // by flipping all the bits and add 1. This is faster than
+ // code with a branch.
+ // See Hacker's Delight, section 2-4.
+ return (x ^ m) - m
+}
+
+func clamp15(x int) int {
+ if x < -16 {
+ return -16
+ }
+ if x > 15 {
+ return 15
+ }
+ return x
+}
+
+func clamp127(x int) int {
+ if x < -128 {
+ return -128
+ }
+ if x > 127 {
+ return 127
+ }
+ return x
+}
+
+func clamp255(x int) uint8 {
+ if x < 0 {
+ return 0
+ }
+ if x > 255 {
+ return 255
+ }
+ return uint8(x)
+}
diff --git a/vendor/golang.org/x/image/vp8/idct.go b/vendor/golang.org/x/image/vp8/idct.go
new file mode 100644
index 0000000..929af2c
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/idct.go
@@ -0,0 +1,98 @@
+// 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.
+
+package vp8
+
+// This file implements the inverse Discrete Cosine Transform and the inverse
+// Walsh Hadamard Transform (WHT), as specified in sections 14.3 and 14.4.
+
+func clip8(i int32) uint8 {
+ if i < 0 {
+ return 0
+ }
+ if i > 255 {
+ return 255
+ }
+ return uint8(i)
+}
+
+func (z *Decoder) inverseDCT4(y, x, coeffBase int) {
+ const (
+ c1 = 85627 // 65536 * cos(pi/8) * sqrt(2).
+ c2 = 35468 // 65536 * sin(pi/8) * sqrt(2).
+ )
+ var m [4][4]int32
+ for i := 0; i < 4; i++ {
+ a := int32(z.coeff[coeffBase+0]) + int32(z.coeff[coeffBase+8])
+ b := int32(z.coeff[coeffBase+0]) - int32(z.coeff[coeffBase+8])
+ c := (int32(z.coeff[coeffBase+4])*c2)>>16 - (int32(z.coeff[coeffBase+12])*c1)>>16
+ d := (int32(z.coeff[coeffBase+4])*c1)>>16 + (int32(z.coeff[coeffBase+12])*c2)>>16
+ m[i][0] = a + d
+ m[i][1] = b + c
+ m[i][2] = b - c
+ m[i][3] = a - d
+ coeffBase++
+ }
+ for j := 0; j < 4; j++ {
+ dc := m[0][j] + 4
+ a := dc + m[2][j]
+ b := dc - m[2][j]
+ c := (m[1][j]*c2)>>16 - (m[3][j]*c1)>>16
+ d := (m[1][j]*c1)>>16 + (m[3][j]*c2)>>16
+ z.ybr[y+j][x+0] = clip8(int32(z.ybr[y+j][x+0]) + (a+d)>>3)
+ z.ybr[y+j][x+1] = clip8(int32(z.ybr[y+j][x+1]) + (b+c)>>3)
+ z.ybr[y+j][x+2] = clip8(int32(z.ybr[y+j][x+2]) + (b-c)>>3)
+ z.ybr[y+j][x+3] = clip8(int32(z.ybr[y+j][x+3]) + (a-d)>>3)
+ }
+}
+
+func (z *Decoder) inverseDCT4DCOnly(y, x, coeffBase int) {
+ dc := (int32(z.coeff[coeffBase+0]) + 4) >> 3
+ for j := 0; j < 4; j++ {
+ for i := 0; i < 4; i++ {
+ z.ybr[y+j][x+i] = clip8(int32(z.ybr[y+j][x+i]) + dc)
+ }
+ }
+}
+
+func (z *Decoder) inverseDCT8(y, x, coeffBase int) {
+ z.inverseDCT4(y+0, x+0, coeffBase+0*16)
+ z.inverseDCT4(y+0, x+4, coeffBase+1*16)
+ z.inverseDCT4(y+4, x+0, coeffBase+2*16)
+ z.inverseDCT4(y+4, x+4, coeffBase+3*16)
+}
+
+func (z *Decoder) inverseDCT8DCOnly(y, x, coeffBase int) {
+ z.inverseDCT4DCOnly(y+0, x+0, coeffBase+0*16)
+ z.inverseDCT4DCOnly(y+0, x+4, coeffBase+1*16)
+ z.inverseDCT4DCOnly(y+4, x+0, coeffBase+2*16)
+ z.inverseDCT4DCOnly(y+4, x+4, coeffBase+3*16)
+}
+
+func (d *Decoder) inverseWHT16() {
+ var m [16]int32
+ for i := 0; i < 4; i++ {
+ a0 := int32(d.coeff[384+0+i]) + int32(d.coeff[384+12+i])
+ a1 := int32(d.coeff[384+4+i]) + int32(d.coeff[384+8+i])
+ a2 := int32(d.coeff[384+4+i]) - int32(d.coeff[384+8+i])
+ a3 := int32(d.coeff[384+0+i]) - int32(d.coeff[384+12+i])
+ m[0+i] = a0 + a1
+ m[8+i] = a0 - a1
+ m[4+i] = a3 + a2
+ m[12+i] = a3 - a2
+ }
+ out := 0
+ for i := 0; i < 4; i++ {
+ dc := m[0+i*4] + 3
+ a0 := dc + m[3+i*4]
+ a1 := m[1+i*4] + m[2+i*4]
+ a2 := m[1+i*4] - m[2+i*4]
+ a3 := dc - m[3+i*4]
+ d.coeff[out+0] = int16((a0 + a1) >> 3)
+ d.coeff[out+16] = int16((a3 + a2) >> 3)
+ d.coeff[out+32] = int16((a0 - a1) >> 3)
+ d.coeff[out+48] = int16((a3 - a2) >> 3)
+ out += 64
+ }
+}
diff --git a/vendor/golang.org/x/image/vp8/partition.go b/vendor/golang.org/x/image/vp8/partition.go
new file mode 100644
index 0000000..72288bd
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/partition.go
@@ -0,0 +1,129 @@
+// 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.
+
+package vp8
+
+// Each VP8 frame consists of between 2 and 9 bitstream partitions.
+// Each partition is byte-aligned and is independently arithmetic-encoded.
+//
+// This file implements decoding a partition's bitstream, as specified in
+// chapter 7. The implementation follows libwebp's approach instead of the
+// specification's reference C implementation. For example, we use a look-up
+// table instead of a for loop to recalibrate the encoded range.
+
+var (
+ lutShift = [127]uint8{
+ 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }
+ lutRangeM1 = [127]uint8{
+ 127,
+ 127, 191,
+ 127, 159, 191, 223,
+ 127, 143, 159, 175, 191, 207, 223, 239,
+ 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, 247,
+ 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, 183, 187,
+ 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251,
+ 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157,
+ 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189,
+ 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221,
+ 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253,
+ }
+)
+
+// uniformProb represents a 50% probability that the next bit is 0.
+const uniformProb = 128
+
+// partition holds arithmetic-coded bits.
+type partition struct {
+ // buf is the input bytes.
+ buf []byte
+ // r is how many of buf's bytes have been consumed.
+ r int
+ // rangeM1 is range minus 1, where range is in the arithmetic coding sense,
+ // not the Go language sense.
+ rangeM1 uint32
+ // bits and nBits hold those bits shifted out of buf but not yet consumed.
+ bits uint32
+ nBits uint8
+ // unexpectedEOF tells whether we tried to read past buf.
+ unexpectedEOF bool
+}
+
+// init initializes the partition.
+func (p *partition) init(buf []byte) {
+ p.buf = buf
+ p.r = 0
+ p.rangeM1 = 254
+ p.bits = 0
+ p.nBits = 0
+ p.unexpectedEOF = false
+}
+
+// readBit returns the next bit.
+func (p *partition) readBit(prob uint8) bool {
+ if p.nBits < 8 {
+ if p.r >= len(p.buf) {
+ p.unexpectedEOF = true
+ return false
+ }
+ // Expression split for 386 compiler.
+ x := uint32(p.buf[p.r])
+ p.bits |= x << (8 - p.nBits)
+ p.r++
+ p.nBits += 8
+ }
+ split := (p.rangeM1*uint32(prob))>>8 + 1
+ bit := p.bits >= split<<8
+ if bit {
+ p.rangeM1 -= split
+ p.bits -= split << 8
+ } else {
+ p.rangeM1 = split - 1
+ }
+ if p.rangeM1 < 127 {
+ shift := lutShift[p.rangeM1]
+ p.rangeM1 = uint32(lutRangeM1[p.rangeM1])
+ p.bits <<= shift
+ p.nBits -= shift
+ }
+ return bit
+}
+
+// readUint returns the next n-bit unsigned integer.
+func (p *partition) readUint(prob, n uint8) uint32 {
+ var u uint32
+ for n > 0 {
+ n--
+ if p.readBit(prob) {
+ u |= 1 << n
+ }
+ }
+ return u
+}
+
+// readInt returns the next n-bit signed integer.
+func (p *partition) readInt(prob, n uint8) int32 {
+ u := p.readUint(prob, n)
+ b := p.readBit(prob)
+ if b {
+ return -int32(u)
+ }
+ return int32(u)
+}
+
+// readOptionalInt returns the next n-bit signed integer in an encoding
+// where the likely result is zero.
+func (p *partition) readOptionalInt(prob, n uint8) int32 {
+ if !p.readBit(prob) {
+ return 0
+ }
+ return p.readInt(prob, n)
+}
diff --git a/vendor/golang.org/x/image/vp8/pred.go b/vendor/golang.org/x/image/vp8/pred.go
new file mode 100644
index 0000000..58c2689
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/pred.go
@@ -0,0 +1,201 @@
+// 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.
+
+package vp8
+
+// This file implements parsing the predictor modes, as specified in chapter
+// 11.
+
+func (d *Decoder) parsePredModeY16(mbx int) {
+ var p uint8
+ if !d.fp.readBit(156) {
+ if !d.fp.readBit(163) {
+ p = predDC
+ } else {
+ p = predVE
+ }
+ } else if !d.fp.readBit(128) {
+ p = predHE
+ } else {
+ p = predTM
+ }
+ for i := 0; i < 4; i++ {
+ d.upMB[mbx].pred[i] = p
+ d.leftMB.pred[i] = p
+ }
+ d.predY16 = p
+}
+
+func (d *Decoder) parsePredModeC8() {
+ if !d.fp.readBit(142) {
+ d.predC8 = predDC
+ } else if !d.fp.readBit(114) {
+ d.predC8 = predVE
+ } else if !d.fp.readBit(183) {
+ d.predC8 = predHE
+ } else {
+ d.predC8 = predTM
+ }
+}
+
+func (d *Decoder) parsePredModeY4(mbx int) {
+ for j := 0; j < 4; j++ {
+ p := d.leftMB.pred[j]
+ for i := 0; i < 4; i++ {
+ prob := &predProb[d.upMB[mbx].pred[i]][p]
+ if !d.fp.readBit(prob[0]) {
+ p = predDC
+ } else if !d.fp.readBit(prob[1]) {
+ p = predTM
+ } else if !d.fp.readBit(prob[2]) {
+ p = predVE
+ } else if !d.fp.readBit(prob[3]) {
+ if !d.fp.readBit(prob[4]) {
+ p = predHE
+ } else if !d.fp.readBit(prob[5]) {
+ p = predRD
+ } else {
+ p = predVR
+ }
+ } else if !d.fp.readBit(prob[6]) {
+ p = predLD
+ } else if !d.fp.readBit(prob[7]) {
+ p = predVL
+ } else if !d.fp.readBit(prob[8]) {
+ p = predHD
+ } else {
+ p = predHU
+ }
+ d.predY4[j][i] = p
+ d.upMB[mbx].pred[i] = p
+ }
+ d.leftMB.pred[j] = p
+ }
+}
+
+// predProb are the probabilities to decode a 4x4 region's predictor mode given
+// the predictor modes of the regions above and left of it.
+// These values are specified in section 11.5.
+var predProb = [nPred][nPred][9]uint8{
+ {
+ {231, 120, 48, 89, 115, 113, 120, 152, 112},
+ {152, 179, 64, 126, 170, 118, 46, 70, 95},
+ {175, 69, 143, 80, 85, 82, 72, 155, 103},
+ {56, 58, 10, 171, 218, 189, 17, 13, 152},
+ {114, 26, 17, 163, 44, 195, 21, 10, 173},
+ {121, 24, 80, 195, 26, 62, 44, 64, 85},
+ {144, 71, 10, 38, 171, 213, 144, 34, 26},
+ {170, 46, 55, 19, 136, 160, 33, 206, 71},
+ {63, 20, 8, 114, 114, 208, 12, 9, 226},
+ {81, 40, 11, 96, 182, 84, 29, 16, 36},
+ },
+ {
+ {134, 183, 89, 137, 98, 101, 106, 165, 148},
+ {72, 187, 100, 130, 157, 111, 32, 75, 80},
+ {66, 102, 167, 99, 74, 62, 40, 234, 128},
+ {41, 53, 9, 178, 241, 141, 26, 8, 107},
+ {74, 43, 26, 146, 73, 166, 49, 23, 157},
+ {65, 38, 105, 160, 51, 52, 31, 115, 128},
+ {104, 79, 12, 27, 217, 255, 87, 17, 7},
+ {87, 68, 71, 44, 114, 51, 15, 186, 23},
+ {47, 41, 14, 110, 182, 183, 21, 17, 194},
+ {66, 45, 25, 102, 197, 189, 23, 18, 22},
+ },
+ {
+ {88, 88, 147, 150, 42, 46, 45, 196, 205},
+ {43, 97, 183, 117, 85, 38, 35, 179, 61},
+ {39, 53, 200, 87, 26, 21, 43, 232, 171},
+ {56, 34, 51, 104, 114, 102, 29, 93, 77},
+ {39, 28, 85, 171, 58, 165, 90, 98, 64},
+ {34, 22, 116, 206, 23, 34, 43, 166, 73},
+ {107, 54, 32, 26, 51, 1, 81, 43, 31},
+ {68, 25, 106, 22, 64, 171, 36, 225, 114},
+ {34, 19, 21, 102, 132, 188, 16, 76, 124},
+ {62, 18, 78, 95, 85, 57, 50, 48, 51},
+ },
+ {
+ {193, 101, 35, 159, 215, 111, 89, 46, 111},
+ {60, 148, 31, 172, 219, 228, 21, 18, 111},
+ {112, 113, 77, 85, 179, 255, 38, 120, 114},
+ {40, 42, 1, 196, 245, 209, 10, 25, 109},
+ {88, 43, 29, 140, 166, 213, 37, 43, 154},
+ {61, 63, 30, 155, 67, 45, 68, 1, 209},
+ {100, 80, 8, 43, 154, 1, 51, 26, 71},
+ {142, 78, 78, 16, 255, 128, 34, 197, 171},
+ {41, 40, 5, 102, 211, 183, 4, 1, 221},
+ {51, 50, 17, 168, 209, 192, 23, 25, 82},
+ },
+ {
+ {138, 31, 36, 171, 27, 166, 38, 44, 229},
+ {67, 87, 58, 169, 82, 115, 26, 59, 179},
+ {63, 59, 90, 180, 59, 166, 93, 73, 154},
+ {40, 40, 21, 116, 143, 209, 34, 39, 175},
+ {47, 15, 16, 183, 34, 223, 49, 45, 183},
+ {46, 17, 33, 183, 6, 98, 15, 32, 183},
+ {57, 46, 22, 24, 128, 1, 54, 17, 37},
+ {65, 32, 73, 115, 28, 128, 23, 128, 205},
+ {40, 3, 9, 115, 51, 192, 18, 6, 223},
+ {87, 37, 9, 115, 59, 77, 64, 21, 47},
+ },
+ {
+ {104, 55, 44, 218, 9, 54, 53, 130, 226},
+ {64, 90, 70, 205, 40, 41, 23, 26, 57},
+ {54, 57, 112, 184, 5, 41, 38, 166, 213},
+ {30, 34, 26, 133, 152, 116, 10, 32, 134},
+ {39, 19, 53, 221, 26, 114, 32, 73, 255},
+ {31, 9, 65, 234, 2, 15, 1, 118, 73},
+ {75, 32, 12, 51, 192, 255, 160, 43, 51},
+ {88, 31, 35, 67, 102, 85, 55, 186, 85},
+ {56, 21, 23, 111, 59, 205, 45, 37, 192},
+ {55, 38, 70, 124, 73, 102, 1, 34, 98},
+ },
+ {
+ {125, 98, 42, 88, 104, 85, 117, 175, 82},
+ {95, 84, 53, 89, 128, 100, 113, 101, 45},
+ {75, 79, 123, 47, 51, 128, 81, 171, 1},
+ {57, 17, 5, 71, 102, 57, 53, 41, 49},
+ {38, 33, 13, 121, 57, 73, 26, 1, 85},
+ {41, 10, 67, 138, 77, 110, 90, 47, 114},
+ {115, 21, 2, 10, 102, 255, 166, 23, 6},
+ {101, 29, 16, 10, 85, 128, 101, 196, 26},
+ {57, 18, 10, 102, 102, 213, 34, 20, 43},
+ {117, 20, 15, 36, 163, 128, 68, 1, 26},
+ },
+ {
+ {102, 61, 71, 37, 34, 53, 31, 243, 192},
+ {69, 60, 71, 38, 73, 119, 28, 222, 37},
+ {68, 45, 128, 34, 1, 47, 11, 245, 171},
+ {62, 17, 19, 70, 146, 85, 55, 62, 70},
+ {37, 43, 37, 154, 100, 163, 85, 160, 1},
+ {63, 9, 92, 136, 28, 64, 32, 201, 85},
+ {75, 15, 9, 9, 64, 255, 184, 119, 16},
+ {86, 6, 28, 5, 64, 255, 25, 248, 1},
+ {56, 8, 17, 132, 137, 255, 55, 116, 128},
+ {58, 15, 20, 82, 135, 57, 26, 121, 40},
+ },
+ {
+ {164, 50, 31, 137, 154, 133, 25, 35, 218},
+ {51, 103, 44, 131, 131, 123, 31, 6, 158},
+ {86, 40, 64, 135, 148, 224, 45, 183, 128},
+ {22, 26, 17, 131, 240, 154, 14, 1, 209},
+ {45, 16, 21, 91, 64, 222, 7, 1, 197},
+ {56, 21, 39, 155, 60, 138, 23, 102, 213},
+ {83, 12, 13, 54, 192, 255, 68, 47, 28},
+ {85, 26, 85, 85, 128, 128, 32, 146, 171},
+ {18, 11, 7, 63, 144, 171, 4, 4, 246},
+ {35, 27, 10, 146, 174, 171, 12, 26, 128},
+ },
+ {
+ {190, 80, 35, 99, 180, 80, 126, 54, 45},
+ {85, 126, 47, 87, 176, 51, 41, 20, 32},
+ {101, 75, 128, 139, 118, 146, 116, 128, 85},
+ {56, 41, 15, 176, 236, 85, 37, 9, 62},
+ {71, 30, 17, 119, 118, 255, 17, 18, 138},
+ {101, 38, 60, 138, 55, 70, 43, 26, 142},
+ {146, 36, 19, 30, 171, 255, 97, 27, 20},
+ {138, 45, 61, 62, 219, 1, 81, 188, 64},
+ {32, 41, 20, 117, 151, 142, 20, 21, 163},
+ {112, 19, 12, 61, 195, 128, 48, 4, 24},
+ },
+}
diff --git a/vendor/golang.org/x/image/vp8/predfunc.go b/vendor/golang.org/x/image/vp8/predfunc.go
new file mode 100644
index 0000000..f899958
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/predfunc.go
@@ -0,0 +1,553 @@
+// 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.
+
+package vp8
+
+// This file implements the predicition functions, as specified in chapter 12.
+//
+// For each macroblock (of 1x16x16 luma and 2x8x8 chroma coefficients), the
+// luma values are either predicted as one large 16x16 region or 16 separate
+// 4x4 regions. The chroma values are always predicted as one 8x8 region.
+//
+// For 4x4 regions, the target block's predicted values (Xs) are a function of
+// its previously-decoded top and left border values, as well as a number of
+// pixels from the top-right:
+//
+// a b c d e f g h
+// p X X X X
+// q X X X X
+// r X X X X
+// s X X X X
+//
+// The predictor modes are:
+// - DC: all Xs = (b + c + d + e + p + q + r + s + 4) / 8.
+// - TM: the first X = (b + p - a), the second X = (c + p - a), and so on.
+// - VE: each X = the weighted average of its column's top value and that
+// value's neighbors, i.e. averages of abc, bcd, cde or def.
+// - HE: similar to VE except rows instead of columns, and the final row is
+// an average of r, s and s.
+// - RD, VR, LD, VL, HD, HU: these diagonal modes ("Right Down", "Vertical
+// Right", etc) are more complicated and are described in section 12.3.
+// All Xs are clipped to the range [0, 255].
+//
+// For 8x8 and 16x16 regions, the target block's predicted values are a
+// function of the top and left border values without the top-right overhang,
+// i.e. without the 8x8 or 16x16 equivalent of f, g and h. Furthermore:
+// - There are no diagonal predictor modes, only DC, TM, VE and HE.
+// - The DC mode has variants for macroblocks in the top row and/or left
+// column, i.e. for macroblocks with mby == 0 || mbx == 0.
+// - The VE and HE modes take only the column top or row left values; they do
+// not smooth that top/left value with its neighbors.
+
+// nPred is the number of predictor modes, not including the Top/Left versions
+// of the DC predictor mode.
+const nPred = 10
+
+const (
+ predDC = iota
+ predTM
+ predVE
+ predHE
+ predRD
+ predVR
+ predLD
+ predVL
+ predHD
+ predHU
+ predDCTop
+ predDCLeft
+ predDCTopLeft
+)
+
+func checkTopLeftPred(mbx, mby int, p uint8) uint8 {
+ if p != predDC {
+ return p
+ }
+ if mbx == 0 {
+ if mby == 0 {
+ return predDCTopLeft
+ }
+ return predDCLeft
+ }
+ if mby == 0 {
+ return predDCTop
+ }
+ return predDC
+}
+
+var predFunc4 = [...]func(*Decoder, int, int){
+ predFunc4DC,
+ predFunc4TM,
+ predFunc4VE,
+ predFunc4HE,
+ predFunc4RD,
+ predFunc4VR,
+ predFunc4LD,
+ predFunc4VL,
+ predFunc4HD,
+ predFunc4HU,
+ nil,
+ nil,
+ nil,
+}
+
+var predFunc8 = [...]func(*Decoder, int, int){
+ predFunc8DC,
+ predFunc8TM,
+ predFunc8VE,
+ predFunc8HE,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ predFunc8DCTop,
+ predFunc8DCLeft,
+ predFunc8DCTopLeft,
+}
+
+var predFunc16 = [...]func(*Decoder, int, int){
+ predFunc16DC,
+ predFunc16TM,
+ predFunc16VE,
+ predFunc16HE,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ predFunc16DCTop,
+ predFunc16DCLeft,
+ predFunc16DCTopLeft,
+}
+
+func predFunc4DC(z *Decoder, y, x int) {
+ sum := uint32(4)
+ for i := 0; i < 4; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ for j := 0; j < 4; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 8)
+ for j := 0; j < 4; j++ {
+ for i := 0; i < 4; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc4TM(z *Decoder, y, x int) {
+ delta0 := -int32(z.ybr[y-1][x-1])
+ for j := 0; j < 4; j++ {
+ delta1 := delta0 + int32(z.ybr[y+j][x-1])
+ for i := 0; i < 4; i++ {
+ delta2 := delta1 + int32(z.ybr[y-1][x+i])
+ z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
+ }
+ }
+}
+
+func predFunc4VE(z *Decoder, y, x int) {
+ a := int32(z.ybr[y-1][x-1])
+ b := int32(z.ybr[y-1][x+0])
+ c := int32(z.ybr[y-1][x+1])
+ d := int32(z.ybr[y-1][x+2])
+ e := int32(z.ybr[y-1][x+3])
+ f := int32(z.ybr[y-1][x+4])
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ def := uint8((d + 2*e + f + 2) / 4)
+ for j := 0; j < 4; j++ {
+ z.ybr[y+j][x+0] = abc
+ z.ybr[y+j][x+1] = bcd
+ z.ybr[y+j][x+2] = cde
+ z.ybr[y+j][x+3] = def
+ }
+}
+
+func predFunc4HE(z *Decoder, y, x int) {
+ s := int32(z.ybr[y+3][x-1])
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ a := int32(z.ybr[y-1][x-1])
+ ssr := uint8((s + 2*s + r + 2) / 4)
+ srq := uint8((s + 2*r + q + 2) / 4)
+ rqp := uint8((r + 2*q + p + 2) / 4)
+ apq := uint8((a + 2*p + q + 2) / 4)
+ for i := 0; i < 4; i++ {
+ z.ybr[y+0][x+i] = apq
+ z.ybr[y+1][x+i] = rqp
+ z.ybr[y+2][x+i] = srq
+ z.ybr[y+3][x+i] = ssr
+ }
+}
+
+func predFunc4RD(z *Decoder, y, x int) {
+ s := int32(z.ybr[y+3][x-1])
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ a := int32(z.ybr[y-1][x-1])
+ b := int32(z.ybr[y-1][x+0])
+ c := int32(z.ybr[y-1][x+1])
+ d := int32(z.ybr[y-1][x+2])
+ e := int32(z.ybr[y-1][x+3])
+ srq := uint8((s + 2*r + q + 2) / 4)
+ rqp := uint8((r + 2*q + p + 2) / 4)
+ qpa := uint8((q + 2*p + a + 2) / 4)
+ pab := uint8((p + 2*a + b + 2) / 4)
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ z.ybr[y+0][x+0] = pab
+ z.ybr[y+0][x+1] = abc
+ z.ybr[y+0][x+2] = bcd
+ z.ybr[y+0][x+3] = cde
+ z.ybr[y+1][x+0] = qpa
+ z.ybr[y+1][x+1] = pab
+ z.ybr[y+1][x+2] = abc
+ z.ybr[y+1][x+3] = bcd
+ z.ybr[y+2][x+0] = rqp
+ z.ybr[y+2][x+1] = qpa
+ z.ybr[y+2][x+2] = pab
+ z.ybr[y+2][x+3] = abc
+ z.ybr[y+3][x+0] = srq
+ z.ybr[y+3][x+1] = rqp
+ z.ybr[y+3][x+2] = qpa
+ z.ybr[y+3][x+3] = pab
+}
+
+func predFunc4VR(z *Decoder, y, x int) {
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ a := int32(z.ybr[y-1][x-1])
+ b := int32(z.ybr[y-1][x+0])
+ c := int32(z.ybr[y-1][x+1])
+ d := int32(z.ybr[y-1][x+2])
+ e := int32(z.ybr[y-1][x+3])
+ ab := uint8((a + b + 1) / 2)
+ bc := uint8((b + c + 1) / 2)
+ cd := uint8((c + d + 1) / 2)
+ de := uint8((d + e + 1) / 2)
+ rqp := uint8((r + 2*q + p + 2) / 4)
+ qpa := uint8((q + 2*p + a + 2) / 4)
+ pab := uint8((p + 2*a + b + 2) / 4)
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ z.ybr[y+0][x+0] = ab
+ z.ybr[y+0][x+1] = bc
+ z.ybr[y+0][x+2] = cd
+ z.ybr[y+0][x+3] = de
+ z.ybr[y+1][x+0] = pab
+ z.ybr[y+1][x+1] = abc
+ z.ybr[y+1][x+2] = bcd
+ z.ybr[y+1][x+3] = cde
+ z.ybr[y+2][x+0] = qpa
+ z.ybr[y+2][x+1] = ab
+ z.ybr[y+2][x+2] = bc
+ z.ybr[y+2][x+3] = cd
+ z.ybr[y+3][x+0] = rqp
+ z.ybr[y+3][x+1] = pab
+ z.ybr[y+3][x+2] = abc
+ z.ybr[y+3][x+3] = bcd
+}
+
+func predFunc4LD(z *Decoder, y, x int) {
+ a := int32(z.ybr[y-1][x+0])
+ b := int32(z.ybr[y-1][x+1])
+ c := int32(z.ybr[y-1][x+2])
+ d := int32(z.ybr[y-1][x+3])
+ e := int32(z.ybr[y-1][x+4])
+ f := int32(z.ybr[y-1][x+5])
+ g := int32(z.ybr[y-1][x+6])
+ h := int32(z.ybr[y-1][x+7])
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ def := uint8((d + 2*e + f + 2) / 4)
+ efg := uint8((e + 2*f + g + 2) / 4)
+ fgh := uint8((f + 2*g + h + 2) / 4)
+ ghh := uint8((g + 2*h + h + 2) / 4)
+ z.ybr[y+0][x+0] = abc
+ z.ybr[y+0][x+1] = bcd
+ z.ybr[y+0][x+2] = cde
+ z.ybr[y+0][x+3] = def
+ z.ybr[y+1][x+0] = bcd
+ z.ybr[y+1][x+1] = cde
+ z.ybr[y+1][x+2] = def
+ z.ybr[y+1][x+3] = efg
+ z.ybr[y+2][x+0] = cde
+ z.ybr[y+2][x+1] = def
+ z.ybr[y+2][x+2] = efg
+ z.ybr[y+2][x+3] = fgh
+ z.ybr[y+3][x+0] = def
+ z.ybr[y+3][x+1] = efg
+ z.ybr[y+3][x+2] = fgh
+ z.ybr[y+3][x+3] = ghh
+}
+
+func predFunc4VL(z *Decoder, y, x int) {
+ a := int32(z.ybr[y-1][x+0])
+ b := int32(z.ybr[y-1][x+1])
+ c := int32(z.ybr[y-1][x+2])
+ d := int32(z.ybr[y-1][x+3])
+ e := int32(z.ybr[y-1][x+4])
+ f := int32(z.ybr[y-1][x+5])
+ g := int32(z.ybr[y-1][x+6])
+ h := int32(z.ybr[y-1][x+7])
+ ab := uint8((a + b + 1) / 2)
+ bc := uint8((b + c + 1) / 2)
+ cd := uint8((c + d + 1) / 2)
+ de := uint8((d + e + 1) / 2)
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ def := uint8((d + 2*e + f + 2) / 4)
+ efg := uint8((e + 2*f + g + 2) / 4)
+ fgh := uint8((f + 2*g + h + 2) / 4)
+ z.ybr[y+0][x+0] = ab
+ z.ybr[y+0][x+1] = bc
+ z.ybr[y+0][x+2] = cd
+ z.ybr[y+0][x+3] = de
+ z.ybr[y+1][x+0] = abc
+ z.ybr[y+1][x+1] = bcd
+ z.ybr[y+1][x+2] = cde
+ z.ybr[y+1][x+3] = def
+ z.ybr[y+2][x+0] = bc
+ z.ybr[y+2][x+1] = cd
+ z.ybr[y+2][x+2] = de
+ z.ybr[y+2][x+3] = efg
+ z.ybr[y+3][x+0] = bcd
+ z.ybr[y+3][x+1] = cde
+ z.ybr[y+3][x+2] = def
+ z.ybr[y+3][x+3] = fgh
+}
+
+func predFunc4HD(z *Decoder, y, x int) {
+ s := int32(z.ybr[y+3][x-1])
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ a := int32(z.ybr[y-1][x-1])
+ b := int32(z.ybr[y-1][x+0])
+ c := int32(z.ybr[y-1][x+1])
+ d := int32(z.ybr[y-1][x+2])
+ sr := uint8((s + r + 1) / 2)
+ rq := uint8((r + q + 1) / 2)
+ qp := uint8((q + p + 1) / 2)
+ pa := uint8((p + a + 1) / 2)
+ srq := uint8((s + 2*r + q + 2) / 4)
+ rqp := uint8((r + 2*q + p + 2) / 4)
+ qpa := uint8((q + 2*p + a + 2) / 4)
+ pab := uint8((p + 2*a + b + 2) / 4)
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ z.ybr[y+0][x+0] = pa
+ z.ybr[y+0][x+1] = pab
+ z.ybr[y+0][x+2] = abc
+ z.ybr[y+0][x+3] = bcd
+ z.ybr[y+1][x+0] = qp
+ z.ybr[y+1][x+1] = qpa
+ z.ybr[y+1][x+2] = pa
+ z.ybr[y+1][x+3] = pab
+ z.ybr[y+2][x+0] = rq
+ z.ybr[y+2][x+1] = rqp
+ z.ybr[y+2][x+2] = qp
+ z.ybr[y+2][x+3] = qpa
+ z.ybr[y+3][x+0] = sr
+ z.ybr[y+3][x+1] = srq
+ z.ybr[y+3][x+2] = rq
+ z.ybr[y+3][x+3] = rqp
+}
+
+func predFunc4HU(z *Decoder, y, x int) {
+ s := int32(z.ybr[y+3][x-1])
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ pq := uint8((p + q + 1) / 2)
+ qr := uint8((q + r + 1) / 2)
+ rs := uint8((r + s + 1) / 2)
+ pqr := uint8((p + 2*q + r + 2) / 4)
+ qrs := uint8((q + 2*r + s + 2) / 4)
+ rss := uint8((r + 2*s + s + 2) / 4)
+ sss := uint8(s)
+ z.ybr[y+0][x+0] = pq
+ z.ybr[y+0][x+1] = pqr
+ z.ybr[y+0][x+2] = qr
+ z.ybr[y+0][x+3] = qrs
+ z.ybr[y+1][x+0] = qr
+ z.ybr[y+1][x+1] = qrs
+ z.ybr[y+1][x+2] = rs
+ z.ybr[y+1][x+3] = rss
+ z.ybr[y+2][x+0] = rs
+ z.ybr[y+2][x+1] = rss
+ z.ybr[y+2][x+2] = sss
+ z.ybr[y+2][x+3] = sss
+ z.ybr[y+3][x+0] = sss
+ z.ybr[y+3][x+1] = sss
+ z.ybr[y+3][x+2] = sss
+ z.ybr[y+3][x+3] = sss
+}
+
+func predFunc8DC(z *Decoder, y, x int) {
+ sum := uint32(8)
+ for i := 0; i < 8; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ for j := 0; j < 8; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 16)
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc8TM(z *Decoder, y, x int) {
+ delta0 := -int32(z.ybr[y-1][x-1])
+ for j := 0; j < 8; j++ {
+ delta1 := delta0 + int32(z.ybr[y+j][x-1])
+ for i := 0; i < 8; i++ {
+ delta2 := delta1 + int32(z.ybr[y-1][x+i])
+ z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
+ }
+ }
+}
+
+func predFunc8VE(z *Decoder, y, x int) {
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = z.ybr[y-1][x+i]
+ }
+ }
+}
+
+func predFunc8HE(z *Decoder, y, x int) {
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = z.ybr[y+j][x-1]
+ }
+ }
+}
+
+func predFunc8DCTop(z *Decoder, y, x int) {
+ sum := uint32(4)
+ for j := 0; j < 8; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 8)
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc8DCLeft(z *Decoder, y, x int) {
+ sum := uint32(4)
+ for i := 0; i < 8; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ avg := uint8(sum / 8)
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc8DCTopLeft(z *Decoder, y, x int) {
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = 0x80
+ }
+ }
+}
+
+func predFunc16DC(z *Decoder, y, x int) {
+ sum := uint32(16)
+ for i := 0; i < 16; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ for j := 0; j < 16; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 32)
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc16TM(z *Decoder, y, x int) {
+ delta0 := -int32(z.ybr[y-1][x-1])
+ for j := 0; j < 16; j++ {
+ delta1 := delta0 + int32(z.ybr[y+j][x-1])
+ for i := 0; i < 16; i++ {
+ delta2 := delta1 + int32(z.ybr[y-1][x+i])
+ z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
+ }
+ }
+}
+
+func predFunc16VE(z *Decoder, y, x int) {
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = z.ybr[y-1][x+i]
+ }
+ }
+}
+
+func predFunc16HE(z *Decoder, y, x int) {
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = z.ybr[y+j][x-1]
+ }
+ }
+}
+
+func predFunc16DCTop(z *Decoder, y, x int) {
+ sum := uint32(8)
+ for j := 0; j < 16; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 16)
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc16DCLeft(z *Decoder, y, x int) {
+ sum := uint32(8)
+ for i := 0; i < 16; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ avg := uint8(sum / 16)
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc16DCTopLeft(z *Decoder, y, x int) {
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = 0x80
+ }
+ }
+}
diff --git a/vendor/golang.org/x/image/vp8/quant.go b/vendor/golang.org/x/image/vp8/quant.go
new file mode 100644
index 0000000..da43616
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/quant.go
@@ -0,0 +1,98 @@
+// 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.
+
+package vp8
+
+// This file implements parsing the quantization factors.
+
+// quant are DC/AC quantization factors.
+type quant struct {
+ y1 [2]uint16
+ y2 [2]uint16
+ uv [2]uint16
+}
+
+// clip clips x to the range [min, max] inclusive.
+func clip(x, min, max int32) int32 {
+ if x < min {
+ return min
+ }
+ if x > max {
+ return max
+ }
+ return x
+}
+
+// parseQuant parses the quantization factors, as specified in section 9.6.
+func (d *Decoder) parseQuant() {
+ baseQ0 := d.fp.readUint(uniformProb, 7)
+ dqy1DC := d.fp.readOptionalInt(uniformProb, 4)
+ const dqy1AC = 0
+ dqy2DC := d.fp.readOptionalInt(uniformProb, 4)
+ dqy2AC := d.fp.readOptionalInt(uniformProb, 4)
+ dquvDC := d.fp.readOptionalInt(uniformProb, 4)
+ dquvAC := d.fp.readOptionalInt(uniformProb, 4)
+ for i := 0; i < nSegment; i++ {
+ q := int32(baseQ0)
+ if d.segmentHeader.useSegment {
+ if d.segmentHeader.relativeDelta {
+ q += int32(d.segmentHeader.quantizer[i])
+ } else {
+ q = int32(d.segmentHeader.quantizer[i])
+ }
+ }
+ d.quant[i].y1[0] = dequantTableDC[clip(q+dqy1DC, 0, 127)]
+ d.quant[i].y1[1] = dequantTableAC[clip(q+dqy1AC, 0, 127)]
+ d.quant[i].y2[0] = dequantTableDC[clip(q+dqy2DC, 0, 127)] * 2
+ d.quant[i].y2[1] = dequantTableAC[clip(q+dqy2AC, 0, 127)] * 155 / 100
+ if d.quant[i].y2[1] < 8 {
+ d.quant[i].y2[1] = 8
+ }
+ // The 117 is not a typo. The dequant_init function in the spec's Reference
+ // Decoder Source Code (http://tools.ietf.org/html/rfc6386#section-9.6 Page 145)
+ // says to clamp the LHS value at 132, which is equal to dequantTableDC[117].
+ d.quant[i].uv[0] = dequantTableDC[clip(q+dquvDC, 0, 117)]
+ d.quant[i].uv[1] = dequantTableAC[clip(q+dquvAC, 0, 127)]
+ }
+}
+
+// The dequantization tables are specified in section 14.1.
+var (
+ dequantTableDC = [128]uint16{
+ 4, 5, 6, 7, 8, 9, 10, 10,
+ 11, 12, 13, 14, 15, 16, 17, 17,
+ 18, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 25, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89,
+ 91, 93, 95, 96, 98, 100, 101, 102,
+ 104, 106, 108, 110, 112, 114, 116, 118,
+ 122, 124, 126, 128, 130, 132, 134, 136,
+ 138, 140, 143, 145, 148, 151, 154, 157,
+ }
+ dequantTableAC = [128]uint16{
+ 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 60,
+ 62, 64, 66, 68, 70, 72, 74, 76,
+ 78, 80, 82, 84, 86, 88, 90, 92,
+ 94, 96, 98, 100, 102, 104, 106, 108,
+ 110, 112, 114, 116, 119, 122, 125, 128,
+ 131, 134, 137, 140, 143, 146, 149, 152,
+ 155, 158, 161, 164, 167, 170, 173, 177,
+ 181, 185, 189, 193, 197, 201, 205, 209,
+ 213, 217, 221, 225, 229, 234, 239, 245,
+ 249, 254, 259, 264, 269, 274, 279, 284,
+ }
+)
diff --git a/vendor/golang.org/x/image/vp8/reconstruct.go b/vendor/golang.org/x/image/vp8/reconstruct.go
new file mode 100644
index 0000000..c1cc4b5
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/reconstruct.go
@@ -0,0 +1,442 @@
+// 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.
+
+package vp8
+
+// This file implements decoding DCT/WHT residual coefficients and
+// reconstructing YCbCr data equal to predicted values plus residuals.
+//
+// There are 1*16*16 + 2*8*8 + 1*4*4 coefficients per macroblock:
+// - 1*16*16 luma DCT coefficients,
+// - 2*8*8 chroma DCT coefficients, and
+// - 1*4*4 luma WHT coefficients.
+// Coefficients are read in lots of 16, and the later coefficients in each lot
+// are often zero.
+//
+// The YCbCr data consists of 1*16*16 luma values and 2*8*8 chroma values,
+// plus previously decoded values along the top and left borders. The combined
+// values are laid out as a [1+16+1+8][32]uint8 so that vertically adjacent
+// samples are 32 bytes apart. In detail, the layout is:
+//
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// . . . . . . . a b b b b b b b b b b b b b b b b c c c c . . . . 0
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 1
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 2
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 3
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 4
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 5
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 6
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 7
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 8
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 9
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 10
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 11
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 12
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 13
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 14
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 15
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 16
+// . . . . . . . e f f f f f f f f . . . . . . . g h h h h h h h h 17
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 18
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 19
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 20
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 21
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 22
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 23
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 24
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 25
+//
+// Y, B and R are the reconstructed luma (Y) and chroma (B, R) values.
+// The Y values are predicted (either as one 16x16 region or 16 4x4 regions)
+// based on the row above's Y values (some combination of {abc} or {dYC}) and
+// the column left's Y values (either {ad} or {bY}). Similarly, B and R values
+// are predicted on the row above and column left of their respective 8x8
+// region: {efi} for B, {ghj} for R.
+//
+// For uppermost macroblocks (i.e. those with mby == 0), the {abcefgh} values
+// are initialized to 0x81. Otherwise, they are copied from the bottom row of
+// the macroblock above. The {c} values are then duplicated from row 0 to rows
+// 4, 8 and 12 of the ybr workspace.
+// Similarly, for leftmost macroblocks (i.e. those with mbx == 0), the {adeigj}
+// values are initialized to 0x7f. Otherwise, they are copied from the right
+// column of the macroblock to the left.
+// For the top-left macroblock (with mby == 0 && mbx == 0), {aeg} is 0x81.
+//
+// When moving from one macroblock to the next horizontally, the {adeigj}
+// values can simply be copied from the workspace to itself, shifted by 8 or
+// 16 columns. When moving from one macroblock to the next vertically,
+// filtering can occur and hence the row values have to be copied from the
+// post-filtered image instead of the pre-filtered workspace.
+
+const (
+ bCoeffBase = 1*16*16 + 0*8*8
+ rCoeffBase = 1*16*16 + 1*8*8
+ whtCoeffBase = 1*16*16 + 2*8*8
+)
+
+const (
+ ybrYX = 8
+ ybrYY = 1
+ ybrBX = 8
+ ybrBY = 18
+ ybrRX = 24
+ ybrRY = 18
+)
+
+// prepareYBR prepares the {abcdefghij} elements of ybr.
+func (d *Decoder) prepareYBR(mbx, mby int) {
+ if mbx == 0 {
+ for y := 0; y < 17; y++ {
+ d.ybr[y][7] = 0x81
+ }
+ for y := 17; y < 26; y++ {
+ d.ybr[y][7] = 0x81
+ d.ybr[y][23] = 0x81
+ }
+ } else {
+ for y := 0; y < 17; y++ {
+ d.ybr[y][7] = d.ybr[y][7+16]
+ }
+ for y := 17; y < 26; y++ {
+ d.ybr[y][7] = d.ybr[y][15]
+ d.ybr[y][23] = d.ybr[y][31]
+ }
+ }
+ if mby == 0 {
+ for x := 7; x < 28; x++ {
+ d.ybr[0][x] = 0x7f
+ }
+ for x := 7; x < 16; x++ {
+ d.ybr[17][x] = 0x7f
+ }
+ for x := 23; x < 32; x++ {
+ d.ybr[17][x] = 0x7f
+ }
+ } else {
+ for i := 0; i < 16; i++ {
+ d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
+ }
+ for i := 0; i < 8; i++ {
+ d.ybr[17][8+i] = d.img.Cb[(8*mby-1)*d.img.CStride+8*mbx+i]
+ }
+ for i := 0; i < 8; i++ {
+ d.ybr[17][24+i] = d.img.Cr[(8*mby-1)*d.img.CStride+8*mbx+i]
+ }
+ if mbx == d.mbw-1 {
+ for i := 16; i < 20; i++ {
+ d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+15]
+ }
+ } else {
+ for i := 16; i < 20; i++ {
+ d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
+ }
+ }
+ }
+ for y := 4; y < 16; y += 4 {
+ d.ybr[y][24] = d.ybr[0][24]
+ d.ybr[y][25] = d.ybr[0][25]
+ d.ybr[y][26] = d.ybr[0][26]
+ d.ybr[y][27] = d.ybr[0][27]
+ }
+}
+
+// btou converts a bool to a 0/1 value.
+func btou(b bool) uint8 {
+ if b {
+ return 1
+ }
+ return 0
+}
+
+// pack packs four 0/1 values into four bits of a uint32.
+func pack(x [4]uint8, shift int) uint32 {
+ u := uint32(x[0])<<0 | uint32(x[1])<<1 | uint32(x[2])<<2 | uint32(x[3])<<3
+ return u << uint(shift)
+}
+
+// unpack unpacks four 0/1 values from a four-bit value.
+var unpack = [16][4]uint8{
+ {0, 0, 0, 0},
+ {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {1, 1, 0, 0},
+ {0, 0, 1, 0},
+ {1, 0, 1, 0},
+ {0, 1, 1, 0},
+ {1, 1, 1, 0},
+ {0, 0, 0, 1},
+ {1, 0, 0, 1},
+ {0, 1, 0, 1},
+ {1, 1, 0, 1},
+ {0, 0, 1, 1},
+ {1, 0, 1, 1},
+ {0, 1, 1, 1},
+ {1, 1, 1, 1},
+}
+
+var (
+ // The mapping from 4x4 region position to band is specified in section 13.3.
+ bands = [17]uint8{0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0}
+ // Category probabilties are specified in section 13.2.
+ // Decoding categories 1 and 2 are done inline.
+ cat3456 = [4][12]uint8{
+ {173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0},
+ {180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0},
+ {254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0},
+ }
+ // The zigzag order is:
+ // 0 1 5 6
+ // 2 4 7 12
+ // 3 8 11 13
+ // 9 10 14 15
+ zigzag = [16]uint8{0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15}
+)
+
+// parseResiduals4 parses a 4x4 region of residual coefficients, as specified
+// in section 13.3, and returns a 0/1 value indicating whether there was at
+// least one non-zero coefficient.
+// r is the partition to read bits from.
+// plane and context describe which token probability table to use. context is
+// either 0, 1 or 2, and equals how many of the macroblock left and macroblock
+// above have non-zero coefficients.
+// quant are the DC/AC quantization factors.
+// skipFirstCoeff is whether the DC coefficient has already been parsed.
+// coeffBase is the base index of d.coeff to write to.
+func (d *Decoder) parseResiduals4(r *partition, plane int, context uint8, quant [2]uint16, skipFirstCoeff bool, coeffBase int) uint8 {
+ prob, n := &d.tokenProb[plane], 0
+ if skipFirstCoeff {
+ n = 1
+ }
+ p := prob[bands[n]][context]
+ if !r.readBit(p[0]) {
+ return 0
+ }
+ for n != 16 {
+ n++
+ if !r.readBit(p[1]) {
+ p = prob[bands[n]][0]
+ continue
+ }
+ var v uint32
+ if !r.readBit(p[2]) {
+ v = 1
+ p = prob[bands[n]][1]
+ } else {
+ if !r.readBit(p[3]) {
+ if !r.readBit(p[4]) {
+ v = 2
+ } else {
+ v = 3 + r.readUint(p[5], 1)
+ }
+ } else if !r.readBit(p[6]) {
+ if !r.readBit(p[7]) {
+ // Category 1.
+ v = 5 + r.readUint(159, 1)
+ } else {
+ // Category 2.
+ v = 7 + 2*r.readUint(165, 1) + r.readUint(145, 1)
+ }
+ } else {
+ // Categories 3, 4, 5 or 6.
+ b1 := r.readUint(p[8], 1)
+ b0 := r.readUint(p[9+b1], 1)
+ cat := 2*b1 + b0
+ tab := &cat3456[cat]
+ v = 0
+ for i := 0; tab[i] != 0; i++ {
+ v *= 2
+ v += r.readUint(tab[i], 1)
+ }
+ v += 3 + (8 << cat)
+ }
+ p = prob[bands[n]][2]
+ }
+ z := zigzag[n-1]
+ c := int32(v) * int32(quant[btou(z > 0)])
+ if r.readBit(uniformProb) {
+ c = -c
+ }
+ d.coeff[coeffBase+int(z)] = int16(c)
+ if n == 16 || !r.readBit(p[0]) {
+ return 1
+ }
+ }
+ return 1
+}
+
+// parseResiduals parses the residuals and returns whether inner loop filtering
+// should be skipped for this macroblock.
+func (d *Decoder) parseResiduals(mbx, mby int) (skip bool) {
+ partition := &d.op[mby&(d.nOP-1)]
+ plane := planeY1SansY2
+ quant := &d.quant[d.segment]
+
+ // Parse the DC coefficient of each 4x4 luma region.
+ if d.usePredY16 {
+ nz := d.parseResiduals4(partition, planeY2, d.leftMB.nzY16+d.upMB[mbx].nzY16, quant.y2, false, whtCoeffBase)
+ d.leftMB.nzY16 = nz
+ d.upMB[mbx].nzY16 = nz
+ d.inverseWHT16()
+ plane = planeY1WithY2
+ }
+
+ var (
+ nzDC, nzAC [4]uint8
+ nzDCMask, nzACMask uint32
+ coeffBase int
+ )
+
+ // Parse the luma coefficients.
+ lnz := unpack[d.leftMB.nzMask&0x0f]
+ unz := unpack[d.upMB[mbx].nzMask&0x0f]
+ for y := 0; y < 4; y++ {
+ nz := lnz[y]
+ for x := 0; x < 4; x++ {
+ nz = d.parseResiduals4(partition, plane, nz+unz[x], quant.y1, d.usePredY16, coeffBase)
+ unz[x] = nz
+ nzAC[x] = nz
+ nzDC[x] = btou(d.coeff[coeffBase] != 0)
+ coeffBase += 16
+ }
+ lnz[y] = nz
+ nzDCMask |= pack(nzDC, y*4)
+ nzACMask |= pack(nzAC, y*4)
+ }
+ lnzMask := pack(lnz, 0)
+ unzMask := pack(unz, 0)
+
+ // Parse the chroma coefficients.
+ lnz = unpack[d.leftMB.nzMask>>4]
+ unz = unpack[d.upMB[mbx].nzMask>>4]
+ for c := 0; c < 4; c += 2 {
+ for y := 0; y < 2; y++ {
+ nz := lnz[y+c]
+ for x := 0; x < 2; x++ {
+ nz = d.parseResiduals4(partition, planeUV, nz+unz[x+c], quant.uv, false, coeffBase)
+ unz[x+c] = nz
+ nzAC[y*2+x] = nz
+ nzDC[y*2+x] = btou(d.coeff[coeffBase] != 0)
+ coeffBase += 16
+ }
+ lnz[y+c] = nz
+ }
+ nzDCMask |= pack(nzDC, 16+c*2)
+ nzACMask |= pack(nzAC, 16+c*2)
+ }
+ lnzMask |= pack(lnz, 4)
+ unzMask |= pack(unz, 4)
+
+ // Save decoder state.
+ d.leftMB.nzMask = uint8(lnzMask)
+ d.upMB[mbx].nzMask = uint8(unzMask)
+ d.nzDCMask = nzDCMask
+ d.nzACMask = nzACMask
+
+ // Section 15.1 of the spec says that "Steps 2 and 4 [of the loop filter]
+ // are skipped... [if] there is no DCT coefficient coded for the whole
+ // macroblock."
+ return nzDCMask == 0 && nzACMask == 0
+}
+
+// reconstructMacroblock applies the predictor functions and adds the inverse-
+// DCT transformed residuals to recover the YCbCr data.
+func (d *Decoder) reconstructMacroblock(mbx, mby int) {
+ if d.usePredY16 {
+ p := checkTopLeftPred(mbx, mby, d.predY16)
+ predFunc16[p](d, 1, 8)
+ for j := 0; j < 4; j++ {
+ for i := 0; i < 4; i++ {
+ n := 4*j + i
+ y := 4*j + 1
+ x := 4*i + 8
+ mask := uint32(1) << uint(n)
+ if d.nzACMask&mask != 0 {
+ d.inverseDCT4(y, x, 16*n)
+ } else if d.nzDCMask&mask != 0 {
+ d.inverseDCT4DCOnly(y, x, 16*n)
+ }
+ }
+ }
+ } else {
+ for j := 0; j < 4; j++ {
+ for i := 0; i < 4; i++ {
+ n := 4*j + i
+ y := 4*j + 1
+ x := 4*i + 8
+ predFunc4[d.predY4[j][i]](d, y, x)
+ mask := uint32(1) << uint(n)
+ if d.nzACMask&mask != 0 {
+ d.inverseDCT4(y, x, 16*n)
+ } else if d.nzDCMask&mask != 0 {
+ d.inverseDCT4DCOnly(y, x, 16*n)
+ }
+ }
+ }
+ }
+ p := checkTopLeftPred(mbx, mby, d.predC8)
+ predFunc8[p](d, ybrBY, ybrBX)
+ if d.nzACMask&0x0f0000 != 0 {
+ d.inverseDCT8(ybrBY, ybrBX, bCoeffBase)
+ } else if d.nzDCMask&0x0f0000 != 0 {
+ d.inverseDCT8DCOnly(ybrBY, ybrBX, bCoeffBase)
+ }
+ predFunc8[p](d, ybrRY, ybrRX)
+ if d.nzACMask&0xf00000 != 0 {
+ d.inverseDCT8(ybrRY, ybrRX, rCoeffBase)
+ } else if d.nzDCMask&0xf00000 != 0 {
+ d.inverseDCT8DCOnly(ybrRY, ybrRX, rCoeffBase)
+ }
+}
+
+// reconstruct reconstructs one macroblock and returns whether inner loop
+// filtering should be skipped for it.
+func (d *Decoder) reconstruct(mbx, mby int) (skip bool) {
+ if d.segmentHeader.updateMap {
+ if !d.fp.readBit(d.segmentHeader.prob[0]) {
+ d.segment = int(d.fp.readUint(d.segmentHeader.prob[1], 1))
+ } else {
+ d.segment = int(d.fp.readUint(d.segmentHeader.prob[2], 1)) + 2
+ }
+ }
+ if d.useSkipProb {
+ skip = d.fp.readBit(d.skipProb)
+ }
+ // Prepare the workspace.
+ for i := range d.coeff {
+ d.coeff[i] = 0
+ }
+ d.prepareYBR(mbx, mby)
+ // Parse the predictor modes.
+ d.usePredY16 = d.fp.readBit(145)
+ if d.usePredY16 {
+ d.parsePredModeY16(mbx)
+ } else {
+ d.parsePredModeY4(mbx)
+ }
+ d.parsePredModeC8()
+ // Parse the residuals.
+ if !skip {
+ skip = d.parseResiduals(mbx, mby)
+ } else {
+ if d.usePredY16 {
+ d.leftMB.nzY16 = 0
+ d.upMB[mbx].nzY16 = 0
+ }
+ d.leftMB.nzMask = 0
+ d.upMB[mbx].nzMask = 0
+ d.nzDCMask = 0
+ d.nzACMask = 0
+ }
+ // Reconstruct the YCbCr data and copy it to the image.
+ d.reconstructMacroblock(mbx, mby)
+ for i, y := (mby*d.img.YStride+mbx)*16, 0; y < 16; i, y = i+d.img.YStride, y+1 {
+ copy(d.img.Y[i:i+16], d.ybr[ybrYY+y][ybrYX:ybrYX+16])
+ }
+ for i, y := (mby*d.img.CStride+mbx)*8, 0; y < 8; i, y = i+d.img.CStride, y+1 {
+ copy(d.img.Cb[i:i+8], d.ybr[ybrBY+y][ybrBX:ybrBX+8])
+ copy(d.img.Cr[i:i+8], d.ybr[ybrRY+y][ybrRX:ybrRX+8])
+ }
+ return skip
+}
diff --git a/vendor/golang.org/x/image/vp8/token.go b/vendor/golang.org/x/image/vp8/token.go
new file mode 100644
index 0000000..da99cf0
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/token.go
@@ -0,0 +1,381 @@
+// 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.
+
+package vp8
+
+// This file contains token probabilities for decoding DCT/WHT coefficients, as
+// specified in chapter 13.
+
+func (d *Decoder) parseTokenProb() {
+ for i := range d.tokenProb {
+ for j := range d.tokenProb[i] {
+ for k := range d.tokenProb[i][j] {
+ for l := range d.tokenProb[i][j][k] {
+ if d.fp.readBit(tokenProbUpdateProb[i][j][k][l]) {
+ d.tokenProb[i][j][k][l] = uint8(d.fp.readUint(uniformProb, 8))
+ }
+ }
+ }
+ }
+ }
+}
+
+// The plane enumeration is specified in section 13.3.
+const (
+ planeY1WithY2 = iota
+ planeY2
+ planeUV
+ planeY1SansY2
+ nPlane
+)
+
+const (
+ nBand = 8
+ nContext = 3
+ nProb = 11
+)
+
+// Token probability update probabilities are specified in section 13.4.
+var tokenProbUpdateProb = [nPlane][nBand][nContext][nProb]uint8{
+ {
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255},
+ {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255},
+ {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255},
+ {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ },
+ {
+ {
+ {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255},
+ {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255},
+ },
+ {
+ {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ },
+ {
+ {
+ {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255},
+ {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255},
+ {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ },
+ {
+ {
+ {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255},
+ {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255},
+ {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ },
+}
+
+// Default token probabilities are specified in section 13.5.
+var defaultTokenProb = [nPlane][nBand][nContext][nProb]uint8{
+ {
+ {
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128},
+ {189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128},
+ {106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128},
+ {181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128},
+ {78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128},
+ },
+ {
+ {1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128},
+ {184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128},
+ {77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128},
+ {170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128},
+ {37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128},
+ {207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128},
+ {102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128},
+ {177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128},
+ {80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ },
+ {
+ {
+ {198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62},
+ {131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1},
+ {68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128},
+ },
+ {
+ {1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128},
+ {184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128},
+ {81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128},
+ },
+ {
+ {1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128},
+ {99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128},
+ {23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128},
+ },
+ {
+ {1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128},
+ {109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128},
+ {44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128},
+ {94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128},
+ {22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128},
+ },
+ {
+ {1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128},
+ {124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128},
+ {35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128},
+ },
+ {
+ {1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128},
+ {121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128},
+ {45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128},
+ },
+ {
+ {1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128},
+ {203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128},
+ {137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128},
+ },
+ },
+ {
+ {
+ {253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128},
+ {175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128},
+ {73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128},
+ },
+ {
+ {1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128},
+ {239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128},
+ {155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128},
+ {201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128},
+ {69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128},
+ },
+ {
+ {1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128},
+ {223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128},
+ {141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128},
+ {190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128},
+ {149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128},
+ {213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128},
+ {55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ },
+ {
+ {
+ {202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255},
+ {126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128},
+ {61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128},
+ },
+ {
+ {1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128},
+ {166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128},
+ {39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128},
+ },
+ {
+ {1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128},
+ {124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128},
+ {24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128},
+ },
+ {
+ {1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128},
+ {149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128},
+ {28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128},
+ },
+ {
+ {1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128},
+ {123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128},
+ {20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128},
+ },
+ {
+ {1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128},
+ {168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128},
+ {47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128},
+ {141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128},
+ {42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128},
+ },
+ {
+ {1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ },
+}
diff --git a/vendor/golang.org/x/image/vp8l/decode.go b/vendor/golang.org/x/image/vp8l/decode.go
new file mode 100644
index 0000000..4319487
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8l/decode.go
@@ -0,0 +1,603 @@
+// 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 vp8l implements a decoder for the VP8L lossless image format.
+//
+// The VP8L specification is at:
+// https://developers.google.com/speed/webp/docs/riff_container
+package vp8l // import "golang.org/x/image/vp8l"
+
+import (
+ "bufio"
+ "errors"
+ "image"
+ "image/color"
+ "io"
+)
+
+var (
+ errInvalidCodeLengths = errors.New("vp8l: invalid code lengths")
+ errInvalidHuffmanTree = errors.New("vp8l: invalid Huffman tree")
+)
+
+// colorCacheMultiplier is the multiplier used for the color cache hash
+// function, specified in section 4.2.3.
+const colorCacheMultiplier = 0x1e35a7bd
+
+// distanceMapTable is the look-up table for distanceMap.
+var distanceMapTable = [120]uint8{
+ 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
+ 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
+ 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
+ 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
+ 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
+ 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
+ 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
+ 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
+ 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
+ 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
+ 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
+ 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70,
+}
+
+// distanceMap maps a LZ77 backwards reference distance to a two-dimensional
+// pixel offset, specified in section 4.2.2.
+func distanceMap(w int32, code uint32) int32 {
+ if int32(code) > int32(len(distanceMapTable)) {
+ return int32(code) - int32(len(distanceMapTable))
+ }
+ distCode := int32(distanceMapTable[code-1])
+ yOffset := distCode >> 4
+ xOffset := 8 - distCode&0xf
+ if d := yOffset*w + xOffset; d >= 1 {
+ return d
+ }
+ return 1
+}
+
+// decoder holds the bit-stream for a VP8L image.
+type decoder struct {
+ r io.ByteReader
+ bits uint32
+ nBits uint32
+}
+
+// read reads the next n bits from the decoder's bit-stream.
+func (d *decoder) read(n uint32) (uint32, error) {
+ for d.nBits < n {
+ c, err := d.r.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return 0, err
+ }
+ d.bits |= uint32(c) << d.nBits
+ d.nBits += 8
+ }
+ u := d.bits & (1<>= n
+ d.nBits -= n
+ return u, nil
+}
+
+// decodeTransform decodes the next transform and the width of the image after
+// transformation (or equivalently, before inverse transformation), specified
+// in section 3.
+func (d *decoder) decodeTransform(w int32, h int32) (t transform, newWidth int32, err error) {
+ t.oldWidth = w
+ t.transformType, err = d.read(2)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ switch t.transformType {
+ case transformTypePredictor, transformTypeCrossColor:
+ t.bits, err = d.read(3)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ t.bits += 2
+ t.pix, err = d.decodePix(nTiles(w, t.bits), nTiles(h, t.bits), 0, false)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ case transformTypeSubtractGreen:
+ // No-op.
+ case transformTypeColorIndexing:
+ nColors, err := d.read(8)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ nColors++
+ t.bits = 0
+ switch {
+ case nColors <= 2:
+ t.bits = 3
+ case nColors <= 4:
+ t.bits = 2
+ case nColors <= 16:
+ t.bits = 1
+ }
+ w = nTiles(w, t.bits)
+ pix, err := d.decodePix(int32(nColors), 1, 4*256, false)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ for p := 4; p < len(pix); p += 4 {
+ pix[p+0] += pix[p-4]
+ pix[p+1] += pix[p-3]
+ pix[p+2] += pix[p-2]
+ pix[p+3] += pix[p-1]
+ }
+ // The spec says that "if the index is equal or larger than color_table_size,
+ // the argb color value should be set to 0x00000000 (transparent black)."
+ // We re-slice up to 256 4-byte pixels.
+ t.pix = pix[:4*256]
+ }
+ return t, w, nil
+}
+
+// repeatsCodeLength is the minimum code length for repeated codes.
+const repeatsCodeLength = 16
+
+// These magic numbers are specified at the end of section 5.2.2.
+// The 3-length arrays apply to code lengths >= repeatsCodeLength.
+var (
+ codeLengthCodeOrder = [19]uint8{
+ 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ }
+ repeatBits = [3]uint8{2, 3, 7}
+ repeatOffsets = [3]uint8{3, 3, 11}
+)
+
+// decodeCodeLengths decodes a Huffman tree's code lengths which are themselves
+// encoded via a Huffman tree, specified in section 5.2.2.
+func (d *decoder) decodeCodeLengths(dst []uint32, codeLengthCodeLengths []uint32) error {
+ h := hTree{}
+ if err := h.build(codeLengthCodeLengths); err != nil {
+ return err
+ }
+
+ maxSymbol := len(dst)
+ useLength, err := d.read(1)
+ if err != nil {
+ return err
+ }
+ if useLength != 0 {
+ n, err := d.read(3)
+ if err != nil {
+ return err
+ }
+ n = 2 + 2*n
+ ms, err := d.read(n)
+ if err != nil {
+ return err
+ }
+ maxSymbol = int(ms) + 2
+ if maxSymbol > len(dst) {
+ return errInvalidCodeLengths
+ }
+ }
+
+ // The spec says that "if code 16 [meaning repeat] is used before
+ // a non-zero value has been emitted, a value of 8 is repeated."
+ prevCodeLength := uint32(8)
+
+ for symbol := 0; symbol < len(dst); {
+ if maxSymbol == 0 {
+ break
+ }
+ maxSymbol--
+ codeLength, err := h.next(d)
+ if err != nil {
+ return err
+ }
+ if codeLength < repeatsCodeLength {
+ dst[symbol] = codeLength
+ symbol++
+ if codeLength != 0 {
+ prevCodeLength = codeLength
+ }
+ continue
+ }
+
+ repeat, err := d.read(uint32(repeatBits[codeLength-repeatsCodeLength]))
+ if err != nil {
+ return err
+ }
+ repeat += uint32(repeatOffsets[codeLength-repeatsCodeLength])
+ if symbol+int(repeat) > len(dst) {
+ return errInvalidCodeLengths
+ }
+ // A code length of 16 repeats the previous non-zero code.
+ // A code length of 17 or 18 repeats zeroes.
+ cl := uint32(0)
+ if codeLength == 16 {
+ cl = prevCodeLength
+ }
+ for ; repeat > 0; repeat-- {
+ dst[symbol] = cl
+ symbol++
+ }
+ }
+ return nil
+}
+
+// decodeHuffmanTree decodes a Huffman tree into h.
+func (d *decoder) decodeHuffmanTree(h *hTree, alphabetSize uint32) error {
+ useSimple, err := d.read(1)
+ if err != nil {
+ return err
+ }
+ if useSimple != 0 {
+ nSymbols, err := d.read(1)
+ if err != nil {
+ return err
+ }
+ nSymbols++
+ firstSymbolLengthCode, err := d.read(1)
+ if err != nil {
+ return err
+ }
+ firstSymbolLengthCode = 7*firstSymbolLengthCode + 1
+ var symbols [2]uint32
+ symbols[0], err = d.read(firstSymbolLengthCode)
+ if err != nil {
+ return err
+ }
+ if nSymbols == 2 {
+ symbols[1], err = d.read(8)
+ if err != nil {
+ return err
+ }
+ }
+ return h.buildSimple(nSymbols, symbols, alphabetSize)
+ }
+
+ nCodes, err := d.read(4)
+ if err != nil {
+ return err
+ }
+ nCodes += 4
+ if int(nCodes) > len(codeLengthCodeOrder) {
+ return errInvalidHuffmanTree
+ }
+ codeLengthCodeLengths := [len(codeLengthCodeOrder)]uint32{}
+ for i := uint32(0); i < nCodes; i++ {
+ codeLengthCodeLengths[codeLengthCodeOrder[i]], err = d.read(3)
+ if err != nil {
+ return err
+ }
+ }
+ codeLengths := make([]uint32, alphabetSize)
+ if err = d.decodeCodeLengths(codeLengths, codeLengthCodeLengths[:]); err != nil {
+ return err
+ }
+ return h.build(codeLengths)
+}
+
+const (
+ huffGreen = 0
+ huffRed = 1
+ huffBlue = 2
+ huffAlpha = 3
+ huffDistance = 4
+ nHuff = 5
+)
+
+// hGroup is an array of 5 Huffman trees.
+type hGroup [nHuff]hTree
+
+// decodeHuffmanGroups decodes the one or more hGroups used to decode the pixel
+// data. If one hGroup is used for the entire image, then hPix and hBits will
+// be zero. If more than one hGroup is used, then hPix contains the meta-image
+// that maps tiles to hGroup index, and hBits contains the log-2 tile size.
+func (d *decoder) decodeHuffmanGroups(w int32, h int32, topLevel bool, ccBits uint32) (
+ hGroups []hGroup, hPix []byte, hBits uint32, err error) {
+
+ maxHGroupIndex := 0
+ if topLevel {
+ useMeta, err := d.read(1)
+ if err != nil {
+ return nil, nil, 0, err
+ }
+ if useMeta != 0 {
+ hBits, err = d.read(3)
+ if err != nil {
+ return nil, nil, 0, err
+ }
+ hBits += 2
+ hPix, err = d.decodePix(nTiles(w, hBits), nTiles(h, hBits), 0, false)
+ if err != nil {
+ return nil, nil, 0, err
+ }
+ for p := 0; p < len(hPix); p += 4 {
+ i := int(hPix[p])<<8 | int(hPix[p+1])
+ if maxHGroupIndex < i {
+ maxHGroupIndex = i
+ }
+ }
+ }
+ }
+ hGroups = make([]hGroup, maxHGroupIndex+1)
+ for i := range hGroups {
+ for j, alphabetSize := range alphabetSizes {
+ if j == 0 && ccBits > 0 {
+ alphabetSize += 1 << ccBits
+ }
+ if err := d.decodeHuffmanTree(&hGroups[i][j], alphabetSize); err != nil {
+ return nil, nil, 0, err
+ }
+ }
+ }
+ return hGroups, hPix, hBits, nil
+}
+
+const (
+ nLiteralCodes = 256
+ nLengthCodes = 24
+ nDistanceCodes = 40
+)
+
+var alphabetSizes = [nHuff]uint32{
+ nLiteralCodes + nLengthCodes,
+ nLiteralCodes,
+ nLiteralCodes,
+ nLiteralCodes,
+ nDistanceCodes,
+}
+
+// decodePix decodes pixel data, specified in section 5.2.2.
+func (d *decoder) decodePix(w int32, h int32, minCap int32, topLevel bool) ([]byte, error) {
+ // Decode the color cache parameters.
+ ccBits, ccShift, ccEntries := uint32(0), uint32(0), ([]uint32)(nil)
+ useColorCache, err := d.read(1)
+ if err != nil {
+ return nil, err
+ }
+ if useColorCache != 0 {
+ ccBits, err = d.read(4)
+ if err != nil {
+ return nil, err
+ }
+ if ccBits < 1 || 11 < ccBits {
+ return nil, errors.New("vp8l: invalid color cache parameters")
+ }
+ ccShift = 32 - ccBits
+ ccEntries = make([]uint32, 1<>hBits) + (x >> hBits))
+ hg = &hGroups[uint32(hPix[i])<<8|uint32(hPix[i+1])]
+ }
+
+ green, err := hg[huffGreen].next(d)
+ if err != nil {
+ return nil, err
+ }
+ switch {
+ case green < nLiteralCodes:
+ // We have a literal pixel.
+ red, err := hg[huffRed].next(d)
+ if err != nil {
+ return nil, err
+ }
+ blue, err := hg[huffBlue].next(d)
+ if err != nil {
+ return nil, err
+ }
+ alpha, err := hg[huffAlpha].next(d)
+ if err != nil {
+ return nil, err
+ }
+ pix[p+0] = uint8(red)
+ pix[p+1] = uint8(green)
+ pix[p+2] = uint8(blue)
+ pix[p+3] = uint8(alpha)
+ p += 4
+
+ x++
+ if x == w {
+ x, y = 0, y+1
+ }
+ lookupHG = hMask != 0 && x&hMask == 0
+
+ case green < nLiteralCodes+nLengthCodes:
+ // We have a LZ77 backwards reference.
+ length, err := d.lz77Param(green - nLiteralCodes)
+ if err != nil {
+ return nil, err
+ }
+ distSym, err := hg[huffDistance].next(d)
+ if err != nil {
+ return nil, err
+ }
+ distCode, err := d.lz77Param(distSym)
+ if err != nil {
+ return nil, err
+ }
+ dist := distanceMap(w, distCode)
+ pEnd := p + 4*int(length)
+ q := p - 4*int(dist)
+ qEnd := pEnd - 4*int(dist)
+ if p < 0 || len(pix) < pEnd || q < 0 || len(pix) < qEnd {
+ return nil, errors.New("vp8l: invalid LZ77 parameters")
+ }
+ for ; p < pEnd; p, q = p+1, q+1 {
+ pix[p] = pix[q]
+ }
+
+ x += int32(length)
+ for x >= w {
+ x, y = x-w, y+1
+ }
+ lookupHG = hMask != 0
+
+ default:
+ // We have a color cache lookup. First, insert previous pixels
+ // into the cache. Note that VP8L assumes ARGB order, but the
+ // Go image.RGBA type is in RGBA order.
+ for ; cachedP < p; cachedP += 4 {
+ argb := uint32(pix[cachedP+0])<<16 |
+ uint32(pix[cachedP+1])<<8 |
+ uint32(pix[cachedP+2])<<0 |
+ uint32(pix[cachedP+3])<<24
+ ccEntries[(argb*colorCacheMultiplier)>>ccShift] = argb
+ }
+ green -= nLiteralCodes + nLengthCodes
+ if int(green) >= len(ccEntries) {
+ return nil, errors.New("vp8l: invalid color cache index")
+ }
+ argb := ccEntries[green]
+ pix[p+0] = uint8(argb >> 16)
+ pix[p+1] = uint8(argb >> 8)
+ pix[p+2] = uint8(argb >> 0)
+ pix[p+3] = uint8(argb >> 24)
+ p += 4
+
+ x++
+ if x == w {
+ x, y = 0, y+1
+ }
+ lookupHG = hMask != 0 && x&hMask == 0
+ }
+ }
+ return pix, nil
+}
+
+// lz77Param returns the next LZ77 parameter: a length or a distance, specified
+// in section 4.2.2.
+func (d *decoder) lz77Param(symbol uint32) (uint32, error) {
+ if symbol < 4 {
+ return symbol + 1, nil
+ }
+ extraBits := (symbol - 2) >> 1
+ offset := (2 + symbol&1) << extraBits
+ n, err := d.read(extraBits)
+ if err != nil {
+ return 0, err
+ }
+ return offset + n + 1, nil
+}
+
+// decodeHeader decodes the VP8L header from r.
+func decodeHeader(r io.Reader) (d *decoder, w int32, h int32, err error) {
+ rr, ok := r.(io.ByteReader)
+ if !ok {
+ rr = bufio.NewReader(r)
+ }
+ d = &decoder{r: rr}
+ magic, err := d.read(8)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ if magic != 0x2f {
+ return nil, 0, 0, errors.New("vp8l: invalid header")
+ }
+ width, err := d.read(14)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ width++
+ height, err := d.read(14)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ height++
+ _, err = d.read(1) // Read and ignore the hasAlpha hint.
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ version, err := d.read(3)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ if version != 0 {
+ return nil, 0, 0, errors.New("vp8l: invalid version")
+ }
+ return d, int32(width), int32(height), nil
+}
+
+// DecodeConfig decodes the color model and dimensions of a VP8L image from r.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+ _, w, h, err := decodeHeader(r)
+ if err != nil {
+ return image.Config{}, err
+ }
+ return image.Config{
+ ColorModel: color.NRGBAModel,
+ Width: int(w),
+ Height: int(h),
+ }, nil
+}
+
+// Decode decodes a VP8L image from r.
+func Decode(r io.Reader) (image.Image, error) {
+ d, w, h, err := decodeHeader(r)
+ if err != nil {
+ return nil, err
+ }
+ // Decode the transforms.
+ var (
+ nTransforms int
+ transforms [nTransformTypes]transform
+ transformsSeen [nTransformTypes]bool
+ originalW = w
+ )
+ for {
+ more, err := d.read(1)
+ if err != nil {
+ return nil, err
+ }
+ if more == 0 {
+ break
+ }
+ var t transform
+ t, w, err = d.decodeTransform(w, h)
+ if err != nil {
+ return nil, err
+ }
+ if transformsSeen[t.transformType] {
+ return nil, errors.New("vp8l: repeated transform")
+ }
+ transformsSeen[t.transformType] = true
+ transforms[nTransforms] = t
+ nTransforms++
+ }
+ // Decode the transformed pixels.
+ pix, err := d.decodePix(w, h, 0, true)
+ if err != nil {
+ return nil, err
+ }
+ // Apply the inverse transformations.
+ for i := nTransforms - 1; i >= 0; i-- {
+ t := &transforms[i]
+ pix = inverseTransforms[t.transformType](t, pix, h)
+ }
+ return &image.NRGBA{
+ Pix: pix,
+ Stride: 4 * int(originalW),
+ Rect: image.Rect(0, 0, int(originalW), int(h)),
+ }, nil
+}
diff --git a/vendor/golang.org/x/image/vp8l/huffman.go b/vendor/golang.org/x/image/vp8l/huffman.go
new file mode 100644
index 0000000..36368a8
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8l/huffman.go
@@ -0,0 +1,245 @@
+// 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 vp8l
+
+import (
+ "io"
+)
+
+// reverseBits reverses the bits in a byte.
+var reverseBits = [256]uint8{
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+}
+
+// hNode is a node in a Huffman tree.
+type hNode struct {
+ // symbol is the symbol held by this node.
+ symbol uint32
+ // children, if positive, is the hTree.nodes index of the first of
+ // this node's two children. Zero means an uninitialized node,
+ // and -1 means a leaf node.
+ children int32
+}
+
+const leafNode = -1
+
+// lutSize is the log-2 size of an hTree's look-up table.
+const lutSize, lutMask = 7, 1<<7 - 1
+
+// hTree is a Huffman tree.
+type hTree struct {
+ // nodes are the nodes of the Huffman tree. During construction,
+ // len(nodes) grows from 1 up to cap(nodes) by steps of two.
+ // After construction, len(nodes) == cap(nodes), and both equal
+ // 2*theNumberOfSymbols - 1.
+ nodes []hNode
+ // lut is a look-up table for walking the nodes. The x in lut[x] is
+ // the next lutSize bits in the bit-stream. The low 8 bits of lut[x]
+ // equals 1 plus the number of bits in the next code, or 0 if the
+ // next code requires more than lutSize bits. The high 24 bits are:
+ // - the symbol, if the code requires lutSize or fewer bits, or
+ // - the hTree.nodes index to start the tree traversal from, if
+ // the next code requires more than lutSize bits.
+ lut [1 << lutSize]uint32
+}
+
+// insert inserts into the hTree a symbol whose encoding is the least
+// significant codeLength bits of code.
+func (h *hTree) insert(symbol uint32, code uint32, codeLength uint32) error {
+ if symbol > 0xffff || codeLength > 0xfe {
+ return errInvalidHuffmanTree
+ }
+ baseCode := uint32(0)
+ if codeLength > lutSize {
+ baseCode = uint32(reverseBits[(code>>(codeLength-lutSize))&0xff]) >> (8 - lutSize)
+ } else {
+ baseCode = uint32(reverseBits[code&0xff]) >> (8 - codeLength)
+ for i := 0; i < 1<<(lutSize-codeLength); i++ {
+ h.lut[baseCode|uint32(i)< 0; {
+ codeLength--
+ if int(n) > len(h.nodes) {
+ return errInvalidHuffmanTree
+ }
+ switch h.nodes[n].children {
+ case leafNode:
+ return errInvalidHuffmanTree
+ case 0:
+ if len(h.nodes) == cap(h.nodes) {
+ return errInvalidHuffmanTree
+ }
+ // Create two empty child nodes.
+ h.nodes[n].children = int32(len(h.nodes))
+ h.nodes = h.nodes[:len(h.nodes)+2]
+ }
+ n = uint32(h.nodes[n].children) + 1&(code>>codeLength)
+ jump--
+ if jump == 0 && h.lut[baseCode] == 0 {
+ h.lut[baseCode] = n << 8
+ }
+ }
+
+ switch h.nodes[n].children {
+ case leafNode:
+ // No-op.
+ case 0:
+ // Turn the uninitialized node into a leaf.
+ h.nodes[n].children = leafNode
+ default:
+ return errInvalidHuffmanTree
+ }
+ h.nodes[n].symbol = symbol
+ return nil
+}
+
+// codeLengthsToCodes returns the canonical Huffman codes implied by the
+// sequence of code lengths.
+func codeLengthsToCodes(codeLengths []uint32) ([]uint32, error) {
+ maxCodeLength := uint32(0)
+ for _, cl := range codeLengths {
+ if maxCodeLength < cl {
+ maxCodeLength = cl
+ }
+ }
+ const maxAllowedCodeLength = 15
+ if len(codeLengths) == 0 || maxCodeLength > maxAllowedCodeLength {
+ return nil, errInvalidHuffmanTree
+ }
+ histogram := [maxAllowedCodeLength + 1]uint32{}
+ for _, cl := range codeLengths {
+ histogram[cl]++
+ }
+ currCode, nextCodes := uint32(0), [maxAllowedCodeLength + 1]uint32{}
+ for cl := 1; cl < len(nextCodes); cl++ {
+ currCode = (currCode + histogram[cl-1]) << 1
+ nextCodes[cl] = currCode
+ }
+ codes := make([]uint32, len(codeLengths))
+ for symbol, cl := range codeLengths {
+ if cl > 0 {
+ codes[symbol] = nextCodes[cl]
+ nextCodes[cl]++
+ }
+ }
+ return codes, nil
+}
+
+// build builds a canonical Huffman tree from the given code lengths.
+func (h *hTree) build(codeLengths []uint32) error {
+ // Calculate the number of symbols.
+ var nSymbols, lastSymbol uint32
+ for symbol, cl := range codeLengths {
+ if cl != 0 {
+ nSymbols++
+ lastSymbol = uint32(symbol)
+ }
+ }
+ if nSymbols == 0 {
+ return errInvalidHuffmanTree
+ }
+ h.nodes = make([]hNode, 1, 2*nSymbols-1)
+ // Handle the trivial case.
+ if nSymbols == 1 {
+ if len(codeLengths) <= int(lastSymbol) {
+ return errInvalidHuffmanTree
+ }
+ return h.insert(lastSymbol, 0, 0)
+ }
+ // Handle the non-trivial case.
+ codes, err := codeLengthsToCodes(codeLengths)
+ if err != nil {
+ return err
+ }
+ for symbol, cl := range codeLengths {
+ if cl > 0 {
+ if err := h.insert(uint32(symbol), codes[symbol], cl); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// buildSimple builds a Huffman tree with 1 or 2 symbols.
+func (h *hTree) buildSimple(nSymbols uint32, symbols [2]uint32, alphabetSize uint32) error {
+ h.nodes = make([]hNode, 1, 2*nSymbols-1)
+ for i := uint32(0); i < nSymbols; i++ {
+ if symbols[i] >= alphabetSize {
+ return errInvalidHuffmanTree
+ }
+ if err := h.insert(symbols[i], i, nSymbols-1); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// next returns the next Huffman-encoded symbol from the bit-stream d.
+func (h *hTree) next(d *decoder) (uint32, error) {
+ var n uint32
+ // Read enough bits so that we can use the look-up table.
+ if d.nBits < lutSize {
+ c, err := d.r.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ // There are no more bytes of data, but we may still be able
+ // to read the next symbol out of the previously read bits.
+ goto slowPath
+ }
+ return 0, err
+ }
+ d.bits |= uint32(c) << d.nBits
+ d.nBits += 8
+ }
+ // Use the look-up table.
+ n = h.lut[d.bits&lutMask]
+ if b := n & 0xff; b != 0 {
+ b--
+ d.bits >>= b
+ d.nBits -= b
+ return n >> 8, nil
+ }
+ n >>= 8
+ d.bits >>= lutSize
+ d.nBits -= lutSize
+
+slowPath:
+ for h.nodes[n].children != leafNode {
+ if d.nBits == 0 {
+ c, err := d.r.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return 0, err
+ }
+ d.bits = uint32(c)
+ d.nBits = 8
+ }
+ n = uint32(h.nodes[n].children) + 1&d.bits
+ d.bits >>= 1
+ d.nBits--
+ }
+ return h.nodes[n].symbol, nil
+}
diff --git a/vendor/golang.org/x/image/vp8l/transform.go b/vendor/golang.org/x/image/vp8l/transform.go
new file mode 100644
index 0000000..06543da
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8l/transform.go
@@ -0,0 +1,299 @@
+// 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 vp8l
+
+// This file deals with image transforms, specified in section 3.
+
+// nTiles returns the number of tiles needed to cover size pixels, where each
+// tile's side is 1<> bits
+}
+
+const (
+ transformTypePredictor = 0
+ transformTypeCrossColor = 1
+ transformTypeSubtractGreen = 2
+ transformTypeColorIndexing = 3
+ nTransformTypes = 4
+)
+
+// transform holds the parameters for an invertible transform.
+type transform struct {
+ // transformType is the type of the transform.
+ transformType uint32
+ // oldWidth is the width of the image before transformation (or
+ // equivalently, after inverse transformation). The color-indexing
+ // transform can reduce the width. For example, a 50-pixel-wide
+ // image that only needs 4 bits (half a byte) per color index can
+ // be transformed into a 25-pixel-wide image.
+ oldWidth int32
+ // bits is the log-2 size of the transform's tiles, for the predictor
+ // and cross-color transforms. 8>>bits is the number of bits per
+ // color index, for the color-index transform.
+ bits uint32
+ // pix is the tile values, for the predictor and cross-color
+ // transforms, and the color palette, for the color-index transform.
+ pix []byte
+}
+
+var inverseTransforms = [nTransformTypes]func(*transform, []byte, int32) []byte{
+ transformTypePredictor: inversePredictor,
+ transformTypeCrossColor: inverseCrossColor,
+ transformTypeSubtractGreen: inverseSubtractGreen,
+ transformTypeColorIndexing: inverseColorIndexing,
+}
+
+func inversePredictor(t *transform, pix []byte, h int32) []byte {
+ if t.oldWidth == 0 || h == 0 {
+ return pix
+ }
+ // The first pixel's predictor is mode 0 (opaque black).
+ pix[3] += 0xff
+ p, mask := int32(4), int32(1)<> t.bits) * tilesPerRow
+ predictorMode := t.pix[q+1] & 0x0f
+ q += 4
+ for x := int32(1); x < t.oldWidth; x++ {
+ if x&mask == 0 {
+ predictorMode = t.pix[q+1] & 0x0f
+ q += 4
+ }
+ switch predictorMode {
+ case 0: // Opaque black.
+ pix[p+3] += 0xff
+
+ case 1: // L.
+ pix[p+0] += pix[p-4]
+ pix[p+1] += pix[p-3]
+ pix[p+2] += pix[p-2]
+ pix[p+3] += pix[p-1]
+
+ case 2: // T.
+ pix[p+0] += pix[top+0]
+ pix[p+1] += pix[top+1]
+ pix[p+2] += pix[top+2]
+ pix[p+3] += pix[top+3]
+
+ case 3: // TR.
+ pix[p+0] += pix[top+4]
+ pix[p+1] += pix[top+5]
+ pix[p+2] += pix[top+6]
+ pix[p+3] += pix[top+7]
+
+ case 4: // TL.
+ pix[p+0] += pix[top-4]
+ pix[p+1] += pix[top-3]
+ pix[p+2] += pix[top-2]
+ pix[p+3] += pix[top-1]
+
+ case 5: // Average2(Average2(L, TR), T).
+ pix[p+0] += avg2(avg2(pix[p-4], pix[top+4]), pix[top+0])
+ pix[p+1] += avg2(avg2(pix[p-3], pix[top+5]), pix[top+1])
+ pix[p+2] += avg2(avg2(pix[p-2], pix[top+6]), pix[top+2])
+ pix[p+3] += avg2(avg2(pix[p-1], pix[top+7]), pix[top+3])
+
+ case 6: // Average2(L, TL).
+ pix[p+0] += avg2(pix[p-4], pix[top-4])
+ pix[p+1] += avg2(pix[p-3], pix[top-3])
+ pix[p+2] += avg2(pix[p-2], pix[top-2])
+ pix[p+3] += avg2(pix[p-1], pix[top-1])
+
+ case 7: // Average2(L, T).
+ pix[p+0] += avg2(pix[p-4], pix[top+0])
+ pix[p+1] += avg2(pix[p-3], pix[top+1])
+ pix[p+2] += avg2(pix[p-2], pix[top+2])
+ pix[p+3] += avg2(pix[p-1], pix[top+3])
+
+ case 8: // Average2(TL, T).
+ pix[p+0] += avg2(pix[top-4], pix[top+0])
+ pix[p+1] += avg2(pix[top-3], pix[top+1])
+ pix[p+2] += avg2(pix[top-2], pix[top+2])
+ pix[p+3] += avg2(pix[top-1], pix[top+3])
+
+ case 9: // Average2(T, TR).
+ pix[p+0] += avg2(pix[top+0], pix[top+4])
+ pix[p+1] += avg2(pix[top+1], pix[top+5])
+ pix[p+2] += avg2(pix[top+2], pix[top+6])
+ pix[p+3] += avg2(pix[top+3], pix[top+7])
+
+ case 10: // Average2(Average2(L, TL), Average2(T, TR)).
+ pix[p+0] += avg2(avg2(pix[p-4], pix[top-4]), avg2(pix[top+0], pix[top+4]))
+ pix[p+1] += avg2(avg2(pix[p-3], pix[top-3]), avg2(pix[top+1], pix[top+5]))
+ pix[p+2] += avg2(avg2(pix[p-2], pix[top-2]), avg2(pix[top+2], pix[top+6]))
+ pix[p+3] += avg2(avg2(pix[p-1], pix[top-1]), avg2(pix[top+3], pix[top+7]))
+
+ case 11: // Select(L, T, TL).
+ l0 := int32(pix[p-4])
+ l1 := int32(pix[p-3])
+ l2 := int32(pix[p-2])
+ l3 := int32(pix[p-1])
+ c0 := int32(pix[top-4])
+ c1 := int32(pix[top-3])
+ c2 := int32(pix[top-2])
+ c3 := int32(pix[top-1])
+ t0 := int32(pix[top+0])
+ t1 := int32(pix[top+1])
+ t2 := int32(pix[top+2])
+ t3 := int32(pix[top+3])
+ l := abs(c0-t0) + abs(c1-t1) + abs(c2-t2) + abs(c3-t3)
+ t := abs(c0-l0) + abs(c1-l1) + abs(c2-l2) + abs(c3-l3)
+ if l < t {
+ pix[p+0] += uint8(l0)
+ pix[p+1] += uint8(l1)
+ pix[p+2] += uint8(l2)
+ pix[p+3] += uint8(l3)
+ } else {
+ pix[p+0] += uint8(t0)
+ pix[p+1] += uint8(t1)
+ pix[p+2] += uint8(t2)
+ pix[p+3] += uint8(t3)
+ }
+
+ case 12: // ClampAddSubtractFull(L, T, TL).
+ pix[p+0] += clampAddSubtractFull(pix[p-4], pix[top+0], pix[top-4])
+ pix[p+1] += clampAddSubtractFull(pix[p-3], pix[top+1], pix[top-3])
+ pix[p+2] += clampAddSubtractFull(pix[p-2], pix[top+2], pix[top-2])
+ pix[p+3] += clampAddSubtractFull(pix[p-1], pix[top+3], pix[top-1])
+
+ case 13: // ClampAddSubtractHalf(Average2(L, T), TL).
+ pix[p+0] += clampAddSubtractHalf(avg2(pix[p-4], pix[top+0]), pix[top-4])
+ pix[p+1] += clampAddSubtractHalf(avg2(pix[p-3], pix[top+1]), pix[top-3])
+ pix[p+2] += clampAddSubtractHalf(avg2(pix[p-2], pix[top+2]), pix[top-2])
+ pix[p+3] += clampAddSubtractHalf(avg2(pix[p-1], pix[top+3]), pix[top-1])
+ }
+ p, top = p+4, top+4
+ }
+ }
+ return pix
+}
+
+func inverseCrossColor(t *transform, pix []byte, h int32) []byte {
+ var greenToRed, greenToBlue, redToBlue int32
+ p, mask, tilesPerRow := int32(0), int32(1)<> t.bits) * tilesPerRow
+ for x := int32(0); x < t.oldWidth; x++ {
+ if x&mask == 0 {
+ redToBlue = int32(int8(t.pix[q+0]))
+ greenToBlue = int32(int8(t.pix[q+1]))
+ greenToRed = int32(int8(t.pix[q+2]))
+ q += 4
+ }
+ red := pix[p+0]
+ green := pix[p+1]
+ blue := pix[p+2]
+ red += uint8(uint32(greenToRed*int32(int8(green))) >> 5)
+ blue += uint8(uint32(greenToBlue*int32(int8(green))) >> 5)
+ blue += uint8(uint32(redToBlue*int32(int8(red))) >> 5)
+ pix[p+0] = red
+ pix[p+2] = blue
+ p += 4
+ }
+ }
+ return pix
+}
+
+func inverseSubtractGreen(t *transform, pix []byte, h int32) []byte {
+ for p := 0; p < len(pix); p += 4 {
+ green := pix[p+1]
+ pix[p+0] += green
+ pix[p+2] += green
+ }
+ return pix
+}
+
+func inverseColorIndexing(t *transform, pix []byte, h int32) []byte {
+ if t.bits == 0 {
+ for p := 0; p < len(pix); p += 4 {
+ i := 4 * uint32(pix[p+1])
+ pix[p+0] = t.pix[i+0]
+ pix[p+1] = t.pix[i+1]
+ pix[p+2] = t.pix[i+2]
+ pix[p+3] = t.pix[i+3]
+ }
+ return pix
+ }
+
+ vMask, xMask, bitsPerPixel := uint32(0), int32(0), uint32(8>>t.bits)
+ switch t.bits {
+ case 1:
+ vMask, xMask = 0x0f, 0x01
+ case 2:
+ vMask, xMask = 0x03, 0x03
+ case 3:
+ vMask, xMask = 0x01, 0x07
+ }
+
+ d, p, v, dst := 0, 0, uint32(0), make([]byte, 4*t.oldWidth*h)
+ for y := int32(0); y < h; y++ {
+ for x := int32(0); x < t.oldWidth; x++ {
+ if x&xMask == 0 {
+ v = uint32(pix[p+1])
+ p += 4
+ }
+
+ i := 4 * (v & vMask)
+ dst[d+0] = t.pix[i+0]
+ dst[d+1] = t.pix[i+1]
+ dst[d+2] = t.pix[i+2]
+ dst[d+3] = t.pix[i+3]
+ d += 4
+
+ v >>= bitsPerPixel
+ }
+ }
+ return dst
+}
+
+func abs(x int32) int32 {
+ if x < 0 {
+ return -x
+ }
+ return x
+}
+
+func avg2(a, b uint8) uint8 {
+ return uint8((int32(a) + int32(b)) / 2)
+}
+
+func clampAddSubtractFull(a, b, c uint8) uint8 {
+ x := int32(a) + int32(b) - int32(c)
+ if x < 0 {
+ return 0
+ }
+ if x > 255 {
+ return 255
+ }
+ return uint8(x)
+}
+
+func clampAddSubtractHalf(a, b uint8) uint8 {
+ x := int32(a) + (int32(a)-int32(b))/2
+ if x < 0 {
+ return 0
+ }
+ if x > 255 {
+ return 255
+ }
+ return uint8(x)
+}
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/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).
diff --git a/vendor/golang.org/x/sys/.gitattributes b/vendor/golang.org/x/sys/.gitattributes
new file mode 100644
index 0000000..d2f212e
--- /dev/null
+++ b/vendor/golang.org/x/sys/.gitattributes
@@ -0,0 +1,10 @@
+# Treat all files in this repo as binary, with no git magic updating
+# line endings. Windows users contributing to Go will need to use a
+# modern version of git and editors capable of LF line endings.
+#
+# We'll prevent accidental CRLF line endings from entering the repo
+# via the git-review gofmt checks.
+#
+# See golang.org/issue/9281
+
+* -text
diff --git a/vendor/golang.org/x/sys/.gitignore b/vendor/golang.org/x/sys/.gitignore
new file mode 100644
index 0000000..8339fd6
--- /dev/null
+++ b/vendor/golang.org/x/sys/.gitignore
@@ -0,0 +1,2 @@
+# Add no patterns to .hgignore except for files generated by the build.
+last-change
diff --git a/vendor/golang.org/x/sys/AUTHORS b/vendor/golang.org/x/sys/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/vendor/golang.org/x/sys/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/sys/CONTRIBUTING.md b/vendor/golang.org/x/sys/CONTRIBUTING.md
new file mode 100644
index 0000000..d0485e8
--- /dev/null
+++ b/vendor/golang.org/x/sys/CONTRIBUTING.md
@@ -0,0 +1,26 @@
+# Contributing to Go
+
+Go is an open source project.
+
+It is the work of hundreds of contributors. We appreciate your help!
+
+## Filing issues
+
+When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
+
+1. What version of Go are you using (`go version`)?
+2. What operating system and processor architecture are you using?
+3. What did you do?
+4. What did you expect to see?
+5. What did you see instead?
+
+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
+The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+## Contributing code
+
+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
+before sending patches.
+
+Unless otherwise noted, the Go source files are distributed under
+the BSD-style license found in the LICENSE file.
diff --git a/vendor/golang.org/x/sys/CONTRIBUTORS b/vendor/golang.org/x/sys/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/vendor/golang.org/x/sys/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/sys/LICENSE b/vendor/golang.org/x/sys/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/sys/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/sys/PATENTS b/vendor/golang.org/x/sys/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/sys/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/sys/README.md b/vendor/golang.org/x/sys/README.md
new file mode 100644
index 0000000..ef6c9e5
--- /dev/null
+++ b/vendor/golang.org/x/sys/README.md
@@ -0,0 +1,18 @@
+# sys
+
+This repository holds supplemental Go packages for low-level interactions with
+the operating system.
+
+## Download/Install
+
+The easiest way to install is to run `go get -u golang.org/x/sys`. You can
+also manually git clone the repository to `$GOPATH/src/golang.org/x/sys`.
+
+## Report Issues / Send Patches
+
+This repository uses Gerrit for code changes. To learn how to submit changes to
+this repository, see https://golang.org/doc/contribute.html.
+
+The main issue tracker for the sys repository is located at
+https://github.com/golang/go/issues. Prefix your issue with "x/sys:" in the
+subject line, so it is easy to find.
diff --git a/vendor/golang.org/x/sys/codereview.cfg b/vendor/golang.org/x/sys/codereview.cfg
new file mode 100644
index 0000000..3f8b14b
--- /dev/null
+++ b/vendor/golang.org/x/sys/codereview.cfg
@@ -0,0 +1 @@
+issuerepo: golang/go
diff --git a/vendor/golang.org/x/sys/unix/.gitignore b/vendor/golang.org/x/sys/unix/.gitignore
new file mode 100644
index 0000000..e3e0fc6
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/.gitignore
@@ -0,0 +1,2 @@
+_obj/
+unix.test
diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md
new file mode 100644
index 0000000..bc6f603
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/README.md
@@ -0,0 +1,173 @@
+# Building `sys/unix`
+
+The sys/unix package provides access to the raw system call interface of the
+underlying operating system. See: https://godoc.org/golang.org/x/sys/unix
+
+Porting Go to a new architecture/OS combination or adding syscalls, types, or
+constants to an existing architecture/OS pair requires some manual effort;
+however, there are tools that automate much of the process.
+
+## Build Systems
+
+There are currently two ways we generate the necessary files. We are currently
+migrating the build system to use containers so the builds are reproducible.
+This is being done on an OS-by-OS basis. Please update this documentation as
+components of the build system change.
+
+### Old Build System (currently for `GOOS != "Linux" || GOARCH == "sparc64"`)
+
+The old build system generates the Go files based on the C header files
+present on your system. This means that files
+for a given GOOS/GOARCH pair must be generated on a system with that OS and
+architecture. This also means that the generated code can differ from system
+to system, based on differences in the header files.
+
+To avoid this, if you are using the old build system, only generate the Go
+files on an installation with unmodified header files. It is also important to
+keep track of which version of the OS the files were generated from (ex.
+Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
+and have each OS upgrade correspond to a single change.
+
+To build the files for your current OS and architecture, make sure GOOS and
+GOARCH are set correctly and run `mkall.sh`. This will generate the files for
+your specific system. Running `mkall.sh -n` shows the commands that will be run.
+
+Requirements: bash, perl, go
+
+### New Build System (currently for `GOOS == "Linux" && GOARCH != "sparc64"`)
+
+The new build system uses a Docker container to generate the go files directly
+from source checkouts of the kernel and various system libraries. This means
+that on any platform that supports Docker, all the files using the new build
+system can be generated at once, and generated files will not change based on
+what the person running the scripts has installed on their computer.
+
+The OS specific files for the new build system are located in the `${GOOS}`
+directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
+the kernel or system library updates, modify the Dockerfile at
+`${GOOS}/Dockerfile` to checkout the new release of the source.
+
+To build all the files under the new build system, you must be on an amd64/Linux
+system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
+then generate all of the files for all of the GOOS/GOARCH pairs in the new build
+system. Running `mkall.sh -n` shows the commands that will be run.
+
+Requirements: bash, perl, go, docker
+
+## Component files
+
+This section describes the various files used in the code generation process.
+It also contains instructions on how to modify these files to add a new
+architecture/OS or to add additional syscalls, types, or constants. Note that
+if you are using the new build system, the scripts cannot be called normally.
+They must be called from within the docker container.
+
+### asm files
+
+The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
+call dispatch. There are three entry points:
+```
+ func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+ func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
+ func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+```
+The first and second are the standard ones; they differ only in how many
+arguments can be passed to the kernel. The third is for low-level use by the
+ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
+let it know that a system call is running.
+
+When porting Go to an new architecture/OS, this file must be implemented for
+each GOOS/GOARCH pair.
+
+### mksysnum
+
+Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl`
+for the old system). This script takes in a list of header files containing the
+syscall number declarations and parses them to produce the corresponding list of
+Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
+constants.
+
+Adding new syscall numbers is mostly done by running the build on a sufficiently
+new installation of the target OS (or updating the source checkouts for the
+new build system). However, depending on the OS, you make need to update the
+parsing in mksysnum.
+
+### mksyscall.pl
+
+The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
+hand-written Go files which implement system calls (for unix, the specific OS,
+or the specific OS/Architecture pair respectively) that need special handling
+and list `//sys` comments giving prototypes for ones that can be generated.
+
+The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts
+them into syscalls. This requires the name of the prototype in the comment to
+match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
+prototype can be exported (capitalized) or not.
+
+Adding a new syscall often just requires adding a new `//sys` function prototype
+with the desired arguments and a capitalized name so it is exported. However, if
+you want the interface to the syscall to be different, often one will make an
+unexported `//sys` prototype, an then write a custom wrapper in
+`syscall_${GOOS}.go`.
+
+### types files
+
+For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
+`types_${GOOS}.go` on the old system). This file includes standard C headers and
+creates Go type aliases to the corresponding C types. The file is then fed
+through godef to get the Go compatible definitions. Finally, the generated code
+is fed though mkpost.go to format the code correctly and remove any hidden or
+private identifiers. This cleaned-up code is written to
+`ztypes_${GOOS}_${GOARCH}.go`.
+
+The hardest part about preparing this file is figuring out which headers to
+include and which symbols need to be `#define`d to get the actual data
+structures that pass through to the kernel system calls. Some C libraries
+preset alternate versions for binary compatibility and translate them on the
+way in and out of system calls, but there is almost always a `#define` that can
+get the real ones.
+See `types_darwin.go` and `linux/types.go` for examples.
+
+To add a new type, add in the necessary include statement at the top of the
+file (if it is not already there) and add in a type alias line. Note that if
+your type is significantly different on different architectures, you may need
+some `#if/#elif` macros in your include statements.
+
+### mkerrors.sh
+
+This script is used to generate the system's various constants. This doesn't
+just include the error numbers and error strings, but also the signal numbers
+an a wide variety of miscellaneous constants. The constants come from the list
+of include files in the `includes_${uname}` variable. A regex then picks out
+the desired `#define` statements, and generates the corresponding Go constants.
+The error numbers and strings are generated from `#include `, and the
+signal numbers and strings are generated from `#include `. All of
+these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
+`_errors.c`, which prints out all the constants.
+
+To add a constant, add the header that includes it to the appropriate variable.
+Then, edit the regex (if necessary) to match the desired constant. Avoid making
+the regex too broad to avoid matching unintended constants.
+
+
+## Generated files
+
+### `zerror_${GOOS}_${GOARCH}.go`
+
+A file containing all of the system's generated error numbers, error strings,
+signal numbers, and constants. Generated by `mkerrors.sh` (see above).
+
+### `zsyscall_${GOOS}_${GOARCH}.go`
+
+A file containing all the generated syscalls for a specific GOOS and GOARCH.
+Generated by `mksyscall.pl` (see above).
+
+### `zsysnum_${GOOS}_${GOARCH}.go`
+
+A list of numeric constants for all the syscall number of the specific GOOS
+and GOARCH. Generated by mksysnum (see above).
+
+### `ztypes_${GOOS}_${GOARCH}.go`
+
+A file containing Go types for passing into (or returning from) syscalls.
+Generated by godefs and the types file (see above).
diff --git a/vendor/golang.org/x/sys/unix/affinity_linux.go b/vendor/golang.org/x/sys/unix/affinity_linux.go
new file mode 100644
index 0000000..72afe33
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/affinity_linux.go
@@ -0,0 +1,124 @@
+// Copyright 2018 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.
+
+// CPU affinity functions
+
+package unix
+
+import (
+ "unsafe"
+)
+
+const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
+
+// CPUSet represents a CPU affinity mask.
+type CPUSet [cpuSetSize]cpuMask
+
+func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
+ _, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(*set)), uintptr(unsafe.Pointer(set)))
+ if e != 0 {
+ return errnoErr(e)
+ }
+ return nil
+}
+
+// SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
+// If pid is 0 the calling thread is used.
+func SchedGetaffinity(pid int, set *CPUSet) error {
+ return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set)
+}
+
+// SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
+// If pid is 0 the calling thread is used.
+func SchedSetaffinity(pid int, set *CPUSet) error {
+ return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set)
+}
+
+// Zero clears the set s, so that it contains no CPUs.
+func (s *CPUSet) Zero() {
+ for i := range s {
+ s[i] = 0
+ }
+}
+
+func cpuBitsIndex(cpu int) int {
+ return cpu / _NCPUBITS
+}
+
+func cpuBitsMask(cpu int) cpuMask {
+ return cpuMask(1 << (uint(cpu) % _NCPUBITS))
+}
+
+// Set adds cpu to the set s.
+func (s *CPUSet) Set(cpu int) {
+ i := cpuBitsIndex(cpu)
+ if i < len(s) {
+ s[i] |= cpuBitsMask(cpu)
+ }
+}
+
+// Clear removes cpu from the set s.
+func (s *CPUSet) Clear(cpu int) {
+ i := cpuBitsIndex(cpu)
+ if i < len(s) {
+ s[i] &^= cpuBitsMask(cpu)
+ }
+}
+
+// IsSet reports whether cpu is in the set s.
+func (s *CPUSet) IsSet(cpu int) bool {
+ i := cpuBitsIndex(cpu)
+ if i < len(s) {
+ return s[i]&cpuBitsMask(cpu) != 0
+ }
+ return false
+}
+
+// Count returns the number of CPUs in the set s.
+func (s *CPUSet) Count() int {
+ c := 0
+ for _, b := range s {
+ c += onesCount64(uint64(b))
+ }
+ return c
+}
+
+// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
+// Once this package can require Go 1.9, we can delete this
+// and update the caller to use bits.OnesCount64.
+func onesCount64(x uint64) int {
+ const m0 = 0x5555555555555555 // 01010101 ...
+ const m1 = 0x3333333333333333 // 00110011 ...
+ const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
+ const m3 = 0x00ff00ff00ff00ff // etc.
+ const m4 = 0x0000ffff0000ffff
+
+ // Implementation: Parallel summing of adjacent bits.
+ // See "Hacker's Delight", Chap. 5: Counting Bits.
+ // The following pattern shows the general approach:
+ //
+ // x = x>>1&(m0&m) + x&(m0&m)
+ // x = x>>2&(m1&m) + x&(m1&m)
+ // x = x>>4&(m2&m) + x&(m2&m)
+ // x = x>>8&(m3&m) + x&(m3&m)
+ // x = x>>16&(m4&m) + x&(m4&m)
+ // x = x>>32&(m5&m) + x&(m5&m)
+ // return int(x)
+ //
+ // Masking (& operations) can be left away when there's no
+ // danger that a field's sum will carry over into the next
+ // field: Since the result cannot be > 64, 8 bits is enough
+ // and we can ignore the masks for the shifts by 8 and up.
+ // Per "Hacker's Delight", the first line can be simplified
+ // more, but it saves at best one instruction, so we leave
+ // it alone for clarity.
+ const m = 1<<64 - 1
+ x = x>>1&(m0&m) + x&(m0&m)
+ x = x>>2&(m1&m) + x&(m1&m)
+ x = (x>>4 + x) & (m2 & m)
+ x += x >> 8
+ x += x >> 16
+ x += x >> 32
+ return int(x) & (1<<7 - 1)
+}
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_386.s b/vendor/golang.org/x/sys/unix/asm_darwin_386.s
new file mode 100644
index 0000000..8a72783
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s b/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
new file mode 100644
index 0000000..6321421
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_arm.s b/vendor/golang.org/x/sys/unix/asm_darwin_arm.s
new file mode 100644
index 0000000..333242d
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_arm.s
@@ -0,0 +1,30 @@
+// Copyright 2015 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 !gccgo
+// +build arm,darwin
+
+#include "textflag.h"
+
+//
+// System call support for ARM, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s b/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
new file mode 100644
index 0000000..97e0174
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
@@ -0,0 +1,30 @@
+// Copyright 2015 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 !gccgo
+// +build arm64,darwin
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s b/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
new file mode 100644
index 0000000..603dd57
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, DragonFly
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_386.s b/vendor/golang.org/x/sys/unix/asm_freebsd_386.s
new file mode 100644
index 0000000..c9a0a26
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_freebsd_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, FreeBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
new file mode 100644
index 0000000..3517247
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, FreeBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s b/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
new file mode 100644
index 0000000..9227c87
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2012 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for ARM, FreeBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_386.s b/vendor/golang.org/x/sys/unix/asm_linux_386.s
new file mode 100644
index 0000000..448bebb
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_386.s
@@ -0,0 +1,65 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for 386, Linux
+//
+
+// See ../runtime/sys_linux_386.s for the reason why we always use int 0x80
+// instead of the glibc-specific "CALL 0x10(GS)".
+#define INVOKE_SYSCALL INT $0x80
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
+ CALL runtime·entersyscall(SB)
+ MOVL trap+0(FP), AX // syscall entry
+ MOVL a1+4(FP), BX
+ MOVL a2+8(FP), CX
+ MOVL a3+12(FP), DX
+ MOVL $0, SI
+ MOVL $0, DI
+ INVOKE_SYSCALL
+ MOVL AX, r1+16(FP)
+ MOVL DX, r2+20(FP)
+ CALL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
+ MOVL trap+0(FP), AX // syscall entry
+ MOVL a1+4(FP), BX
+ MOVL a2+8(FP), CX
+ MOVL a3+12(FP), DX
+ MOVL $0, SI
+ MOVL $0, DI
+ INVOKE_SYSCALL
+ MOVL AX, r1+16(FP)
+ MOVL DX, r2+20(FP)
+ RET
+
+TEXT ·socketcall(SB),NOSPLIT,$0-36
+ JMP syscall·socketcall(SB)
+
+TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
+ JMP syscall·rawsocketcall(SB)
+
+TEXT ·seek(SB),NOSPLIT,$0-28
+ JMP syscall·seek(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_amd64.s b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s
new file mode 100644
index 0000000..c6468a9
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s
@@ -0,0 +1,57 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for AMD64, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
+ CALL runtime·entersyscall(SB)
+ MOVQ a1+8(FP), DI
+ MOVQ a2+16(FP), SI
+ MOVQ a3+24(FP), DX
+ MOVQ $0, R10
+ MOVQ $0, R8
+ MOVQ $0, R9
+ MOVQ trap+0(FP), AX // syscall entry
+ SYSCALL
+ MOVQ AX, r1+32(FP)
+ MOVQ DX, r2+40(FP)
+ CALL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
+ MOVQ a1+8(FP), DI
+ MOVQ a2+16(FP), SI
+ MOVQ a3+24(FP), DX
+ MOVQ $0, R10
+ MOVQ $0, R8
+ MOVQ $0, R9
+ MOVQ trap+0(FP), AX // syscall entry
+ SYSCALL
+ MOVQ AX, r1+32(FP)
+ MOVQ DX, r2+40(FP)
+ RET
+
+TEXT ·gettimeofday(SB),NOSPLIT,$0-16
+ JMP syscall·gettimeofday(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm.s b/vendor/golang.org/x/sys/unix/asm_linux_arm.s
new file mode 100644
index 0000000..cf0f357
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_arm.s
@@ -0,0 +1,56 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for arm, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
+ BL runtime·entersyscall(SB)
+ MOVW trap+0(FP), R7
+ MOVW a1+4(FP), R0
+ MOVW a2+8(FP), R1
+ MOVW a3+12(FP), R2
+ MOVW $0, R3
+ MOVW $0, R4
+ MOVW $0, R5
+ SWI $0
+ MOVW R0, r1+16(FP)
+ MOVW $0, R0
+ MOVW R0, r2+20(FP)
+ BL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
+
+TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
+ MOVW trap+0(FP), R7 // syscall entry
+ MOVW a1+4(FP), R0
+ MOVW a2+8(FP), R1
+ MOVW a3+12(FP), R2
+ SWI $0
+ MOVW R0, r1+16(FP)
+ MOVW $0, R0
+ MOVW R0, r2+20(FP)
+ RET
+
+TEXT ·seek(SB),NOSPLIT,$0-28
+ B syscall·seek(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm64.s b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s
new file mode 100644
index 0000000..afe6fdf
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s
@@ -0,0 +1,52 @@
+// Copyright 2015 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 linux
+// +build arm64
+// +build !gccgo
+
+#include "textflag.h"
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ B syscall·Syscall6(SB)
+
+TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
+ BL runtime·entersyscall(SB)
+ MOVD a1+8(FP), R0
+ MOVD a2+16(FP), R1
+ MOVD a3+24(FP), R2
+ MOVD $0, R3
+ MOVD $0, R4
+ MOVD $0, R5
+ MOVD trap+0(FP), R8 // syscall entry
+ SVC
+ MOVD R0, r1+32(FP) // r1
+ MOVD R1, r2+40(FP) // r2
+ BL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ B syscall·RawSyscall6(SB)
+
+TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
+ MOVD a1+8(FP), R0
+ MOVD a2+16(FP), R1
+ MOVD a3+24(FP), R2
+ MOVD $0, R3
+ MOVD $0, R4
+ MOVD $0, R5
+ MOVD trap+0(FP), R8 // syscall entry
+ SVC
+ MOVD R0, r1+32(FP)
+ MOVD R1, r2+40(FP)
+ RET
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
new file mode 100644
index 0000000..ab9d638
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
@@ -0,0 +1,56 @@
+// Copyright 2015 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 linux
+// +build mips64 mips64le
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for mips64, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
+ JAL runtime·entersyscall(SB)
+ MOVV a1+8(FP), R4
+ MOVV a2+16(FP), R5
+ MOVV a3+24(FP), R6
+ MOVV R0, R7
+ MOVV R0, R8
+ MOVV R0, R9
+ MOVV trap+0(FP), R2 // syscall entry
+ SYSCALL
+ MOVV R2, r1+32(FP)
+ MOVV R3, r2+40(FP)
+ JAL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
+ MOVV a1+8(FP), R4
+ MOVV a2+16(FP), R5
+ MOVV a3+24(FP), R6
+ MOVV R0, R7
+ MOVV R0, R8
+ MOVV R0, R9
+ MOVV trap+0(FP), R2 // syscall entry
+ SYSCALL
+ MOVV R2, r1+32(FP)
+ MOVV R3, r2+40(FP)
+ RET
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
new file mode 100644
index 0000000..99e5399
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
@@ -0,0 +1,54 @@
+// 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.
+
+// +build linux
+// +build mips mipsle
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for mips, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
+ JAL runtime·entersyscall(SB)
+ MOVW a1+4(FP), R4
+ MOVW a2+8(FP), R5
+ MOVW a3+12(FP), R6
+ MOVW R0, R7
+ MOVW trap+0(FP), R2 // syscall entry
+ SYSCALL
+ MOVW R2, r1+16(FP) // r1
+ MOVW R3, r2+20(FP) // r2
+ JAL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
+ MOVW a1+4(FP), R4
+ MOVW a2+8(FP), R5
+ MOVW a3+12(FP), R6
+ MOVW trap+0(FP), R2 // syscall entry
+ SYSCALL
+ MOVW R2, r1+16(FP)
+ MOVW R3, r2+20(FP)
+ RET
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
new file mode 100644
index 0000000..649e587
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
@@ -0,0 +1,56 @@
+// 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 linux
+// +build ppc64 ppc64le
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for ppc64, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ BR syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ BR syscall·Syscall6(SB)
+
+TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
+ BL runtime·entersyscall(SB)
+ MOVD a1+8(FP), R3
+ MOVD a2+16(FP), R4
+ MOVD a3+24(FP), R5
+ MOVD R0, R6
+ MOVD R0, R7
+ MOVD R0, R8
+ MOVD trap+0(FP), R9 // syscall entry
+ SYSCALL R9
+ MOVD R3, r1+32(FP)
+ MOVD R4, r2+40(FP)
+ BL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ BR syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ BR syscall·RawSyscall6(SB)
+
+TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
+ MOVD a1+8(FP), R3
+ MOVD a2+16(FP), R4
+ MOVD a3+24(FP), R5
+ MOVD R0, R6
+ MOVD R0, R7
+ MOVD R0, R8
+ MOVD trap+0(FP), R9 // syscall entry
+ SYSCALL R9
+ MOVD R3, r1+32(FP)
+ MOVD R4, r2+40(FP)
+ RET
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_s390x.s b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s
new file mode 100644
index 0000000..a5a863c
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s
@@ -0,0 +1,56 @@
+// 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.
+
+// +build s390x
+// +build linux
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for s390x, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ BR syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ BR syscall·Syscall6(SB)
+
+TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
+ BL runtime·entersyscall(SB)
+ MOVD a1+8(FP), R2
+ MOVD a2+16(FP), R3
+ MOVD a3+24(FP), R4
+ MOVD $0, R5
+ MOVD $0, R6
+ MOVD $0, R7
+ MOVD trap+0(FP), R1 // syscall entry
+ SYSCALL
+ MOVD R2, r1+32(FP)
+ MOVD R3, r2+40(FP)
+ BL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ BR syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ BR syscall·RawSyscall6(SB)
+
+TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
+ MOVD a1+8(FP), R2
+ MOVD a2+16(FP), R3
+ MOVD a3+24(FP), R4
+ MOVD $0, R5
+ MOVD $0, R6
+ MOVD $0, R7
+ MOVD trap+0(FP), R1 // syscall entry
+ SYSCALL
+ MOVD R2, r1+32(FP)
+ MOVD R3, r2+40(FP)
+ RET
diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_386.s b/vendor/golang.org/x/sys/unix/asm_netbsd_386.s
new file mode 100644
index 0000000..48bdcd7
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_netbsd_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, NetBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
new file mode 100644
index 0000000..2ede05c
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, NetBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s b/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
new file mode 100644
index 0000000..e892857
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2013 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for ARM, NetBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_386.s b/vendor/golang.org/x/sys/unix/asm_openbsd_386.s
new file mode 100644
index 0000000..00576f3
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_openbsd_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, OpenBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
new file mode 100644
index 0000000..790ef77
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, OpenBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s b/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
new file mode 100644
index 0000000..469bfa1
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2017 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for ARM, OpenBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
new file mode 100644
index 0000000..ded8260
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
@@ -0,0 +1,17 @@
+// 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
+//
+
+TEXT ·sysvicall6(SB),NOSPLIT,$0-88
+ JMP syscall·sysvicall6(SB)
+
+TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
+ JMP syscall·rawSysvicall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/bluetooth_linux.go b/vendor/golang.org/x/sys/unix/bluetooth_linux.go
new file mode 100644
index 0000000..6e32296
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/bluetooth_linux.go
@@ -0,0 +1,35 @@
+// 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.
+
+// Bluetooth sockets and messages
+
+package unix
+
+// Bluetooth Protocols
+const (
+ BTPROTO_L2CAP = 0
+ BTPROTO_HCI = 1
+ BTPROTO_SCO = 2
+ BTPROTO_RFCOMM = 3
+ BTPROTO_BNEP = 4
+ BTPROTO_CMTP = 5
+ BTPROTO_HIDP = 6
+ BTPROTO_AVDTP = 7
+)
+
+const (
+ HCI_CHANNEL_RAW = 0
+ HCI_CHANNEL_USER = 1
+ HCI_CHANNEL_MONITOR = 2
+ HCI_CHANNEL_CONTROL = 3
+)
+
+// Socketoption Level
+const (
+ SOL_BLUETOOTH = 0x112
+ SOL_HCI = 0x0
+ SOL_L2CAP = 0x6
+ SOL_RFCOMM = 0x12
+ SOL_SCO = 0x11
+)
diff --git a/vendor/golang.org/x/sys/unix/cap_freebsd.go b/vendor/golang.org/x/sys/unix/cap_freebsd.go
new file mode 100644
index 0000000..df52048
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/cap_freebsd.go
@@ -0,0 +1,195 @@
+// Copyright 2017 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 freebsd
+
+package unix
+
+import (
+ "errors"
+ "fmt"
+)
+
+// Go implementation of C mostly found in /usr/src/sys/kern/subr_capability.c
+
+const (
+ // This is the version of CapRights this package understands. See C implementation for parallels.
+ capRightsGoVersion = CAP_RIGHTS_VERSION_00
+ capArSizeMin = CAP_RIGHTS_VERSION_00 + 2
+ capArSizeMax = capRightsGoVersion + 2
+)
+
+var (
+ bit2idx = []int{
+ -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
+ 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ }
+)
+
+func capidxbit(right uint64) int {
+ return int((right >> 57) & 0x1f)
+}
+
+func rightToIndex(right uint64) (int, error) {
+ idx := capidxbit(right)
+ if idx < 0 || idx >= len(bit2idx) {
+ return -2, fmt.Errorf("index for right 0x%x out of range", right)
+ }
+ return bit2idx[idx], nil
+}
+
+func caprver(right uint64) int {
+ return int(right >> 62)
+}
+
+func capver(rights *CapRights) int {
+ return caprver(rights.Rights[0])
+}
+
+func caparsize(rights *CapRights) int {
+ return capver(rights) + 2
+}
+
+// CapRightsSet sets the permissions in setrights in rights.
+func CapRightsSet(rights *CapRights, setrights []uint64) error {
+ // This is essentially a copy of cap_rights_vset()
+ if capver(rights) != CAP_RIGHTS_VERSION_00 {
+ return fmt.Errorf("bad rights version %d", capver(rights))
+ }
+
+ n := caparsize(rights)
+ if n < capArSizeMin || n > capArSizeMax {
+ return errors.New("bad rights size")
+ }
+
+ for _, right := range setrights {
+ if caprver(right) != CAP_RIGHTS_VERSION_00 {
+ return errors.New("bad right version")
+ }
+ i, err := rightToIndex(right)
+ if err != nil {
+ return err
+ }
+ if i >= n {
+ return errors.New("index overflow")
+ }
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return errors.New("index mismatch")
+ }
+ rights.Rights[i] |= right
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return errors.New("index mismatch (after assign)")
+ }
+ }
+
+ return nil
+}
+
+// CapRightsClear clears the permissions in clearrights from rights.
+func CapRightsClear(rights *CapRights, clearrights []uint64) error {
+ // This is essentially a copy of cap_rights_vclear()
+ if capver(rights) != CAP_RIGHTS_VERSION_00 {
+ return fmt.Errorf("bad rights version %d", capver(rights))
+ }
+
+ n := caparsize(rights)
+ if n < capArSizeMin || n > capArSizeMax {
+ return errors.New("bad rights size")
+ }
+
+ for _, right := range clearrights {
+ if caprver(right) != CAP_RIGHTS_VERSION_00 {
+ return errors.New("bad right version")
+ }
+ i, err := rightToIndex(right)
+ if err != nil {
+ return err
+ }
+ if i >= n {
+ return errors.New("index overflow")
+ }
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return errors.New("index mismatch")
+ }
+ rights.Rights[i] &= ^(right & 0x01FFFFFFFFFFFFFF)
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return errors.New("index mismatch (after assign)")
+ }
+ }
+
+ return nil
+}
+
+// CapRightsIsSet checks whether all the permissions in setrights are present in rights.
+func CapRightsIsSet(rights *CapRights, setrights []uint64) (bool, error) {
+ // This is essentially a copy of cap_rights_is_vset()
+ if capver(rights) != CAP_RIGHTS_VERSION_00 {
+ return false, fmt.Errorf("bad rights version %d", capver(rights))
+ }
+
+ n := caparsize(rights)
+ if n < capArSizeMin || n > capArSizeMax {
+ return false, errors.New("bad rights size")
+ }
+
+ for _, right := range setrights {
+ if caprver(right) != CAP_RIGHTS_VERSION_00 {
+ return false, errors.New("bad right version")
+ }
+ i, err := rightToIndex(right)
+ if err != nil {
+ return false, err
+ }
+ if i >= n {
+ return false, errors.New("index overflow")
+ }
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return false, errors.New("index mismatch")
+ }
+ if (rights.Rights[i] & right) != right {
+ return false, nil
+ }
+ }
+
+ return true, nil
+}
+
+func capright(idx uint64, bit uint64) uint64 {
+ return ((1 << (57 + idx)) | bit)
+}
+
+// CapRightsInit returns a pointer to an initialised CapRights structure filled with rights.
+// See man cap_rights_init(3) and rights(4).
+func CapRightsInit(rights []uint64) (*CapRights, error) {
+ var r CapRights
+ r.Rights[0] = (capRightsGoVersion << 62) | capright(0, 0)
+ r.Rights[1] = capright(1, 0)
+
+ err := CapRightsSet(&r, rights)
+ if err != nil {
+ return nil, err
+ }
+ return &r, nil
+}
+
+// CapRightsLimit reduces the operations permitted on fd to at most those contained in rights.
+// The capability rights on fd can never be increased by CapRightsLimit.
+// See man cap_rights_limit(2) and rights(4).
+func CapRightsLimit(fd uintptr, rights *CapRights) error {
+ return capRightsLimit(int(fd), rights)
+}
+
+// CapRightsGet returns a CapRights structure containing the operations permitted on fd.
+// See man cap_rights_get(3) and rights(4).
+func CapRightsGet(fd uintptr) (*CapRights, error) {
+ r, err := CapRightsInit(nil)
+ if err != nil {
+ return nil, err
+ }
+ err = capRightsGet(capRightsGoVersion, int(fd), r)
+ if err != nil {
+ return nil, err
+ }
+ return r, nil
+}
diff --git a/vendor/golang.org/x/sys/unix/constants.go b/vendor/golang.org/x/sys/unix/constants.go
new file mode 100644
index 0000000..a96f0eb
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/constants.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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 darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package unix
+
+const (
+ R_OK = 0x4
+ W_OK = 0x2
+ X_OK = 0x1
+)
diff --git a/vendor/golang.org/x/sys/unix/creds_test.go b/vendor/golang.org/x/sys/unix/creds_test.go
new file mode 100644
index 0000000..1b50831
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/creds_test.go
@@ -0,0 +1,134 @@
+// Copyright 2012 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 linux
+
+package unix_test
+
+import (
+ "bytes"
+ "go/build"
+ "net"
+ "os"
+ "testing"
+
+ "golang.org/x/sys/unix"
+)
+
+// TestSCMCredentials tests the sending and receiving of credentials
+// (PID, UID, GID) in an ancillary message between two UNIX
+// sockets. The SO_PASSCRED socket option is enabled on the sending
+// socket for this to work.
+func TestSCMCredentials(t *testing.T) {
+ socketTypeTests := []struct {
+ socketType int
+ dataLen int
+ }{
+ {
+ unix.SOCK_STREAM,
+ 1,
+ }, {
+ unix.SOCK_DGRAM,
+ 0,
+ },
+ }
+
+ for _, tt := range socketTypeTests {
+ if tt.socketType == unix.SOCK_DGRAM && !atLeast1p10() {
+ t.Log("skipping DGRAM test on pre-1.10")
+ continue
+ }
+
+ fds, err := unix.Socketpair(unix.AF_LOCAL, tt.socketType, 0)
+ if err != nil {
+ t.Fatalf("Socketpair: %v", err)
+ }
+ defer unix.Close(fds[0])
+ defer unix.Close(fds[1])
+
+ err = unix.SetsockoptInt(fds[0], unix.SOL_SOCKET, unix.SO_PASSCRED, 1)
+ if err != nil {
+ t.Fatalf("SetsockoptInt: %v", err)
+ }
+
+ srvFile := os.NewFile(uintptr(fds[0]), "server")
+ defer srvFile.Close()
+ srv, err := net.FileConn(srvFile)
+ if err != nil {
+ t.Errorf("FileConn: %v", err)
+ return
+ }
+ defer srv.Close()
+
+ cliFile := os.NewFile(uintptr(fds[1]), "client")
+ defer cliFile.Close()
+ cli, err := net.FileConn(cliFile)
+ if err != nil {
+ t.Errorf("FileConn: %v", err)
+ return
+ }
+ defer cli.Close()
+
+ var ucred unix.Ucred
+ ucred.Pid = int32(os.Getpid())
+ ucred.Uid = uint32(os.Getuid())
+ ucred.Gid = uint32(os.Getgid())
+ oob := unix.UnixCredentials(&ucred)
+
+ // On SOCK_STREAM, this is internally going to send a dummy byte
+ n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+ if err != nil {
+ t.Fatalf("WriteMsgUnix: %v", err)
+ }
+ if n != 0 {
+ t.Fatalf("WriteMsgUnix n = %d, want 0", n)
+ }
+ if oobn != len(oob) {
+ t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob))
+ }
+
+ oob2 := make([]byte, 10*len(oob))
+ n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2)
+ if err != nil {
+ t.Fatalf("ReadMsgUnix: %v", err)
+ }
+ if flags != 0 {
+ t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
+ }
+ if n != tt.dataLen {
+ t.Fatalf("ReadMsgUnix n = %d, want %d", n, tt.dataLen)
+ }
+ if oobn2 != oobn {
+ // without SO_PASSCRED set on the socket, ReadMsgUnix will
+ // return zero oob bytes
+ t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn)
+ }
+ oob2 = oob2[:oobn2]
+ if !bytes.Equal(oob, oob2) {
+ t.Fatal("ReadMsgUnix oob bytes don't match")
+ }
+
+ scm, err := unix.ParseSocketControlMessage(oob2)
+ if err != nil {
+ t.Fatalf("ParseSocketControlMessage: %v", err)
+ }
+ newUcred, err := unix.ParseUnixCredentials(&scm[0])
+ if err != nil {
+ t.Fatalf("ParseUnixCredentials: %v", err)
+ }
+ if *newUcred != ucred {
+ t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
+ }
+ }
+}
+
+// atLeast1p10 reports whether we are running on Go 1.10 or later.
+func atLeast1p10() bool {
+ for _, ver := range build.Default.ReleaseTags {
+ if ver == "go1.10" {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_darwin.go b/vendor/golang.org/x/sys/unix/dev_darwin.go
new file mode 100644
index 0000000..8d1dc0f
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_darwin.go
@@ -0,0 +1,24 @@
+// Copyright 2017 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.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in Darwin's sys/types.h header.
+
+package unix
+
+// Major returns the major component of a Darwin device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev >> 24) & 0xff)
+}
+
+// Minor returns the minor component of a Darwin device number.
+func Minor(dev uint64) uint32 {
+ return uint32(dev & 0xffffff)
+}
+
+// Mkdev returns a Darwin device number generated from the given major and minor
+// components.
+func Mkdev(major, minor uint32) uint64 {
+ return (uint64(major) << 24) | uint64(minor)
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_dragonfly.go b/vendor/golang.org/x/sys/unix/dev_dragonfly.go
new file mode 100644
index 0000000..8502f20
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_dragonfly.go
@@ -0,0 +1,30 @@
+// Copyright 2017 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.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in Dragonfly's sys/types.h header.
+//
+// The information below is extracted and adapted from sys/types.h:
+//
+// Minor gives a cookie instead of an index since in order to avoid changing the
+// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
+// devices that don't use them.
+
+package unix
+
+// Major returns the major component of a DragonFlyBSD device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev >> 8) & 0xff)
+}
+
+// Minor returns the minor component of a DragonFlyBSD device number.
+func Minor(dev uint64) uint32 {
+ return uint32(dev & 0xffff00ff)
+}
+
+// Mkdev returns a DragonFlyBSD device number generated from the given major and
+// minor components.
+func Mkdev(major, minor uint32) uint64 {
+ return (uint64(major) << 8) | uint64(minor)
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_freebsd.go b/vendor/golang.org/x/sys/unix/dev_freebsd.go
new file mode 100644
index 0000000..eba3b4b
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_freebsd.go
@@ -0,0 +1,30 @@
+// Copyright 2017 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.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in FreeBSD's sys/types.h header.
+//
+// The information below is extracted and adapted from sys/types.h:
+//
+// Minor gives a cookie instead of an index since in order to avoid changing the
+// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
+// devices that don't use them.
+
+package unix
+
+// Major returns the major component of a FreeBSD device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev >> 8) & 0xff)
+}
+
+// Minor returns the minor component of a FreeBSD device number.
+func Minor(dev uint64) uint32 {
+ return uint32(dev & 0xffff00ff)
+}
+
+// Mkdev returns a FreeBSD device number generated from the given major and
+// minor components.
+func Mkdev(major, minor uint32) uint64 {
+ return (uint64(major) << 8) | uint64(minor)
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_linux.go b/vendor/golang.org/x/sys/unix/dev_linux.go
new file mode 100644
index 0000000..d165d6f
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_linux.go
@@ -0,0 +1,42 @@
+// Copyright 2017 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.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used by the Linux kernel and glibc.
+//
+// The information below is extracted and adapted from bits/sysmacros.h in the
+// glibc sources:
+//
+// dev_t in glibc is 64-bit, with 32-bit major and minor numbers. glibc's
+// default encoding is MMMM Mmmm mmmM MMmm, where M is a hex digit of the major
+// number and m is a hex digit of the minor number. This is backward compatible
+// with legacy systems where dev_t is 16 bits wide, encoded as MMmm. It is also
+// backward compatible with the Linux kernel, which for some architectures uses
+// 32-bit dev_t, encoded as mmmM MMmm.
+
+package unix
+
+// Major returns the major component of a Linux device number.
+func Major(dev uint64) uint32 {
+ major := uint32((dev & 0x00000000000fff00) >> 8)
+ major |= uint32((dev & 0xfffff00000000000) >> 32)
+ return major
+}
+
+// Minor returns the minor component of a Linux device number.
+func Minor(dev uint64) uint32 {
+ minor := uint32((dev & 0x00000000000000ff) >> 0)
+ minor |= uint32((dev & 0x00000ffffff00000) >> 12)
+ return minor
+}
+
+// Mkdev returns a Linux device number generated from the given major and minor
+// components.
+func Mkdev(major, minor uint32) uint64 {
+ dev := (uint64(major) & 0x00000fff) << 8
+ dev |= (uint64(major) & 0xfffff000) << 32
+ dev |= (uint64(minor) & 0x000000ff) << 0
+ dev |= (uint64(minor) & 0xffffff00) << 12
+ return dev
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_linux_test.go b/vendor/golang.org/x/sys/unix/dev_linux_test.go
new file mode 100644
index 0000000..5164528
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_linux_test.go
@@ -0,0 +1,56 @@
+// Copyright 2017 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.7
+
+package unix_test
+
+import (
+ "fmt"
+ "testing"
+
+ "golang.org/x/sys/unix"
+)
+
+func TestDevices(t *testing.T) {
+ testCases := []struct {
+ path string
+ major uint32
+ minor uint32
+ }{
+ // well known major/minor numbers according to
+ // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/devices.txt
+ {"/dev/null", 1, 3},
+ {"/dev/zero", 1, 5},
+ {"/dev/random", 1, 8},
+ {"/dev/full", 1, 7},
+ {"/dev/urandom", 1, 9},
+ {"/dev/tty", 5, 0},
+ }
+ for _, tc := range testCases {
+ t.Run(fmt.Sprintf("%s %v:%v", tc.path, tc.major, tc.minor), func(t *testing.T) {
+ var stat unix.Stat_t
+ err := unix.Stat(tc.path, &stat)
+ if err != nil {
+ if err == unix.EACCES {
+ t.Skip("no permission to stat device, skipping test")
+ }
+ t.Errorf("failed to stat device: %v", err)
+ return
+ }
+
+ dev := uint64(stat.Rdev)
+ if unix.Major(dev) != tc.major {
+ t.Errorf("for %s Major(%#x) == %d, want %d", tc.path, dev, unix.Major(dev), tc.major)
+ }
+ if unix.Minor(dev) != tc.minor {
+ t.Errorf("for %s Minor(%#x) == %d, want %d", tc.path, dev, unix.Minor(dev), tc.minor)
+ }
+ if unix.Mkdev(tc.major, tc.minor) != dev {
+ t.Errorf("for %s Mkdev(%d, %d) == %#x, want %#x", tc.path, tc.major, tc.minor, unix.Mkdev(tc.major, tc.minor), dev)
+ }
+ })
+
+ }
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_netbsd.go b/vendor/golang.org/x/sys/unix/dev_netbsd.go
new file mode 100644
index 0000000..b4a203d
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_netbsd.go
@@ -0,0 +1,29 @@
+// Copyright 2017 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.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in NetBSD's sys/types.h header.
+
+package unix
+
+// Major returns the major component of a NetBSD device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev & 0x000fff00) >> 8)
+}
+
+// Minor returns the minor component of a NetBSD device number.
+func Minor(dev uint64) uint32 {
+ minor := uint32((dev & 0x000000ff) >> 0)
+ minor |= uint32((dev & 0xfff00000) >> 12)
+ return minor
+}
+
+// Mkdev returns a NetBSD device number generated from the given major and minor
+// components.
+func Mkdev(major, minor uint32) uint64 {
+ dev := (uint64(major) << 8) & 0x000fff00
+ dev |= (uint64(minor) << 12) & 0xfff00000
+ dev |= (uint64(minor) << 0) & 0x000000ff
+ return dev
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_openbsd.go b/vendor/golang.org/x/sys/unix/dev_openbsd.go
new file mode 100644
index 0000000..f3430c4
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_openbsd.go
@@ -0,0 +1,29 @@
+// Copyright 2017 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.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in OpenBSD's sys/types.h header.
+
+package unix
+
+// Major returns the major component of an OpenBSD device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev & 0x0000ff00) >> 8)
+}
+
+// Minor returns the minor component of an OpenBSD device number.
+func Minor(dev uint64) uint32 {
+ minor := uint32((dev & 0x000000ff) >> 0)
+ minor |= uint32((dev & 0xffff0000) >> 8)
+ return minor
+}
+
+// Mkdev returns an OpenBSD device number generated from the given major and minor
+// components.
+func Mkdev(major, minor uint32) uint64 {
+ dev := (uint64(major) << 8) & 0x0000ff00
+ dev |= (uint64(minor) << 8) & 0xffff0000
+ dev |= (uint64(minor) << 0) & 0x000000ff
+ return dev
+}
diff --git a/vendor/golang.org/x/sys/unix/dirent.go b/vendor/golang.org/x/sys/unix/dirent.go
new file mode 100644
index 0000000..95fd353
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dirent.go
@@ -0,0 +1,17 @@
+// Copyright 2009 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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package unix
+
+import "syscall"
+
+// ParseDirent parses up to max directory entries in buf,
+// appending the names to names. It returns the number of
+// bytes consumed from buf, the number of entries added
+// to names, and the new names slice.
+func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
+ return syscall.ParseDirent(buf, max, names)
+}
diff --git a/vendor/golang.org/x/sys/unix/endian_big.go b/vendor/golang.org/x/sys/unix/endian_big.go
new file mode 100644
index 0000000..5e92690
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/endian_big.go
@@ -0,0 +1,9 @@
+// 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.
+//
+// +build ppc64 s390x mips mips64
+
+package unix
+
+const isBigEndian = true
diff --git a/vendor/golang.org/x/sys/unix/endian_little.go b/vendor/golang.org/x/sys/unix/endian_little.go
new file mode 100644
index 0000000..085df2d
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/endian_little.go
@@ -0,0 +1,9 @@
+// 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.
+//
+// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le
+
+package unix
+
+const isBigEndian = false
diff --git a/vendor/golang.org/x/sys/unix/env_unix.go b/vendor/golang.org/x/sys/unix/env_unix.go
new file mode 100644
index 0000000..706b3cd
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/env_unix.go
@@ -0,0 +1,31 @@
+// Copyright 2010 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 darwin dragonfly freebsd linux netbsd openbsd solaris
+
+// Unix environment variables.
+
+package unix
+
+import "syscall"
+
+func Getenv(key string) (value string, found bool) {
+ return syscall.Getenv(key)
+}
+
+func Setenv(key, value string) error {
+ return syscall.Setenv(key, value)
+}
+
+func Clearenv() {
+ syscall.Clearenv()
+}
+
+func Environ() []string {
+ return syscall.Environ()
+}
+
+func Unsetenv(key string) error {
+ return syscall.Unsetenv(key)
+}
diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_386.go b/vendor/golang.org/x/sys/unix/errors_freebsd_386.go
new file mode 100644
index 0000000..c56bc8b
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/errors_freebsd_386.go
@@ -0,0 +1,227 @@
+// Copyright 2017 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.
+
+// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
+// them here for backwards compatibility.
+
+package unix
+
+const (
+ IFF_SMART = 0x20
+ IFT_1822 = 0x2
+ IFT_A12MPPSWITCH = 0x82
+ IFT_AAL2 = 0xbb
+ IFT_AAL5 = 0x31
+ IFT_ADSL = 0x5e
+ IFT_AFLANE8023 = 0x3b
+ IFT_AFLANE8025 = 0x3c
+ IFT_ARAP = 0x58
+ IFT_ARCNET = 0x23
+ IFT_ARCNETPLUS = 0x24
+ IFT_ASYNC = 0x54
+ IFT_ATM = 0x25
+ IFT_ATMDXI = 0x69
+ IFT_ATMFUNI = 0x6a
+ IFT_ATMIMA = 0x6b
+ IFT_ATMLOGICAL = 0x50
+ IFT_ATMRADIO = 0xbd
+ IFT_ATMSUBINTERFACE = 0x86
+ IFT_ATMVCIENDPT = 0xc2
+ IFT_ATMVIRTUAL = 0x95
+ IFT_BGPPOLICYACCOUNTING = 0xa2
+ IFT_BSC = 0x53
+ IFT_CCTEMUL = 0x3d
+ IFT_CEPT = 0x13
+ IFT_CES = 0x85
+ IFT_CHANNEL = 0x46
+ IFT_CNR = 0x55
+ IFT_COFFEE = 0x84
+ IFT_COMPOSITELINK = 0x9b
+ IFT_DCN = 0x8d
+ IFT_DIGITALPOWERLINE = 0x8a
+ IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+ IFT_DLSW = 0x4a
+ IFT_DOCSCABLEDOWNSTREAM = 0x80
+ IFT_DOCSCABLEMACLAYER = 0x7f
+ IFT_DOCSCABLEUPSTREAM = 0x81
+ IFT_DS0 = 0x51
+ IFT_DS0BUNDLE = 0x52
+ IFT_DS1FDL = 0xaa
+ IFT_DS3 = 0x1e
+ IFT_DTM = 0x8c
+ IFT_DVBASILN = 0xac
+ IFT_DVBASIOUT = 0xad
+ IFT_DVBRCCDOWNSTREAM = 0x93
+ IFT_DVBRCCMACLAYER = 0x92
+ IFT_DVBRCCUPSTREAM = 0x94
+ IFT_ENC = 0xf4
+ IFT_EON = 0x19
+ IFT_EPLRS = 0x57
+ IFT_ESCON = 0x49
+ IFT_ETHER = 0x6
+ IFT_FAITH = 0xf2
+ IFT_FAST = 0x7d
+ IFT_FASTETHER = 0x3e
+ IFT_FASTETHERFX = 0x45
+ IFT_FDDI = 0xf
+ IFT_FIBRECHANNEL = 0x38
+ IFT_FRAMERELAYINTERCONNECT = 0x3a
+ IFT_FRAMERELAYMPI = 0x5c
+ IFT_FRDLCIENDPT = 0xc1
+ IFT_FRELAY = 0x20
+ IFT_FRELAYDCE = 0x2c
+ IFT_FRF16MFRBUNDLE = 0xa3
+ IFT_FRFORWARD = 0x9e
+ IFT_G703AT2MB = 0x43
+ IFT_G703AT64K = 0x42
+ IFT_GIF = 0xf0
+ IFT_GIGABITETHERNET = 0x75
+ IFT_GR303IDT = 0xb2
+ IFT_GR303RDT = 0xb1
+ IFT_H323GATEKEEPER = 0xa4
+ IFT_H323PROXY = 0xa5
+ IFT_HDH1822 = 0x3
+ IFT_HDLC = 0x76
+ IFT_HDSL2 = 0xa8
+ IFT_HIPERLAN2 = 0xb7
+ IFT_HIPPI = 0x2f
+ IFT_HIPPIINTERFACE = 0x39
+ IFT_HOSTPAD = 0x5a
+ IFT_HSSI = 0x2e
+ IFT_HY = 0xe
+ IFT_IBM370PARCHAN = 0x48
+ IFT_IDSL = 0x9a
+ IFT_IEEE80211 = 0x47
+ IFT_IEEE80212 = 0x37
+ IFT_IEEE8023ADLAG = 0xa1
+ IFT_IFGSN = 0x91
+ IFT_IMT = 0xbe
+ IFT_INTERLEAVE = 0x7c
+ IFT_IP = 0x7e
+ IFT_IPFORWARD = 0x8e
+ IFT_IPOVERATM = 0x72
+ IFT_IPOVERCDLC = 0x6d
+ IFT_IPOVERCLAW = 0x6e
+ IFT_IPSWITCH = 0x4e
+ IFT_IPXIP = 0xf9
+ IFT_ISDN = 0x3f
+ IFT_ISDNBASIC = 0x14
+ IFT_ISDNPRIMARY = 0x15
+ IFT_ISDNS = 0x4b
+ IFT_ISDNU = 0x4c
+ IFT_ISO88022LLC = 0x29
+ IFT_ISO88023 = 0x7
+ IFT_ISO88024 = 0x8
+ IFT_ISO88025 = 0x9
+ IFT_ISO88025CRFPINT = 0x62
+ IFT_ISO88025DTR = 0x56
+ IFT_ISO88025FIBER = 0x73
+ IFT_ISO88026 = 0xa
+ IFT_ISUP = 0xb3
+ IFT_L3IPXVLAN = 0x89
+ IFT_LAPB = 0x10
+ IFT_LAPD = 0x4d
+ IFT_LAPF = 0x77
+ IFT_LOCALTALK = 0x2a
+ IFT_LOOP = 0x18
+ IFT_MEDIAMAILOVERIP = 0x8b
+ IFT_MFSIGLINK = 0xa7
+ IFT_MIOX25 = 0x26
+ IFT_MODEM = 0x30
+ IFT_MPC = 0x71
+ IFT_MPLS = 0xa6
+ IFT_MPLSTUNNEL = 0x96
+ IFT_MSDSL = 0x8f
+ IFT_MVL = 0xbf
+ IFT_MYRINET = 0x63
+ IFT_NFAS = 0xaf
+ IFT_NSIP = 0x1b
+ IFT_OPTICALCHANNEL = 0xc3
+ IFT_OPTICALTRANSPORT = 0xc4
+ IFT_OTHER = 0x1
+ IFT_P10 = 0xc
+ IFT_P80 = 0xd
+ IFT_PARA = 0x22
+ IFT_PFLOG = 0xf6
+ IFT_PFSYNC = 0xf7
+ IFT_PLC = 0xae
+ IFT_POS = 0xab
+ IFT_PPPMULTILINKBUNDLE = 0x6c
+ IFT_PROPBWAP2MP = 0xb8
+ IFT_PROPCNLS = 0x59
+ IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
+ IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
+ IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
+ IFT_PROPMUX = 0x36
+ IFT_PROPWIRELESSP2P = 0x9d
+ IFT_PTPSERIAL = 0x16
+ IFT_PVC = 0xf1
+ IFT_QLLC = 0x44
+ IFT_RADIOMAC = 0xbc
+ IFT_RADSL = 0x5f
+ IFT_REACHDSL = 0xc0
+ IFT_RFC1483 = 0x9f
+ IFT_RS232 = 0x21
+ IFT_RSRB = 0x4f
+ IFT_SDLC = 0x11
+ IFT_SDSL = 0x60
+ IFT_SHDSL = 0xa9
+ IFT_SIP = 0x1f
+ IFT_SLIP = 0x1c
+ IFT_SMDSDXI = 0x2b
+ IFT_SMDSICIP = 0x34
+ IFT_SONET = 0x27
+ IFT_SONETOVERHEADCHANNEL = 0xb9
+ IFT_SONETPATH = 0x32
+ IFT_SONETVT = 0x33
+ IFT_SRP = 0x97
+ IFT_SS7SIGLINK = 0x9c
+ IFT_STACKTOSTACK = 0x6f
+ IFT_STARLAN = 0xb
+ IFT_STF = 0xd7
+ IFT_T1 = 0x12
+ IFT_TDLC = 0x74
+ IFT_TERMPAD = 0x5b
+ IFT_TR008 = 0xb0
+ IFT_TRANSPHDLC = 0x7b
+ IFT_TUNNEL = 0x83
+ IFT_ULTRA = 0x1d
+ IFT_USB = 0xa0
+ IFT_V11 = 0x40
+ IFT_V35 = 0x2d
+ IFT_V36 = 0x41
+ IFT_V37 = 0x78
+ IFT_VDSL = 0x61
+ IFT_VIRTUALIPADDRESS = 0x70
+ IFT_VOICEEM = 0x64
+ IFT_VOICEENCAP = 0x67
+ IFT_VOICEFXO = 0x65
+ IFT_VOICEFXS = 0x66
+ IFT_VOICEOVERATM = 0x98
+ IFT_VOICEOVERFRAMERELAY = 0x99
+ IFT_VOICEOVERIP = 0x68
+ IFT_X213 = 0x5d
+ IFT_X25 = 0x5
+ IFT_X25DDN = 0x4
+ IFT_X25HUNTGROUP = 0x7a
+ IFT_X25MLP = 0x79
+ IFT_X25PLE = 0x28
+ IFT_XETHER = 0x1a
+ IPPROTO_MAXID = 0x34
+ IPV6_FAITH = 0x1d
+ IP_FAITH = 0x16
+ MAP_NORESERVE = 0x40
+ MAP_RENAME = 0x20
+ NET_RT_MAXID = 0x6
+ RTF_PRCLONING = 0x10000
+ RTM_OLDADD = 0x9
+ RTM_OLDDEL = 0xa
+ SIOCADDRT = 0x8030720a
+ SIOCALIFADDR = 0x8118691b
+ SIOCDELRT = 0x8030720b
+ SIOCDLIFADDR = 0x8118691d
+ SIOCGLIFADDR = 0xc118691c
+ SIOCGLIFPHYADDR = 0xc118694b
+ SIOCSLIFPHYADDR = 0x8118694a
+)
diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go
new file mode 100644
index 0000000..3e97711
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go
@@ -0,0 +1,227 @@
+// Copyright 2017 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.
+
+// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
+// them here for backwards compatibility.
+
+package unix
+
+const (
+ IFF_SMART = 0x20
+ IFT_1822 = 0x2
+ IFT_A12MPPSWITCH = 0x82
+ IFT_AAL2 = 0xbb
+ IFT_AAL5 = 0x31
+ IFT_ADSL = 0x5e
+ IFT_AFLANE8023 = 0x3b
+ IFT_AFLANE8025 = 0x3c
+ IFT_ARAP = 0x58
+ IFT_ARCNET = 0x23
+ IFT_ARCNETPLUS = 0x24
+ IFT_ASYNC = 0x54
+ IFT_ATM = 0x25
+ IFT_ATMDXI = 0x69
+ IFT_ATMFUNI = 0x6a
+ IFT_ATMIMA = 0x6b
+ IFT_ATMLOGICAL = 0x50
+ IFT_ATMRADIO = 0xbd
+ IFT_ATMSUBINTERFACE = 0x86
+ IFT_ATMVCIENDPT = 0xc2
+ IFT_ATMVIRTUAL = 0x95
+ IFT_BGPPOLICYACCOUNTING = 0xa2
+ IFT_BSC = 0x53
+ IFT_CCTEMUL = 0x3d
+ IFT_CEPT = 0x13
+ IFT_CES = 0x85
+ IFT_CHANNEL = 0x46
+ IFT_CNR = 0x55
+ IFT_COFFEE = 0x84
+ IFT_COMPOSITELINK = 0x9b
+ IFT_DCN = 0x8d
+ IFT_DIGITALPOWERLINE = 0x8a
+ IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+ IFT_DLSW = 0x4a
+ IFT_DOCSCABLEDOWNSTREAM = 0x80
+ IFT_DOCSCABLEMACLAYER = 0x7f
+ IFT_DOCSCABLEUPSTREAM = 0x81
+ IFT_DS0 = 0x51
+ IFT_DS0BUNDLE = 0x52
+ IFT_DS1FDL = 0xaa
+ IFT_DS3 = 0x1e
+ IFT_DTM = 0x8c
+ IFT_DVBASILN = 0xac
+ IFT_DVBASIOUT = 0xad
+ IFT_DVBRCCDOWNSTREAM = 0x93
+ IFT_DVBRCCMACLAYER = 0x92
+ IFT_DVBRCCUPSTREAM = 0x94
+ IFT_ENC = 0xf4
+ IFT_EON = 0x19
+ IFT_EPLRS = 0x57
+ IFT_ESCON = 0x49
+ IFT_ETHER = 0x6
+ IFT_FAITH = 0xf2
+ IFT_FAST = 0x7d
+ IFT_FASTETHER = 0x3e
+ IFT_FASTETHERFX = 0x45
+ IFT_FDDI = 0xf
+ IFT_FIBRECHANNEL = 0x38
+ IFT_FRAMERELAYINTERCONNECT = 0x3a
+ IFT_FRAMERELAYMPI = 0x5c
+ IFT_FRDLCIENDPT = 0xc1
+ IFT_FRELAY = 0x20
+ IFT_FRELAYDCE = 0x2c
+ IFT_FRF16MFRBUNDLE = 0xa3
+ IFT_FRFORWARD = 0x9e
+ IFT_G703AT2MB = 0x43
+ IFT_G703AT64K = 0x42
+ IFT_GIF = 0xf0
+ IFT_GIGABITETHERNET = 0x75
+ IFT_GR303IDT = 0xb2
+ IFT_GR303RDT = 0xb1
+ IFT_H323GATEKEEPER = 0xa4
+ IFT_H323PROXY = 0xa5
+ IFT_HDH1822 = 0x3
+ IFT_HDLC = 0x76
+ IFT_HDSL2 = 0xa8
+ IFT_HIPERLAN2 = 0xb7
+ IFT_HIPPI = 0x2f
+ IFT_HIPPIINTERFACE = 0x39
+ IFT_HOSTPAD = 0x5a
+ IFT_HSSI = 0x2e
+ IFT_HY = 0xe
+ IFT_IBM370PARCHAN = 0x48
+ IFT_IDSL = 0x9a
+ IFT_IEEE80211 = 0x47
+ IFT_IEEE80212 = 0x37
+ IFT_IEEE8023ADLAG = 0xa1
+ IFT_IFGSN = 0x91
+ IFT_IMT = 0xbe
+ IFT_INTERLEAVE = 0x7c
+ IFT_IP = 0x7e
+ IFT_IPFORWARD = 0x8e
+ IFT_IPOVERATM = 0x72
+ IFT_IPOVERCDLC = 0x6d
+ IFT_IPOVERCLAW = 0x6e
+ IFT_IPSWITCH = 0x4e
+ IFT_IPXIP = 0xf9
+ IFT_ISDN = 0x3f
+ IFT_ISDNBASIC = 0x14
+ IFT_ISDNPRIMARY = 0x15
+ IFT_ISDNS = 0x4b
+ IFT_ISDNU = 0x4c
+ IFT_ISO88022LLC = 0x29
+ IFT_ISO88023 = 0x7
+ IFT_ISO88024 = 0x8
+ IFT_ISO88025 = 0x9
+ IFT_ISO88025CRFPINT = 0x62
+ IFT_ISO88025DTR = 0x56
+ IFT_ISO88025FIBER = 0x73
+ IFT_ISO88026 = 0xa
+ IFT_ISUP = 0xb3
+ IFT_L3IPXVLAN = 0x89
+ IFT_LAPB = 0x10
+ IFT_LAPD = 0x4d
+ IFT_LAPF = 0x77
+ IFT_LOCALTALK = 0x2a
+ IFT_LOOP = 0x18
+ IFT_MEDIAMAILOVERIP = 0x8b
+ IFT_MFSIGLINK = 0xa7
+ IFT_MIOX25 = 0x26
+ IFT_MODEM = 0x30
+ IFT_MPC = 0x71
+ IFT_MPLS = 0xa6
+ IFT_MPLSTUNNEL = 0x96
+ IFT_MSDSL = 0x8f
+ IFT_MVL = 0xbf
+ IFT_MYRINET = 0x63
+ IFT_NFAS = 0xaf
+ IFT_NSIP = 0x1b
+ IFT_OPTICALCHANNEL = 0xc3
+ IFT_OPTICALTRANSPORT = 0xc4
+ IFT_OTHER = 0x1
+ IFT_P10 = 0xc
+ IFT_P80 = 0xd
+ IFT_PARA = 0x22
+ IFT_PFLOG = 0xf6
+ IFT_PFSYNC = 0xf7
+ IFT_PLC = 0xae
+ IFT_POS = 0xab
+ IFT_PPPMULTILINKBUNDLE = 0x6c
+ IFT_PROPBWAP2MP = 0xb8
+ IFT_PROPCNLS = 0x59
+ IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
+ IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
+ IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
+ IFT_PROPMUX = 0x36
+ IFT_PROPWIRELESSP2P = 0x9d
+ IFT_PTPSERIAL = 0x16
+ IFT_PVC = 0xf1
+ IFT_QLLC = 0x44
+ IFT_RADIOMAC = 0xbc
+ IFT_RADSL = 0x5f
+ IFT_REACHDSL = 0xc0
+ IFT_RFC1483 = 0x9f
+ IFT_RS232 = 0x21
+ IFT_RSRB = 0x4f
+ IFT_SDLC = 0x11
+ IFT_SDSL = 0x60
+ IFT_SHDSL = 0xa9
+ IFT_SIP = 0x1f
+ IFT_SLIP = 0x1c
+ IFT_SMDSDXI = 0x2b
+ IFT_SMDSICIP = 0x34
+ IFT_SONET = 0x27
+ IFT_SONETOVERHEADCHANNEL = 0xb9
+ IFT_SONETPATH = 0x32
+ IFT_SONETVT = 0x33
+ IFT_SRP = 0x97
+ IFT_SS7SIGLINK = 0x9c
+ IFT_STACKTOSTACK = 0x6f
+ IFT_STARLAN = 0xb
+ IFT_STF = 0xd7
+ IFT_T1 = 0x12
+ IFT_TDLC = 0x74
+ IFT_TERMPAD = 0x5b
+ IFT_TR008 = 0xb0
+ IFT_TRANSPHDLC = 0x7b
+ IFT_TUNNEL = 0x83
+ IFT_ULTRA = 0x1d
+ IFT_USB = 0xa0
+ IFT_V11 = 0x40
+ IFT_V35 = 0x2d
+ IFT_V36 = 0x41
+ IFT_V37 = 0x78
+ IFT_VDSL = 0x61
+ IFT_VIRTUALIPADDRESS = 0x70
+ IFT_VOICEEM = 0x64
+ IFT_VOICEENCAP = 0x67
+ IFT_VOICEFXO = 0x65
+ IFT_VOICEFXS = 0x66
+ IFT_VOICEOVERATM = 0x98
+ IFT_VOICEOVERFRAMERELAY = 0x99
+ IFT_VOICEOVERIP = 0x68
+ IFT_X213 = 0x5d
+ IFT_X25 = 0x5
+ IFT_X25DDN = 0x4
+ IFT_X25HUNTGROUP = 0x7a
+ IFT_X25MLP = 0x79
+ IFT_X25PLE = 0x28
+ IFT_XETHER = 0x1a
+ IPPROTO_MAXID = 0x34
+ IPV6_FAITH = 0x1d
+ IP_FAITH = 0x16
+ MAP_NORESERVE = 0x40
+ MAP_RENAME = 0x20
+ NET_RT_MAXID = 0x6
+ RTF_PRCLONING = 0x10000
+ RTM_OLDADD = 0x9
+ RTM_OLDDEL = 0xa
+ SIOCADDRT = 0x8040720a
+ SIOCALIFADDR = 0x8118691b
+ SIOCDELRT = 0x8040720b
+ SIOCDLIFADDR = 0x8118691d
+ SIOCGLIFADDR = 0xc118691c
+ SIOCGLIFPHYADDR = 0xc118694b
+ SIOCSLIFPHYADDR = 0x8118694a
+)
diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go b/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go
new file mode 100644
index 0000000..856dca3
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go
@@ -0,0 +1,226 @@
+// Copyright 2017 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 unix
+
+const (
+ IFT_1822 = 0x2
+ IFT_A12MPPSWITCH = 0x82
+ IFT_AAL2 = 0xbb
+ IFT_AAL5 = 0x31
+ IFT_ADSL = 0x5e
+ IFT_AFLANE8023 = 0x3b
+ IFT_AFLANE8025 = 0x3c
+ IFT_ARAP = 0x58
+ IFT_ARCNET = 0x23
+ IFT_ARCNETPLUS = 0x24
+ IFT_ASYNC = 0x54
+ IFT_ATM = 0x25
+ IFT_ATMDXI = 0x69
+ IFT_ATMFUNI = 0x6a
+ IFT_ATMIMA = 0x6b
+ IFT_ATMLOGICAL = 0x50
+ IFT_ATMRADIO = 0xbd
+ IFT_ATMSUBINTERFACE = 0x86
+ IFT_ATMVCIENDPT = 0xc2
+ IFT_ATMVIRTUAL = 0x95
+ IFT_BGPPOLICYACCOUNTING = 0xa2
+ IFT_BSC = 0x53
+ IFT_CCTEMUL = 0x3d
+ IFT_CEPT = 0x13
+ IFT_CES = 0x85
+ IFT_CHANNEL = 0x46
+ IFT_CNR = 0x55
+ IFT_COFFEE = 0x84
+ IFT_COMPOSITELINK = 0x9b
+ IFT_DCN = 0x8d
+ IFT_DIGITALPOWERLINE = 0x8a
+ IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+ IFT_DLSW = 0x4a
+ IFT_DOCSCABLEDOWNSTREAM = 0x80
+ IFT_DOCSCABLEMACLAYER = 0x7f
+ IFT_DOCSCABLEUPSTREAM = 0x81
+ IFT_DS0 = 0x51
+ IFT_DS0BUNDLE = 0x52
+ IFT_DS1FDL = 0xaa
+ IFT_DS3 = 0x1e
+ IFT_DTM = 0x8c
+ IFT_DVBASILN = 0xac
+ IFT_DVBASIOUT = 0xad
+ IFT_DVBRCCDOWNSTREAM = 0x93
+ IFT_DVBRCCMACLAYER = 0x92
+ IFT_DVBRCCUPSTREAM = 0x94
+ IFT_ENC = 0xf4
+ IFT_EON = 0x19
+ IFT_EPLRS = 0x57
+ IFT_ESCON = 0x49
+ IFT_ETHER = 0x6
+ IFT_FAST = 0x7d
+ IFT_FASTETHER = 0x3e
+ IFT_FASTETHERFX = 0x45
+ IFT_FDDI = 0xf
+ IFT_FIBRECHANNEL = 0x38
+ IFT_FRAMERELAYINTERCONNECT = 0x3a
+ IFT_FRAMERELAYMPI = 0x5c
+ IFT_FRDLCIENDPT = 0xc1
+ IFT_FRELAY = 0x20
+ IFT_FRELAYDCE = 0x2c
+ IFT_FRF16MFRBUNDLE = 0xa3
+ IFT_FRFORWARD = 0x9e
+ IFT_G703AT2MB = 0x43
+ IFT_G703AT64K = 0x42
+ IFT_GIF = 0xf0
+ IFT_GIGABITETHERNET = 0x75
+ IFT_GR303IDT = 0xb2
+ IFT_GR303RDT = 0xb1
+ IFT_H323GATEKEEPER = 0xa4
+ IFT_H323PROXY = 0xa5
+ IFT_HDH1822 = 0x3
+ IFT_HDLC = 0x76
+ IFT_HDSL2 = 0xa8
+ IFT_HIPERLAN2 = 0xb7
+ IFT_HIPPI = 0x2f
+ IFT_HIPPIINTERFACE = 0x39
+ IFT_HOSTPAD = 0x5a
+ IFT_HSSI = 0x2e
+ IFT_HY = 0xe
+ IFT_IBM370PARCHAN = 0x48
+ IFT_IDSL = 0x9a
+ IFT_IEEE80211 = 0x47
+ IFT_IEEE80212 = 0x37
+ IFT_IEEE8023ADLAG = 0xa1
+ IFT_IFGSN = 0x91
+ IFT_IMT = 0xbe
+ IFT_INTERLEAVE = 0x7c
+ IFT_IP = 0x7e
+ IFT_IPFORWARD = 0x8e
+ IFT_IPOVERATM = 0x72
+ IFT_IPOVERCDLC = 0x6d
+ IFT_IPOVERCLAW = 0x6e
+ IFT_IPSWITCH = 0x4e
+ IFT_ISDN = 0x3f
+ IFT_ISDNBASIC = 0x14
+ IFT_ISDNPRIMARY = 0x15
+ IFT_ISDNS = 0x4b
+ IFT_ISDNU = 0x4c
+ IFT_ISO88022LLC = 0x29
+ IFT_ISO88023 = 0x7
+ IFT_ISO88024 = 0x8
+ IFT_ISO88025 = 0x9
+ IFT_ISO88025CRFPINT = 0x62
+ IFT_ISO88025DTR = 0x56
+ IFT_ISO88025FIBER = 0x73
+ IFT_ISO88026 = 0xa
+ IFT_ISUP = 0xb3
+ IFT_L3IPXVLAN = 0x89
+ IFT_LAPB = 0x10
+ IFT_LAPD = 0x4d
+ IFT_LAPF = 0x77
+ IFT_LOCALTALK = 0x2a
+ IFT_LOOP = 0x18
+ IFT_MEDIAMAILOVERIP = 0x8b
+ IFT_MFSIGLINK = 0xa7
+ IFT_MIOX25 = 0x26
+ IFT_MODEM = 0x30
+ IFT_MPC = 0x71
+ IFT_MPLS = 0xa6
+ IFT_MPLSTUNNEL = 0x96
+ IFT_MSDSL = 0x8f
+ IFT_MVL = 0xbf
+ IFT_MYRINET = 0x63
+ IFT_NFAS = 0xaf
+ IFT_NSIP = 0x1b
+ IFT_OPTICALCHANNEL = 0xc3
+ IFT_OPTICALTRANSPORT = 0xc4
+ IFT_OTHER = 0x1
+ IFT_P10 = 0xc
+ IFT_P80 = 0xd
+ IFT_PARA = 0x22
+ IFT_PFLOG = 0xf6
+ IFT_PFSYNC = 0xf7
+ IFT_PLC = 0xae
+ IFT_POS = 0xab
+ IFT_PPPMULTILINKBUNDLE = 0x6c
+ IFT_PROPBWAP2MP = 0xb8
+ IFT_PROPCNLS = 0x59
+ IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
+ IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
+ IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
+ IFT_PROPMUX = 0x36
+ IFT_PROPWIRELESSP2P = 0x9d
+ IFT_PTPSERIAL = 0x16
+ IFT_PVC = 0xf1
+ IFT_QLLC = 0x44
+ IFT_RADIOMAC = 0xbc
+ IFT_RADSL = 0x5f
+ IFT_REACHDSL = 0xc0
+ IFT_RFC1483 = 0x9f
+ IFT_RS232 = 0x21
+ IFT_RSRB = 0x4f
+ IFT_SDLC = 0x11
+ IFT_SDSL = 0x60
+ IFT_SHDSL = 0xa9
+ IFT_SIP = 0x1f
+ IFT_SLIP = 0x1c
+ IFT_SMDSDXI = 0x2b
+ IFT_SMDSICIP = 0x34
+ IFT_SONET = 0x27
+ IFT_SONETOVERHEADCHANNEL = 0xb9
+ IFT_SONETPATH = 0x32
+ IFT_SONETVT = 0x33
+ IFT_SRP = 0x97
+ IFT_SS7SIGLINK = 0x9c
+ IFT_STACKTOSTACK = 0x6f
+ IFT_STARLAN = 0xb
+ IFT_STF = 0xd7
+ IFT_T1 = 0x12
+ IFT_TDLC = 0x74
+ IFT_TERMPAD = 0x5b
+ IFT_TR008 = 0xb0
+ IFT_TRANSPHDLC = 0x7b
+ IFT_TUNNEL = 0x83
+ IFT_ULTRA = 0x1d
+ IFT_USB = 0xa0
+ IFT_V11 = 0x40
+ IFT_V35 = 0x2d
+ IFT_V36 = 0x41
+ IFT_V37 = 0x78
+ IFT_VDSL = 0x61
+ IFT_VIRTUALIPADDRESS = 0x70
+ IFT_VOICEEM = 0x64
+ IFT_VOICEENCAP = 0x67
+ IFT_VOICEFXO = 0x65
+ IFT_VOICEFXS = 0x66
+ IFT_VOICEOVERATM = 0x98
+ IFT_VOICEOVERFRAMERELAY = 0x99
+ IFT_VOICEOVERIP = 0x68
+ IFT_X213 = 0x5d
+ IFT_X25 = 0x5
+ IFT_X25DDN = 0x4
+ IFT_X25HUNTGROUP = 0x7a
+ IFT_X25MLP = 0x79
+ IFT_X25PLE = 0x28
+ IFT_XETHER = 0x1a
+
+ // missing constants on FreeBSD-11.1-RELEASE, copied from old values in ztypes_freebsd_arm.go
+ IFF_SMART = 0x20
+ IFT_FAITH = 0xf2
+ IFT_IPXIP = 0xf9
+ IPPROTO_MAXID = 0x34
+ IPV6_FAITH = 0x1d
+ IP_FAITH = 0x16
+ MAP_NORESERVE = 0x40
+ MAP_RENAME = 0x20
+ NET_RT_MAXID = 0x6
+ RTF_PRCLONING = 0x10000
+ RTM_OLDADD = 0x9
+ RTM_OLDDEL = 0xa
+ SIOCADDRT = 0x8030720a
+ SIOCALIFADDR = 0x8118691b
+ SIOCDELRT = 0x8030720b
+ SIOCDLIFADDR = 0x8118691d
+ SIOCGLIFADDR = 0xc118691c
+ SIOCGLIFPHYADDR = 0xc118694b
+ SIOCSLIFPHYADDR = 0x8118694a
+)
diff --git a/vendor/golang.org/x/sys/unix/example_test.go b/vendor/golang.org/x/sys/unix/example_test.go
new file mode 100644
index 0000000..10619af
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/example_test.go
@@ -0,0 +1,19 @@
+// Copyright 2018 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 darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package unix_test
+
+import (
+ "log"
+ "os"
+
+ "golang.org/x/sys/unix"
+)
+
+func ExampleExec() {
+ err := unix.Exec("/bin/ls", []string{"ls", "-al"}, os.Environ())
+ log.Fatal(err)
+}
diff --git a/vendor/golang.org/x/sys/unix/export_test.go b/vendor/golang.org/x/sys/unix/export_test.go
new file mode 100644
index 0000000..e802469
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/export_test.go
@@ -0,0 +1,9 @@
+// Copyright 2015 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 darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package unix
+
+var Itoa = itoa
diff --git a/vendor/golang.org/x/sys/unix/fcntl.go b/vendor/golang.org/x/sys/unix/fcntl.go
new file mode 100644
index 0000000..0c58c7e
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/fcntl.go
@@ -0,0 +1,28 @@
+// 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 darwin dragonfly freebsd linux netbsd openbsd
+
+package unix
+
+import "unsafe"
+
+// fcntl64Syscall is usually SYS_FCNTL, but is overridden on 32-bit Linux
+// systems by flock_linux_32bit.go to be SYS_FCNTL64.
+var fcntl64Syscall uintptr = SYS_FCNTL
+
+// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
+func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
+ valptr, _, err := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(arg))
+ return int(valptr), err
+}
+
+// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
+func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
+ _, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
+ if errno == 0 {
+ return nil
+ }
+ return errno
+}
diff --git a/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go b/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
new file mode 100644
index 0000000..fc0e50e
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
@@ -0,0 +1,13 @@
+// +build linux,386 linux,arm linux,mips linux,mipsle
+
+// 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 unix
+
+func init() {
+ // On 32-bit Linux systems, the fcntl syscall that matches Go's
+ // Flock_t type is SYS_FCNTL64, not SYS_FCNTL.
+ fcntl64Syscall = SYS_FCNTL64
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo.go b/vendor/golang.org/x/sys/unix/gccgo.go
new file mode 100644
index 0000000..50062e3
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo.go
@@ -0,0 +1,61 @@
+// Copyright 2015 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 gccgo
+
+package unix
+
+import "syscall"
+
+// We can't use the gc-syntax .s files for gccgo. On the plus side
+// much of the functionality can be written directly in Go.
+
+//extern gccgoRealSyscallNoError
+func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr)
+
+//extern gccgoRealSyscall
+func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
+
+func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
+ syscall.Entersyscall()
+ r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
+ syscall.Exitsyscall()
+ return r, 0
+}
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ syscall.Entersyscall()
+ r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
+ syscall.Exitsyscall()
+ return r, 0, syscall.Errno(errno)
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ syscall.Entersyscall()
+ r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
+ syscall.Exitsyscall()
+ return r, 0, syscall.Errno(errno)
+}
+
+func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ syscall.Entersyscall()
+ r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+ syscall.Exitsyscall()
+ return r, 0, syscall.Errno(errno)
+}
+
+func RawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
+ r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
+ return r, 0
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
+ return r, 0, syscall.Errno(errno)
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
+ return r, 0, syscall.Errno(errno)
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo_c.c b/vendor/golang.org/x/sys/unix/gccgo_c.c
new file mode 100644
index 0000000..24e96b1
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo_c.c
@@ -0,0 +1,47 @@
+// Copyright 2015 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 gccgo
+
+#include
+#include
+#include
+
+#define _STRINGIFY2_(x) #x
+#define _STRINGIFY_(x) _STRINGIFY2_(x)
+#define GOSYM_PREFIX _STRINGIFY_(__USER_LABEL_PREFIX__)
+
+// Call syscall from C code because the gccgo support for calling from
+// Go to C does not support varargs functions.
+
+struct ret {
+ uintptr_t r;
+ uintptr_t err;
+};
+
+struct ret
+gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
+{
+ struct ret r;
+
+ errno = 0;
+ r.r = syscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ r.err = errno;
+ return r;
+}
+
+uintptr_t
+gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
+{
+ return syscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+}
+
+// Define the use function in C so that it is not inlined.
+
+extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline));
+
+void
+use(void *p __attribute__ ((unused)))
+{
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
new file mode 100644
index 0000000..251a977
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
@@ -0,0 +1,20 @@
+// Copyright 2015 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 gccgo,linux,amd64
+
+package unix
+
+import "syscall"
+
+//extern gettimeofday
+func realGettimeofday(*Timeval, *byte) int32
+
+func gettimeofday(tv *Timeval) (err syscall.Errno) {
+ r := realGettimeofday(tv, nil)
+ if r < 0 {
+ return syscall.GetErrno()
+ }
+ return 0
+}
diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh
new file mode 100755
index 0000000..1715122
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mkall.sh
@@ -0,0 +1,188 @@
+#!/usr/bin/env bash
+# Copyright 2009 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.
+
+# This script runs or (given -n) prints suggested commands to generate files for
+# the Architecture/OS specified by the GOARCH and GOOS environment variables.
+# See README.md for more information about how the build system works.
+
+GOOSARCH="${GOOS}_${GOARCH}"
+
+# defaults
+mksyscall="./mksyscall.pl"
+mkerrors="./mkerrors.sh"
+zerrors="zerrors_$GOOSARCH.go"
+mksysctl=""
+zsysctl="zsysctl_$GOOSARCH.go"
+mksysnum=
+mktypes=
+run="sh"
+cmd=""
+
+case "$1" in
+-syscalls)
+ for i in zsyscall*go
+ do
+ # Run the command line that appears in the first line
+ # of the generated file to regenerate it.
+ sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
+ rm _$i
+ done
+ exit 0
+ ;;
+-n)
+ run="cat"
+ cmd="echo"
+ shift
+esac
+
+case "$#" in
+0)
+ ;;
+*)
+ echo 'usage: mkall.sh [-n]' 1>&2
+ exit 2
+esac
+
+if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then
+ # Use then new build system
+ # Files generated through docker (use $cmd so you can Ctl-C the build or run)
+ $cmd docker build --tag generate:$GOOS $GOOS
+ $cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS
+ exit
+fi
+
+GOOSARCH_in=syscall_$GOOSARCH.go
+case "$GOOSARCH" in
+_* | *_ | _)
+ echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
+ exit 1
+ ;;
+darwin_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+darwin_amd64)
+ mkerrors="$mkerrors -m64"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+darwin_arm)
+ mkerrors="$mkerrors"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+darwin_arm64)
+ mkerrors="$mkerrors -m64"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+dragonfly_amd64)
+ mkerrors="$mkerrors -m64"
+ mksyscall="./mksyscall.pl -dragonfly"
+ mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+freebsd_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32"
+ mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+freebsd_amd64)
+ mkerrors="$mkerrors -m64"
+ mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+freebsd_arm)
+ mkerrors="$mkerrors"
+ mksyscall="./mksyscall.pl -l32 -arm"
+ mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+ # Let the type of C char be signed for making the bare syscall
+ # API consistent across platforms.
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
+ ;;
+linux_sparc64)
+ GOOSARCH_in=syscall_linux_sparc64.go
+ unistd_h=/usr/include/sparc64-linux-gnu/asm/unistd.h
+ mkerrors="$mkerrors -m64"
+ mksysnum="./mksysnum_linux.pl $unistd_h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+netbsd_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32 -netbsd"
+ mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+netbsd_amd64)
+ mkerrors="$mkerrors -m64"
+ mksyscall="./mksyscall.pl -netbsd"
+ mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+netbsd_arm)
+ mkerrors="$mkerrors"
+ mksyscall="./mksyscall.pl -l32 -netbsd -arm"
+ mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+ # Let the type of C char be signed for making the bare syscall
+ # API consistent across platforms.
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
+ ;;
+openbsd_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32 -openbsd"
+ mksysctl="./mksysctl_openbsd.pl"
+ mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+openbsd_amd64)
+ mkerrors="$mkerrors -m64"
+ mksyscall="./mksyscall.pl -openbsd"
+ mksysctl="./mksysctl_openbsd.pl"
+ mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+openbsd_arm)
+ mkerrors="$mkerrors"
+ mksyscall="./mksyscall.pl -l32 -openbsd -arm"
+ mksysctl="./mksysctl_openbsd.pl"
+ mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+ # Let the type of C char be signed for making the bare syscall
+ # API consistent across platforms.
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
+ ;;
+solaris_amd64)
+ mksyscall="./mksyscall_solaris.pl"
+ mkerrors="$mkerrors -m64"
+ mksysnum=
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+*)
+ echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
+ exit 1
+ ;;
+esac
+
+(
+ if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
+ case "$GOOS" in
+ *)
+ syscall_goos="syscall_$GOOS.go"
+ case "$GOOS" in
+ darwin | dragonfly | freebsd | netbsd | openbsd)
+ syscall_goos="syscall_bsd.go $syscall_goos"
+ ;;
+ esac
+ if [ -n "$mksyscall" ]; then echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi
+ ;;
+ esac
+ if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
+ if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
+ if [ -n "$mktypes" ]; then
+ echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go";
+ fi
+) | $run
diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh
new file mode 100755
index 0000000..ddc50a0
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -0,0 +1,603 @@
+#!/usr/bin/env bash
+# Copyright 2009 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.
+
+# Generate Go code listing errors and other #defined constant
+# values (ENAMETOOLONG etc.), by asking the preprocessor
+# about the definitions.
+
+unset LANG
+export LC_ALL=C
+export LC_CTYPE=C
+
+if test -z "$GOARCH" -o -z "$GOOS"; then
+ echo 1>&2 "GOARCH or GOOS not defined in environment"
+ exit 1
+fi
+
+# Check that we are using the new build system if we should
+if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then
+ if [[ "$GOLANG_SYS_BUILD" != "docker" ]]; then
+ echo 1>&2 "In the new build system, mkerrors should not be called directly."
+ echo 1>&2 "See README.md"
+ exit 1
+ fi
+fi
+
+CC=${CC:-cc}
+
+if [[ "$GOOS" = "solaris" ]]; then
+ # Assumes GNU versions of utilities in PATH.
+ export PATH=/usr/gnu/bin:$PATH
+fi
+
+uname=$(uname)
+
+includes_Darwin='
+#define _DARWIN_C_SOURCE
+#define KERNEL
+#define _DARWIN_USE_64_BIT_INODE
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+includes_DragonFly='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+includes_FreeBSD='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if __FreeBSD__ >= 10
+#define IFT_CARP 0xf8 // IFT_CARP is deprecated in FreeBSD 10
+#undef SIOCAIFADDR
+#define SIOCAIFADDR _IOW(105, 26, struct oifaliasreq) // ifaliasreq contains if_data
+#undef SIOCSIFPHYADDR
+#define SIOCSIFPHYADDR _IOW(105, 70, struct oifaliasreq) // ifaliasreq contains if_data
+#endif
+'
+
+includes_Linux='
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#ifndef __LP64__
+#define _FILE_OFFSET_BITS 64
+#endif
+#define _GNU_SOURCE
+
+// is broken on powerpc64, as it fails to include definitions of
+// these structures. We just include them copied from .
+#if defined(__powerpc__)
+struct sgttyb {
+ char sg_ispeed;
+ char sg_ospeed;
+ char sg_erase;
+ char sg_kill;
+ short sg_flags;
+};
+
+struct tchars {
+ char t_intrc;
+ char t_quitc;
+ char t_startc;
+ char t_stopc;
+ char t_eofc;
+ char t_brkc;
+};
+
+struct ltchars {
+ char t_suspc;
+ char t_dsuspc;
+ char t_rprntc;
+ char t_flushc;
+ char t_werasc;
+ char t_lnextc;
+};
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef MSG_FASTOPEN
+#define MSG_FASTOPEN 0x20000000
+#endif
+
+#ifndef PTRACE_GETREGS
+#define PTRACE_GETREGS 0xc
+#endif
+
+#ifndef PTRACE_SETREGS
+#define PTRACE_SETREGS 0xd
+#endif
+
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
+#ifdef SOL_BLUETOOTH
+// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
+// but it is already in bluetooth_linux.go
+#undef SOL_BLUETOOTH
+#endif
+
+// Certain constants are missing from the fs/crypto UAPI
+#define FS_KEY_DESC_PREFIX "fscrypt:"
+#define FS_KEY_DESC_PREFIX_SIZE 8
+#define FS_MAX_KEY_SIZE 64
+'
+
+includes_NetBSD='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Needed since refers to it...
+#define schedppq 1
+'
+
+includes_OpenBSD='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// We keep some constants not supported in OpenBSD 5.5 and beyond for
+// the promise of compatibility.
+#define EMUL_ENABLED 0x1
+#define EMUL_NATIVE 0x2
+#define IPV6_FAITH 0x1d
+#define IPV6_OPTIONS 0x1
+#define IPV6_RTHDR_STRICT 0x1
+#define IPV6_SOCKOPT_RESERVED1 0x3
+#define SIOCGIFGENERIC 0xc020693a
+#define SIOCSIFGENERIC 0x80206939
+#define WALTSIG 0x4
+'
+
+includes_SunOS='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+
+includes='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+ccflags="$@"
+
+# Write go tool cgo -godefs input.
+(
+ echo package unix
+ echo
+ echo '/*'
+ indirect="includes_$(uname)"
+ echo "${!indirect} $includes"
+ echo '*/'
+ echo 'import "C"'
+ echo 'import "syscall"'
+ echo
+ echo 'const ('
+
+ # The gcc command line prints all the #defines
+ # it encounters while processing the input
+ echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
+ awk '
+ $1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
+
+ $2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
+ $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
+ $2 ~ /^(SCM_SRCRT)$/ {next}
+ $2 ~ /^(MAP_FAILED)$/ {next}
+ $2 ~ /^ELF_.*$/ {next}# contains ELF_ARCH, etc.
+
+ $2 ~ /^EXTATTR_NAMESPACE_NAMES/ ||
+ $2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next}
+
+ $2 !~ /^ETH_/ &&
+ $2 !~ /^EPROC_/ &&
+ $2 !~ /^EQUIV_/ &&
+ $2 !~ /^EXPR_/ &&
+ $2 ~ /^E[A-Z0-9_]+$/ ||
+ $2 ~ /^B[0-9_]+$/ ||
+ $2 ~ /^(OLD|NEW)DEV$/ ||
+ $2 == "BOTHER" ||
+ $2 ~ /^CI?BAUD(EX)?$/ ||
+ $2 == "IBSHIFT" ||
+ $2 ~ /^V[A-Z0-9]+$/ ||
+ $2 ~ /^CS[A-Z0-9]/ ||
+ $2 ~ /^I(SIG|CANON|CRNL|UCLC|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
+ $2 ~ /^IGN/ ||
+ $2 ~ /^IX(ON|ANY|OFF)$/ ||
+ $2 ~ /^IN(LCR|PCK)$/ ||
+ $2 !~ "X86_CR3_PCID_NOFLUSH" &&
+ $2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
+ $2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ ||
+ $2 == "BRKINT" ||
+ $2 == "HUPCL" ||
+ $2 == "PENDIN" ||
+ $2 == "TOSTOP" ||
+ $2 == "XCASE" ||
+ $2 == "ALTWERASE" ||
+ $2 == "NOKERNINFO" ||
+ $2 ~ /^PAR/ ||
+ $2 ~ /^SIG[^_]/ ||
+ $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
+ $2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
+ $2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
+ $2 ~ /^O?XTABS$/ ||
+ $2 ~ /^TC[IO](ON|OFF)$/ ||
+ $2 ~ /^IN_/ ||
+ $2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
+ $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
+ $2 ~ /^TP_STATUS_/ ||
+ $2 ~ /^FALLOC_/ ||
+ $2 == "ICMPV6_FILTER" ||
+ $2 == "SOMAXCONN" ||
+ $2 == "NAME_MAX" ||
+ $2 == "IFNAMSIZ" ||
+ $2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ ||
+ $2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ ||
+ $2 ~ /^HW_MACHINE$/ ||
+ $2 ~ /^SYSCTL_VERS/ ||
+ $2 ~ /^(MS|MNT|UMOUNT)_/ ||
+ $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
+ $2 ~ /^(O|F|E?FD|NAME|S|PTRACE|PT)_/ ||
+ $2 ~ /^LINUX_REBOOT_CMD_/ ||
+ $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
+ $2 !~ "NLA_TYPE_MASK" &&
+ $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
+ $2 ~ /^SIOC/ ||
+ $2 ~ /^TIOC/ ||
+ $2 ~ /^TCGET/ ||
+ $2 ~ /^TCSET/ ||
+ $2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
+ $2 !~ "RTF_BITS" &&
+ $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
+ $2 ~ /^BIOC/ ||
+ $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
+ $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
+ $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
+ $2 ~ /^CLONE_[A-Z_]+/ ||
+ $2 !~ /^(BPF_TIMEVAL)$/ &&
+ $2 ~ /^(BPF|DLT)_/ ||
+ $2 ~ /^CLOCK_/ ||
+ $2 ~ /^CAN_/ ||
+ $2 ~ /^CAP_/ ||
+ $2 ~ /^ALG_/ ||
+ $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ ||
+ $2 ~ /^GRND_/ ||
+ $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
+ $2 ~ /^KEYCTL_/ ||
+ $2 ~ /^PERF_EVENT_IOC_/ ||
+ $2 ~ /^SECCOMP_MODE_/ ||
+ $2 ~ /^SPLICE_/ ||
+ $2 !~ /^AUDIT_RECORD_MAGIC/ &&
+ $2 ~ /^[A-Z0-9_]+_MAGIC2?$/ ||
+ $2 ~ /^(VM|VMADDR)_/ ||
+ $2 ~ /^IOCTL_VM_SOCKETS_/ ||
+ $2 ~ /^(TASKSTATS|TS)_/ ||
+ $2 ~ /^CGROUPSTATS_/ ||
+ $2 ~ /^GENL_/ ||
+ $2 ~ /^STATX_/ ||
+ $2 ~ /^UTIME_/ ||
+ $2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ ||
+ $2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
+ $2 ~ /^FSOPT_/ ||
+ $2 ~ /^WDIOC_/ ||
+ $2 ~ /^NFN/ ||
+ $2 ~ /^(HDIO|WIN|SMART)_/ ||
+ $2 !~ "WMESGLEN" &&
+ $2 ~ /^W[A-Z0-9]+$/ ||
+ $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
+ $2 ~ /^__WCOREFLAG$/ {next}
+ $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
+
+ {next}
+ ' | sort
+
+ echo ')'
+) >_const.go
+
+# Pull out the error names for later.
+errors=$(
+ echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
+ sort
+)
+
+# Pull out the signal names for later.
+signals=$(
+ echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
+ egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
+ sort
+)
+
+# Again, writing regexps to a file.
+echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
+ sort >_error.grep
+echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
+ egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
+ sort >_signal.grep
+
+echo '// mkerrors.sh' "$@"
+echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
+echo
+echo "// +build ${GOARCH},${GOOS}"
+echo
+go tool cgo -godefs -- "$@" _const.go >_error.out
+cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
+echo
+echo '// Errors'
+echo 'const ('
+cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= syscall.Errno(\1)/'
+echo ')'
+
+echo
+echo '// Signals'
+echo 'const ('
+cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= syscall.Signal(\1)/'
+echo ')'
+
+# Run C program to print error and syscall strings.
+(
+ echo -E "
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
+
+enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
+
+struct tuple {
+ int num;
+ const char *name;
+};
+
+struct tuple errors[] = {
+"
+ for i in $errors
+ do
+ echo -E ' {'$i', "'$i'" },'
+ done
+
+ echo -E "
+};
+
+struct tuple signals[] = {
+"
+ for i in $signals
+ do
+ echo -E ' {'$i', "'$i'" },'
+ done
+
+ # Use -E because on some systems bash builtin interprets \n itself.
+ echo -E '
+};
+
+static int
+tuplecmp(const void *a, const void *b)
+{
+ return ((struct tuple *)a)->num - ((struct tuple *)b)->num;
+}
+
+int
+main(void)
+{
+ int i, e;
+ char buf[1024], *p;
+
+ printf("\n\n// Error table\n");
+ printf("var errorList = [...]struct {\n");
+ printf("\tnum syscall.Errno\n");
+ printf("\tname string\n");
+ printf("\tdesc string\n");
+ printf("} {\n");
+ qsort(errors, nelem(errors), sizeof errors[0], tuplecmp);
+ for(i=0; i 0 && errors[i-1].num == e)
+ continue;
+ strcpy(buf, strerror(e));
+ // lowercase first letter: Bad -> bad, but STREAM -> STREAM.
+ if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
+ buf[0] += a - A;
+ printf("\t{ %d, \"%s\", \"%s\" },\n", e, errors[i].name, buf);
+ }
+ printf("}\n\n");
+
+ printf("\n\n// Signal table\n");
+ printf("var signalList = [...]struct {\n");
+ printf("\tnum syscall.Signal\n");
+ printf("\tname string\n");
+ printf("\tdesc string\n");
+ printf("} {\n");
+ qsort(signals, nelem(signals), sizeof signals[0], tuplecmp);
+ for(i=0; i 0 && signals[i-1].num == e)
+ continue;
+ strcpy(buf, strsignal(e));
+ // lowercase first letter: Bad -> bad, but STREAM -> STREAM.
+ if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
+ buf[0] += a - A;
+ // cut trailing : number.
+ p = strrchr(buf, ":"[0]);
+ if(p)
+ *p = '\0';
+ printf("\t{ %d, \"%s\", \"%s\" },\n", e, signals[i].name, buf);
+ }
+ printf("}\n\n");
+
+ return 0;
+}
+
+'
+) >_errors.c
+
+$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out
diff --git a/vendor/golang.org/x/sys/unix/mkpost.go b/vendor/golang.org/x/sys/unix/mkpost.go
new file mode 100644
index 0000000..7e5c22c
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mkpost.go
@@ -0,0 +1,98 @@
+// 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.
+
+// +build ignore
+
+// mkpost processes the output of cgo -godefs to
+// modify the generated types. It is used to clean up
+// the sys API in an architecture specific manner.
+//
+// mkpost is run after cgo -godefs; see README.md.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "log"
+ "os"
+ "regexp"
+)
+
+func main() {
+ // Get the OS and architecture (using GOARCH_TARGET if it exists)
+ goos := os.Getenv("GOOS")
+ goarch := os.Getenv("GOARCH_TARGET")
+ if goarch == "" {
+ goarch = os.Getenv("GOARCH")
+ }
+ // Check that we are using the new build system if we should be.
+ if goos == "linux" && goarch != "sparc64" {
+ if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
+ os.Stderr.WriteString("In the new build system, mkpost should not be called directly.\n")
+ os.Stderr.WriteString("See README.md\n")
+ os.Exit(1)
+ }
+ }
+
+ b, err := ioutil.ReadAll(os.Stdin)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Intentionally export __val fields in Fsid and Sigset_t
+ valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__val(\s+\S+\s+)}`)
+ b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$3}"))
+
+ // If we have empty Ptrace structs, we should delete them. Only s390x emits
+ // nonempty Ptrace structs.
+ ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`)
+ b = ptraceRexexp.ReplaceAll(b, nil)
+
+ // Replace the control_regs union with a blank identifier for now.
+ controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`)
+ b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64"))
+
+ // Remove fields that are added by glibc
+ // Note that this is unstable as the identifers are private.
+ removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`)
+ b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
+
+ // Convert [65]int8 to [65]byte in Utsname members to simplify
+ // conversion to string; see golang.org/issue/20753
+ convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
+ b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
+
+ // Remove spare fields (e.g. in Statx_t)
+ spareFieldsRegex := regexp.MustCompile(`X__spare\S*`)
+ b = spareFieldsRegex.ReplaceAll(b, []byte("_"))
+
+ // Remove cgo padding fields
+ removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`)
+ b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_"))
+
+ // Remove padding, hidden, or unused fields
+ removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`)
+ b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
+
+ // Remove the first line of warning from cgo
+ b = b[bytes.IndexByte(b, '\n')+1:]
+ // Modify the command in the header to include:
+ // mkpost, our own warning, and a build tag.
+ replacement := fmt.Sprintf(`$1 | go run mkpost.go
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build %s,%s`, goarch, goos)
+ cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
+ b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
+
+ // gofmt
+ b, err = format.Source(b)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ os.Stdout.Write(b)
+}
diff --git a/vendor/golang.org/x/sys/unix/mksyscall.pl b/vendor/golang.org/x/sys/unix/mksyscall.pl
new file mode 100755
index 0000000..1f6b926
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mksyscall.pl
@@ -0,0 +1,341 @@
+#!/usr/bin/env perl
+# Copyright 2009 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.
+
+# This program reads a file containing function prototypes
+# (like syscall_darwin.go) and generates system call bodies.
+# The prototypes are marked by lines beginning with "//sys"
+# and read like func declarations if //sys is replaced by func, but:
+# * The parameter lists must give a name for each argument.
+# This includes return parameters.
+# * The parameter lists must give a type for each argument:
+# the (x, y, z int) shorthand is not allowed.
+# * If the return parameter is an error number, it must be named errno.
+
+# A line beginning with //sysnb is like //sys, except that the
+# goroutine will not be suspended during the execution of the system
+# call. This must only be used for system calls which can never
+# block, as otherwise the system call could cause all goroutines to
+# hang.
+
+use strict;
+
+my $cmdline = "mksyscall.pl " . join(' ', @ARGV);
+my $errors = 0;
+my $_32bit = "";
+my $plan9 = 0;
+my $openbsd = 0;
+my $netbsd = 0;
+my $dragonfly = 0;
+my $arm = 0; # 64-bit value should use (even, odd)-pair
+my $tags = ""; # build tags
+
+if($ARGV[0] eq "-b32") {
+ $_32bit = "big-endian";
+ shift;
+} elsif($ARGV[0] eq "-l32") {
+ $_32bit = "little-endian";
+ shift;
+}
+if($ARGV[0] eq "-plan9") {
+ $plan9 = 1;
+ shift;
+}
+if($ARGV[0] eq "-openbsd") {
+ $openbsd = 1;
+ shift;
+}
+if($ARGV[0] eq "-netbsd") {
+ $netbsd = 1;
+ shift;
+}
+if($ARGV[0] eq "-dragonfly") {
+ $dragonfly = 1;
+ shift;
+}
+if($ARGV[0] eq "-arm") {
+ $arm = 1;
+ shift;
+}
+if($ARGV[0] eq "-tags") {
+ shift;
+ $tags = $ARGV[0];
+ shift;
+}
+
+if($ARGV[0] =~ /^-/) {
+ print STDERR "usage: mksyscall.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
+ exit 1;
+}
+
+# Check that we are using the new build system if we should
+if($ENV{'GOOS'} eq "linux" && $ENV{'GOARCH'} ne "sparc64") {
+ if($ENV{'GOLANG_SYS_BUILD'} ne "docker") {
+ print STDERR "In the new build system, mksyscall should not be called directly.\n";
+ print STDERR "See README.md\n";
+ exit 1;
+ }
+}
+
+
+sub parseparamlist($) {
+ my ($list) = @_;
+ $list =~ s/^\s*//;
+ $list =~ s/\s*$//;
+ if($list eq "") {
+ return ();
+ }
+ return split(/\s*,\s*/, $list);
+}
+
+sub parseparam($) {
+ my ($p) = @_;
+ if($p !~ /^(\S*) (\S*)$/) {
+ print STDERR "$ARGV:$.: malformed parameter: $p\n";
+ $errors = 1;
+ return ("xx", "int");
+ }
+ return ($1, $2);
+}
+
+my $text = "";
+while(<>) {
+ chomp;
+ s/\s+/ /g;
+ s/^\s+//;
+ s/\s+$//;
+ my $nonblock = /^\/\/sysnb /;
+ next if !/^\/\/sys / && !$nonblock;
+
+ # Line must be of the form
+ # func Open(path string, mode int, perm int) (fd int, errno error)
+ # Split into name, in params, out params.
+ if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$/) {
+ print STDERR "$ARGV:$.: malformed //sys declaration\n";
+ $errors = 1;
+ next;
+ }
+ my ($func, $in, $out, $sysname) = ($2, $3, $4, $5);
+
+ # Split argument lists on comma.
+ my @in = parseparamlist($in);
+ my @out = parseparamlist($out);
+
+ # Try in vain to keep people from editing this file.
+ # The theory is that they jump into the middle of the file
+ # without reading the header.
+ $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
+
+ # Go function header.
+ my $out_decl = @out ? sprintf(" (%s)", join(', ', @out)) : "";
+ $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out_decl;
+
+ # Check if err return available
+ my $errvar = "";
+ foreach my $p (@out) {
+ my ($name, $type) = parseparam($p);
+ if($type eq "error") {
+ $errvar = $name;
+ last;
+ }
+ }
+
+ # Prepare arguments to Syscall.
+ my @args = ();
+ my $n = 0;
+ foreach my $p (@in) {
+ my ($name, $type) = parseparam($p);
+ if($type =~ /^\*/) {
+ push @args, "uintptr(unsafe.Pointer($name))";
+ } elsif($type eq "string" && $errvar ne "") {
+ $text .= "\tvar _p$n *byte\n";
+ $text .= "\t_p$n, $errvar = BytePtrFromString($name)\n";
+ $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type eq "string") {
+ print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
+ $text .= "\tvar _p$n *byte\n";
+ $text .= "\t_p$n, _ = BytePtrFromString($name)\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type =~ /^\[\](.*)/) {
+ # Convert slice into pointer, length.
+ # Have to be careful not to take address of &a[0] if len == 0:
+ # pass dummy pointer in that case.
+ # Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
+ $text .= "\tvar _p$n unsafe.Pointer\n";
+ $text .= "\tif len($name) > 0 {\n\t\t_p$n = unsafe.Pointer(\&${name}[0])\n\t}";
+ $text .= " else {\n\t\t_p$n = unsafe.Pointer(&_zero)\n\t}";
+ $text .= "\n";
+ push @args, "uintptr(_p$n)", "uintptr(len($name))";
+ $n++;
+ } elsif($type eq "int64" && ($openbsd || $netbsd)) {
+ push @args, "0";
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name>>32)", "uintptr($name)";
+ } elsif($_32bit eq "little-endian") {
+ push @args, "uintptr($name)", "uintptr($name>>32)";
+ } else {
+ push @args, "uintptr($name)";
+ }
+ } elsif($type eq "int64" && $dragonfly) {
+ if ($func !~ /^extp(read|write)/i) {
+ push @args, "0";
+ }
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name>>32)", "uintptr($name)";
+ } elsif($_32bit eq "little-endian") {
+ push @args, "uintptr($name)", "uintptr($name>>32)";
+ } else {
+ push @args, "uintptr($name)";
+ }
+ } elsif($type eq "int64" && $_32bit ne "") {
+ if(@args % 2 && $arm) {
+ # arm abi specifies 64-bit argument uses
+ # (even, odd) pair
+ push @args, "0"
+ }
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name>>32)", "uintptr($name)";
+ } else {
+ push @args, "uintptr($name)", "uintptr($name>>32)";
+ }
+ } else {
+ push @args, "uintptr($name)";
+ }
+ }
+
+ # Determine which form to use; pad args with zeros.
+ my $asm = "Syscall";
+ if ($nonblock) {
+ if ($errvar eq "" && $ENV{'GOOS'} eq "linux") {
+ $asm = "RawSyscallNoError";
+ } else {
+ $asm = "RawSyscall";
+ }
+ } else {
+ if ($errvar eq "" && $ENV{'GOOS'} eq "linux") {
+ $asm = "SyscallNoError";
+ }
+ }
+ if(@args <= 3) {
+ while(@args < 3) {
+ push @args, "0";
+ }
+ } elsif(@args <= 6) {
+ $asm .= "6";
+ while(@args < 6) {
+ push @args, "0";
+ }
+ } elsif(@args <= 9) {
+ $asm .= "9";
+ while(@args < 9) {
+ push @args, "0";
+ }
+ } else {
+ print STDERR "$ARGV:$.: too many arguments to system call\n";
+ }
+
+ # System call number.
+ if($sysname eq "") {
+ $sysname = "SYS_$func";
+ $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar
+ $sysname =~ y/a-z/A-Z/;
+ }
+
+ # Actual call.
+ my $args = join(', ', @args);
+ my $call = "$asm($sysname, $args)";
+
+ # Assign return values.
+ my $body = "";
+ my @ret = ("_", "_", "_");
+ my $do_errno = 0;
+ for(my $i=0; $i<@out; $i++) {
+ my $p = $out[$i];
+ my ($name, $type) = parseparam($p);
+ my $reg = "";
+ if($name eq "err" && !$plan9) {
+ $reg = "e1";
+ $ret[2] = $reg;
+ $do_errno = 1;
+ } elsif($name eq "err" && $plan9) {
+ $ret[0] = "r0";
+ $ret[2] = "e1";
+ next;
+ } else {
+ $reg = sprintf("r%d", $i);
+ $ret[$i] = $reg;
+ }
+ if($type eq "bool") {
+ $reg = "$reg != 0";
+ }
+ if($type eq "int64" && $_32bit ne "") {
+ # 64-bit number in r1:r0 or r0:r1.
+ if($i+2 > @out) {
+ print STDERR "$ARGV:$.: not enough registers for int64 return\n";
+ }
+ if($_32bit eq "big-endian") {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
+ } else {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
+ }
+ $ret[$i] = sprintf("r%d", $i);
+ $ret[$i+1] = sprintf("r%d", $i+1);
+ }
+ if($reg ne "e1" || $plan9) {
+ $body .= "\t$name = $type($reg)\n";
+ }
+ }
+ if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
+ $text .= "\t$call\n";
+ } else {
+ if ($errvar eq "" && $ENV{'GOOS'} eq "linux") {
+ # raw syscall without error on Linux, see golang.org/issue/22924
+ $text .= "\t$ret[0], $ret[1] := $call\n";
+ } else {
+ $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
+ }
+ }
+ $text .= $body;
+
+ if ($plan9 && $ret[2] eq "e1") {
+ $text .= "\tif int32(r0) == -1 {\n";
+ $text .= "\t\terr = e1\n";
+ $text .= "\t}\n";
+ } elsif ($do_errno) {
+ $text .= "\tif e1 != 0 {\n";
+ $text .= "\t\terr = errnoErr(e1)\n";
+ $text .= "\t}\n";
+ }
+ $text .= "\treturn\n";
+ $text .= "}\n\n";
+}
+
+chomp $text;
+chomp $text;
+
+if($errors) {
+ exit 1;
+}
+
+print <) {
+ chomp;
+ s/\s+/ /g;
+ s/^\s+//;
+ s/\s+$//;
+ $package = $1 if !$package && /^package (\S+)$/;
+ my $nonblock = /^\/\/sysnb /;
+ next if !/^\/\/sys / && !$nonblock;
+
+ # Line must be of the form
+ # func Open(path string, mode int, perm int) (fd int, err error)
+ # Split into name, in params, out params.
+ if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
+ print STDERR "$ARGV:$.: malformed //sys declaration\n";
+ $errors = 1;
+ next;
+ }
+ my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
+
+ # Split argument lists on comma.
+ my @in = parseparamlist($in);
+ my @out = parseparamlist($out);
+
+ # So file name.
+ if($modname eq "") {
+ $modname = "libc";
+ }
+
+ # System call name.
+ if($sysname eq "") {
+ $sysname = "$func";
+ }
+
+ # System call pointer variable name.
+ my $sysvarname = "proc$sysname";
+
+ my $strconvfunc = "BytePtrFromString";
+ my $strconvtype = "*byte";
+
+ $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
+
+ # Runtime import of function to allow cross-platform builds.
+ $dynimports .= "//go:cgo_import_dynamic libc_${sysname} ${sysname} \"$modname.so\"\n";
+ # Link symbol to proc address variable.
+ $linknames .= "//go:linkname ${sysvarname} libc_${sysname}\n";
+ # Library proc address variable.
+ push @vars, $sysvarname;
+
+ # Go function header.
+ $out = join(', ', @out);
+ if($out ne "") {
+ $out = " ($out)";
+ }
+ if($text ne "") {
+ $text .= "\n"
+ }
+ $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out;
+
+ # Check if err return available
+ my $errvar = "";
+ foreach my $p (@out) {
+ my ($name, $type) = parseparam($p);
+ if($type eq "error") {
+ $errvar = $name;
+ last;
+ }
+ }
+
+ # Prepare arguments to Syscall.
+ my @args = ();
+ my $n = 0;
+ foreach my $p (@in) {
+ my ($name, $type) = parseparam($p);
+ if($type =~ /^\*/) {
+ push @args, "uintptr(unsafe.Pointer($name))";
+ } elsif($type eq "string" && $errvar ne "") {
+ $text .= "\tvar _p$n $strconvtype\n";
+ $text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
+ $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type eq "string") {
+ print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
+ $text .= "\tvar _p$n $strconvtype\n";
+ $text .= "\t_p$n, _ = $strconvfunc($name)\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type =~ /^\[\](.*)/) {
+ # Convert slice into pointer, length.
+ # Have to be careful not to take address of &a[0] if len == 0:
+ # pass nil in that case.
+ $text .= "\tvar _p$n *$1\n";
+ $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))";
+ $n++;
+ } elsif($type eq "int64" && $_32bit ne "") {
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name >> 32)", "uintptr($name)";
+ } else {
+ push @args, "uintptr($name)", "uintptr($name >> 32)";
+ }
+ } elsif($type eq "bool") {
+ $text .= "\tvar _p$n uint32\n";
+ $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
+ push @args, "uintptr(_p$n)";
+ $n++;
+ } else {
+ push @args, "uintptr($name)";
+ }
+ }
+ my $nargs = @args;
+
+ # Determine which form to use; pad args with zeros.
+ my $asm = "sysvicall6";
+ if ($nonblock) {
+ $asm = "rawSysvicall6";
+ }
+ if(@args <= 6) {
+ while(@args < 6) {
+ push @args, "0";
+ }
+ } else {
+ print STDERR "$ARGV:$.: too many arguments to system call\n";
+ }
+
+ # Actual call.
+ my $args = join(', ', @args);
+ my $call = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $args)";
+
+ # Assign return values.
+ my $body = "";
+ my $failexpr = "";
+ my @ret = ("_", "_", "_");
+ my @pout= ();
+ my $do_errno = 0;
+ for(my $i=0; $i<@out; $i++) {
+ my $p = $out[$i];
+ my ($name, $type) = parseparam($p);
+ my $reg = "";
+ if($name eq "err") {
+ $reg = "e1";
+ $ret[2] = $reg;
+ $do_errno = 1;
+ } else {
+ $reg = sprintf("r%d", $i);
+ $ret[$i] = $reg;
+ }
+ if($type eq "bool") {
+ $reg = "$reg != 0";
+ }
+ if($type eq "int64" && $_32bit ne "") {
+ # 64-bit number in r1:r0 or r0:r1.
+ if($i+2 > @out) {
+ print STDERR "$ARGV:$.: not enough registers for int64 return\n";
+ }
+ if($_32bit eq "big-endian") {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
+ } else {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
+ }
+ $ret[$i] = sprintf("r%d", $i);
+ $ret[$i+1] = sprintf("r%d", $i+1);
+ }
+ if($reg ne "e1") {
+ $body .= "\t$name = $type($reg)\n";
+ }
+ }
+ if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
+ $text .= "\t$call\n";
+ } else {
+ $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
+ }
+ $text .= $body;
+
+ if ($do_errno) {
+ $text .= "\tif e1 != 0 {\n";
+ $text .= "\t\terr = e1\n";
+ $text .= "\t}\n";
+ }
+ $text .= "\treturn\n";
+ $text .= "}\n";
+}
+
+if($errors) {
+ exit 1;
+}
+
+print < "net.inet",
+ "net.inet.ipproto" => "net.inet",
+ "net.inet6.ipv6proto" => "net.inet6",
+ "net.inet6.ipv6" => "net.inet6.ip6",
+ "net.inet.icmpv6" => "net.inet6.icmp6",
+ "net.inet6.divert6" => "net.inet6.divert",
+ "net.inet6.tcp6" => "net.inet.tcp",
+ "net.inet6.udp6" => "net.inet.udp",
+ "mpls" => "net.mpls",
+ "swpenc" => "vm.swapencrypt"
+);
+
+# Node mappings
+my %node_map = (
+ "net.inet.ip.ifq" => "net.ifq",
+ "net.inet.pfsync" => "net.pfsync",
+ "net.mpls.ifq" => "net.ifq"
+);
+
+my $ctlname;
+my %mib = ();
+my %sysctl = ();
+my $node;
+
+sub debug() {
+ print STDERR "$_[0]\n" if $debug;
+}
+
+# Walk the MIB and build a sysctl name to OID mapping.
+sub build_sysctl() {
+ my ($node, $name, $oid) = @_;
+ my %node = %{$node};
+ my @oid = @{$oid};
+
+ foreach my $key (sort keys %node) {
+ my @node = @{$node{$key}};
+ my $nodename = $name.($name ne '' ? '.' : '').$key;
+ my @nodeoid = (@oid, $node[0]);
+ if ($node[1] eq 'CTLTYPE_NODE') {
+ if (exists $node_map{$nodename}) {
+ $node = \%mib;
+ $ctlname = $node_map{$nodename};
+ foreach my $part (split /\./, $ctlname) {
+ $node = \%{@{$$node{$part}}[2]};
+ }
+ } else {
+ $node = $node[2];
+ }
+ &build_sysctl($node, $nodename, \@nodeoid);
+ } elsif ($node[1] ne '') {
+ $sysctl{$nodename} = \@nodeoid;
+ }
+ }
+}
+
+foreach my $ctl (@ctls) {
+ $ctls{$ctl} = $ctl;
+}
+
+# Build MIB
+foreach my $header (@headers) {
+ &debug("Processing $header...");
+ open HEADER, "/usr/include/$header" ||
+ print STDERR "Failed to open $header\n";
+ while () {
+ if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ ||
+ $_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ ||
+ $_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) {
+ if ($1 eq 'CTL_NAMES') {
+ # Top level.
+ $node = \%mib;
+ } else {
+ # Node.
+ my $nodename = lc($2);
+ if ($header =~ /^netinet\//) {
+ $ctlname = "net.inet.$nodename";
+ } elsif ($header =~ /^netinet6\//) {
+ $ctlname = "net.inet6.$nodename";
+ } elsif ($header =~ /^net\//) {
+ $ctlname = "net.$nodename";
+ } else {
+ $ctlname = "$nodename";
+ $ctlname =~ s/^(fs|net|kern)_/$1\./;
+ }
+ if (exists $ctl_map{$ctlname}) {
+ $ctlname = $ctl_map{$ctlname};
+ }
+ if (not exists $ctls{$ctlname}) {
+ &debug("Ignoring $ctlname...");
+ next;
+ }
+
+ # Walk down from the top of the MIB.
+ $node = \%mib;
+ foreach my $part (split /\./, $ctlname) {
+ if (not exists $$node{$part}) {
+ &debug("Missing node $part");
+ $$node{$part} = [ 0, '', {} ];
+ }
+ $node = \%{@{$$node{$part}}[2]};
+ }
+ }
+
+ # Populate current node with entries.
+ my $i = -1;
+ while (defined($_) && $_ !~ /^}/) {
+ $_ = ;
+ $i++ if $_ =~ /{.*}/;
+ next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/;
+ $$node{$1} = [ $i, $2, {} ];
+ }
+ }
+ }
+ close HEADER;
+}
+
+&build_sysctl(\%mib, "", []);
+
+print <){
+ if(/^#define\s+SYS_(\w+)\s+([0-9]+)/){
+ my $name = $1;
+ my $num = $2;
+ $name =~ y/a-z/A-Z/;
+ print " SYS_$name = $num;"
+ }
+}
+
+print <){
+ if(/^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$/){
+ my $num = $1;
+ my $proto = $2;
+ my $name = "SYS_$3";
+ $name =~ y/a-z/A-Z/;
+
+ # There are multiple entries for enosys and nosys, so comment them out.
+ if($name =~ /^SYS_E?NOSYS$/){
+ $name = "// $name";
+ }
+ if($name eq 'SYS_SYS_EXIT'){
+ $name = 'SYS_EXIT';
+ }
+
+ print " $name = $num; // $proto\n";
+ }
+}
+
+print <){
+ if(/^([0-9]+)\s+\S+\s+STD\s+({ \S+\s+(\w+).*)$/){
+ my $num = $1;
+ my $proto = $2;
+ my $name = "SYS_$3";
+ $name =~ y/a-z/A-Z/;
+
+ # There are multiple entries for enosys and nosys, so comment them out.
+ if($name =~ /^SYS_E?NOSYS$/){
+ $name = "// $name";
+ }
+ if($name eq 'SYS_SYS_EXIT'){
+ $name = 'SYS_EXIT';
+ }
+
+ print " $name = $num; // $proto\n";
+ }
+}
+
+print <){
+ if($line =~ /^(.*)\\$/) {
+ # Handle continuation
+ $line = $1;
+ $_ =~ s/^\s+//;
+ $line .= $_;
+ } else {
+ # New line
+ $line = $_;
+ }
+ next if $line =~ /\\$/;
+ if($line =~ /^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$/) {
+ my $num = $1;
+ my $proto = $6;
+ my $compat = $8;
+ my $name = "$7_$9";
+
+ $name = "$7_$11" if $11 ne '';
+ $name =~ y/a-z/A-Z/;
+
+ if($compat eq '' || $compat eq '13' || $compat eq '30' || $compat eq '50') {
+ print " $name = $num; // $proto\n";
+ }
+ }
+}
+
+print <){
+ if(/^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$/){
+ my $num = $1;
+ my $proto = $3;
+ my $name = $4;
+ $name =~ y/a-z/A-Z/;
+
+ # There are multiple entries for enosys and nosys, so comment them out.
+ if($name =~ /^SYS_E?NOSYS$/){
+ $name = "// $name";
+ }
+ if($name eq 'SYS_SYS_EXIT'){
+ $name = 'SYS_EXIT';
+ }
+
+ print " $name = $num; // $proto\n";
+ }
+}
+
+print <