diff --git a/go.mod b/go.mod
index a2f96f56b..c4e0b226a 100644
--- a/go.mod
+++ b/go.mod
@@ -40,7 +40,7 @@ require (
 	github.com/spf13/viper v1.14.0
 	github.com/stretchr/testify v1.8.1
 	github.com/superseriousbusiness/activity v1.2.1-gts
-	github.com/superseriousbusiness/exif-terminator v0.4.0
+	github.com/superseriousbusiness/exif-terminator v0.5.0
 	github.com/superseriousbusiness/oauth2/v4 v4.3.2-SSB
 	github.com/tdewolff/minify/v2 v2.12.4
 	github.com/ulule/limiter/v3 v3.10.0
@@ -50,6 +50,7 @@ require (
 	github.com/wagslane/go-password-validator v0.3.0
 	golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
 	golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d
+	golang.org/x/image v0.1.0
 	golang.org/x/net v0.0.0-20221014081412-f15817d10f9b
 	golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783
 	golang.org/x/text v0.4.0
@@ -134,7 +135,6 @@ require (
 	github.com/ugorji/go/codec v1.2.7 // indirect
 	github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
 	github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
-	golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 // indirect
 	golang.org/x/mod v0.6.0-dev.0.20220907135952-02c991387e35 // indirect
 	golang.org/x/sys v0.2.0 // indirect
 	golang.org/x/tools v0.1.12 // indirect
diff --git a/go.sum b/go.sum
index 9167234f3..1e41c106a 100644
--- a/go.sum
+++ b/go.sum
@@ -571,8 +571,8 @@ github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs
 github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/superseriousbusiness/activity v1.2.1-gts h1:wh7v0zYa1mJmqB35PSfvgl4cs51Dh5PyfKvcZLSxMQU=
 github.com/superseriousbusiness/activity v1.2.1-gts/go.mod h1:AZw0Xb4Oju8rmaJCZ21gc5CPg47MmNgyac+Hx5jo8VM=
-github.com/superseriousbusiness/exif-terminator v0.4.0 h1:pzAg7luCi8oc2LVDwgTLvTinh/+/2UuWgJZrM8MMaT4=
-github.com/superseriousbusiness/exif-terminator v0.4.0/go.mod h1:OPfOSEDWjXaW3BILJBN89j0VLD8bglmHwHHwwwSLb5A=
+github.com/superseriousbusiness/exif-terminator v0.5.0 h1:57SO/geyaOl2v/lJSQLVcQbdghpyFuK8ZTtaHL81fUQ=
+github.com/superseriousbusiness/exif-terminator v0.5.0/go.mod h1:d5IkskXco/3XRXzOrI73uGYn+wahJEqPlQSSqn6jxSw=
 github.com/superseriousbusiness/go-jpeg-image-structure/v2 v2.0.0-20220321154430-d89a106fdabe h1:ksl2oCx/Qo8sNDc3Grb8WGKBM9nkvhCm25uvlT86azE=
 github.com/superseriousbusiness/go-jpeg-image-structure/v2 v2.0.0-20220321154430-d89a106fdabe/go.mod h1:gH4P6gN1V+wmIw5o97KGaa1RgXB/tVpC2UNzijhg3E4=
 github.com/superseriousbusiness/oauth2/v4 v4.3.2-SSB h1:PtW2w6budTvRV2J5QAoSvThTHBuvh8t/+BXIZFAaBSc=
@@ -644,6 +644,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
 github.com/zeebo/blake3 v0.2.1/go.mod h1:TSQ0KjMH+pht+bRyvVooJ1rBpvvngSGaPISafq9MxJk=
 github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
@@ -678,6 +679,7 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
@@ -698,8 +700,8 @@ golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d/go.mod h1:Kr81I6Kryrl9sr8s2F
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
-golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
+golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
+golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -723,6 +725,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.6.0-dev.0.20220907135952-02c991387e35 h1:CZP0Rbk/s1EIiUMx5DS2MhK2ct52xpQxqddVD0FmF+o=
 golang.org/x/mod v0.6.0-dev.0.20220907135952-02c991387e35/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -774,6 +777,7 @@ golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su
 golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
 golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
 golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
@@ -812,6 +816,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -888,6 +893,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/internal/api/client/instance/instancepatch_test.go b/internal/api/client/instance/instancepatch_test.go
index 5ce2daaa3..edf724d4a 100644
--- a/internal/api/client/instance/instancepatch_test.go
+++ b/internal/api/client/instance/instancepatch_test.go
@@ -65,7 +65,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() {
 	b, err := io.ReadAll(result.Body)
 	suite.NoError(err)
 
-	suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"Example Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"someone@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, string(b))
+	suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"Example Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"someone@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png","image/webp"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, string(b))
 }
 
 func (suite *InstancePatchTestSuite) TestInstancePatch2() {
@@ -95,7 +95,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() {
 	b, err := io.ReadAll(result.Body)
 	suite.NoError(err)
 
-	suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"Geoff's Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, string(b))
+	suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"Geoff's Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png","image/webp"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, string(b))
 }
 
 func (suite *InstancePatchTestSuite) TestInstancePatch3() {
@@ -125,7 +125,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() {
 	b, err := io.ReadAll(result.Body)
 	suite.NoError(err)
 
-	suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is some html, which is \u003cem\u003eallowed\u003c/em\u003e in short descriptions.\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, string(b))
+	suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is some html, which is \u003cem\u003eallowed\u003c/em\u003e in short descriptions.\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png","image/webp"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, string(b))
 }
 
 func (suite *InstancePatchTestSuite) TestInstancePatch4() {
@@ -216,7 +216,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() {
 	b, err := io.ReadAll(result.Body)
 	suite.NoError(err)
 
-	suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, string(b))
+	suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png","image/webp"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, string(b))
 }
 
 func (suite *InstancePatchTestSuite) TestInstancePatch7() {
@@ -279,7 +279,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
 	}
 	suite.NotEmpty(instanceAccount.AvatarMediaAttachmentID)
 
-	expectedInstanceResponse := fmt.Sprintf(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/fileserver/%s/attachment/original/%s.gif","thumbnail_type":"image/gif","thumbnail_description":"A bouncing little green peglin.","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, instanceAccount.ID, instanceAccount.AvatarMediaAttachmentID)
+	expectedInstanceResponse := fmt.Sprintf(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":25},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png","image/webp"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746},"accounts":{"allow_custom_css":true},"emojis":{"emoji_size_limit":51200}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/fileserver/%s/attachment/original/%s.gif","thumbnail_type":"image/gif","thumbnail_description":"A bouncing little green peglin.","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[],"enable_rss":true,"role":"admin"},"max_toot_chars":5000}`, instanceAccount.ID, instanceAccount.AvatarMediaAttachmentID)
 	suite.Equal(expectedInstanceResponse, string(b))
 }
 
diff --git a/internal/media/image.go b/internal/media/image.go
index e1fc5c331..b095a6c49 100644
--- a/internal/media/image.go
+++ b/internal/media/image.go
@@ -30,6 +30,7 @@ import (
 
 	"github.com/buckket/go-blurhash"
 	"github.com/disintegration/imaging"
+	_ "golang.org/x/image/webp" // blank import to support WebP decoding
 )
 
 const (
@@ -71,7 +72,7 @@ func decodeImage(r io.Reader, contentType string) (*imageMeta, error) {
 	var err error
 
 	switch contentType {
-	case mimeImageJpeg:
+	case mimeImageJpeg, mimeImageWebp:
 		i, err = imaging.Decode(r, imaging.AutoOrientation(true))
 	case mimeImagePng:
 		strippedPngReader := io.Reader(&PNGAncillaryChunkStripper{
@@ -104,7 +105,7 @@ func decodeImage(r io.Reader, contentType string) (*imageMeta, error) {
 }
 
 // deriveThumbnail returns a byte slice and metadata for a thumbnail
-// of a given jpeg, png, or gif, or an error if something goes wrong.
+// of a given jpeg, png, gif or webp, or an error if something goes wrong.
 //
 // If createBlurhash is true, then a blurhash will also be generated from a tiny
 // version of the image. This costs precious CPU cycles, so only use it if you
@@ -117,7 +118,7 @@ func deriveThumbnail(r io.Reader, contentType string, createBlurhash bool) (*ima
 	var err error
 
 	switch contentType {
-	case mimeImageJpeg, mimeImageGif:
+	case mimeImageJpeg, mimeImageGif, mimeImageWebp:
 		i, err = imaging.Decode(r, imaging.AutoOrientation(true))
 	case mimeImagePng:
 		strippedPngReader := io.Reader(&PNGAncillaryChunkStripper{
diff --git a/internal/media/processingmedia.go b/internal/media/processingmedia.go
index 81eef2f84..1fd9423f5 100644
--- a/internal/media/processingmedia.go
+++ b/internal/media/processingmedia.go
@@ -215,7 +215,7 @@ func (p *ProcessingMedia) loadFullSize(ctx context.Context) error {
 		// decode the image
 		ct := p.attachment.File.ContentType
 		switch ct {
-		case mimeImageJpeg, mimeImagePng:
+		case mimeImageJpeg, mimeImagePng, mimeImageWebp:
 			decoded, err = decodeImage(stored, ct)
 		case mimeImageGif:
 			decoded, err = decodeGif(stored)
@@ -319,7 +319,7 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
 		p.attachment.Type = gtsmodel.FileTypeImage
 		// nothing to terminate, we can just store the multireader
 		readerToStore = multiReader
-	case mimeJpeg, mimePng:
+	case mimeJpeg, mimePng, mimeWebp:
 		p.attachment.Type = gtsmodel.FileTypeImage
 		if fileSize > 0 {
 			terminated, err := terminator.Terminate(multiReader, int(fileSize), extension)
diff --git a/internal/media/types.go b/internal/media/types.go
index 763a8137f..b855d72b5 100644
--- a/internal/media/types.go
+++ b/internal/media/types.go
@@ -43,6 +43,9 @@ const (
 
 	mimePng      = "png"
 	mimeImagePng = mimeImage + "/" + mimePng
+
+	mimeWebp      = "webp"
+	mimeImageWebp = mimeImage + "/" + mimeWebp
 )
 
 type processState int32
diff --git a/internal/media/util.go b/internal/media/util.go
index 316d63dec..7efd788a1 100644
--- a/internal/media/util.go
+++ b/internal/media/util.go
@@ -37,6 +37,7 @@ func AllSupportedMIMETypes() []string {
 		mimeImageJpeg,
 		mimeImageGif,
 		mimeImagePng,
+		mimeImageWebp,
 	}
 }
 
@@ -68,6 +69,7 @@ func supportedImage(mimeType string) bool {
 		mimeImageJpeg,
 		mimeImageGif,
 		mimeImagePng,
+		mimeImageWebp,
 	}
 	for _, accepted := range acceptedImageTypes {
 		if mimeType == accepted {
diff --git a/vendor/github.com/superseriousbusiness/exif-terminator/jpeg.go b/vendor/github.com/superseriousbusiness/exif-terminator/jpeg.go
index aa6940a71..576c4e430 100644
--- a/vendor/github.com/superseriousbusiness/exif-terminator/jpeg.go
+++ b/vendor/github.com/superseriousbusiness/exif-terminator/jpeg.go
@@ -91,7 +91,7 @@ func (v *jpegVisitor) HandleSegment(segmentMarker byte, _ string, _ int, _ bool)
 	if segmentMarker == jpegstructure.MARKER_EOI {
 		// take account of the last 2 bytes taken up by the EOI
 		eoiLength := 2
-		
+
 		// this is the total file size we will
 		// have written including the EOI
 		willHaveWritten := v.writtenTotalBytes + eoiLength
diff --git a/vendor/github.com/superseriousbusiness/exif-terminator/terminator.go b/vendor/github.com/superseriousbusiness/exif-terminator/terminator.go
index 575bb1e42..9d9e6e743 100644
--- a/vendor/github.com/superseriousbusiness/exif-terminator/terminator.go
+++ b/vendor/github.com/superseriousbusiness/exif-terminator/terminator.go
@@ -43,6 +43,8 @@ func Terminate(in io.Reader, fileSize int, mediaType string) (io.Reader, error)
 	switch mediaType {
 	case "image/jpeg", "jpeg", "jpg":
 		err = terminateJpeg(scanner, pipeWriter, fileSize)
+	case "image/webp", "webp":
+		err = terminateWebp(scanner, pipeWriter)
 	case "image/png", "png":
 		// for pngs we need to skip the header bytes, so read them in
 		// and check we're really dealing with a png here
@@ -86,6 +88,18 @@ func terminateJpeg(scanner *bufio.Scanner, writer io.WriteCloser, expectedFileSi
 	return nil
 }
 
+func terminateWebp(scanner *bufio.Scanner, writer io.WriteCloser) error {
+	v := &webpVisitor{
+		writer: writer,
+	}
+
+	// use the webp visitor's 'split' function, which satisfies the bufio.SplitFunc interface
+	scanner.Split(v.split)
+
+	scanAndClose(scanner, writer)
+	return nil
+}
+
 func terminatePng(scanner *bufio.Scanner, writer io.WriteCloser) error {
 	ps := pngstructure.NewPngSplitter()
 
diff --git a/vendor/github.com/superseriousbusiness/exif-terminator/webp.go b/vendor/github.com/superseriousbusiness/exif-terminator/webp.go
new file mode 100644
index 000000000..392c4871d
--- /dev/null
+++ b/vendor/github.com/superseriousbusiness/exif-terminator/webp.go
@@ -0,0 +1,101 @@
+/*
+   exif-terminator
+   Copyright (C) 2022 SuperSeriousBusiness admin@gotosocial.org
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Affero General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package terminator
+
+import (
+	"encoding/binary"
+	"errors"
+	"io"
+)
+
+const (
+	riffHeaderSize = 4 * 3
+)
+
+var (
+	riffHeader = [4]byte{'R', 'I', 'F', 'F'}
+	webpHeader = [4]byte{'W', 'E', 'B', 'P'}
+	exifFourcc = [4]byte{'E', 'X', 'I', 'F'}
+	xmpFourcc  = [4]byte{'X', 'M', 'P', ' '}
+
+	errNoRiffHeader = errors.New("no RIFF header")
+	errNoWebpHeader = errors.New("not a WEBP file")
+)
+
+type webpVisitor struct {
+	writer     io.Writer
+	doneHeader bool
+}
+
+func fourCC(b []byte) [4]byte {
+	return [4]byte{b[0], b[1], b[2], b[3]}
+}
+
+func (v *webpVisitor) split(data []byte, atEOF bool) (advance int, token []byte, err error) {
+	// parse/write the header first
+	if !v.doneHeader {
+		if len(data) < riffHeaderSize {
+			// need the full header
+			return
+		}
+		if fourCC(data) != riffHeader {
+			err = errNoRiffHeader
+			return
+		}
+		if fourCC(data[8:]) != webpHeader {
+			err = errNoWebpHeader
+			return
+		}
+		if _, err = v.writer.Write(data[:riffHeaderSize]); err != nil {
+			return
+		}
+		advance += riffHeaderSize
+		data = data[riffHeaderSize:]
+		v.doneHeader = true
+	}
+
+	// need enough for fourcc and size
+	if len(data) < 8 {
+		return
+	}
+	size := int64(binary.LittleEndian.Uint32(data[4:]))
+	if (size & 1) != 0 {
+		// odd chunk size - extra padding byte
+		size++
+	}
+	// wait until there is enough
+	if int64(len(data)-8) < size {
+		return
+	}
+
+	fourcc := fourCC(data)
+	rawChunkData := data[8 : 8+size]
+	if fourcc == exifFourcc || fourcc == xmpFourcc {
+		// replace exif/xmp with blank
+		rawChunkData = make([]byte, size)
+	}
+
+	if _, err = v.writer.Write(data[:8]); err == nil {
+		if _, err = v.writer.Write(rawChunkData); err == nil {
+			advance += 8 + int(size)
+		}
+	}
+
+	return
+}
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 000000000..38dc0e568
--- /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/vp8/decode.go b/vendor/golang.org/x/image/vp8/decode.go
new file mode 100644
index 000000000..2aa9fee03
--- /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 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 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 000000000..e34a811b1
--- /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 000000000..929af2cc9
--- /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 000000000..72288bdeb
--- /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 000000000..58c2689ea
--- /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 000000000..f8999582b
--- /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 000000000..da4361604
--- /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 000000000..c1cc4b532
--- /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 000000000..da99cf0f9
--- /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 000000000..431948701
--- /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 - 1)
+	d.bits >>= 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<<ccBits)
+	}
+
+	// Decode the Huffman groups.
+	hGroups, hPix, hBits, err := d.decodeHuffmanGroups(w, h, topLevel, ccBits)
+	if err != nil {
+		return nil, err
+	}
+	hMask, tilesPerRow := int32(0), int32(0)
+	if hBits != 0 {
+		hMask, tilesPerRow = 1<<hBits-1, nTiles(w, hBits)
+	}
+
+	// Decode the pixels.
+	if minCap < 4*w*h {
+		minCap = 4 * w * h
+	}
+	pix := make([]byte, 4*w*h, minCap)
+	p, cachedP := 0, 0
+	x, y := int32(0), int32(0)
+	hg, lookupHG := &hGroups[0], hMask != 0
+	for p < len(pix) {
+		if lookupHG {
+			i := 4 * (tilesPerRow*(y>>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 000000000..36368a872
--- /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)<<codeLength] = symbol<<8 | (codeLength + 1)
+		}
+	}
+
+	n := uint32(0)
+	for jump := lutSize; codeLength > 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 000000000..06543dacb
--- /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 pixels long.
+func nTiles(size int32, bits uint32) int32 {
+	return (size + 1<<bits - 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-1
+	for x := int32(1); x < t.oldWidth; x++ {
+		// The rest of the first row's predictor is mode 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]
+		p += 4
+	}
+	top, tilesPerRow := 0, nTiles(t.oldWidth, t.bits)
+	for y := int32(1); y < h; y++ {
+		// The first column's predictor is mode 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]
+		p, top = p+4, top+4
+
+		q := 4 * (y >> 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-1, nTiles(t.oldWidth, t.bits)
+	for y := int32(0); y < h; y++ {
+		q := 4 * (y >> 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 000000000..d6eefd596
--- /dev/null
+++ b/vendor/golang.org/x/image/webp/decode.go
@@ -0,0 +1,271 @@
+// 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 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
+			)
+			wantAlpha = (buf[0] & alphaBit) != 0
+			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 {
+				if wantAlpha {
+					return nil, image.Config{
+						ColorModel: color.NYCbCrAModel,
+						Width:      int(widthMinusOne) + 1,
+						Height:     int(heightMinusOne) + 1,
+					}, nil
+				}
+				return nil, image.Config{
+					ColorModel: color.YCbCrModel,
+					Width:      int(widthMinusOne) + 1,
+					Height:     int(heightMinusOne) + 1,
+				}, nil
+			}
+		}
+	}
+}
+
+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/doc.go b/vendor/golang.org/x/image/webp/doc.go
new file mode 100644
index 000000000..e321c8542
--- /dev/null
+++ b/vendor/golang.org/x/image/webp/doc.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.
+
+// Package webp implements a decoder for WEBP images.
+//
+// WEBP is defined at:
+// https://developers.google.com/speed/webp/docs/riff_container
+package webp // import "golang.org/x/image/webp"
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 015173b45..ad7b0f294 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -569,7 +569,7 @@ github.com/superseriousbusiness/activity/streams/values/rfc2045
 github.com/superseriousbusiness/activity/streams/values/rfc5988
 github.com/superseriousbusiness/activity/streams/values/string
 github.com/superseriousbusiness/activity/streams/vocab
-# github.com/superseriousbusiness/exif-terminator v0.4.0
+# github.com/superseriousbusiness/exif-terminator v0.5.0
 ## explicit; go 1.17
 github.com/superseriousbusiness/exif-terminator
 # github.com/superseriousbusiness/go-jpeg-image-structure/v2 v2.0.0-20220321154430-d89a106fdabe
@@ -660,12 +660,16 @@ golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
 ## explicit; go 1.18
 golang.org/x/exp/constraints
 golang.org/x/exp/slices
-# golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
+# golang.org/x/image v0.1.0
 ## explicit; go 1.12
 golang.org/x/image/bmp
 golang.org/x/image/ccitt
+golang.org/x/image/riff
 golang.org/x/image/tiff
 golang.org/x/image/tiff/lzw
+golang.org/x/image/vp8
+golang.org/x/image/vp8l
+golang.org/x/image/webp
 # golang.org/x/mod v0.6.0-dev.0.20220907135952-02c991387e35
 ## explicit; go 1.17
 golang.org/x/mod/semver