From 0a1555521d8579b6971f408d298b201c8fd59140 Mon Sep 17 00:00:00 2001
From: kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>
Date: Sat, 31 Aug 2024 08:41:38 +0000
Subject: [PATCH] [performance] use single-threaded image transforms (#3252)
* use single-threaded image resizing in native code so we have more control over goroutines
* implement parallel-free versions of image transform functions also
* remove debug code
---
go.mod | 1 -
go.sum | 3 -
.../api/client/instance/instancepatch_test.go | 2 +-
internal/api/client/media/mediacreate_test.go | 4 +-
internal/media/imaging.go | 623 +++++++++++
internal/media/manager_test.go | 16 +-
internal/media/thumbnail.go | 44 +-
.../disintegration/imaging/.travis.yml | 12 -
.../github.com/disintegration/imaging/LICENSE | 21 -
.../disintegration/imaging/README.md | 226 ----
.../disintegration/imaging/adjust.go | 253 -----
.../disintegration/imaging/convolution.go | 148 ---
.../github.com/disintegration/imaging/doc.go | 7 -
.../disintegration/imaging/effects.go | 169 ---
.../disintegration/imaging/histogram.go | 52 -
.../github.com/disintegration/imaging/io.go | 444 --------
.../disintegration/imaging/resize.go | 595 -----------
.../disintegration/imaging/scanner.go | 285 -----
.../disintegration/imaging/tools.go | 249 -----
.../disintegration/imaging/transform.go | 268 -----
.../disintegration/imaging/utils.go | 167 ---
vendor/golang.org/x/image/bmp/reader.go | 253 -----
vendor/golang.org/x/image/bmp/writer.go | 262 -----
vendor/golang.org/x/image/ccitt/reader.go | 795 --------------
vendor/golang.org/x/image/ccitt/table.go | 972 ------------------
vendor/golang.org/x/image/ccitt/writer.go | 102 --
vendor/golang.org/x/image/tiff/buffer.go | 69 --
vendor/golang.org/x/image/tiff/compress.go | 58 --
vendor/golang.org/x/image/tiff/consts.go | 149 ---
vendor/golang.org/x/image/tiff/fuzz.go | 29 -
vendor/golang.org/x/image/tiff/lzw/reader.go | 272 -----
vendor/golang.org/x/image/tiff/reader.go | 785 --------------
vendor/golang.org/x/image/tiff/writer.go | 441 --------
vendor/modules.txt | 7 -
34 files changed, 653 insertions(+), 7130 deletions(-)
create mode 100644 internal/media/imaging.go
delete mode 100644 vendor/github.com/disintegration/imaging/.travis.yml
delete mode 100644 vendor/github.com/disintegration/imaging/LICENSE
delete mode 100644 vendor/github.com/disintegration/imaging/README.md
delete mode 100644 vendor/github.com/disintegration/imaging/adjust.go
delete mode 100644 vendor/github.com/disintegration/imaging/convolution.go
delete mode 100644 vendor/github.com/disintegration/imaging/doc.go
delete mode 100644 vendor/github.com/disintegration/imaging/effects.go
delete mode 100644 vendor/github.com/disintegration/imaging/histogram.go
delete mode 100644 vendor/github.com/disintegration/imaging/io.go
delete mode 100644 vendor/github.com/disintegration/imaging/resize.go
delete mode 100644 vendor/github.com/disintegration/imaging/scanner.go
delete mode 100644 vendor/github.com/disintegration/imaging/tools.go
delete mode 100644 vendor/github.com/disintegration/imaging/transform.go
delete mode 100644 vendor/github.com/disintegration/imaging/utils.go
delete mode 100644 vendor/golang.org/x/image/bmp/reader.go
delete mode 100644 vendor/golang.org/x/image/bmp/writer.go
delete mode 100644 vendor/golang.org/x/image/ccitt/reader.go
delete mode 100644 vendor/golang.org/x/image/ccitt/table.go
delete mode 100644 vendor/golang.org/x/image/ccitt/writer.go
delete mode 100644 vendor/golang.org/x/image/tiff/buffer.go
delete mode 100644 vendor/golang.org/x/image/tiff/compress.go
delete mode 100644 vendor/golang.org/x/image/tiff/consts.go
delete mode 100644 vendor/golang.org/x/image/tiff/fuzz.go
delete mode 100644 vendor/golang.org/x/image/tiff/lzw/reader.go
delete mode 100644 vendor/golang.org/x/image/tiff/reader.go
delete mode 100644 vendor/golang.org/x/image/tiff/writer.go
diff --git a/go.mod b/go.mod
index 28c1a4e09..ab82ba8ae 100644
--- a/go.mod
+++ b/go.mod
@@ -29,7 +29,6 @@ require (
github.com/KimMachineGun/automemlimit v0.6.1
github.com/buckket/go-blurhash v1.1.0
github.com/coreos/go-oidc/v3 v3.11.0
- github.com/disintegration/imaging v1.6.2
github.com/gin-contrib/cors v1.7.2
github.com/gin-contrib/gzip v1.0.1
github.com/gin-contrib/sessions v1.0.1
diff --git a/go.sum b/go.sum
index d76d57b49..7230ee68e 100644
--- a/go.sum
+++ b/go.sum
@@ -145,8 +145,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
-github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
@@ -692,7 +690,6 @@ golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUF
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
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.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ=
golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
diff --git a/internal/api/client/instance/instancepatch_test.go b/internal/api/client/instance/instancepatch_test.go
index 6148ed93e..8b099984d 100644
--- a/internal/api/client/instance/instancepatch_test.go
+++ b/internal/api/client/instance/instancepatch_test.go
@@ -858,7 +858,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
"static_url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/small/`+instanceAccount.AvatarMediaAttachment.ID+`.webp",`+`
"thumbnail_static_type": "image/webp",
"thumbnail_description": "A bouncing little green peglin.",
- "blurhash": "LF9kG$RR4YtP%dR+V^t5D,oxx?WC"
+ "blurhash": "LE9801Rl4Yt5%dWCV]t5Dmoex?WC"
}`, string(instanceV2ThumbnailJson))
// double extra special bonus: now update the image description without changing the image
diff --git a/internal/api/client/media/mediacreate_test.go b/internal/api/client/media/mediacreate_test.go
index e7f98d6d7..2eec8341f 100644
--- a/internal/api/client/media/mediacreate_test.go
+++ b/internal/api/client/media/mediacreate_test.go
@@ -206,7 +206,7 @@ func (suite *MediaCreateTestSuite) TestMediaCreateSuccessful() {
Y: 0.5,
},
}, *attachmentReply.Meta)
- suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", *attachmentReply.Blurhash)
+ suite.Equal("LiB|W-#6RQR.~qvzRjWF_3rqV@a$", *attachmentReply.Blurhash)
suite.NotEmpty(attachmentReply.ID)
suite.NotEmpty(attachmentReply.URL)
suite.NotEmpty(attachmentReply.PreviewURL)
@@ -291,7 +291,7 @@ func (suite *MediaCreateTestSuite) TestMediaCreateSuccessfulV2() {
Y: 0.5,
},
}, *attachmentReply.Meta)
- suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", *attachmentReply.Blurhash)
+ suite.Equal("LiB|W-#6RQR.~qvzRjWF_3rqV@a$", *attachmentReply.Blurhash)
suite.NotEmpty(attachmentReply.ID)
suite.Nil(attachmentReply.URL)
suite.NotEmpty(attachmentReply.PreviewURL)
diff --git a/internal/media/imaging.go b/internal/media/imaging.go
new file mode 100644
index 000000000..a9f73a066
--- /dev/null
+++ b/internal/media/imaging.go
@@ -0,0 +1,623 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// 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 .
+
+package media
+
+import (
+ "image"
+ "image/color"
+ "math"
+)
+
+// NOTE:
+// the following code is borrowed from
+// github.com/disintegration/imaging
+// and collapses in some places for our
+// particular usecases and with parallel()
+// function (spans work across goroutines)
+// removed, instead working synchronously.
+//
+// at gotosocial we take particular
+// care about where we spawn goroutines
+// to ensure we're in control of the
+// amount of concurrency in relation
+// to the amount configured by user.
+
+// resizeDownLinear resizes image to given width x height using linear resampling.
+// This is specifically optimized for resizing down (i.e. smaller), else is noop.
+func resizeDownLinear(img image.Image, width, height int) image.Image {
+ srcW, srcH := img.Bounds().Dx(), img.Bounds().Dy()
+ if srcW <= 0 || srcH <= 0 ||
+ width < 0 || height < 0 {
+ return &image.NRGBA{}
+ }
+
+ if width == 0 {
+ // If no width is given, use aspect preserving width.
+ tmp := float64(height) * float64(srcW) / float64(srcH)
+ width = int(math.Max(1.0, math.Floor(tmp+0.5)))
+ }
+
+ if height == 0 {
+ // If no height is given, use aspect preserving height.
+ tmp := float64(width) * float64(srcH) / float64(srcW)
+ height = int(math.Max(1.0, math.Floor(tmp+0.5)))
+ }
+
+ if width < srcW {
+ // Width is smaller, resize horizontally.
+ img = resizeHorizontalLinear(img, width)
+ }
+
+ if height < srcH {
+ // Height is smaller, resize vertically.
+ img = resizeVerticalLinear(img, height)
+ }
+
+ return img
+}
+
+// flipH flips the image horizontally (left to right).
+func flipH(img image.Image) image.Image {
+ src := newScanner(img)
+ dstW := src.w
+ dstH := src.h
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ for y := 0; y < dstH; y++ {
+ i := y * dst.Stride
+ srcY := y
+ src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ return dst
+}
+
+// flipV flips the image vertically (from top to bottom).
+func flipV(img image.Image) image.Image {
+ src := newScanner(img)
+ dstW := src.w
+ dstH := src.h
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ for y := 0; y < dstH; y++ {
+ i := y * dst.Stride
+ srcY := dstH - y - 1
+ src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
+ }
+ return dst
+}
+
+// rotate90 rotates the image 90 counter-clockwise.
+func rotate90(img image.Image) image.Image {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ for y := 0; y < dstH; y++ {
+ i := y * dst.Stride
+ srcX := dstH - y - 1
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ }
+ return dst
+}
+
+// rotate180 rotates the image 180 counter-clockwise.
+func rotate180(img image.Image) image.Image {
+ src := newScanner(img)
+ dstW := src.w
+ dstH := src.h
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ for y := 0; y < dstH; y++ {
+ i := y * dst.Stride
+ srcY := dstH - y - 1
+ src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ return dst
+}
+
+// rotate270 rotates the image 270 counter-clockwise.
+func rotate270(img image.Image) image.Image {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ for y := 0; y < dstH; y++ {
+ i := y * dst.Stride
+ srcX := y
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ return dst
+}
+
+// transpose flips the image horizontally and rotates 90 counter-clockwise.
+func transpose(img image.Image) image.Image {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ for y := 0; y < dstH; y++ {
+ i := y * dst.Stride
+ srcX := y
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ }
+ return dst
+}
+
+// transverse flips the image vertically and rotates 90 counter-clockwise.
+func transverse(img image.Image) image.Image {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ for y := 0; y < dstH; y++ {
+ i := y * dst.Stride
+ srcX := dstH - y - 1
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ return dst
+}
+
+// resizeHorizontalLinear resizes image to given width using linear resampling.
+func resizeHorizontalLinear(img image.Image, dstWidth int) image.Image {
+ src := newScanner(img)
+ dst := image.NewRGBA(image.Rect(0, 0, dstWidth, src.h))
+ weights := precomputeWeightsLinear(dstWidth, src.w)
+ scanLine := make([]uint8, src.w*4)
+ for y := 0; y < src.h; y++ {
+ src.scan(0, y, src.w, y+1, scanLine)
+ j0 := y * dst.Stride
+ for x := range weights {
+ var r, g, b, a float64
+ for _, w := range weights[x] {
+ i := w.index * 4
+ s := scanLine[i : i+4 : i+4]
+ aw := float64(s[3]) * w.weight
+ r += float64(s[0]) * aw
+ g += float64(s[1]) * aw
+ b += float64(s[2]) * aw
+ a += aw
+ }
+ if a != 0 {
+ aInv := 1 / a
+ j := j0 + x*4
+ d := dst.Pix[j : j+4 : j+4]
+ d[0] = clampFloat(r * aInv)
+ d[1] = clampFloat(g * aInv)
+ d[2] = clampFloat(b * aInv)
+ d[3] = clampFloat(a)
+ }
+ }
+ }
+ return dst
+}
+
+// resizeVerticalLinear resizes image to given height using linear resampling.
+func resizeVerticalLinear(img image.Image, height int) image.Image {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, height))
+ weights := precomputeWeightsLinear(height, src.h)
+ scanLine := make([]uint8, src.h*4)
+ for x := 0; x < src.w; x++ {
+ src.scan(x, 0, x+1, src.h, scanLine)
+ for y := range weights {
+ var r, g, b, a float64
+ for _, w := range weights[y] {
+ i := w.index * 4
+ s := scanLine[i : i+4 : i+4]
+ aw := float64(s[3]) * w.weight
+ r += float64(s[0]) * aw
+ g += float64(s[1]) * aw
+ b += float64(s[2]) * aw
+ a += aw
+ }
+ if a != 0 {
+ aInv := 1 / a
+ j := y*dst.Stride + x*4
+ d := dst.Pix[j : j+4 : j+4]
+ d[0] = clampFloat(r * aInv)
+ d[1] = clampFloat(g * aInv)
+ d[2] = clampFloat(b * aInv)
+ d[3] = clampFloat(a)
+ }
+ }
+ }
+ return dst
+}
+
+type indexWeight struct {
+ index int
+ weight float64
+}
+
+func precomputeWeightsLinear(dstSize, srcSize int) [][]indexWeight {
+ du := float64(srcSize) / float64(dstSize)
+ scale := du
+ if scale < 1.0 {
+ scale = 1.0
+ }
+
+ ru := math.Ceil(scale)
+ out := make([][]indexWeight, dstSize)
+ tmp := make([]indexWeight, 0, dstSize*int(ru+2)*2)
+
+ for v := 0; v < dstSize; v++ {
+ fu := (float64(v)+0.5)*du - 0.5
+
+ begin := int(math.Ceil(fu - ru))
+ if begin < 0 {
+ begin = 0
+ }
+ end := int(math.Floor(fu + ru))
+ if end > srcSize-1 {
+ end = srcSize - 1
+ }
+
+ var sum float64
+ for u := begin; u <= end; u++ {
+ w := resampleLinear((float64(u) - fu) / scale)
+ if w != 0 {
+ sum += w
+ tmp = append(tmp, indexWeight{index: u, weight: w})
+ }
+ }
+ if sum != 0 {
+ for i := range tmp {
+ tmp[i].weight /= sum
+ }
+ }
+
+ out[v] = tmp
+ tmp = tmp[len(tmp):]
+ }
+
+ return out
+}
+
+// resampleLinear is the resample kernel func for linear filtering.
+func resampleLinear(x float64) float64 {
+ x = math.Abs(x)
+ if x < 1.0 {
+ return 1.0 - x
+ }
+ return 0
+}
+
+// scanner wraps an image.Image for
+// easier size access and image type
+// agnostic access to data at coords.
+type scanner struct {
+ image image.Image
+ w, h int
+ palette []color.NRGBA
+}
+
+// newScanner wraps an image.Image in scanner{} type.
+func newScanner(img image.Image) *scanner {
+ b := img.Bounds()
+ s := &scanner{
+ image: img,
+
+ w: b.Dx(),
+ h: b.Dy(),
+ }
+ if img, ok := img.(*image.Paletted); ok {
+ s.palette = make([]color.NRGBA, len(img.Palette))
+ for i := 0; i < len(img.Palette); i++ {
+ s.palette[i] = color.NRGBAModel.Convert(img.Palette[i]).(color.NRGBA)
+ }
+ }
+ return s
+}
+
+// scan scans the given rectangular region of the image into dst.
+func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) {
+ switch img := s.image.(type) {
+ case *image.NRGBA:
+ size := (x2 - x1) * 4
+ j := 0
+ i := y1*img.Stride + x1*4
+ if size == 4 {
+ for y := y1; y < y2; y++ {
+ d := dst[j : j+4 : j+4]
+ s := img.Pix[i : i+4 : i+4]
+ d[0] = s[0]
+ d[1] = s[1]
+ d[2] = s[2]
+ d[3] = s[3]
+ j += size
+ i += img.Stride
+ }
+ } else {
+ for y := y1; y < y2; y++ {
+ copy(dst[j:j+size], img.Pix[i:i+size])
+ j += size
+ i += img.Stride
+ }
+ }
+
+ case *image.NRGBA64:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1*8
+ for x := x1; x < x2; x++ {
+ s := img.Pix[i : i+8 : i+8]
+ d := dst[j : j+4 : j+4]
+ d[0] = s[0]
+ d[1] = s[2]
+ d[2] = s[4]
+ d[3] = s[6]
+ j += 4
+ i += 8
+ }
+ }
+
+ case *image.RGBA:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1*4
+ for x := x1; x < x2; x++ {
+ d := dst[j : j+4 : j+4]
+ a := img.Pix[i+3]
+ switch a {
+ case 0:
+ d[0] = 0
+ d[1] = 0
+ d[2] = 0
+ d[3] = a
+ case 0xff:
+ s := img.Pix[i : i+4 : i+4]
+ d[0] = s[0]
+ d[1] = s[1]
+ d[2] = s[2]
+ d[3] = a
+ default:
+ s := img.Pix[i : i+4 : i+4]
+ r16 := uint16(s[0])
+ g16 := uint16(s[1])
+ b16 := uint16(s[2])
+ a16 := uint16(a)
+ d[0] = uint8(r16 * 0xff / a16)
+ d[1] = uint8(g16 * 0xff / a16)
+ d[2] = uint8(b16 * 0xff / a16)
+ d[3] = a
+ }
+ j += 4
+ i += 4
+ }
+ }
+
+ case *image.RGBA64:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1*8
+ for x := x1; x < x2; x++ {
+ s := img.Pix[i : i+8 : i+8]
+ d := dst[j : j+4 : j+4]
+ a := s[6]
+ switch a {
+ case 0:
+ d[0] = 0
+ d[1] = 0
+ d[2] = 0
+ case 0xff:
+ d[0] = s[0]
+ d[1] = s[2]
+ d[2] = s[4]
+ default:
+ r32 := uint32(s[0])<<8 | uint32(s[1])
+ g32 := uint32(s[2])<<8 | uint32(s[3])
+ b32 := uint32(s[4])<<8 | uint32(s[5])
+ a32 := uint32(s[6])<<8 | uint32(s[7])
+ d[0] = uint8((r32 * 0xffff / a32) >> 8)
+ d[1] = uint8((g32 * 0xffff / a32) >> 8)
+ d[2] = uint8((b32 * 0xffff / a32) >> 8)
+ }
+ d[3] = a
+ j += 4
+ i += 8
+ }
+ }
+
+ case *image.Gray:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1
+ for x := x1; x < x2; x++ {
+ c := img.Pix[i]
+ d := dst[j : j+4 : j+4]
+ d[0] = c
+ d[1] = c
+ d[2] = c
+ d[3] = 0xff
+ j += 4
+ i++
+ }
+ }
+
+ case *image.Gray16:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1*2
+ for x := x1; x < x2; x++ {
+ c := img.Pix[i]
+ d := dst[j : j+4 : j+4]
+ d[0] = c
+ d[1] = c
+ d[2] = c
+ d[3] = 0xff
+ j += 4
+ i += 2
+ }
+ }
+
+ case *image.YCbCr:
+ j := 0
+ x1 += img.Rect.Min.X
+ x2 += img.Rect.Min.X
+ y1 += img.Rect.Min.Y
+ y2 += img.Rect.Min.Y
+
+ hy := img.Rect.Min.Y / 2
+ hx := img.Rect.Min.X / 2
+ for y := y1; y < y2; y++ {
+ iy := (y-img.Rect.Min.Y)*img.YStride + (x1 - img.Rect.Min.X)
+
+ var yBase int
+ switch img.SubsampleRatio {
+ case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio422:
+ yBase = (y - img.Rect.Min.Y) * img.CStride
+ case image.YCbCrSubsampleRatio420, image.YCbCrSubsampleRatio440:
+ yBase = (y/2 - hy) * img.CStride
+ }
+
+ for x := x1; x < x2; x++ {
+ var ic int
+ switch img.SubsampleRatio {
+ case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio440:
+ ic = yBase + (x - img.Rect.Min.X)
+ case image.YCbCrSubsampleRatio422, image.YCbCrSubsampleRatio420:
+ ic = yBase + (x/2 - hx)
+ default:
+ ic = img.COffset(x, y)
+ }
+
+ yy1 := int32(img.Y[iy]) * 0x10101
+ cb1 := int32(img.Cb[ic]) - 128
+ cr1 := int32(img.Cr[ic]) - 128
+
+ r := yy1 + 91881*cr1
+ if uint32(r)&0xff000000 == 0 {
+ r >>= 16
+ } else {
+ r = ^(r >> 31)
+ }
+
+ g := yy1 - 22554*cb1 - 46802*cr1
+ if uint32(g)&0xff000000 == 0 {
+ g >>= 16
+ } else {
+ g = ^(g >> 31)
+ }
+
+ b := yy1 + 116130*cb1
+ if uint32(b)&0xff000000 == 0 {
+ b >>= 16
+ } else {
+ b = ^(b >> 31)
+ }
+
+ d := dst[j : j+4 : j+4]
+ d[0] = uint8(r)
+ d[1] = uint8(g)
+ d[2] = uint8(b)
+ d[3] = 0xff
+
+ iy++
+ j += 4
+ }
+ }
+
+ case *image.Paletted:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1
+ for x := x1; x < x2; x++ {
+ c := s.palette[img.Pix[i]]
+ d := dst[j : j+4 : j+4]
+ d[0] = c.R
+ d[1] = c.G
+ d[2] = c.B
+ d[3] = c.A
+ j += 4
+ i++
+ }
+ }
+
+ default:
+ j := 0
+ b := s.image.Bounds()
+ x1 += b.Min.X
+ x2 += b.Min.X
+ y1 += b.Min.Y
+ y2 += b.Min.Y
+ for y := y1; y < y2; y++ {
+ for x := x1; x < x2; x++ {
+ r16, g16, b16, a16 := s.image.At(x, y).RGBA()
+ d := dst[j : j+4 : j+4]
+ switch a16 {
+ case 0xffff:
+ d[0] = uint8(r16 >> 8)
+ d[1] = uint8(g16 >> 8)
+ d[2] = uint8(b16 >> 8)
+ d[3] = 0xff
+ case 0:
+ d[0] = 0
+ d[1] = 0
+ d[2] = 0
+ d[3] = 0
+ default:
+ d[0] = uint8(((r16 * 0xffff) / a16) >> 8)
+ d[1] = uint8(((g16 * 0xffff) / a16) >> 8)
+ d[2] = uint8(((b16 * 0xffff) / a16) >> 8)
+ d[3] = uint8(a16 >> 8)
+ }
+ j += 4
+ }
+ }
+ }
+}
+
+// reverse reverses the data
+// in contained pixel slice.
+func reverse(pix []uint8) {
+ if len(pix) <= 4 {
+ return
+ }
+ i := 0
+ j := len(pix) - 4
+ for i < j {
+ pi := pix[i : i+4 : i+4]
+ pj := pix[j : j+4 : j+4]
+ pi[0], pj[0] = pj[0], pi[0]
+ pi[1], pj[1] = pj[1], pi[1]
+ pi[2], pj[2] = pj[2], pi[2]
+ pi[3], pj[3] = pj[3], pi[3]
+ i += 4
+ j -= 4
+ }
+}
+
+// clampFloat rounds and clamps float64 value to fit into uint8.
+func clampFloat(x float64) uint8 {
+ v := int64(x + 0.5)
+ if v > 255 {
+ return 255
+ }
+ if v > 0 {
+ return uint8(v)
+ }
+ return 0
+}
diff --git a/internal/media/manager_test.go b/internal/media/manager_test.go
index ff38176f1..29ed95ffa 100644
--- a/internal/media/manager_test.go
+++ b/internal/media/manager_test.go
@@ -276,7 +276,7 @@ func (suite *ManagerTestSuite) TestSimpleJpegProcess() {
suite.Equal("image/jpeg", attachment.Thumbnail.ContentType)
suite.Equal(269739, attachment.File.FileSize)
suite.Equal(22858, attachment.Thumbnail.FileSize)
- suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", attachment.Blurhash)
+ suite.Equal("LiB|W-#6RQR.~qvzRjWF_3rqV@a$", attachment.Blurhash)
// now make sure the attachment is in the database
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
@@ -429,7 +429,7 @@ func (suite *ManagerTestSuite) TestSlothVineProcess() {
suite.Equal("image/webp", attachment.Thumbnail.ContentType)
suite.Equal(312453, attachment.File.FileSize)
suite.Equal(5648, attachment.Thumbnail.FileSize)
- suite.Equal("LfIYH~xtNskCxtfPW.kB_4aespof", attachment.Blurhash)
+ suite.Equal("LgIYH}xtNsofxtfPW.j[_4axn+of", attachment.Blurhash)
// now make sure the attachment is in the database
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
@@ -489,7 +489,7 @@ func (suite *ManagerTestSuite) TestLongerMp4Process() {
suite.Equal("image/webp", attachment.Thumbnail.ContentType)
suite.Equal(109569, attachment.File.FileSize)
suite.Equal(2976, attachment.Thumbnail.FileSize)
- suite.Equal("LJQJfm?bM{?b~qRjt7WBayWBofWB", attachment.Blurhash)
+ suite.Equal("LIQJfl_3IU?b~qM{ofayWBWVofRj", attachment.Blurhash)
// now make sure the attachment is in the database
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
@@ -549,7 +549,7 @@ func (suite *ManagerTestSuite) TestBirdnestMp4Process() {
suite.Equal("image/webp", attachment.Thumbnail.ContentType)
suite.Equal(1409625, attachment.File.FileSize)
suite.Equal(14478, attachment.Thumbnail.FileSize)
- suite.Equal("LJF?FZV@RO.99DM_RPWAx]V?ayMw", attachment.Blurhash)
+ suite.Equal("LLF$qyaeRO.9DgM_RPaetkV@WCMw", attachment.Blurhash)
// now make sure the attachment is in the database
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
@@ -657,7 +657,7 @@ func (suite *ManagerTestSuite) TestPngNoAlphaChannelProcess() {
suite.Equal("image/jpeg", attachment.Thumbnail.ContentType)
suite.Equal(17471, attachment.File.FileSize)
suite.Equal(6446, attachment.Thumbnail.FileSize)
- suite.Equal("LFQT7e.A%O%4?co$M}M{_1W9~TxV", attachment.Blurhash)
+ suite.Equal("LGP%YL.A-?tA.9o#RURQ~ojp^~xW", attachment.Blurhash)
// now make sure the attachment is in the database
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
@@ -713,7 +713,7 @@ func (suite *ManagerTestSuite) TestPngAlphaChannelProcess() {
suite.Equal("image/webp", attachment.Thumbnail.ContentType)
suite.Equal(18832, attachment.File.FileSize)
suite.Equal(3592, attachment.Thumbnail.FileSize)
- suite.Equal("LCONII.A%Oxw?co#M}M{_1ac~TxV", attachment.Blurhash)
+ suite.Equal("LCN^lE.A-?xd?co#N1RQ~ojp~SxW", attachment.Blurhash)
// now make sure the attachment is in the database
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
@@ -769,7 +769,7 @@ func (suite *ManagerTestSuite) TestSimpleJpegProcessWithCallback() {
suite.Equal("image/jpeg", attachment.Thumbnail.ContentType)
suite.Equal(269739, attachment.File.FileSize)
suite.Equal(22858, attachment.Thumbnail.FileSize)
- suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", attachment.Blurhash)
+ suite.Equal("LiB|W-#6RQR.~qvzRjWF_3rqV@a$", attachment.Blurhash)
// now make sure the attachment is in the database
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
@@ -847,7 +847,7 @@ func (suite *ManagerTestSuite) TestSimpleJpegProcessWithDiskStorage() {
suite.Equal("image/jpeg", attachment.Thumbnail.ContentType)
suite.Equal(269739, attachment.File.FileSize)
suite.Equal(22858, attachment.Thumbnail.FileSize)
- suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", attachment.Blurhash)
+ suite.Equal("LiB|W-#6RQR.~qvzRjWF_3rqV@a$", attachment.Blurhash)
// now make sure the attachment is in the database
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
diff --git a/internal/media/thumbnail.go b/internal/media/thumbnail.go
index a562dc2ad..322af8d7e 100644
--- a/internal/media/thumbnail.go
+++ b/internal/media/thumbnail.go
@@ -28,7 +28,6 @@ import (
"strings"
"github.com/buckket/go-blurhash"
- "github.com/disintegration/imaging"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/log"
"golang.org/x/image/webp"
@@ -248,32 +247,25 @@ func generateNativeThumb(
// taking orientation into account.
switch orientation {
case orientationFlipH:
- img = imaging.FlipH(img)
+ img = flipH(img)
case orientationFlipV:
- img = imaging.FlipV(img)
+ img = flipV(img)
case orientationRotate90:
- img = imaging.Rotate90(img)
+ img = rotate90(img)
case orientationRotate180:
- img = imaging.Rotate180(img)
+ img = rotate180(img)
case orientationRotate270:
- img = imaging.Rotate270(img)
+ img = rotate270(img)
case orientationTranspose:
- img = imaging.Transpose(img)
+ img = transpose(img)
case orientationTransverse:
- img = imaging.Transverse(img)
+ img = transverse(img)
}
- // Resize image to dimens only if necessary.
- if img.Bounds().Dx() > maxThumbWidth ||
- img.Bounds().Dy() > maxThumbHeight {
- // Note: We could call "imaging.Fit" here
- // but there's no point, as we've already
- // calculated target dimensions beforehand.
- img = imaging.Resize(img,
- width, height,
- imaging.Linear,
- )
- }
+ // Resize image to dimens.
+ img = resizeDownLinear(img,
+ width, height,
+ )
// Open output file at given path.
outfile, err := os.Create(outpath)
@@ -293,9 +285,10 @@ func generateNativeThumb(
}
if needBlurhash {
- // for generating blurhashes, it's more cost effective to
- // lose detail since it's blurry, so make a tiny version.
- tiny := imaging.Resize(img, 32, 0, imaging.NearestNeighbor)
+ // for generating blurhashes, it's more
+ // cost effective to lose detail since
+ // it's blurry, so make a tiny version.
+ tiny := resizeDownLinear(img, 32, 0)
// Drop the larger image
// ref as soon as possible
@@ -332,9 +325,10 @@ func generateWebpBlurhash(filepath string) (string, error) {
return "", gtserror.Newf("error decoding file %s: %w", filepath, err)
}
- // for generating blurhashes, it's more cost effective to
- // lose detail since it's blurry, so make a tiny version.
- tiny := imaging.Resize(img, 32, 0, imaging.NearestNeighbor)
+ // for generating blurhashes, it's more
+ // cost effective to lose detail since
+ // it's blurry, so make a tiny version.
+ tiny := resizeDownLinear(img, 32, 0)
// Drop the larger image
// ref as soon as possible
diff --git a/vendor/github.com/disintegration/imaging/.travis.yml b/vendor/github.com/disintegration/imaging/.travis.yml
deleted file mode 100644
index 7ae5e4b25..000000000
--- a/vendor/github.com/disintegration/imaging/.travis.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-language: go
-go:
- - "1.10.x"
- - "1.11.x"
- - "1.12.x"
-
-before_install:
- - go get github.com/mattn/goveralls
-
-script:
- - go test -v -race -cover
- - $GOPATH/bin/goveralls -service=travis-ci
diff --git a/vendor/github.com/disintegration/imaging/LICENSE b/vendor/github.com/disintegration/imaging/LICENSE
deleted file mode 100644
index a4144a9d2..000000000
--- a/vendor/github.com/disintegration/imaging/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2012 Grigory Dryapak
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/disintegration/imaging/README.md b/vendor/github.com/disintegration/imaging/README.md
deleted file mode 100644
index a1fd764d2..000000000
--- a/vendor/github.com/disintegration/imaging/README.md
+++ /dev/null
@@ -1,226 +0,0 @@
-# Imaging
-
-[![GoDoc](https://godoc.org/github.com/disintegration/imaging?status.svg)](https://godoc.org/github.com/disintegration/imaging)
-[![Build Status](https://travis-ci.org/disintegration/imaging.svg?branch=master)](https://travis-ci.org/disintegration/imaging)
-[![Coverage Status](https://coveralls.io/repos/github/disintegration/imaging/badge.svg?branch=master&service=github)](https://coveralls.io/github/disintegration/imaging?branch=master)
-[![Go Report Card](https://goreportcard.com/badge/github.com/disintegration/imaging)](https://goreportcard.com/report/github.com/disintegration/imaging)
-
-Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).
-
-All the image processing functions provided by the package accept any image type that implements `image.Image` interface
-as an input, and return a new image of `*image.NRGBA` type (32bit RGBA colors, non-premultiplied alpha).
-
-## Installation
-
- go get -u github.com/disintegration/imaging
-
-## Documentation
-
-http://godoc.org/github.com/disintegration/imaging
-
-## Usage examples
-
-A few usage examples can be found below. See the documentation for the full list of supported functions.
-
-### Image resizing
-
-```go
-// Resize srcImage to size = 128x128px using the Lanczos filter.
-dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos)
-
-// Resize srcImage to width = 800px preserving the aspect ratio.
-dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos)
-
-// Scale down srcImage to fit the 800x600px bounding box.
-dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
-
-// Resize and crop the srcImage to fill the 100x100px area.
-dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos)
-```
-
-Imaging supports image resizing using various resampling filters. The most notable ones:
-- `Lanczos` - A high-quality resampling filter for photographic images yielding sharp results.
-- `CatmullRom` - A sharp cubic filter that is faster than Lanczos filter while providing similar results.
-- `MitchellNetravali` - A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.
-- `Linear` - Bilinear resampling filter, produces smooth output. Faster than cubic filters.
-- `Box` - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor.
-- `NearestNeighbor` - Fastest resampling filter, no antialiasing.
-
-The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. Custom filters can be created using ResampleFilter struct.
-
-**Resampling filters comparison**
-
-Original image:
-
-![srcImage](testdata/branches.png)
-
-The same image resized from 600x400px to 150x100px using different resampling filters.
-From faster (lower quality) to slower (higher quality):
-
-Filter | Resize result
---------------------------|---------------------------------------------
-`imaging.NearestNeighbor` | ![dstImage](testdata/out_resize_nearest.png)
-`imaging.Linear` | ![dstImage](testdata/out_resize_linear.png)
-`imaging.CatmullRom` | ![dstImage](testdata/out_resize_catrom.png)
-`imaging.Lanczos` | ![dstImage](testdata/out_resize_lanczos.png)
-
-
-### Gaussian Blur
-
-```go
-dstImage := imaging.Blur(srcImage, 0.5)
-```
-
-Sigma parameter allows to control the strength of the blurring effect.
-
-Original image | Sigma = 0.5 | Sigma = 1.5
------------------------------------|----------------------------------------|---------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png)
-
-### Sharpening
-
-```go
-dstImage := imaging.Sharpen(srcImage, 0.5)
-```
-
-`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
-
-Original image | Sigma = 0.5 | Sigma = 1.5
------------------------------------|-------------------------------------------|------------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png)
-
-### Gamma correction
-
-```go
-dstImage := imaging.AdjustGamma(srcImage, 0.75)
-```
-
-Original image | Gamma = 0.75 | Gamma = 1.25
------------------------------------|------------------------------------------|-----------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png)
-
-### Contrast adjustment
-
-```go
-dstImage := imaging.AdjustContrast(srcImage, 20)
-```
-
-Original image | Contrast = 15 | Contrast = -15
------------------------------------|--------------------------------------------|-------------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_contrast_p15.png) | ![dstImage](testdata/out_contrast_m15.png)
-
-### Brightness adjustment
-
-```go
-dstImage := imaging.AdjustBrightness(srcImage, 20)
-```
-
-Original image | Brightness = 10 | Brightness = -10
------------------------------------|----------------------------------------------|---------------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png)
-
-### Saturation adjustment
-
-```go
-dstImage := imaging.AdjustSaturation(srcImage, 20)
-```
-
-Original image | Saturation = 30 | Saturation = -30
------------------------------------|----------------------------------------------|---------------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_saturation_p30.png) | ![dstImage](testdata/out_saturation_m30.png)
-
-## FAQ
-
-### Incorrect image orientation after processing (e.g. an image appears rotated after resizing)
-
-Most probably, the given image contains the EXIF orientation tag.
-The stadard `image/*` packages do not support loading and saving
-this kind of information. To fix the issue, try opening images with
-the `AutoOrientation` decode option. If this option is set to `true`,
-the image orientation is changed after decoding, according to the
-orientation tag (if present). Here's the example:
-
-```go
-img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true))
-```
-
-### What's the difference between `imaging` and `gift` packages?
-
-[imaging](https://github.com/disintegration/imaging)
-is designed to be a lightweight and simple image manipulation package.
-It provides basic image processing functions and a few helper functions
-such as `Open` and `Save`. It consistently returns *image.NRGBA image
-type (8 bits per channel, RGBA).
-
-[gift](https://github.com/disintegration/gift)
-supports more advanced image processing, for example, sRGB/Linear color
-space conversions. It also supports different output image types
-(e.g. 16 bits per channel) and provides easy-to-use API for chaining
-multiple processing steps together.
-
-## Example code
-
-```go
-package main
-
-import (
- "image"
- "image/color"
- "log"
-
- "github.com/disintegration/imaging"
-)
-
-func main() {
- // Open a test image.
- src, err := imaging.Open("testdata/flowers.png")
- if err != nil {
- log.Fatalf("failed to open image: %v", err)
- }
-
- // Crop the original image to 300x300px size using the center anchor.
- src = imaging.CropAnchor(src, 300, 300, imaging.Center)
-
- // Resize the cropped image to width = 200px preserving the aspect ratio.
- src = imaging.Resize(src, 200, 0, imaging.Lanczos)
-
- // Create a blurred version of the image.
- img1 := imaging.Blur(src, 5)
-
- // Create a grayscale version of the image with higher contrast and sharpness.
- img2 := imaging.Grayscale(src)
- img2 = imaging.AdjustContrast(img2, 20)
- img2 = imaging.Sharpen(img2, 2)
-
- // Create an inverted version of the image.
- img3 := imaging.Invert(src)
-
- // Create an embossed version of the image using a convolution filter.
- img4 := imaging.Convolve3x3(
- src,
- [9]float64{
- -1, -1, 0,
- -1, 1, 1,
- 0, 1, 1,
- },
- nil,
- )
-
- // Create a new image and paste the four produced images into it.
- dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0})
- dst = imaging.Paste(dst, img1, image.Pt(0, 0))
- dst = imaging.Paste(dst, img2, image.Pt(0, 200))
- dst = imaging.Paste(dst, img3, image.Pt(200, 0))
- dst = imaging.Paste(dst, img4, image.Pt(200, 200))
-
- // Save the resulting image as JPEG.
- err = imaging.Save(dst, "testdata/out_example.jpg")
- if err != nil {
- log.Fatalf("failed to save image: %v", err)
- }
-}
-```
-
-Output:
-
-![dstImage](testdata/out_example.jpg)
diff --git a/vendor/github.com/disintegration/imaging/adjust.go b/vendor/github.com/disintegration/imaging/adjust.go
deleted file mode 100644
index daaf1de86..000000000
--- a/vendor/github.com/disintegration/imaging/adjust.go
+++ /dev/null
@@ -1,253 +0,0 @@
-package imaging
-
-import (
- "image"
- "image/color"
- "math"
-)
-
-// Grayscale produces a grayscale version of the image.
-func Grayscale(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
- parallel(0, src.h, func(ys <-chan int) {
- for y := range ys {
- i := y * dst.Stride
- src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
- for x := 0; x < src.w; x++ {
- d := dst.Pix[i : i+3 : i+3]
- r := d[0]
- g := d[1]
- b := d[2]
- f := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)
- y := uint8(f + 0.5)
- d[0] = y
- d[1] = y
- d[2] = y
- i += 4
- }
- }
- })
- return dst
-}
-
-// Invert produces an inverted (negated) version of the image.
-func Invert(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
- parallel(0, src.h, func(ys <-chan int) {
- for y := range ys {
- i := y * dst.Stride
- src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
- for x := 0; x < src.w; x++ {
- d := dst.Pix[i : i+3 : i+3]
- d[0] = 255 - d[0]
- d[1] = 255 - d[1]
- d[2] = 255 - d[2]
- i += 4
- }
- }
- })
- return dst
-}
-
-// AdjustSaturation changes the saturation of the image using the percentage parameter and returns the adjusted image.
-// The percentage must be in the range (-100, 100).
-// The percentage = 0 gives the original image.
-// The percentage = 100 gives the image with the saturation value doubled for each pixel.
-// The percentage = -100 gives the image with the saturation value zeroed for each pixel (grayscale).
-//
-// Examples:
-// dstImage = imaging.AdjustSaturation(srcImage, 25) // Increase image saturation by 25%.
-// dstImage = imaging.AdjustSaturation(srcImage, -10) // Decrease image saturation by 10%.
-//
-func AdjustSaturation(img image.Image, percentage float64) *image.NRGBA {
- percentage = math.Min(math.Max(percentage, -100), 100)
- multiplier := 1 + percentage/100
-
- return AdjustFunc(img, func(c color.NRGBA) color.NRGBA {
- h, s, l := rgbToHSL(c.R, c.G, c.B)
- s *= multiplier
- if s > 1 {
- s = 1
- }
- r, g, b := hslToRGB(h, s, l)
- return color.NRGBA{r, g, b, c.A}
- })
-}
-
-// AdjustContrast changes the contrast of the image using the percentage parameter and returns the adjusted image.
-// The percentage must be in range (-100, 100). The percentage = 0 gives the original image.
-// The percentage = -100 gives solid gray image.
-//
-// Examples:
-//
-// dstImage = imaging.AdjustContrast(srcImage, -10) // Decrease image contrast by 10%.
-// dstImage = imaging.AdjustContrast(srcImage, 20) // Increase image contrast by 20%.
-//
-func AdjustContrast(img image.Image, percentage float64) *image.NRGBA {
- percentage = math.Min(math.Max(percentage, -100.0), 100.0)
- lut := make([]uint8, 256)
-
- v := (100.0 + percentage) / 100.0
- for i := 0; i < 256; i++ {
- switch {
- case 0 <= v && v <= 1:
- lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*v) * 255.0)
- case 1 < v && v < 2:
- lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*(1/(2.0-v))) * 255.0)
- default:
- lut[i] = uint8(float64(i)/255.0+0.5) * 255
- }
- }
-
- return adjustLUT(img, lut)
-}
-
-// AdjustBrightness changes the brightness of the image using the percentage parameter and returns the adjusted image.
-// The percentage must be in range (-100, 100). The percentage = 0 gives the original image.
-// The percentage = -100 gives solid black image. The percentage = 100 gives solid white image.
-//
-// Examples:
-//
-// dstImage = imaging.AdjustBrightness(srcImage, -15) // Decrease image brightness by 15%.
-// dstImage = imaging.AdjustBrightness(srcImage, 10) // Increase image brightness by 10%.
-//
-func AdjustBrightness(img image.Image, percentage float64) *image.NRGBA {
- percentage = math.Min(math.Max(percentage, -100.0), 100.0)
- lut := make([]uint8, 256)
-
- shift := 255.0 * percentage / 100.0
- for i := 0; i < 256; i++ {
- lut[i] = clamp(float64(i) + shift)
- }
-
- return adjustLUT(img, lut)
-}
-
-// AdjustGamma performs a gamma correction on the image and returns the adjusted image.
-// Gamma parameter must be positive. Gamma = 1.0 gives the original image.
-// Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it.
-//
-// Example:
-//
-// dstImage = imaging.AdjustGamma(srcImage, 0.7)
-//
-func AdjustGamma(img image.Image, gamma float64) *image.NRGBA {
- e := 1.0 / math.Max(gamma, 0.0001)
- lut := make([]uint8, 256)
-
- for i := 0; i < 256; i++ {
- lut[i] = clamp(math.Pow(float64(i)/255.0, e) * 255.0)
- }
-
- return adjustLUT(img, lut)
-}
-
-// AdjustSigmoid changes the contrast of the image using a sigmoidal function and returns the adjusted image.
-// It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail.
-// The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5.
-// The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10).
-// If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased.
-//
-// Examples:
-//
-// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, 3.0) // Increase the contrast.
-// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, -3.0) // Decrease the contrast.
-//
-func AdjustSigmoid(img image.Image, midpoint, factor float64) *image.NRGBA {
- if factor == 0 {
- return Clone(img)
- }
-
- lut := make([]uint8, 256)
- a := math.Min(math.Max(midpoint, 0.0), 1.0)
- b := math.Abs(factor)
- sig0 := sigmoid(a, b, 0)
- sig1 := sigmoid(a, b, 1)
- e := 1.0e-6
-
- if factor > 0 {
- for i := 0; i < 256; i++ {
- x := float64(i) / 255.0
- sigX := sigmoid(a, b, x)
- f := (sigX - sig0) / (sig1 - sig0)
- lut[i] = clamp(f * 255.0)
- }
- } else {
- for i := 0; i < 256; i++ {
- x := float64(i) / 255.0
- arg := math.Min(math.Max((sig1-sig0)*x+sig0, e), 1.0-e)
- f := a - math.Log(1.0/arg-1.0)/b
- lut[i] = clamp(f * 255.0)
- }
- }
-
- return adjustLUT(img, lut)
-}
-
-func sigmoid(a, b, x float64) float64 {
- return 1 / (1 + math.Exp(b*(a-x)))
-}
-
-// adjustLUT applies the given lookup table to the colors of the image.
-func adjustLUT(img image.Image, lut []uint8) *image.NRGBA {
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
- lut = lut[0:256]
- parallel(0, src.h, func(ys <-chan int) {
- for y := range ys {
- i := y * dst.Stride
- src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
- for x := 0; x < src.w; x++ {
- d := dst.Pix[i : i+3 : i+3]
- d[0] = lut[d[0]]
- d[1] = lut[d[1]]
- d[2] = lut[d[2]]
- i += 4
- }
- }
- })
- return dst
-}
-
-// AdjustFunc applies the fn function to each pixel of the img image and returns the adjusted image.
-//
-// Example:
-//
-// dstImage = imaging.AdjustFunc(
-// srcImage,
-// func(c color.NRGBA) color.NRGBA {
-// // Shift the red channel by 16.
-// r := int(c.R) + 16
-// if r > 255 {
-// r = 255
-// }
-// return color.NRGBA{uint8(r), c.G, c.B, c.A}
-// }
-// )
-//
-func AdjustFunc(img image.Image, fn func(c color.NRGBA) color.NRGBA) *image.NRGBA {
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
- parallel(0, src.h, func(ys <-chan int) {
- for y := range ys {
- i := y * dst.Stride
- src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
- for x := 0; x < src.w; x++ {
- d := dst.Pix[i : i+4 : i+4]
- r := d[0]
- g := d[1]
- b := d[2]
- a := d[3]
- c := fn(color.NRGBA{r, g, b, a})
- d[0] = c.R
- d[1] = c.G
- d[2] = c.B
- d[3] = c.A
- i += 4
- }
- }
- })
- return dst
-}
diff --git a/vendor/github.com/disintegration/imaging/convolution.go b/vendor/github.com/disintegration/imaging/convolution.go
deleted file mode 100644
index 11eddc162..000000000
--- a/vendor/github.com/disintegration/imaging/convolution.go
+++ /dev/null
@@ -1,148 +0,0 @@
-package imaging
-
-import (
- "image"
-)
-
-// ConvolveOptions are convolution parameters.
-type ConvolveOptions struct {
- // If Normalize is true the kernel is normalized before convolution.
- Normalize bool
-
- // If Abs is true the absolute value of each color channel is taken after convolution.
- Abs bool
-
- // Bias is added to each color channel value after convolution.
- Bias int
-}
-
-// Convolve3x3 convolves the image with the specified 3x3 convolution kernel.
-// Default parameters are used if a nil *ConvolveOptions is passed.
-func Convolve3x3(img image.Image, kernel [9]float64, options *ConvolveOptions) *image.NRGBA {
- return convolve(img, kernel[:], options)
-}
-
-// Convolve5x5 convolves the image with the specified 5x5 convolution kernel.
-// Default parameters are used if a nil *ConvolveOptions is passed.
-func Convolve5x5(img image.Image, kernel [25]float64, options *ConvolveOptions) *image.NRGBA {
- return convolve(img, kernel[:], options)
-}
-
-func convolve(img image.Image, kernel []float64, options *ConvolveOptions) *image.NRGBA {
- src := toNRGBA(img)
- w := src.Bounds().Max.X
- h := src.Bounds().Max.Y
- dst := image.NewNRGBA(image.Rect(0, 0, w, h))
-
- if w < 1 || h < 1 {
- return dst
- }
-
- if options == nil {
- options = &ConvolveOptions{}
- }
-
- if options.Normalize {
- normalizeKernel(kernel)
- }
-
- type coef struct {
- x, y int
- k float64
- }
- var coefs []coef
- var m int
-
- switch len(kernel) {
- case 9:
- m = 1
- case 25:
- m = 2
- }
-
- i := 0
- for y := -m; y <= m; y++ {
- for x := -m; x <= m; x++ {
- if kernel[i] != 0 {
- coefs = append(coefs, coef{x: x, y: y, k: kernel[i]})
- }
- i++
- }
- }
-
- parallel(0, h, func(ys <-chan int) {
- for y := range ys {
- for x := 0; x < w; x++ {
- var r, g, b float64
- for _, c := range coefs {
- ix := x + c.x
- if ix < 0 {
- ix = 0
- } else if ix >= w {
- ix = w - 1
- }
-
- iy := y + c.y
- if iy < 0 {
- iy = 0
- } else if iy >= h {
- iy = h - 1
- }
-
- off := iy*src.Stride + ix*4
- s := src.Pix[off : off+3 : off+3]
- r += float64(s[0]) * c.k
- g += float64(s[1]) * c.k
- b += float64(s[2]) * c.k
- }
-
- if options.Abs {
- if r < 0 {
- r = -r
- }
- if g < 0 {
- g = -g
- }
- if b < 0 {
- b = -b
- }
- }
-
- if options.Bias != 0 {
- r += float64(options.Bias)
- g += float64(options.Bias)
- b += float64(options.Bias)
- }
-
- srcOff := y*src.Stride + x*4
- dstOff := y*dst.Stride + x*4
- d := dst.Pix[dstOff : dstOff+4 : dstOff+4]
- d[0] = clamp(r)
- d[1] = clamp(g)
- d[2] = clamp(b)
- d[3] = src.Pix[srcOff+3]
- }
- }
- })
-
- return dst
-}
-
-func normalizeKernel(kernel []float64) {
- var sum, sumpos float64
- for i := range kernel {
- sum += kernel[i]
- if kernel[i] > 0 {
- sumpos += kernel[i]
- }
- }
- if sum != 0 {
- for i := range kernel {
- kernel[i] /= sum
- }
- } else if sumpos != 0 {
- for i := range kernel {
- kernel[i] /= sumpos
- }
- }
-}
diff --git a/vendor/github.com/disintegration/imaging/doc.go b/vendor/github.com/disintegration/imaging/doc.go
deleted file mode 100644
index c98c91250..000000000
--- a/vendor/github.com/disintegration/imaging/doc.go
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
-Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).
-
-All the image processing functions provided by the package accept any image type that implements image.Image interface
-as an input, and return a new image of *image.NRGBA type (32bit RGBA colors, non-premultiplied alpha).
-*/
-package imaging
diff --git a/vendor/github.com/disintegration/imaging/effects.go b/vendor/github.com/disintegration/imaging/effects.go
deleted file mode 100644
index 47316b701..000000000
--- a/vendor/github.com/disintegration/imaging/effects.go
+++ /dev/null
@@ -1,169 +0,0 @@
-package imaging
-
-import (
- "image"
- "math"
-)
-
-func gaussianBlurKernel(x, sigma float64) float64 {
- return math.Exp(-(x*x)/(2*sigma*sigma)) / (sigma * math.Sqrt(2*math.Pi))
-}
-
-// Blur produces a blurred version of the image using a Gaussian function.
-// Sigma parameter must be positive and indicates how much the image will be blurred.
-//
-// Example:
-//
-// dstImage := imaging.Blur(srcImage, 3.5)
-//
-func Blur(img image.Image, sigma float64) *image.NRGBA {
- if sigma <= 0 {
- return Clone(img)
- }
-
- radius := int(math.Ceil(sigma * 3.0))
- kernel := make([]float64, radius+1)
-
- for i := 0; i <= radius; i++ {
- kernel[i] = gaussianBlurKernel(float64(i), sigma)
- }
-
- return blurVertical(blurHorizontal(img, kernel), kernel)
-}
-
-func blurHorizontal(img image.Image, kernel []float64) *image.NRGBA {
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
- radius := len(kernel) - 1
-
- parallel(0, src.h, func(ys <-chan int) {
- scanLine := make([]uint8, src.w*4)
- scanLineF := make([]float64, len(scanLine))
- for y := range ys {
- src.scan(0, y, src.w, y+1, scanLine)
- for i, v := range scanLine {
- scanLineF[i] = float64(v)
- }
- for x := 0; x < src.w; x++ {
- min := x - radius
- if min < 0 {
- min = 0
- }
- max := x + radius
- if max > src.w-1 {
- max = src.w - 1
- }
- var r, g, b, a, wsum float64
- for ix := min; ix <= max; ix++ {
- i := ix * 4
- weight := kernel[absint(x-ix)]
- wsum += weight
- s := scanLineF[i : i+4 : i+4]
- wa := s[3] * weight
- r += s[0] * wa
- g += s[1] * wa
- b += s[2] * wa
- a += wa
- }
- if a != 0 {
- aInv := 1 / a
- j := y*dst.Stride + x*4
- d := dst.Pix[j : j+4 : j+4]
- d[0] = clamp(r * aInv)
- d[1] = clamp(g * aInv)
- d[2] = clamp(b * aInv)
- d[3] = clamp(a / wsum)
- }
- }
- }
- })
-
- return dst
-}
-
-func blurVertical(img image.Image, kernel []float64) *image.NRGBA {
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
- radius := len(kernel) - 1
-
- parallel(0, src.w, func(xs <-chan int) {
- scanLine := make([]uint8, src.h*4)
- scanLineF := make([]float64, len(scanLine))
- for x := range xs {
- src.scan(x, 0, x+1, src.h, scanLine)
- for i, v := range scanLine {
- scanLineF[i] = float64(v)
- }
- for y := 0; y < src.h; y++ {
- min := y - radius
- if min < 0 {
- min = 0
- }
- max := y + radius
- if max > src.h-1 {
- max = src.h - 1
- }
- var r, g, b, a, wsum float64
- for iy := min; iy <= max; iy++ {
- i := iy * 4
- weight := kernel[absint(y-iy)]
- wsum += weight
- s := scanLineF[i : i+4 : i+4]
- wa := s[3] * weight
- r += s[0] * wa
- g += s[1] * wa
- b += s[2] * wa
- a += wa
- }
- if a != 0 {
- aInv := 1 / a
- j := y*dst.Stride + x*4
- d := dst.Pix[j : j+4 : j+4]
- d[0] = clamp(r * aInv)
- d[1] = clamp(g * aInv)
- d[2] = clamp(b * aInv)
- d[3] = clamp(a / wsum)
- }
- }
- }
- })
-
- return dst
-}
-
-// Sharpen produces a sharpened version of the image.
-// Sigma parameter must be positive and indicates how much the image will be sharpened.
-//
-// Example:
-//
-// dstImage := imaging.Sharpen(srcImage, 3.5)
-//
-func Sharpen(img image.Image, sigma float64) *image.NRGBA {
- if sigma <= 0 {
- return Clone(img)
- }
-
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
- blurred := Blur(img, sigma)
-
- parallel(0, src.h, func(ys <-chan int) {
- scanLine := make([]uint8, src.w*4)
- for y := range ys {
- src.scan(0, y, src.w, y+1, scanLine)
- j := y * dst.Stride
- for i := 0; i < src.w*4; i++ {
- val := int(scanLine[i])<<1 - int(blurred.Pix[j])
- if val < 0 {
- val = 0
- } else if val > 0xff {
- val = 0xff
- }
- dst.Pix[j] = uint8(val)
- j++
- }
- }
- })
-
- return dst
-}
diff --git a/vendor/github.com/disintegration/imaging/histogram.go b/vendor/github.com/disintegration/imaging/histogram.go
deleted file mode 100644
index c547fe822..000000000
--- a/vendor/github.com/disintegration/imaging/histogram.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package imaging
-
-import (
- "image"
- "sync"
-)
-
-// Histogram returns a normalized histogram of an image.
-//
-// Resulting histogram is represented as an array of 256 floats, where
-// histogram[i] is a probability of a pixel being of a particular luminance i.
-func Histogram(img image.Image) [256]float64 {
- var mu sync.Mutex
- var histogram [256]float64
- var total float64
-
- src := newScanner(img)
- if src.w == 0 || src.h == 0 {
- return histogram
- }
-
- parallel(0, src.h, func(ys <-chan int) {
- var tmpHistogram [256]float64
- var tmpTotal float64
- scanLine := make([]uint8, src.w*4)
- for y := range ys {
- src.scan(0, y, src.w, y+1, scanLine)
- i := 0
- for x := 0; x < src.w; x++ {
- s := scanLine[i : i+3 : i+3]
- r := s[0]
- g := s[1]
- b := s[2]
- y := 0.299*float32(r) + 0.587*float32(g) + 0.114*float32(b)
- tmpHistogram[int(y+0.5)]++
- tmpTotal++
- i += 4
- }
- }
- mu.Lock()
- for i := 0; i < 256; i++ {
- histogram[i] += tmpHistogram[i]
- }
- total += tmpTotal
- mu.Unlock()
- })
-
- for i := 0; i < 256; i++ {
- histogram[i] = histogram[i] / total
- }
- return histogram
-}
diff --git a/vendor/github.com/disintegration/imaging/io.go b/vendor/github.com/disintegration/imaging/io.go
deleted file mode 100644
index f6c6da86b..000000000
--- a/vendor/github.com/disintegration/imaging/io.go
+++ /dev/null
@@ -1,444 +0,0 @@
-package imaging
-
-import (
- "encoding/binary"
- "errors"
- "image"
- "image/draw"
- "image/gif"
- "image/jpeg"
- "image/png"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
-
- "golang.org/x/image/bmp"
- "golang.org/x/image/tiff"
-)
-
-type fileSystem interface {
- Create(string) (io.WriteCloser, error)
- Open(string) (io.ReadCloser, error)
-}
-
-type localFS struct{}
-
-func (localFS) Create(name string) (io.WriteCloser, error) { return os.Create(name) }
-func (localFS) Open(name string) (io.ReadCloser, error) { return os.Open(name) }
-
-var fs fileSystem = localFS{}
-
-type decodeConfig struct {
- autoOrientation bool
-}
-
-var defaultDecodeConfig = decodeConfig{
- autoOrientation: false,
-}
-
-// DecodeOption sets an optional parameter for the Decode and Open functions.
-type DecodeOption func(*decodeConfig)
-
-// AutoOrientation returns a DecodeOption that sets the auto-orientation mode.
-// If auto-orientation is enabled, the image will be transformed after decoding
-// according to the EXIF orientation tag (if present). By default it's disabled.
-func AutoOrientation(enabled bool) DecodeOption {
- return func(c *decodeConfig) {
- c.autoOrientation = enabled
- }
-}
-
-// Decode reads an image from r.
-func Decode(r io.Reader, opts ...DecodeOption) (image.Image, error) {
- cfg := defaultDecodeConfig
- for _, option := range opts {
- option(&cfg)
- }
-
- if !cfg.autoOrientation {
- img, _, err := image.Decode(r)
- return img, err
- }
-
- var orient orientation
- pr, pw := io.Pipe()
- r = io.TeeReader(r, pw)
- done := make(chan struct{})
- go func() {
- defer close(done)
- orient = readOrientation(pr)
- io.Copy(ioutil.Discard, pr)
- }()
-
- img, _, err := image.Decode(r)
- pw.Close()
- <-done
- if err != nil {
- return nil, err
- }
-
- return fixOrientation(img, orient), nil
-}
-
-// Open loads an image from file.
-//
-// Examples:
-//
-// // Load an image from file.
-// img, err := imaging.Open("test.jpg")
-//
-// // Load an image and transform it depending on the EXIF orientation tag (if present).
-// img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true))
-//
-func Open(filename string, opts ...DecodeOption) (image.Image, error) {
- file, err := fs.Open(filename)
- if err != nil {
- return nil, err
- }
- defer file.Close()
- return Decode(file, opts...)
-}
-
-// Format is an image file format.
-type Format int
-
-// Image file formats.
-const (
- JPEG Format = iota
- PNG
- GIF
- TIFF
- BMP
-)
-
-var formatExts = map[string]Format{
- "jpg": JPEG,
- "jpeg": JPEG,
- "png": PNG,
- "gif": GIF,
- "tif": TIFF,
- "tiff": TIFF,
- "bmp": BMP,
-}
-
-var formatNames = map[Format]string{
- JPEG: "JPEG",
- PNG: "PNG",
- GIF: "GIF",
- TIFF: "TIFF",
- BMP: "BMP",
-}
-
-func (f Format) String() string {
- return formatNames[f]
-}
-
-// ErrUnsupportedFormat means the given image format is not supported.
-var ErrUnsupportedFormat = errors.New("imaging: unsupported image format")
-
-// FormatFromExtension parses image format from filename extension:
-// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
-func FormatFromExtension(ext string) (Format, error) {
- if f, ok := formatExts[strings.ToLower(strings.TrimPrefix(ext, "."))]; ok {
- return f, nil
- }
- return -1, ErrUnsupportedFormat
-}
-
-// FormatFromFilename parses image format from filename:
-// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
-func FormatFromFilename(filename string) (Format, error) {
- ext := filepath.Ext(filename)
- return FormatFromExtension(ext)
-}
-
-type encodeConfig struct {
- jpegQuality int
- gifNumColors int
- gifQuantizer draw.Quantizer
- gifDrawer draw.Drawer
- pngCompressionLevel png.CompressionLevel
-}
-
-var defaultEncodeConfig = encodeConfig{
- jpegQuality: 95,
- gifNumColors: 256,
- gifQuantizer: nil,
- gifDrawer: nil,
- pngCompressionLevel: png.DefaultCompression,
-}
-
-// EncodeOption sets an optional parameter for the Encode and Save functions.
-type EncodeOption func(*encodeConfig)
-
-// JPEGQuality returns an EncodeOption that sets the output JPEG quality.
-// Quality ranges from 1 to 100 inclusive, higher is better. Default is 95.
-func JPEGQuality(quality int) EncodeOption {
- return func(c *encodeConfig) {
- c.jpegQuality = quality
- }
-}
-
-// GIFNumColors returns an EncodeOption that sets the maximum number of colors
-// used in the GIF-encoded image. It ranges from 1 to 256. Default is 256.
-func GIFNumColors(numColors int) EncodeOption {
- return func(c *encodeConfig) {
- c.gifNumColors = numColors
- }
-}
-
-// GIFQuantizer returns an EncodeOption that sets the quantizer that is used to produce
-// a palette of the GIF-encoded image.
-func GIFQuantizer(quantizer draw.Quantizer) EncodeOption {
- return func(c *encodeConfig) {
- c.gifQuantizer = quantizer
- }
-}
-
-// GIFDrawer returns an EncodeOption that sets the drawer that is used to convert
-// the source image to the desired palette of the GIF-encoded image.
-func GIFDrawer(drawer draw.Drawer) EncodeOption {
- return func(c *encodeConfig) {
- c.gifDrawer = drawer
- }
-}
-
-// PNGCompressionLevel returns an EncodeOption that sets the compression level
-// of the PNG-encoded image. Default is png.DefaultCompression.
-func PNGCompressionLevel(level png.CompressionLevel) EncodeOption {
- return func(c *encodeConfig) {
- c.pngCompressionLevel = level
- }
-}
-
-// Encode writes the image img to w in the specified format (JPEG, PNG, GIF, TIFF or BMP).
-func Encode(w io.Writer, img image.Image, format Format, opts ...EncodeOption) error {
- cfg := defaultEncodeConfig
- for _, option := range opts {
- option(&cfg)
- }
-
- switch format {
- case JPEG:
- if nrgba, ok := img.(*image.NRGBA); ok && nrgba.Opaque() {
- rgba := &image.RGBA{
- Pix: nrgba.Pix,
- Stride: nrgba.Stride,
- Rect: nrgba.Rect,
- }
- return jpeg.Encode(w, rgba, &jpeg.Options{Quality: cfg.jpegQuality})
- }
- return jpeg.Encode(w, img, &jpeg.Options{Quality: cfg.jpegQuality})
-
- case PNG:
- encoder := png.Encoder{CompressionLevel: cfg.pngCompressionLevel}
- return encoder.Encode(w, img)
-
- case GIF:
- return gif.Encode(w, img, &gif.Options{
- NumColors: cfg.gifNumColors,
- Quantizer: cfg.gifQuantizer,
- Drawer: cfg.gifDrawer,
- })
-
- case TIFF:
- return tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true})
-
- case BMP:
- return bmp.Encode(w, img)
- }
-
- return ErrUnsupportedFormat
-}
-
-// Save saves the image to file with the specified filename.
-// The format is determined from the filename extension:
-// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
-//
-// Examples:
-//
-// // Save the image as PNG.
-// err := imaging.Save(img, "out.png")
-//
-// // Save the image as JPEG with optional quality parameter set to 80.
-// err := imaging.Save(img, "out.jpg", imaging.JPEGQuality(80))
-//
-func Save(img image.Image, filename string, opts ...EncodeOption) (err error) {
- f, err := FormatFromFilename(filename)
- if err != nil {
- return err
- }
- file, err := fs.Create(filename)
- if err != nil {
- return err
- }
- err = Encode(file, img, f, opts...)
- errc := file.Close()
- if err == nil {
- err = errc
- }
- return err
-}
-
-// orientation is an EXIF flag that specifies the transformation
-// that should be applied to image to display it correctly.
-type orientation int
-
-const (
- orientationUnspecified = 0
- orientationNormal = 1
- orientationFlipH = 2
- orientationRotate180 = 3
- orientationFlipV = 4
- orientationTranspose = 5
- orientationRotate270 = 6
- orientationTransverse = 7
- orientationRotate90 = 8
-)
-
-// readOrientation tries to read the orientation EXIF flag from image data in r.
-// If the EXIF data block is not found or the orientation flag is not found
-// or any other error occures while reading the data, it returns the
-// orientationUnspecified (0) value.
-func readOrientation(r io.Reader) orientation {
- const (
- markerSOI = 0xffd8
- markerAPP1 = 0xffe1
- exifHeader = 0x45786966
- byteOrderBE = 0x4d4d
- byteOrderLE = 0x4949
- orientationTag = 0x0112
- )
-
- // Check if JPEG SOI marker is present.
- var soi uint16
- if err := binary.Read(r, binary.BigEndian, &soi); err != nil {
- return orientationUnspecified
- }
- if soi != markerSOI {
- return orientationUnspecified // Missing JPEG SOI marker.
- }
-
- // Find JPEG APP1 marker.
- for {
- var marker, size uint16
- if err := binary.Read(r, binary.BigEndian, &marker); err != nil {
- return orientationUnspecified
- }
- if err := binary.Read(r, binary.BigEndian, &size); err != nil {
- return orientationUnspecified
- }
- if marker>>8 != 0xff {
- return orientationUnspecified // Invalid JPEG marker.
- }
- if marker == markerAPP1 {
- break
- }
- if size < 2 {
- return orientationUnspecified // Invalid block size.
- }
- if _, err := io.CopyN(ioutil.Discard, r, int64(size-2)); err != nil {
- return orientationUnspecified
- }
- }
-
- // Check if EXIF header is present.
- var header uint32
- if err := binary.Read(r, binary.BigEndian, &header); err != nil {
- return orientationUnspecified
- }
- if header != exifHeader {
- return orientationUnspecified
- }
- if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil {
- return orientationUnspecified
- }
-
- // Read byte order information.
- var (
- byteOrderTag uint16
- byteOrder binary.ByteOrder
- )
- if err := binary.Read(r, binary.BigEndian, &byteOrderTag); err != nil {
- return orientationUnspecified
- }
- switch byteOrderTag {
- case byteOrderBE:
- byteOrder = binary.BigEndian
- case byteOrderLE:
- byteOrder = binary.LittleEndian
- default:
- return orientationUnspecified // Invalid byte order flag.
- }
- if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil {
- return orientationUnspecified
- }
-
- // Skip the EXIF offset.
- var offset uint32
- if err := binary.Read(r, byteOrder, &offset); err != nil {
- return orientationUnspecified
- }
- if offset < 8 {
- return orientationUnspecified // Invalid offset value.
- }
- if _, err := io.CopyN(ioutil.Discard, r, int64(offset-8)); err != nil {
- return orientationUnspecified
- }
-
- // Read the number of tags.
- var numTags uint16
- if err := binary.Read(r, byteOrder, &numTags); err != nil {
- return orientationUnspecified
- }
-
- // Find the orientation tag.
- for i := 0; i < int(numTags); i++ {
- var tag uint16
- if err := binary.Read(r, byteOrder, &tag); err != nil {
- return orientationUnspecified
- }
- if tag != orientationTag {
- if _, err := io.CopyN(ioutil.Discard, r, 10); err != nil {
- return orientationUnspecified
- }
- continue
- }
- if _, err := io.CopyN(ioutil.Discard, r, 6); err != nil {
- return orientationUnspecified
- }
- var val uint16
- if err := binary.Read(r, byteOrder, &val); err != nil {
- return orientationUnspecified
- }
- if val < 1 || val > 8 {
- return orientationUnspecified // Invalid tag value.
- }
- return orientation(val)
- }
- return orientationUnspecified // Missing orientation tag.
-}
-
-// fixOrientation applies a transform to img corresponding to the given orientation flag.
-func fixOrientation(img image.Image, o orientation) image.Image {
- switch o {
- case orientationNormal:
- case orientationFlipH:
- img = FlipH(img)
- case orientationFlipV:
- img = FlipV(img)
- case orientationRotate90:
- img = Rotate90(img)
- case orientationRotate180:
- img = Rotate180(img)
- case orientationRotate270:
- img = Rotate270(img)
- case orientationTranspose:
- img = Transpose(img)
- case orientationTransverse:
- img = Transverse(img)
- }
- return img
-}
diff --git a/vendor/github.com/disintegration/imaging/resize.go b/vendor/github.com/disintegration/imaging/resize.go
deleted file mode 100644
index 706435e3d..000000000
--- a/vendor/github.com/disintegration/imaging/resize.go
+++ /dev/null
@@ -1,595 +0,0 @@
-package imaging
-
-import (
- "image"
- "math"
-)
-
-type indexWeight struct {
- index int
- weight float64
-}
-
-func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWeight {
- du := float64(srcSize) / float64(dstSize)
- scale := du
- if scale < 1.0 {
- scale = 1.0
- }
- ru := math.Ceil(scale * filter.Support)
-
- out := make([][]indexWeight, dstSize)
- tmp := make([]indexWeight, 0, dstSize*int(ru+2)*2)
-
- for v := 0; v < dstSize; v++ {
- fu := (float64(v)+0.5)*du - 0.5
-
- begin := int(math.Ceil(fu - ru))
- if begin < 0 {
- begin = 0
- }
- end := int(math.Floor(fu + ru))
- if end > srcSize-1 {
- end = srcSize - 1
- }
-
- var sum float64
- for u := begin; u <= end; u++ {
- w := filter.Kernel((float64(u) - fu) / scale)
- if w != 0 {
- sum += w
- tmp = append(tmp, indexWeight{index: u, weight: w})
- }
- }
- if sum != 0 {
- for i := range tmp {
- tmp[i].weight /= sum
- }
- }
-
- out[v] = tmp
- tmp = tmp[len(tmp):]
- }
-
- return out
-}
-
-// Resize resizes the image to the specified width and height using the specified resampling
-// filter and returns the transformed image. If one of width or height is 0, the image aspect
-// ratio is preserved.
-//
-// Example:
-//
-// dstImage := imaging.Resize(srcImage, 800, 600, imaging.Lanczos)
-//
-func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA {
- dstW, dstH := width, height
- if dstW < 0 || dstH < 0 {
- return &image.NRGBA{}
- }
- if dstW == 0 && dstH == 0 {
- return &image.NRGBA{}
- }
-
- srcW := img.Bounds().Dx()
- srcH := img.Bounds().Dy()
- if srcW <= 0 || srcH <= 0 {
- return &image.NRGBA{}
- }
-
- // If new width or height is 0 then preserve aspect ratio, minimum 1px.
- if dstW == 0 {
- tmpW := float64(dstH) * float64(srcW) / float64(srcH)
- dstW = int(math.Max(1.0, math.Floor(tmpW+0.5)))
- }
- if dstH == 0 {
- tmpH := float64(dstW) * float64(srcH) / float64(srcW)
- dstH = int(math.Max(1.0, math.Floor(tmpH+0.5)))
- }
-
- if filter.Support <= 0 {
- // Nearest-neighbor special case.
- return resizeNearest(img, dstW, dstH)
- }
-
- if srcW != dstW && srcH != dstH {
- return resizeVertical(resizeHorizontal(img, dstW, filter), dstH, filter)
- }
- if srcW != dstW {
- return resizeHorizontal(img, dstW, filter)
- }
- if srcH != dstH {
- return resizeVertical(img, dstH, filter)
- }
- return Clone(img)
-}
-
-func resizeHorizontal(img image.Image, width int, filter ResampleFilter) *image.NRGBA {
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, width, src.h))
- weights := precomputeWeights(width, src.w, filter)
- parallel(0, src.h, func(ys <-chan int) {
- scanLine := make([]uint8, src.w*4)
- for y := range ys {
- src.scan(0, y, src.w, y+1, scanLine)
- j0 := y * dst.Stride
- for x := range weights {
- var r, g, b, a float64
- for _, w := range weights[x] {
- i := w.index * 4
- s := scanLine[i : i+4 : i+4]
- aw := float64(s[3]) * w.weight
- r += float64(s[0]) * aw
- g += float64(s[1]) * aw
- b += float64(s[2]) * aw
- a += aw
- }
- if a != 0 {
- aInv := 1 / a
- j := j0 + x*4
- d := dst.Pix[j : j+4 : j+4]
- d[0] = clamp(r * aInv)
- d[1] = clamp(g * aInv)
- d[2] = clamp(b * aInv)
- d[3] = clamp(a)
- }
- }
- }
- })
- return dst
-}
-
-func resizeVertical(img image.Image, height int, filter ResampleFilter) *image.NRGBA {
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, src.w, height))
- weights := precomputeWeights(height, src.h, filter)
- parallel(0, src.w, func(xs <-chan int) {
- scanLine := make([]uint8, src.h*4)
- for x := range xs {
- src.scan(x, 0, x+1, src.h, scanLine)
- for y := range weights {
- var r, g, b, a float64
- for _, w := range weights[y] {
- i := w.index * 4
- s := scanLine[i : i+4 : i+4]
- aw := float64(s[3]) * w.weight
- r += float64(s[0]) * aw
- g += float64(s[1]) * aw
- b += float64(s[2]) * aw
- a += aw
- }
- if a != 0 {
- aInv := 1 / a
- j := y*dst.Stride + x*4
- d := dst.Pix[j : j+4 : j+4]
- d[0] = clamp(r * aInv)
- d[1] = clamp(g * aInv)
- d[2] = clamp(b * aInv)
- d[3] = clamp(a)
- }
- }
- }
- })
- return dst
-}
-
-// resizeNearest is a fast nearest-neighbor resize, no filtering.
-func resizeNearest(img image.Image, width, height int) *image.NRGBA {
- dst := image.NewNRGBA(image.Rect(0, 0, width, height))
- dx := float64(img.Bounds().Dx()) / float64(width)
- dy := float64(img.Bounds().Dy()) / float64(height)
-
- if dx > 1 && dy > 1 {
- src := newScanner(img)
- parallel(0, height, func(ys <-chan int) {
- for y := range ys {
- srcY := int((float64(y) + 0.5) * dy)
- dstOff := y * dst.Stride
- for x := 0; x < width; x++ {
- srcX := int((float64(x) + 0.5) * dx)
- src.scan(srcX, srcY, srcX+1, srcY+1, dst.Pix[dstOff:dstOff+4])
- dstOff += 4
- }
- }
- })
- } else {
- src := toNRGBA(img)
- parallel(0, height, func(ys <-chan int) {
- for y := range ys {
- srcY := int((float64(y) + 0.5) * dy)
- srcOff0 := srcY * src.Stride
- dstOff := y * dst.Stride
- for x := 0; x < width; x++ {
- srcX := int((float64(x) + 0.5) * dx)
- srcOff := srcOff0 + srcX*4
- copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4])
- dstOff += 4
- }
- }
- })
- }
-
- return dst
-}
-
-// Fit scales down the image using the specified resample filter to fit the specified
-// maximum width and height and returns the transformed image.
-//
-// Example:
-//
-// dstImage := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
-//
-func Fit(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA {
- maxW, maxH := width, height
-
- if maxW <= 0 || maxH <= 0 {
- return &image.NRGBA{}
- }
-
- srcBounds := img.Bounds()
- srcW := srcBounds.Dx()
- srcH := srcBounds.Dy()
-
- if srcW <= 0 || srcH <= 0 {
- return &image.NRGBA{}
- }
-
- if srcW <= maxW && srcH <= maxH {
- return Clone(img)
- }
-
- srcAspectRatio := float64(srcW) / float64(srcH)
- maxAspectRatio := float64(maxW) / float64(maxH)
-
- var newW, newH int
- if srcAspectRatio > maxAspectRatio {
- newW = maxW
- newH = int(float64(newW) / srcAspectRatio)
- } else {
- newH = maxH
- newW = int(float64(newH) * srcAspectRatio)
- }
-
- return Resize(img, newW, newH, filter)
-}
-
-// Fill creates an image with the specified dimensions and fills it with the scaled source image.
-// To achieve the correct aspect ratio without stretching, the source image will be cropped.
-//
-// Example:
-//
-// dstImage := imaging.Fill(srcImage, 800, 600, imaging.Center, imaging.Lanczos)
-//
-func Fill(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA {
- dstW, dstH := width, height
-
- if dstW <= 0 || dstH <= 0 {
- return &image.NRGBA{}
- }
-
- srcBounds := img.Bounds()
- srcW := srcBounds.Dx()
- srcH := srcBounds.Dy()
-
- if srcW <= 0 || srcH <= 0 {
- return &image.NRGBA{}
- }
-
- if srcW == dstW && srcH == dstH {
- return Clone(img)
- }
-
- if srcW >= 100 && srcH >= 100 {
- return cropAndResize(img, dstW, dstH, anchor, filter)
- }
- return resizeAndCrop(img, dstW, dstH, anchor, filter)
-}
-
-// cropAndResize crops the image to the smallest possible size that has the required aspect ratio using
-// the given anchor point, then scales it to the specified dimensions and returns the transformed image.
-//
-// This is generally faster than resizing first, but may result in inaccuracies when used on small source images.
-func cropAndResize(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA {
- dstW, dstH := width, height
-
- srcBounds := img.Bounds()
- srcW := srcBounds.Dx()
- srcH := srcBounds.Dy()
- srcAspectRatio := float64(srcW) / float64(srcH)
- dstAspectRatio := float64(dstW) / float64(dstH)
-
- var tmp *image.NRGBA
- if srcAspectRatio < dstAspectRatio {
- cropH := float64(srcW) * float64(dstH) / float64(dstW)
- tmp = CropAnchor(img, srcW, int(math.Max(1, cropH)+0.5), anchor)
- } else {
- cropW := float64(srcH) * float64(dstW) / float64(dstH)
- tmp = CropAnchor(img, int(math.Max(1, cropW)+0.5), srcH, anchor)
- }
-
- return Resize(tmp, dstW, dstH, filter)
-}
-
-// resizeAndCrop resizes the image to the smallest possible size that will cover the specified dimensions,
-// crops the resized image to the specified dimensions using the given anchor point and returns
-// the transformed image.
-func resizeAndCrop(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA {
- dstW, dstH := width, height
-
- srcBounds := img.Bounds()
- srcW := srcBounds.Dx()
- srcH := srcBounds.Dy()
- srcAspectRatio := float64(srcW) / float64(srcH)
- dstAspectRatio := float64(dstW) / float64(dstH)
-
- var tmp *image.NRGBA
- if srcAspectRatio < dstAspectRatio {
- tmp = Resize(img, dstW, 0, filter)
- } else {
- tmp = Resize(img, 0, dstH, filter)
- }
-
- return CropAnchor(tmp, dstW, dstH, anchor)
-}
-
-// Thumbnail scales the image up or down using the specified resample filter, crops it
-// to the specified width and hight and returns the transformed image.
-//
-// Example:
-//
-// dstImage := imaging.Thumbnail(srcImage, 100, 100, imaging.Lanczos)
-//
-func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA {
- return Fill(img, width, height, Center, filter)
-}
-
-// ResampleFilter specifies a resampling filter to be used for image resizing.
-//
-// General filter recommendations:
-//
-// - Lanczos
-// A high-quality resampling filter for photographic images yielding sharp results.
-//
-// - CatmullRom
-// A sharp cubic filter that is faster than Lanczos filter while providing similar results.
-//
-// - MitchellNetravali
-// A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.
-//
-// - Linear
-// Bilinear resampling filter, produces a smooth output. Faster than cubic filters.
-//
-// - Box
-// Simple and fast averaging filter appropriate for downscaling.
-// When upscaling it's similar to NearestNeighbor.
-//
-// - NearestNeighbor
-// Fastest resampling filter, no antialiasing.
-//
-type ResampleFilter struct {
- Support float64
- Kernel func(float64) float64
-}
-
-// NearestNeighbor is a nearest-neighbor filter (no anti-aliasing).
-var NearestNeighbor ResampleFilter
-
-// Box filter (averaging pixels).
-var Box ResampleFilter
-
-// Linear filter.
-var Linear ResampleFilter
-
-// Hermite cubic spline filter (BC-spline; B=0; C=0).
-var Hermite ResampleFilter
-
-// MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
-var MitchellNetravali ResampleFilter
-
-// CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
-var CatmullRom ResampleFilter
-
-// BSpline is a smooth cubic filter (BC-spline; B=1; C=0).
-var BSpline ResampleFilter
-
-// Gaussian is a Gaussian blurring filter.
-var Gaussian ResampleFilter
-
-// Bartlett is a Bartlett-windowed sinc filter (3 lobes).
-var Bartlett ResampleFilter
-
-// Lanczos filter (3 lobes).
-var Lanczos ResampleFilter
-
-// Hann is a Hann-windowed sinc filter (3 lobes).
-var Hann ResampleFilter
-
-// Hamming is a Hamming-windowed sinc filter (3 lobes).
-var Hamming ResampleFilter
-
-// Blackman is a Blackman-windowed sinc filter (3 lobes).
-var Blackman ResampleFilter
-
-// Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes).
-var Welch ResampleFilter
-
-// Cosine is a Cosine-windowed sinc filter (3 lobes).
-var Cosine ResampleFilter
-
-func bcspline(x, b, c float64) float64 {
- var y float64
- x = math.Abs(x)
- if x < 1.0 {
- y = ((12-9*b-6*c)*x*x*x + (-18+12*b+6*c)*x*x + (6 - 2*b)) / 6
- } else if x < 2.0 {
- y = ((-b-6*c)*x*x*x + (6*b+30*c)*x*x + (-12*b-48*c)*x + (8*b + 24*c)) / 6
- }
- return y
-}
-
-func sinc(x float64) float64 {
- if x == 0 {
- return 1
- }
- return math.Sin(math.Pi*x) / (math.Pi * x)
-}
-
-func init() {
- NearestNeighbor = ResampleFilter{
- Support: 0.0, // special case - not applying the filter
- }
-
- Box = ResampleFilter{
- Support: 0.5,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x <= 0.5 {
- return 1.0
- }
- return 0
- },
- }
-
- Linear = ResampleFilter{
- Support: 1.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 1.0 {
- return 1.0 - x
- }
- return 0
- },
- }
-
- Hermite = ResampleFilter{
- Support: 1.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 1.0 {
- return bcspline(x, 0.0, 0.0)
- }
- return 0
- },
- }
-
- MitchellNetravali = ResampleFilter{
- Support: 2.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 2.0 {
- return bcspline(x, 1.0/3.0, 1.0/3.0)
- }
- return 0
- },
- }
-
- CatmullRom = ResampleFilter{
- Support: 2.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 2.0 {
- return bcspline(x, 0.0, 0.5)
- }
- return 0
- },
- }
-
- BSpline = ResampleFilter{
- Support: 2.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 2.0 {
- return bcspline(x, 1.0, 0.0)
- }
- return 0
- },
- }
-
- Gaussian = ResampleFilter{
- Support: 2.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 2.0 {
- return math.Exp(-2 * x * x)
- }
- return 0
- },
- }
-
- Bartlett = ResampleFilter{
- Support: 3.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 3.0 {
- return sinc(x) * (3.0 - x) / 3.0
- }
- return 0
- },
- }
-
- Lanczos = ResampleFilter{
- Support: 3.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 3.0 {
- return sinc(x) * sinc(x/3.0)
- }
- return 0
- },
- }
-
- Hann = ResampleFilter{
- Support: 3.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 3.0 {
- return sinc(x) * (0.5 + 0.5*math.Cos(math.Pi*x/3.0))
- }
- return 0
- },
- }
-
- Hamming = ResampleFilter{
- Support: 3.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 3.0 {
- return sinc(x) * (0.54 + 0.46*math.Cos(math.Pi*x/3.0))
- }
- return 0
- },
- }
-
- Blackman = ResampleFilter{
- Support: 3.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 3.0 {
- return sinc(x) * (0.42 - 0.5*math.Cos(math.Pi*x/3.0+math.Pi) + 0.08*math.Cos(2.0*math.Pi*x/3.0))
- }
- return 0
- },
- }
-
- Welch = ResampleFilter{
- Support: 3.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 3.0 {
- return sinc(x) * (1.0 - (x * x / 9.0))
- }
- return 0
- },
- }
-
- Cosine = ResampleFilter{
- Support: 3.0,
- Kernel: func(x float64) float64 {
- x = math.Abs(x)
- if x < 3.0 {
- return sinc(x) * math.Cos((math.Pi/2.0)*(x/3.0))
- }
- return 0
- },
- }
-}
diff --git a/vendor/github.com/disintegration/imaging/scanner.go b/vendor/github.com/disintegration/imaging/scanner.go
deleted file mode 100644
index 37d92cef8..000000000
--- a/vendor/github.com/disintegration/imaging/scanner.go
+++ /dev/null
@@ -1,285 +0,0 @@
-package imaging
-
-import (
- "image"
- "image/color"
-)
-
-type scanner struct {
- image image.Image
- w, h int
- palette []color.NRGBA
-}
-
-func newScanner(img image.Image) *scanner {
- s := &scanner{
- image: img,
- w: img.Bounds().Dx(),
- h: img.Bounds().Dy(),
- }
- if img, ok := img.(*image.Paletted); ok {
- s.palette = make([]color.NRGBA, len(img.Palette))
- for i := 0; i < len(img.Palette); i++ {
- s.palette[i] = color.NRGBAModel.Convert(img.Palette[i]).(color.NRGBA)
- }
- }
- return s
-}
-
-// scan scans the given rectangular region of the image into dst.
-func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) {
- switch img := s.image.(type) {
- case *image.NRGBA:
- size := (x2 - x1) * 4
- j := 0
- i := y1*img.Stride + x1*4
- if size == 4 {
- for y := y1; y < y2; y++ {
- d := dst[j : j+4 : j+4]
- s := img.Pix[i : i+4 : i+4]
- d[0] = s[0]
- d[1] = s[1]
- d[2] = s[2]
- d[3] = s[3]
- j += size
- i += img.Stride
- }
- } else {
- for y := y1; y < y2; y++ {
- copy(dst[j:j+size], img.Pix[i:i+size])
- j += size
- i += img.Stride
- }
- }
-
- case *image.NRGBA64:
- j := 0
- for y := y1; y < y2; y++ {
- i := y*img.Stride + x1*8
- for x := x1; x < x2; x++ {
- s := img.Pix[i : i+8 : i+8]
- d := dst[j : j+4 : j+4]
- d[0] = s[0]
- d[1] = s[2]
- d[2] = s[4]
- d[3] = s[6]
- j += 4
- i += 8
- }
- }
-
- case *image.RGBA:
- j := 0
- for y := y1; y < y2; y++ {
- i := y*img.Stride + x1*4
- for x := x1; x < x2; x++ {
- d := dst[j : j+4 : j+4]
- a := img.Pix[i+3]
- switch a {
- case 0:
- d[0] = 0
- d[1] = 0
- d[2] = 0
- d[3] = a
- case 0xff:
- s := img.Pix[i : i+4 : i+4]
- d[0] = s[0]
- d[1] = s[1]
- d[2] = s[2]
- d[3] = a
- default:
- s := img.Pix[i : i+4 : i+4]
- r16 := uint16(s[0])
- g16 := uint16(s[1])
- b16 := uint16(s[2])
- a16 := uint16(a)
- d[0] = uint8(r16 * 0xff / a16)
- d[1] = uint8(g16 * 0xff / a16)
- d[2] = uint8(b16 * 0xff / a16)
- d[3] = a
- }
- j += 4
- i += 4
- }
- }
-
- case *image.RGBA64:
- j := 0
- for y := y1; y < y2; y++ {
- i := y*img.Stride + x1*8
- for x := x1; x < x2; x++ {
- s := img.Pix[i : i+8 : i+8]
- d := dst[j : j+4 : j+4]
- a := s[6]
- switch a {
- case 0:
- d[0] = 0
- d[1] = 0
- d[2] = 0
- case 0xff:
- d[0] = s[0]
- d[1] = s[2]
- d[2] = s[4]
- default:
- r32 := uint32(s[0])<<8 | uint32(s[1])
- g32 := uint32(s[2])<<8 | uint32(s[3])
- b32 := uint32(s[4])<<8 | uint32(s[5])
- a32 := uint32(s[6])<<8 | uint32(s[7])
- d[0] = uint8((r32 * 0xffff / a32) >> 8)
- d[1] = uint8((g32 * 0xffff / a32) >> 8)
- d[2] = uint8((b32 * 0xffff / a32) >> 8)
- }
- d[3] = a
- j += 4
- i += 8
- }
- }
-
- case *image.Gray:
- j := 0
- for y := y1; y < y2; y++ {
- i := y*img.Stride + x1
- for x := x1; x < x2; x++ {
- c := img.Pix[i]
- d := dst[j : j+4 : j+4]
- d[0] = c
- d[1] = c
- d[2] = c
- d[3] = 0xff
- j += 4
- i++
- }
- }
-
- case *image.Gray16:
- j := 0
- for y := y1; y < y2; y++ {
- i := y*img.Stride + x1*2
- for x := x1; x < x2; x++ {
- c := img.Pix[i]
- d := dst[j : j+4 : j+4]
- d[0] = c
- d[1] = c
- d[2] = c
- d[3] = 0xff
- j += 4
- i += 2
- }
- }
-
- case *image.YCbCr:
- j := 0
- x1 += img.Rect.Min.X
- x2 += img.Rect.Min.X
- y1 += img.Rect.Min.Y
- y2 += img.Rect.Min.Y
-
- hy := img.Rect.Min.Y / 2
- hx := img.Rect.Min.X / 2
- for y := y1; y < y2; y++ {
- iy := (y-img.Rect.Min.Y)*img.YStride + (x1 - img.Rect.Min.X)
-
- var yBase int
- switch img.SubsampleRatio {
- case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio422:
- yBase = (y - img.Rect.Min.Y) * img.CStride
- case image.YCbCrSubsampleRatio420, image.YCbCrSubsampleRatio440:
- yBase = (y/2 - hy) * img.CStride
- }
-
- for x := x1; x < x2; x++ {
- var ic int
- switch img.SubsampleRatio {
- case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio440:
- ic = yBase + (x - img.Rect.Min.X)
- case image.YCbCrSubsampleRatio422, image.YCbCrSubsampleRatio420:
- ic = yBase + (x/2 - hx)
- default:
- ic = img.COffset(x, y)
- }
-
- yy1 := int32(img.Y[iy]) * 0x10101
- cb1 := int32(img.Cb[ic]) - 128
- cr1 := int32(img.Cr[ic]) - 128
-
- r := yy1 + 91881*cr1
- if uint32(r)&0xff000000 == 0 {
- r >>= 16
- } else {
- r = ^(r >> 31)
- }
-
- g := yy1 - 22554*cb1 - 46802*cr1
- if uint32(g)&0xff000000 == 0 {
- g >>= 16
- } else {
- g = ^(g >> 31)
- }
-
- b := yy1 + 116130*cb1
- if uint32(b)&0xff000000 == 0 {
- b >>= 16
- } else {
- b = ^(b >> 31)
- }
-
- d := dst[j : j+4 : j+4]
- d[0] = uint8(r)
- d[1] = uint8(g)
- d[2] = uint8(b)
- d[3] = 0xff
-
- iy++
- j += 4
- }
- }
-
- case *image.Paletted:
- j := 0
- for y := y1; y < y2; y++ {
- i := y*img.Stride + x1
- for x := x1; x < x2; x++ {
- c := s.palette[img.Pix[i]]
- d := dst[j : j+4 : j+4]
- d[0] = c.R
- d[1] = c.G
- d[2] = c.B
- d[3] = c.A
- j += 4
- i++
- }
- }
-
- default:
- j := 0
- b := s.image.Bounds()
- x1 += b.Min.X
- x2 += b.Min.X
- y1 += b.Min.Y
- y2 += b.Min.Y
- for y := y1; y < y2; y++ {
- for x := x1; x < x2; x++ {
- r16, g16, b16, a16 := s.image.At(x, y).RGBA()
- d := dst[j : j+4 : j+4]
- switch a16 {
- case 0xffff:
- d[0] = uint8(r16 >> 8)
- d[1] = uint8(g16 >> 8)
- d[2] = uint8(b16 >> 8)
- d[3] = 0xff
- case 0:
- d[0] = 0
- d[1] = 0
- d[2] = 0
- d[3] = 0
- default:
- d[0] = uint8(((r16 * 0xffff) / a16) >> 8)
- d[1] = uint8(((g16 * 0xffff) / a16) >> 8)
- d[2] = uint8(((b16 * 0xffff) / a16) >> 8)
- d[3] = uint8(a16 >> 8)
- }
- j += 4
- }
- }
- }
-}
diff --git a/vendor/github.com/disintegration/imaging/tools.go b/vendor/github.com/disintegration/imaging/tools.go
deleted file mode 100644
index 0ec19a039..000000000
--- a/vendor/github.com/disintegration/imaging/tools.go
+++ /dev/null
@@ -1,249 +0,0 @@
-package imaging
-
-import (
- "bytes"
- "image"
- "image/color"
- "math"
-)
-
-// New creates a new image with the specified width and height, and fills it with the specified color.
-func New(width, height int, fillColor color.Color) *image.NRGBA {
- if width <= 0 || height <= 0 {
- return &image.NRGBA{}
- }
-
- c := color.NRGBAModel.Convert(fillColor).(color.NRGBA)
- if (c == color.NRGBA{0, 0, 0, 0}) {
- return image.NewNRGBA(image.Rect(0, 0, width, height))
- }
-
- return &image.NRGBA{
- Pix: bytes.Repeat([]byte{c.R, c.G, c.B, c.A}, width*height),
- Stride: 4 * width,
- Rect: image.Rect(0, 0, width, height),
- }
-}
-
-// Clone returns a copy of the given image.
-func Clone(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
- size := src.w * 4
- parallel(0, src.h, func(ys <-chan int) {
- for y := range ys {
- i := y * dst.Stride
- src.scan(0, y, src.w, y+1, dst.Pix[i:i+size])
- }
- })
- return dst
-}
-
-// Anchor is the anchor point for image alignment.
-type Anchor int
-
-// Anchor point positions.
-const (
- Center Anchor = iota
- TopLeft
- Top
- TopRight
- Left
- Right
- BottomLeft
- Bottom
- BottomRight
-)
-
-func anchorPt(b image.Rectangle, w, h int, anchor Anchor) image.Point {
- var x, y int
- switch anchor {
- case TopLeft:
- x = b.Min.X
- y = b.Min.Y
- case Top:
- x = b.Min.X + (b.Dx()-w)/2
- y = b.Min.Y
- case TopRight:
- x = b.Max.X - w
- y = b.Min.Y
- case Left:
- x = b.Min.X
- y = b.Min.Y + (b.Dy()-h)/2
- case Right:
- x = b.Max.X - w
- y = b.Min.Y + (b.Dy()-h)/2
- case BottomLeft:
- x = b.Min.X
- y = b.Max.Y - h
- case Bottom:
- x = b.Min.X + (b.Dx()-w)/2
- y = b.Max.Y - h
- case BottomRight:
- x = b.Max.X - w
- y = b.Max.Y - h
- default:
- x = b.Min.X + (b.Dx()-w)/2
- y = b.Min.Y + (b.Dy()-h)/2
- }
- return image.Pt(x, y)
-}
-
-// Crop cuts out a rectangular region with the specified bounds
-// from the image and returns the cropped image.
-func Crop(img image.Image, rect image.Rectangle) *image.NRGBA {
- r := rect.Intersect(img.Bounds()).Sub(img.Bounds().Min)
- if r.Empty() {
- return &image.NRGBA{}
- }
- src := newScanner(img)
- dst := image.NewNRGBA(image.Rect(0, 0, r.Dx(), r.Dy()))
- rowSize := r.Dx() * 4
- parallel(r.Min.Y, r.Max.Y, func(ys <-chan int) {
- for y := range ys {
- i := (y - r.Min.Y) * dst.Stride
- src.scan(r.Min.X, y, r.Max.X, y+1, dst.Pix[i:i+rowSize])
- }
- })
- return dst
-}
-
-// CropAnchor cuts out a rectangular region with the specified size
-// from the image using the specified anchor point and returns the cropped image.
-func CropAnchor(img image.Image, width, height int, anchor Anchor) *image.NRGBA {
- srcBounds := img.Bounds()
- pt := anchorPt(srcBounds, width, height, anchor)
- r := image.Rect(0, 0, width, height).Add(pt)
- b := srcBounds.Intersect(r)
- return Crop(img, b)
-}
-
-// CropCenter cuts out a rectangular region with the specified size
-// from the center of the image and returns the cropped image.
-func CropCenter(img image.Image, width, height int) *image.NRGBA {
- return CropAnchor(img, width, height, Center)
-}
-
-// Paste pastes the img image to the background image at the specified position and returns the combined image.
-func Paste(background, img image.Image, pos image.Point) *image.NRGBA {
- dst := Clone(background)
- pos = pos.Sub(background.Bounds().Min)
- pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())}
- interRect := pasteRect.Intersect(dst.Bounds())
- if interRect.Empty() {
- return dst
- }
- src := newScanner(img)
- parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) {
- for y := range ys {
- x1 := interRect.Min.X - pasteRect.Min.X
- x2 := interRect.Max.X - pasteRect.Min.X
- y1 := y - pasteRect.Min.Y
- y2 := y1 + 1
- i1 := y*dst.Stride + interRect.Min.X*4
- i2 := i1 + interRect.Dx()*4
- src.scan(x1, y1, x2, y2, dst.Pix[i1:i2])
- }
- })
- return dst
-}
-
-// PasteCenter pastes the img image to the center of the background image and returns the combined image.
-func PasteCenter(background, img image.Image) *image.NRGBA {
- bgBounds := background.Bounds()
- bgW := bgBounds.Dx()
- bgH := bgBounds.Dy()
- bgMinX := bgBounds.Min.X
- bgMinY := bgBounds.Min.Y
-
- centerX := bgMinX + bgW/2
- centerY := bgMinY + bgH/2
-
- x0 := centerX - img.Bounds().Dx()/2
- y0 := centerY - img.Bounds().Dy()/2
-
- return Paste(background, img, image.Pt(x0, y0))
-}
-
-// Overlay draws the img image over the background image at given position
-// and returns the combined image. Opacity parameter is the opacity of the img
-// image layer, used to compose the images, it must be from 0.0 to 1.0.
-//
-// Examples:
-//
-// // Draw spriteImage over backgroundImage at the given position (x=50, y=50).
-// dstImage := imaging.Overlay(backgroundImage, spriteImage, image.Pt(50, 50), 1.0)
-//
-// // Blend two opaque images of the same size.
-// dstImage := imaging.Overlay(imageOne, imageTwo, image.Pt(0, 0), 0.5)
-//
-func Overlay(background, img image.Image, pos image.Point, opacity float64) *image.NRGBA {
- opacity = math.Min(math.Max(opacity, 0.0), 1.0) // Ensure 0.0 <= opacity <= 1.0.
- dst := Clone(background)
- pos = pos.Sub(background.Bounds().Min)
- pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())}
- interRect := pasteRect.Intersect(dst.Bounds())
- if interRect.Empty() {
- return dst
- }
- src := newScanner(img)
- parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) {
- scanLine := make([]uint8, interRect.Dx()*4)
- for y := range ys {
- x1 := interRect.Min.X - pasteRect.Min.X
- x2 := interRect.Max.X - pasteRect.Min.X
- y1 := y - pasteRect.Min.Y
- y2 := y1 + 1
- src.scan(x1, y1, x2, y2, scanLine)
- i := y*dst.Stride + interRect.Min.X*4
- j := 0
- for x := interRect.Min.X; x < interRect.Max.X; x++ {
- d := dst.Pix[i : i+4 : i+4]
- r1 := float64(d[0])
- g1 := float64(d[1])
- b1 := float64(d[2])
- a1 := float64(d[3])
-
- s := scanLine[j : j+4 : j+4]
- r2 := float64(s[0])
- g2 := float64(s[1])
- b2 := float64(s[2])
- a2 := float64(s[3])
-
- coef2 := opacity * a2 / 255
- coef1 := (1 - coef2) * a1 / 255
- coefSum := coef1 + coef2
- coef1 /= coefSum
- coef2 /= coefSum
-
- d[0] = uint8(r1*coef1 + r2*coef2)
- d[1] = uint8(g1*coef1 + g2*coef2)
- d[2] = uint8(b1*coef1 + b2*coef2)
- d[3] = uint8(math.Min(a1+a2*opacity*(255-a1)/255, 255))
-
- i += 4
- j += 4
- }
- }
- })
- return dst
-}
-
-// OverlayCenter overlays the img image to the center of the background image and
-// returns the combined image. Opacity parameter is the opacity of the img
-// image layer, used to compose the images, it must be from 0.0 to 1.0.
-func OverlayCenter(background, img image.Image, opacity float64) *image.NRGBA {
- bgBounds := background.Bounds()
- bgW := bgBounds.Dx()
- bgH := bgBounds.Dy()
- bgMinX := bgBounds.Min.X
- bgMinY := bgBounds.Min.Y
-
- centerX := bgMinX + bgW/2
- centerY := bgMinY + bgH/2
-
- x0 := centerX - img.Bounds().Dx()/2
- y0 := centerY - img.Bounds().Dy()/2
-
- return Overlay(background, img, image.Point{x0, y0}, opacity)
-}
diff --git a/vendor/github.com/disintegration/imaging/transform.go b/vendor/github.com/disintegration/imaging/transform.go
deleted file mode 100644
index fe4a92f9d..000000000
--- a/vendor/github.com/disintegration/imaging/transform.go
+++ /dev/null
@@ -1,268 +0,0 @@
-package imaging
-
-import (
- "image"
- "image/color"
- "math"
-)
-
-// FlipH flips the image horizontally (from left to right) and returns the transformed image.
-func FlipH(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dstW := src.w
- dstH := src.h
- rowSize := dstW * 4
- dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
- parallel(0, dstH, func(ys <-chan int) {
- for dstY := range ys {
- i := dstY * dst.Stride
- srcY := dstY
- src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
- reverse(dst.Pix[i : i+rowSize])
- }
- })
- return dst
-}
-
-// FlipV flips the image vertically (from top to bottom) and returns the transformed image.
-func FlipV(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dstW := src.w
- dstH := src.h
- rowSize := dstW * 4
- dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
- parallel(0, dstH, func(ys <-chan int) {
- for dstY := range ys {
- i := dstY * dst.Stride
- srcY := dstH - dstY - 1
- src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
- }
- })
- return dst
-}
-
-// Transpose flips the image horizontally and rotates 90 degrees counter-clockwise.
-func Transpose(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dstW := src.h
- dstH := src.w
- rowSize := dstW * 4
- dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
- parallel(0, dstH, func(ys <-chan int) {
- for dstY := range ys {
- i := dstY * dst.Stride
- srcX := dstY
- src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
- }
- })
- return dst
-}
-
-// Transverse flips the image vertically and rotates 90 degrees counter-clockwise.
-func Transverse(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dstW := src.h
- dstH := src.w
- rowSize := dstW * 4
- dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
- parallel(0, dstH, func(ys <-chan int) {
- for dstY := range ys {
- i := dstY * dst.Stride
- srcX := dstH - dstY - 1
- src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
- reverse(dst.Pix[i : i+rowSize])
- }
- })
- return dst
-}
-
-// Rotate90 rotates the image 90 degrees counter-clockwise and returns the transformed image.
-func Rotate90(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dstW := src.h
- dstH := src.w
- rowSize := dstW * 4
- dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
- parallel(0, dstH, func(ys <-chan int) {
- for dstY := range ys {
- i := dstY * dst.Stride
- srcX := dstH - dstY - 1
- src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
- }
- })
- return dst
-}
-
-// Rotate180 rotates the image 180 degrees counter-clockwise and returns the transformed image.
-func Rotate180(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dstW := src.w
- dstH := src.h
- rowSize := dstW * 4
- dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
- parallel(0, dstH, func(ys <-chan int) {
- for dstY := range ys {
- i := dstY * dst.Stride
- srcY := dstH - dstY - 1
- src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
- reverse(dst.Pix[i : i+rowSize])
- }
- })
- return dst
-}
-
-// Rotate270 rotates the image 270 degrees counter-clockwise and returns the transformed image.
-func Rotate270(img image.Image) *image.NRGBA {
- src := newScanner(img)
- dstW := src.h
- dstH := src.w
- rowSize := dstW * 4
- dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
- parallel(0, dstH, func(ys <-chan int) {
- for dstY := range ys {
- i := dstY * dst.Stride
- srcX := dstY
- src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
- reverse(dst.Pix[i : i+rowSize])
- }
- })
- return dst
-}
-
-// Rotate rotates an image by the given angle counter-clockwise .
-// The angle parameter is the rotation angle in degrees.
-// The bgColor parameter specifies the color of the uncovered zone after the rotation.
-func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA {
- angle = angle - math.Floor(angle/360)*360
-
- switch angle {
- case 0:
- return Clone(img)
- case 90:
- return Rotate90(img)
- case 180:
- return Rotate180(img)
- case 270:
- return Rotate270(img)
- }
-
- src := toNRGBA(img)
- srcW := src.Bounds().Max.X
- srcH := src.Bounds().Max.Y
- dstW, dstH := rotatedSize(srcW, srcH, angle)
- dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
-
- if dstW <= 0 || dstH <= 0 {
- return dst
- }
-
- srcXOff := float64(srcW)/2 - 0.5
- srcYOff := float64(srcH)/2 - 0.5
- dstXOff := float64(dstW)/2 - 0.5
- dstYOff := float64(dstH)/2 - 0.5
-
- bgColorNRGBA := color.NRGBAModel.Convert(bgColor).(color.NRGBA)
- sin, cos := math.Sincos(math.Pi * angle / 180)
-
- parallel(0, dstH, func(ys <-chan int) {
- for dstY := range ys {
- for dstX := 0; dstX < dstW; dstX++ {
- xf, yf := rotatePoint(float64(dstX)-dstXOff, float64(dstY)-dstYOff, sin, cos)
- xf, yf = xf+srcXOff, yf+srcYOff
- interpolatePoint(dst, dstX, dstY, src, xf, yf, bgColorNRGBA)
- }
- }
- })
-
- return dst
-}
-
-func rotatePoint(x, y, sin, cos float64) (float64, float64) {
- return x*cos - y*sin, x*sin + y*cos
-}
-
-func rotatedSize(w, h int, angle float64) (int, int) {
- if w <= 0 || h <= 0 {
- return 0, 0
- }
-
- sin, cos := math.Sincos(math.Pi * angle / 180)
- x1, y1 := rotatePoint(float64(w-1), 0, sin, cos)
- x2, y2 := rotatePoint(float64(w-1), float64(h-1), sin, cos)
- x3, y3 := rotatePoint(0, float64(h-1), sin, cos)
-
- minx := math.Min(x1, math.Min(x2, math.Min(x3, 0)))
- maxx := math.Max(x1, math.Max(x2, math.Max(x3, 0)))
- miny := math.Min(y1, math.Min(y2, math.Min(y3, 0)))
- maxy := math.Max(y1, math.Max(y2, math.Max(y3, 0)))
-
- neww := maxx - minx + 1
- if neww-math.Floor(neww) > 0.1 {
- neww++
- }
- newh := maxy - miny + 1
- if newh-math.Floor(newh) > 0.1 {
- newh++
- }
-
- return int(neww), int(newh)
-}
-
-func interpolatePoint(dst *image.NRGBA, dstX, dstY int, src *image.NRGBA, xf, yf float64, bgColor color.NRGBA) {
- j := dstY*dst.Stride + dstX*4
- d := dst.Pix[j : j+4 : j+4]
-
- x0 := int(math.Floor(xf))
- y0 := int(math.Floor(yf))
- bounds := src.Bounds()
- if !image.Pt(x0, y0).In(image.Rect(bounds.Min.X-1, bounds.Min.Y-1, bounds.Max.X, bounds.Max.Y)) {
- d[0] = bgColor.R
- d[1] = bgColor.G
- d[2] = bgColor.B
- d[3] = bgColor.A
- return
- }
-
- xq := xf - float64(x0)
- yq := yf - float64(y0)
- points := [4]image.Point{
- {x0, y0},
- {x0 + 1, y0},
- {x0, y0 + 1},
- {x0 + 1, y0 + 1},
- }
- weights := [4]float64{
- (1 - xq) * (1 - yq),
- xq * (1 - yq),
- (1 - xq) * yq,
- xq * yq,
- }
-
- var r, g, b, a float64
- for i := 0; i < 4; i++ {
- p := points[i]
- w := weights[i]
- if p.In(bounds) {
- i := p.Y*src.Stride + p.X*4
- s := src.Pix[i : i+4 : i+4]
- wa := float64(s[3]) * w
- r += float64(s[0]) * wa
- g += float64(s[1]) * wa
- b += float64(s[2]) * wa
- a += wa
- } else {
- wa := float64(bgColor.A) * w
- r += float64(bgColor.R) * wa
- g += float64(bgColor.G) * wa
- b += float64(bgColor.B) * wa
- a += wa
- }
- }
- if a != 0 {
- aInv := 1 / a
- d[0] = clamp(r * aInv)
- d[1] = clamp(g * aInv)
- d[2] = clamp(b * aInv)
- d[3] = clamp(a)
- }
-}
diff --git a/vendor/github.com/disintegration/imaging/utils.go b/vendor/github.com/disintegration/imaging/utils.go
deleted file mode 100644
index 6c7af1a51..000000000
--- a/vendor/github.com/disintegration/imaging/utils.go
+++ /dev/null
@@ -1,167 +0,0 @@
-package imaging
-
-import (
- "image"
- "math"
- "runtime"
- "sync"
-)
-
-// parallel processes the data in separate goroutines.
-func parallel(start, stop int, fn func(<-chan int)) {
- count := stop - start
- if count < 1 {
- return
- }
-
- procs := runtime.GOMAXPROCS(0)
- if procs > count {
- procs = count
- }
-
- c := make(chan int, count)
- for i := start; i < stop; i++ {
- c <- i
- }
- close(c)
-
- var wg sync.WaitGroup
- for i := 0; i < procs; i++ {
- wg.Add(1)
- go func() {
- defer wg.Done()
- fn(c)
- }()
- }
- wg.Wait()
-}
-
-// absint returns the absolute value of i.
-func absint(i int) int {
- if i < 0 {
- return -i
- }
- return i
-}
-
-// clamp rounds and clamps float64 value to fit into uint8.
-func clamp(x float64) uint8 {
- v := int64(x + 0.5)
- if v > 255 {
- return 255
- }
- if v > 0 {
- return uint8(v)
- }
- return 0
-}
-
-func reverse(pix []uint8) {
- if len(pix) <= 4 {
- return
- }
- i := 0
- j := len(pix) - 4
- for i < j {
- pi := pix[i : i+4 : i+4]
- pj := pix[j : j+4 : j+4]
- pi[0], pj[0] = pj[0], pi[0]
- pi[1], pj[1] = pj[1], pi[1]
- pi[2], pj[2] = pj[2], pi[2]
- pi[3], pj[3] = pj[3], pi[3]
- i += 4
- j -= 4
- }
-}
-
-func toNRGBA(img image.Image) *image.NRGBA {
- if img, ok := img.(*image.NRGBA); ok {
- return &image.NRGBA{
- Pix: img.Pix,
- Stride: img.Stride,
- Rect: img.Rect.Sub(img.Rect.Min),
- }
- }
- return Clone(img)
-}
-
-// rgbToHSL converts a color from RGB to HSL.
-func rgbToHSL(r, g, b uint8) (float64, float64, float64) {
- rr := float64(r) / 255
- gg := float64(g) / 255
- bb := float64(b) / 255
-
- max := math.Max(rr, math.Max(gg, bb))
- min := math.Min(rr, math.Min(gg, bb))
-
- l := (max + min) / 2
-
- if max == min {
- return 0, 0, l
- }
-
- var h, s float64
- d := max - min
- if l > 0.5 {
- s = d / (2 - max - min)
- } else {
- s = d / (max + min)
- }
-
- switch max {
- case rr:
- h = (gg - bb) / d
- if g < b {
- h += 6
- }
- case gg:
- h = (bb-rr)/d + 2
- case bb:
- h = (rr-gg)/d + 4
- }
- h /= 6
-
- return h, s, l
-}
-
-// hslToRGB converts a color from HSL to RGB.
-func hslToRGB(h, s, l float64) (uint8, uint8, uint8) {
- var r, g, b float64
- if s == 0 {
- v := clamp(l * 255)
- return v, v, v
- }
-
- var q float64
- if l < 0.5 {
- q = l * (1 + s)
- } else {
- q = l + s - l*s
- }
- p := 2*l - q
-
- r = hueToRGB(p, q, h+1/3.0)
- g = hueToRGB(p, q, h)
- b = hueToRGB(p, q, h-1/3.0)
-
- return clamp(r * 255), clamp(g * 255), clamp(b * 255)
-}
-
-func hueToRGB(p, q, t float64) float64 {
- if t < 0 {
- t++
- }
- if t > 1 {
- t--
- }
- if t < 1/6.0 {
- return p + (q-p)*6*t
- }
- if t < 1/2.0 {
- return q
- }
- if t < 2/3.0 {
- return p + (q-p)*(2/3.0-t)*6
- }
- return p
-}
diff --git a/vendor/golang.org/x/image/bmp/reader.go b/vendor/golang.org/x/image/bmp/reader.go
deleted file mode 100644
index 1939c1120..000000000
--- a/vendor/golang.org/x/image/bmp/reader.go
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package bmp implements a BMP image decoder and encoder.
-//
-// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html.
-package bmp // import "golang.org/x/image/bmp"
-
-import (
- "errors"
- "image"
- "image/color"
- "io"
-)
-
-// ErrUnsupported means that the input BMP image uses a valid but unsupported
-// feature.
-var ErrUnsupported = errors.New("bmp: unsupported BMP image")
-
-func readUint16(b []byte) uint16 {
- return uint16(b[0]) | uint16(b[1])<<8
-}
-
-func readUint32(b []byte) uint32 {
- return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-}
-
-// decodePaletted reads an 8 bit-per-pixel BMP image from r.
-// If topDown is false, the image rows will be read bottom-up.
-func decodePaletted(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
- paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette))
- if c.Width == 0 || c.Height == 0 {
- return paletted, nil
- }
- var tmp [4]byte
- y0, y1, yDelta := c.Height-1, -1, -1
- if topDown {
- y0, y1, yDelta = 0, c.Height, +1
- }
- for y := y0; y != y1; y += yDelta {
- p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width]
- if _, err := io.ReadFull(r, p); err != nil {
- return nil, err
- }
- // Each row is 4-byte aligned.
- if c.Width%4 != 0 {
- _, err := io.ReadFull(r, tmp[:4-c.Width%4])
- if err != nil {
- return nil, err
- }
- }
- }
- return paletted, nil
-}
-
-// decodeRGB reads a 24 bit-per-pixel BMP image from r.
-// If topDown is false, the image rows will be read bottom-up.
-func decodeRGB(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
- rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height))
- if c.Width == 0 || c.Height == 0 {
- return rgba, nil
- }
- // There are 3 bytes per pixel, and each row is 4-byte aligned.
- b := make([]byte, (3*c.Width+3)&^3)
- y0, y1, yDelta := c.Height-1, -1, -1
- if topDown {
- y0, y1, yDelta = 0, c.Height, +1
- }
- for y := y0; y != y1; y += yDelta {
- if _, err := io.ReadFull(r, b); err != nil {
- return nil, err
- }
- p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
- for i, j := 0, 0; i < len(p); i, j = i+4, j+3 {
- // BMP images are stored in BGR order rather than RGB order.
- p[i+0] = b[j+2]
- p[i+1] = b[j+1]
- p[i+2] = b[j+0]
- p[i+3] = 0xFF
- }
- }
- return rgba, nil
-}
-
-// decodeNRGBA reads a 32 bit-per-pixel BMP image from r.
-// If topDown is false, the image rows will be read bottom-up.
-func decodeNRGBA(r io.Reader, c image.Config, topDown, allowAlpha bool) (image.Image, error) {
- rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height))
- if c.Width == 0 || c.Height == 0 {
- return rgba, nil
- }
- y0, y1, yDelta := c.Height-1, -1, -1
- if topDown {
- y0, y1, yDelta = 0, c.Height, +1
- }
- for y := y0; y != y1; y += yDelta {
- p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
- if _, err := io.ReadFull(r, p); err != nil {
- return nil, err
- }
- for i := 0; i < len(p); i += 4 {
- // BMP images are stored in BGRA order rather than RGBA order.
- p[i+0], p[i+2] = p[i+2], p[i+0]
- if !allowAlpha {
- p[i+3] = 0xFF
- }
- }
- }
- return rgba, nil
-}
-
-// Decode reads a BMP image from r and returns it as an image.Image.
-// Limitation: The file must be 8, 24 or 32 bits per pixel.
-func Decode(r io.Reader) (image.Image, error) {
- c, bpp, topDown, allowAlpha, err := decodeConfig(r)
- if err != nil {
- return nil, err
- }
- switch bpp {
- case 8:
- return decodePaletted(r, c, topDown)
- case 24:
- return decodeRGB(r, c, topDown)
- case 32:
- return decodeNRGBA(r, c, topDown, allowAlpha)
- }
- panic("unreachable")
-}
-
-// DecodeConfig returns the color model and dimensions of a BMP image without
-// decoding the entire image.
-// Limitation: The file must be 8, 24 or 32 bits per pixel.
-func DecodeConfig(r io.Reader) (image.Config, error) {
- config, _, _, _, err := decodeConfig(r)
- return config, err
-}
-
-func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, allowAlpha bool, err error) {
- // We only support those BMP images with one of the following DIB headers:
- // - BITMAPINFOHEADER (40 bytes)
- // - BITMAPV4HEADER (108 bytes)
- // - BITMAPV5HEADER (124 bytes)
- const (
- fileHeaderLen = 14
- infoHeaderLen = 40
- v4InfoHeaderLen = 108
- v5InfoHeaderLen = 124
- )
- var b [1024]byte
- if _, err := io.ReadFull(r, b[:fileHeaderLen+4]); err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return image.Config{}, 0, false, false, err
- }
- if string(b[:2]) != "BM" {
- return image.Config{}, 0, false, false, errors.New("bmp: invalid format")
- }
- offset := readUint32(b[10:14])
- infoLen := readUint32(b[14:18])
- if infoLen != infoHeaderLen && infoLen != v4InfoHeaderLen && infoLen != v5InfoHeaderLen {
- return image.Config{}, 0, false, false, ErrUnsupported
- }
- if _, err := io.ReadFull(r, b[fileHeaderLen+4:fileHeaderLen+infoLen]); err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return image.Config{}, 0, false, false, err
- }
- width := int(int32(readUint32(b[18:22])))
- height := int(int32(readUint32(b[22:26])))
- if height < 0 {
- height, topDown = -height, true
- }
- if width < 0 || height < 0 {
- return image.Config{}, 0, false, false, ErrUnsupported
- }
- // We only support 1 plane and 8, 24 or 32 bits per pixel and no
- // compression.
- planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34])
- // if compression is set to BI_BITFIELDS, but the bitmask is set to the default bitmask
- // that would be used if compression was set to 0, we can continue as if compression was 0
- if compression == 3 && infoLen > infoHeaderLen &&
- readUint32(b[54:58]) == 0xff0000 && readUint32(b[58:62]) == 0xff00 &&
- readUint32(b[62:66]) == 0xff && readUint32(b[66:70]) == 0xff000000 {
- compression = 0
- }
- if planes != 1 || compression != 0 {
- return image.Config{}, 0, false, false, ErrUnsupported
- }
- switch bpp {
- case 8:
- colorUsed := readUint32(b[46:50])
- // If colorUsed is 0, it is set to the maximum number of colors for the given bpp, which is 2^bpp.
- if colorUsed == 0 {
- colorUsed = 256
- } else if colorUsed > 256 {
- return image.Config{}, 0, false, false, ErrUnsupported
- }
-
- if offset != fileHeaderLen+infoLen+colorUsed*4 {
- return image.Config{}, 0, false, false, ErrUnsupported
- }
- _, err = io.ReadFull(r, b[:colorUsed*4])
- if err != nil {
- return image.Config{}, 0, false, false, err
- }
- pcm := make(color.Palette, colorUsed)
- for i := range pcm {
- // BMP images are stored in BGR order rather than RGB order.
- // Every 4th byte is padding.
- pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
- }
- return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, false, nil
- case 24:
- if offset != fileHeaderLen+infoLen {
- return image.Config{}, 0, false, false, ErrUnsupported
- }
- return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, false, nil
- case 32:
- if offset != fileHeaderLen+infoLen {
- return image.Config{}, 0, false, false, ErrUnsupported
- }
- // 32 bits per pixel is possibly RGBX (X is padding) or RGBA (A is
- // alpha transparency). However, for BMP images, "Alpha is a
- // poorly-documented and inconsistently-used feature" says
- // https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc;l=621
- //
- // That goes on to say "BITMAPV3HEADER+ have an alpha bitmask in the
- // info header... so we respect it at all times... [For earlier
- // (smaller) headers we] ignore alpha in Windows V3 BMPs except inside
- // ICO files".
- //
- // "Ignore" means to always set alpha to 0xFF (fully opaque):
- // https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h;l=272
- //
- // Confusingly, "Windows V3" does not correspond to BITMAPV3HEADER, but
- // instead corresponds to the earlier (smaller) BITMAPINFOHEADER:
- // https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc;l=258
- //
- // This Go package does not support ICO files and the (infoLen >
- // infoHeaderLen) condition distinguishes BITMAPINFOHEADER (40 bytes)
- // vs later (larger) headers.
- allowAlpha = infoLen > infoHeaderLen
- return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, allowAlpha, nil
- }
- return image.Config{}, 0, false, false, ErrUnsupported
-}
-
-func init() {
- image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig)
-}
diff --git a/vendor/golang.org/x/image/bmp/writer.go b/vendor/golang.org/x/image/bmp/writer.go
deleted file mode 100644
index f07b39dba..000000000
--- a/vendor/golang.org/x/image/bmp/writer.go
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package bmp
-
-import (
- "encoding/binary"
- "errors"
- "image"
- "io"
-)
-
-type header struct {
- sigBM [2]byte
- fileSize uint32
- resverved [2]uint16
- pixOffset uint32
- dibHeaderSize uint32
- width uint32
- height uint32
- colorPlane uint16
- bpp uint16
- compression uint32
- imageSize uint32
- xPixelsPerMeter uint32
- yPixelsPerMeter uint32
- colorUse uint32
- colorImportant uint32
-}
-
-func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
- var padding []byte
- if dx < step {
- padding = make([]byte, step-dx)
- }
- for y := dy - 1; y >= 0; y-- {
- min := y*stride + 0
- max := y*stride + dx
- if _, err := w.Write(pix[min:max]); err != nil {
- return err
- }
- if padding != nil {
- if _, err := w.Write(padding); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error {
- buf := make([]byte, step)
- if opaque {
- for y := dy - 1; y >= 0; y-- {
- min := y*stride + 0
- max := y*stride + dx*4
- off := 0
- for i := min; i < max; i += 4 {
- buf[off+2] = pix[i+0]
- buf[off+1] = pix[i+1]
- buf[off+0] = pix[i+2]
- off += 3
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- } else {
- for y := dy - 1; y >= 0; y-- {
- min := y*stride + 0
- max := y*stride + dx*4
- off := 0
- for i := min; i < max; i += 4 {
- a := uint32(pix[i+3])
- if a == 0 {
- buf[off+2] = 0
- buf[off+1] = 0
- buf[off+0] = 0
- buf[off+3] = 0
- off += 4
- continue
- } else if a == 0xff {
- buf[off+2] = pix[i+0]
- buf[off+1] = pix[i+1]
- buf[off+0] = pix[i+2]
- buf[off+3] = 0xff
- off += 4
- continue
- }
- buf[off+2] = uint8(((uint32(pix[i+0]) * 0xffff) / a) >> 8)
- buf[off+1] = uint8(((uint32(pix[i+1]) * 0xffff) / a) >> 8)
- buf[off+0] = uint8(((uint32(pix[i+2]) * 0xffff) / a) >> 8)
- buf[off+3] = uint8(a)
- off += 4
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func encodeNRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error {
- buf := make([]byte, step)
- if opaque {
- for y := dy - 1; y >= 0; y-- {
- min := y*stride + 0
- max := y*stride + dx*4
- off := 0
- for i := min; i < max; i += 4 {
- buf[off+2] = pix[i+0]
- buf[off+1] = pix[i+1]
- buf[off+0] = pix[i+2]
- off += 3
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- } else {
- for y := dy - 1; y >= 0; y-- {
- min := y*stride + 0
- max := y*stride + dx*4
- off := 0
- for i := min; i < max; i += 4 {
- buf[off+2] = pix[i+0]
- buf[off+1] = pix[i+1]
- buf[off+0] = pix[i+2]
- buf[off+3] = pix[i+3]
- off += 4
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func encode(w io.Writer, m image.Image, step int) error {
- b := m.Bounds()
- buf := make([]byte, step)
- for y := b.Max.Y - 1; y >= b.Min.Y; y-- {
- off := 0
- for x := b.Min.X; x < b.Max.X; x++ {
- r, g, b, _ := m.At(x, y).RGBA()
- buf[off+2] = byte(r >> 8)
- buf[off+1] = byte(g >> 8)
- buf[off+0] = byte(b >> 8)
- off += 3
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-// Encode writes the image m to w in BMP format.
-func Encode(w io.Writer, m image.Image) error {
- d := m.Bounds().Size()
- if d.X < 0 || d.Y < 0 {
- return errors.New("bmp: negative bounds")
- }
- h := &header{
- sigBM: [2]byte{'B', 'M'},
- fileSize: 14 + 40,
- pixOffset: 14 + 40,
- dibHeaderSize: 40,
- width: uint32(d.X),
- height: uint32(d.Y),
- colorPlane: 1,
- }
-
- var step int
- var palette []byte
- var opaque bool
- switch m := m.(type) {
- case *image.Gray:
- step = (d.X + 3) &^ 3
- palette = make([]byte, 1024)
- for i := 0; i < 256; i++ {
- palette[i*4+0] = uint8(i)
- palette[i*4+1] = uint8(i)
- palette[i*4+2] = uint8(i)
- palette[i*4+3] = 0xFF
- }
- h.imageSize = uint32(d.Y * step)
- h.fileSize += uint32(len(palette)) + h.imageSize
- h.pixOffset += uint32(len(palette))
- h.bpp = 8
-
- case *image.Paletted:
- step = (d.X + 3) &^ 3
- palette = make([]byte, 1024)
- for i := 0; i < len(m.Palette) && i < 256; i++ {
- r, g, b, _ := m.Palette[i].RGBA()
- palette[i*4+0] = uint8(b >> 8)
- palette[i*4+1] = uint8(g >> 8)
- palette[i*4+2] = uint8(r >> 8)
- palette[i*4+3] = 0xFF
- }
- h.imageSize = uint32(d.Y * step)
- h.fileSize += uint32(len(palette)) + h.imageSize
- h.pixOffset += uint32(len(palette))
- h.bpp = 8
- case *image.RGBA:
- opaque = m.Opaque()
- if opaque {
- step = (3*d.X + 3) &^ 3
- h.bpp = 24
- } else {
- step = 4 * d.X
- h.bpp = 32
- }
- h.imageSize = uint32(d.Y * step)
- h.fileSize += h.imageSize
- case *image.NRGBA:
- opaque = m.Opaque()
- if opaque {
- step = (3*d.X + 3) &^ 3
- h.bpp = 24
- } else {
- step = 4 * d.X
- h.bpp = 32
- }
- h.imageSize = uint32(d.Y * step)
- h.fileSize += h.imageSize
- default:
- step = (3*d.X + 3) &^ 3
- h.imageSize = uint32(d.Y * step)
- h.fileSize += h.imageSize
- h.bpp = 24
- }
-
- if err := binary.Write(w, binary.LittleEndian, h); err != nil {
- return err
- }
- if palette != nil {
- if err := binary.Write(w, binary.LittleEndian, palette); err != nil {
- return err
- }
- }
-
- if d.X == 0 || d.Y == 0 {
- return nil
- }
-
- switch m := m.(type) {
- case *image.Gray:
- return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
- case *image.Paletted:
- return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
- case *image.RGBA:
- return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque)
- case *image.NRGBA:
- return encodeNRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque)
- }
- return encode(w, m, step)
-}
diff --git a/vendor/golang.org/x/image/ccitt/reader.go b/vendor/golang.org/x/image/ccitt/reader.go
deleted file mode 100644
index 340de0536..000000000
--- a/vendor/golang.org/x/image/ccitt/reader.go
+++ /dev/null
@@ -1,795 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:generate go run gen.go
-
-// Package ccitt implements a CCITT (fax) image decoder.
-package ccitt
-
-import (
- "encoding/binary"
- "errors"
- "image"
- "io"
- "math/bits"
-)
-
-var (
- errIncompleteCode = errors.New("ccitt: incomplete code")
- errInvalidBounds = errors.New("ccitt: invalid bounds")
- errInvalidCode = errors.New("ccitt: invalid code")
- errInvalidMode = errors.New("ccitt: invalid mode")
- errInvalidOffset = errors.New("ccitt: invalid offset")
- errMissingEOL = errors.New("ccitt: missing End-of-Line")
- errRunLengthOverflowsWidth = errors.New("ccitt: run length overflows width")
- errRunLengthTooLong = errors.New("ccitt: run length too long")
- errUnsupportedMode = errors.New("ccitt: unsupported mode")
- errUnsupportedSubFormat = errors.New("ccitt: unsupported sub-format")
- errUnsupportedWidth = errors.New("ccitt: unsupported width")
-)
-
-// Order specifies the bit ordering in a CCITT data stream.
-type Order uint32
-
-const (
- // LSB means Least Significant Bits first.
- LSB Order = iota
- // MSB means Most Significant Bits first.
- MSB
-)
-
-// SubFormat represents that the CCITT format consists of a number of
-// sub-formats. Decoding or encoding a CCITT data stream requires knowing the
-// sub-format context. It is not represented in the data stream per se.
-type SubFormat uint32
-
-const (
- Group3 SubFormat = iota
- Group4
-)
-
-// AutoDetectHeight is passed as the height argument to NewReader to indicate
-// that the image height (the number of rows) is not known in advance.
-const AutoDetectHeight = -1
-
-// Options are optional parameters.
-type Options struct {
- // Align means that some variable-bit-width codes are byte-aligned.
- Align bool
- // Invert means that black is the 1 bit or 0xFF byte, and white is 0.
- Invert bool
-}
-
-// maxWidth is the maximum (inclusive) supported width. This is a limitation of
-// this implementation, to guard against integer overflow, and not anything
-// inherent to the CCITT format.
-const maxWidth = 1 << 20
-
-func invertBytes(b []byte) {
- for i, c := range b {
- b[i] = ^c
- }
-}
-
-func reverseBitsWithinBytes(b []byte) {
- for i, c := range b {
- b[i] = bits.Reverse8(c)
- }
-}
-
-// highBits writes to dst (1 bit per pixel, most significant bit first) the
-// high (0x80) bits from src (1 byte per pixel). It returns the number of bytes
-// written and read such that dst[:d] is the packed form of src[:s].
-//
-// For example, if src starts with the 8 bytes [0x7D, 0x7E, 0x7F, 0x80, 0x81,
-// 0x82, 0x00, 0xFF] then 0x1D will be written to dst[0].
-//
-// If src has (8 * len(dst)) or more bytes then only len(dst) bytes are
-// written, (8 * len(dst)) bytes are read, and invert is ignored.
-//
-// Otherwise, if len(src) is not a multiple of 8 then the final byte written to
-// dst is padded with 1 bits (if invert is true) or 0 bits. If inverted, the 1s
-// are typically temporary, e.g. they will be flipped back to 0s by an
-// invertBytes call in the highBits caller, reader.Read.
-func highBits(dst []byte, src []byte, invert bool) (d int, s int) {
- // Pack as many complete groups of 8 src bytes as we can.
- n := len(src) / 8
- if n > len(dst) {
- n = len(dst)
- }
- dstN := dst[:n]
- for i := range dstN {
- src8 := src[i*8 : i*8+8]
- dstN[i] = ((src8[0] & 0x80) >> 0) |
- ((src8[1] & 0x80) >> 1) |
- ((src8[2] & 0x80) >> 2) |
- ((src8[3] & 0x80) >> 3) |
- ((src8[4] & 0x80) >> 4) |
- ((src8[5] & 0x80) >> 5) |
- ((src8[6] & 0x80) >> 6) |
- ((src8[7] & 0x80) >> 7)
- }
- d, s = n, 8*n
- dst, src = dst[d:], src[s:]
-
- // Pack up to 7 remaining src bytes, if there's room in dst.
- if (len(dst) > 0) && (len(src) > 0) {
- dstByte := byte(0)
- if invert {
- dstByte = 0xFF >> uint(len(src))
- }
- for n, srcByte := range src {
- dstByte |= (srcByte & 0x80) >> uint(n)
- }
- dst[0] = dstByte
- d, s = d+1, s+len(src)
- }
- return d, s
-}
-
-type bitReader struct {
- r io.Reader
-
- // readErr is the error returned from the most recent r.Read call. As the
- // io.Reader documentation says, when r.Read returns (n, err), "always
- // process the n > 0 bytes returned before considering the error err".
- readErr error
-
- // order is whether to process r's bytes LSB first or MSB first.
- order Order
-
- // The high nBits bits of the bits field hold upcoming bits in MSB order.
- bits uint64
- nBits uint32
-
- // bytes[br:bw] holds bytes read from r but not yet loaded into bits.
- br uint32
- bw uint32
- bytes [1024]uint8
-}
-
-func (b *bitReader) alignToByteBoundary() {
- n := b.nBits & 7
- b.bits <<= n
- b.nBits -= n
-}
-
-// nextBitMaxNBits is the maximum possible value of bitReader.nBits after a
-// bitReader.nextBit call, provided that bitReader.nBits was not more than this
-// value before that call.
-//
-// Note that the decode function can unread bits, which can temporarily set the
-// bitReader.nBits value above nextBitMaxNBits.
-const nextBitMaxNBits = 31
-
-func (b *bitReader) nextBit() (uint64, error) {
- for {
- if b.nBits > 0 {
- bit := b.bits >> 63
- b.bits <<= 1
- b.nBits--
- return bit, nil
- }
-
- if available := b.bw - b.br; available >= 4 {
- // Read 32 bits, even though b.bits is a uint64, since the decode
- // function may need to unread up to maxCodeLength bits, putting
- // them back in the remaining (64 - 32) bits. TestMaxCodeLength
- // checks that the generated maxCodeLength constant fits.
- //
- // If changing the Uint32 call, also change nextBitMaxNBits.
- b.bits = uint64(binary.BigEndian.Uint32(b.bytes[b.br:])) << 32
- b.br += 4
- b.nBits = 32
- continue
- } else if available > 0 {
- b.bits = uint64(b.bytes[b.br]) << (7 * 8)
- b.br++
- b.nBits = 8
- continue
- }
-
- if b.readErr != nil {
- return 0, b.readErr
- }
-
- n, err := b.r.Read(b.bytes[:])
- b.br = 0
- b.bw = uint32(n)
- b.readErr = err
-
- if b.order != MSB {
- reverseBitsWithinBytes(b.bytes[:b.bw])
- }
- }
-}
-
-func decode(b *bitReader, decodeTable [][2]int16) (uint32, error) {
- nBitsRead, bitsRead, state := uint32(0), uint64(0), int32(1)
- for {
- bit, err := b.nextBit()
- if err != nil {
- if err == io.EOF {
- err = errIncompleteCode
- }
- return 0, err
- }
- bitsRead |= bit << (63 - nBitsRead)
- nBitsRead++
-
- // The "&1" is redundant, but can eliminate a bounds check.
- state = int32(decodeTable[state][bit&1])
- if state < 0 {
- return uint32(^state), nil
- } else if state == 0 {
- // Unread the bits we've read, then return errInvalidCode.
- b.bits = (b.bits >> nBitsRead) | bitsRead
- b.nBits += nBitsRead
- return 0, errInvalidCode
- }
- }
-}
-
-// decodeEOL decodes the 12-bit EOL code 0000_0000_0001.
-func decodeEOL(b *bitReader) error {
- nBitsRead, bitsRead := uint32(0), uint64(0)
- for {
- bit, err := b.nextBit()
- if err != nil {
- if err == io.EOF {
- err = errMissingEOL
- }
- return err
- }
- bitsRead |= bit << (63 - nBitsRead)
- nBitsRead++
-
- if nBitsRead < 12 {
- if bit&1 == 0 {
- continue
- }
- } else if bit&1 != 0 {
- return nil
- }
-
- // Unread the bits we've read, then return errMissingEOL.
- b.bits = (b.bits >> nBitsRead) | bitsRead
- b.nBits += nBitsRead
- return errMissingEOL
- }
-}
-
-type reader struct {
- br bitReader
- subFormat SubFormat
-
- // width is the image width in pixels.
- width int
-
- // rowsRemaining starts at the image height in pixels, when the reader is
- // driven through the io.Reader interface, and decrements to zero as rows
- // are decoded. Alternatively, it may be negative if the image height is
- // not known in advance at the time of the NewReader call.
- //
- // When driven through DecodeIntoGray, this field is unused.
- rowsRemaining int
-
- // curr and prev hold the current and previous rows. Each element is either
- // 0x00 (black) or 0xFF (white).
- //
- // prev may be nil, when processing the first row.
- curr []byte
- prev []byte
-
- // ri is the read index. curr[:ri] are those bytes of curr that have been
- // passed along via the Read method.
- //
- // When the reader is driven through DecodeIntoGray, instead of through the
- // io.Reader interface, this field is unused.
- ri int
-
- // wi is the write index. curr[:wi] are those bytes of curr that have
- // already been decoded via the decodeRow method.
- //
- // What this implementation calls wi is roughly equivalent to what the spec
- // calls the a0 index.
- wi int
-
- // These fields are copied from the *Options (which may be nil).
- align bool
- invert bool
-
- // atStartOfRow is whether we have just started the row. Some parts of the
- // spec say to treat this situation as if "wi = -1".
- atStartOfRow bool
-
- // penColorIsWhite is whether the next run is black or white.
- penColorIsWhite bool
-
- // seenStartOfImage is whether we've called the startDecode method.
- seenStartOfImage bool
-
- // truncated is whether the input is missing the final 6 consecutive EOL's
- // (for Group3) or 2 consecutive EOL's (for Group4). Omitting that trailer
- // (but otherwise padding to a byte boundary, with either all 0 bits or all
- // 1 bits) is invalid according to the spec, but happens in practice when
- // exporting from Adobe Acrobat to TIFF + CCITT. This package silently
- // ignores the format error for CCITT input that has been truncated in that
- // fashion, returning the full decoded image.
- //
- // Detecting trailer truncation (just after the final row of pixels)
- // requires knowing which row is the final row, and therefore does not
- // trigger if the image height is not known in advance.
- truncated bool
-
- // readErr is a sticky error for the Read method.
- readErr error
-}
-
-func (z *reader) Read(p []byte) (int, error) {
- if z.readErr != nil {
- return 0, z.readErr
- }
- originalP := p
-
- for len(p) > 0 {
- // Allocate buffers (and decode any start-of-image codes), if
- // processing the first or second row.
- if z.curr == nil {
- if !z.seenStartOfImage {
- if z.readErr = z.startDecode(); z.readErr != nil {
- break
- }
- z.atStartOfRow = true
- }
- z.curr = make([]byte, z.width)
- }
-
- // Decode the next row, if necessary.
- if z.atStartOfRow {
- if z.rowsRemaining < 0 {
- // We do not know the image height in advance. See if the next
- // code is an EOL. If it is, it is consumed. If it isn't, the
- // bitReader shouldn't advance along the bit stream, and we
- // simply decode another row of pixel data.
- //
- // For the Group4 subFormat, we may need to align to a byte
- // boundary. For the Group3 subFormat, the previous z.decodeRow
- // call (or z.startDecode call) has already consumed one of the
- // 6 consecutive EOL's. The next EOL is actually the second of
- // 6, in the middle, and we shouldn't align at that point.
- if z.align && (z.subFormat == Group4) {
- z.br.alignToByteBoundary()
- }
-
- if err := z.decodeEOL(); err == errMissingEOL {
- // No-op. It's another row of pixel data.
- } else if err != nil {
- z.readErr = err
- break
- } else {
- if z.readErr = z.finishDecode(true); z.readErr != nil {
- break
- }
- z.readErr = io.EOF
- break
- }
-
- } else if z.rowsRemaining == 0 {
- // We do know the image height in advance, and we have already
- // decoded exactly that many rows.
- if z.readErr = z.finishDecode(false); z.readErr != nil {
- break
- }
- z.readErr = io.EOF
- break
-
- } else {
- z.rowsRemaining--
- }
-
- if z.readErr = z.decodeRow(z.rowsRemaining == 0); z.readErr != nil {
- break
- }
- }
-
- // Pack from z.curr (1 byte per pixel) to p (1 bit per pixel).
- packD, packS := highBits(p, z.curr[z.ri:], z.invert)
- p = p[packD:]
- z.ri += packS
-
- // Prepare to decode the next row, if necessary.
- if z.ri == len(z.curr) {
- z.ri, z.curr, z.prev = 0, z.prev, z.curr
- z.atStartOfRow = true
- }
- }
-
- n := len(originalP) - len(p)
- if z.invert {
- invertBytes(originalP[:n])
- }
- return n, z.readErr
-}
-
-func (z *reader) penColor() byte {
- if z.penColorIsWhite {
- return 0xFF
- }
- return 0x00
-}
-
-func (z *reader) startDecode() error {
- switch z.subFormat {
- case Group3:
- if err := z.decodeEOL(); err != nil {
- return err
- }
-
- case Group4:
- // No-op.
-
- default:
- return errUnsupportedSubFormat
- }
-
- z.seenStartOfImage = true
- return nil
-}
-
-func (z *reader) finishDecode(alreadySeenEOL bool) error {
- numberOfEOLs := 0
- switch z.subFormat {
- case Group3:
- if z.truncated {
- return nil
- }
- // The stream ends with a RTC (Return To Control) of 6 consecutive
- // EOL's, but we should have already just seen an EOL, either in
- // z.startDecode (for a zero-height image) or in z.decodeRow.
- numberOfEOLs = 5
-
- case Group4:
- autoDetectHeight := z.rowsRemaining < 0
- if autoDetectHeight {
- // Aligning to a byte boundary was already handled by reader.Read.
- } else if z.align {
- z.br.alignToByteBoundary()
- }
- // The stream ends with two EOL's. If the first one is missing, and we
- // had an explicit image height, we just assume that the trailing two
- // EOL's were truncated and return a nil error.
- if err := z.decodeEOL(); err != nil {
- if (err == errMissingEOL) && !autoDetectHeight {
- z.truncated = true
- return nil
- }
- return err
- }
- numberOfEOLs = 1
-
- default:
- return errUnsupportedSubFormat
- }
-
- if alreadySeenEOL {
- numberOfEOLs--
- }
- for ; numberOfEOLs > 0; numberOfEOLs-- {
- if err := z.decodeEOL(); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (z *reader) decodeEOL() error {
- return decodeEOL(&z.br)
-}
-
-func (z *reader) decodeRow(finalRow bool) error {
- z.wi = 0
- z.atStartOfRow = true
- z.penColorIsWhite = true
-
- if z.align {
- z.br.alignToByteBoundary()
- }
-
- switch z.subFormat {
- case Group3:
- for ; z.wi < len(z.curr); z.atStartOfRow = false {
- if err := z.decodeRun(); err != nil {
- return err
- }
- }
- err := z.decodeEOL()
- if finalRow && (err == errMissingEOL) {
- z.truncated = true
- return nil
- }
- return err
-
- case Group4:
- for ; z.wi < len(z.curr); z.atStartOfRow = false {
- mode, err := decode(&z.br, modeDecodeTable[:])
- if err != nil {
- return err
- }
- rm := readerMode{}
- if mode < uint32(len(readerModes)) {
- rm = readerModes[mode]
- }
- if rm.function == nil {
- return errInvalidMode
- }
- if err := rm.function(z, rm.arg); err != nil {
- return err
- }
- }
- return nil
- }
-
- return errUnsupportedSubFormat
-}
-
-func (z *reader) decodeRun() error {
- table := blackDecodeTable[:]
- if z.penColorIsWhite {
- table = whiteDecodeTable[:]
- }
-
- total := 0
- for {
- n, err := decode(&z.br, table)
- if err != nil {
- return err
- }
- if n > maxWidth {
- panic("unreachable")
- }
- total += int(n)
- if total > maxWidth {
- return errRunLengthTooLong
- }
- // Anything 0x3F or below is a terminal code.
- if n <= 0x3F {
- break
- }
- }
-
- if total > (len(z.curr) - z.wi) {
- return errRunLengthOverflowsWidth
- }
- dst := z.curr[z.wi : z.wi+total]
- penColor := z.penColor()
- for i := range dst {
- dst[i] = penColor
- }
- z.wi += total
- z.penColorIsWhite = !z.penColorIsWhite
-
- return nil
-}
-
-// The various modes' semantics are based on determining a row of pixels'
-// "changing elements": those pixels whose color differs from the one on its
-// immediate left.
-//
-// The row above the first row is implicitly all white. Similarly, the column
-// to the left of the first column is implicitly all white.
-//
-// For example, here's Figure 1 in "ITU-T Recommendation T.6", where the
-// current and previous rows contain black (B) and white (w) pixels. The a?
-// indexes point into curr, the b? indexes point into prev.
-//
-// b1 b2
-// v v
-// prev: BBBBBwwwwwBBBwwwww
-// curr: BBBwwwwwBBBBBBwwww
-// ^ ^ ^
-// a0 a1 a2
-//
-// a0 is the "reference element" or current decoder position, roughly
-// equivalent to what this implementation calls reader.wi.
-//
-// a1 is the next changing element to the right of a0, on the "coding line"
-// (the current row).
-//
-// a2 is the next changing element to the right of a1, again on curr.
-//
-// b1 is the first changing element on the "reference line" (the previous row)
-// to the right of a0 and of opposite color to a0.
-//
-// b2 is the next changing element to the right of b1, again on prev.
-//
-// The various modes calculate a1 (and a2, for modeH):
-// - modePass calculates that a1 is at or to the right of b2.
-// - modeH calculates a1 and a2 without considering b1 or b2.
-// - modeV* calculates a1 to be b1 plus an adjustment (between -3 and +3).
-
-const (
- findB1 = false
- findB2 = true
-)
-
-// findB finds either the b1 or b2 value.
-func (z *reader) findB(whichB bool) int {
- // The initial row is a special case. The previous row is implicitly all
- // white, so that there are no changing pixel elements. We return b1 or b2
- // to be at the end of the row.
- if len(z.prev) != len(z.curr) {
- return len(z.curr)
- }
-
- i := z.wi
-
- if z.atStartOfRow {
- // a0 is implicitly at -1, on a white pixel. b1 is the first black
- // pixel in the previous row. b2 is the first white pixel after that.
- for ; (i < len(z.prev)) && (z.prev[i] == 0xFF); i++ {
- }
- if whichB == findB2 {
- for ; (i < len(z.prev)) && (z.prev[i] == 0x00); i++ {
- }
- }
- return i
- }
-
- // As per figure 1 above, assume that the current pen color is white.
- // First, walk past every contiguous black pixel in prev, starting at a0.
- oppositeColor := ^z.penColor()
- for ; (i < len(z.prev)) && (z.prev[i] == oppositeColor); i++ {
- }
-
- // Then walk past every contiguous white pixel.
- penColor := ^oppositeColor
- for ; (i < len(z.prev)) && (z.prev[i] == penColor); i++ {
- }
-
- // We're now at a black pixel (or at the end of the row). That's b1.
- if whichB == findB2 {
- // If we're looking for b2, walk past every contiguous black pixel
- // again.
- oppositeColor := ^penColor
- for ; (i < len(z.prev)) && (z.prev[i] == oppositeColor); i++ {
- }
- }
-
- return i
-}
-
-type readerMode struct {
- function func(z *reader, arg int) error
- arg int
-}
-
-var readerModes = [...]readerMode{
- modePass: {function: readerModePass},
- modeH: {function: readerModeH},
- modeV0: {function: readerModeV, arg: +0},
- modeVR1: {function: readerModeV, arg: +1},
- modeVR2: {function: readerModeV, arg: +2},
- modeVR3: {function: readerModeV, arg: +3},
- modeVL1: {function: readerModeV, arg: -1},
- modeVL2: {function: readerModeV, arg: -2},
- modeVL3: {function: readerModeV, arg: -3},
- modeExt: {function: readerModeExt},
-}
-
-func readerModePass(z *reader, arg int) error {
- b2 := z.findB(findB2)
- if (b2 < z.wi) || (len(z.curr) < b2) {
- return errInvalidOffset
- }
- dst := z.curr[z.wi:b2]
- penColor := z.penColor()
- for i := range dst {
- dst[i] = penColor
- }
- z.wi = b2
- return nil
-}
-
-func readerModeH(z *reader, arg int) error {
- // The first iteration finds a1. The second finds a2.
- for i := 0; i < 2; i++ {
- if err := z.decodeRun(); err != nil {
- return err
- }
- }
- return nil
-}
-
-func readerModeV(z *reader, arg int) error {
- a1 := z.findB(findB1) + arg
- if (a1 < z.wi) || (len(z.curr) < a1) {
- return errInvalidOffset
- }
- dst := z.curr[z.wi:a1]
- penColor := z.penColor()
- for i := range dst {
- dst[i] = penColor
- }
- z.wi = a1
- z.penColorIsWhite = !z.penColorIsWhite
- return nil
-}
-
-func readerModeExt(z *reader, arg int) error {
- return errUnsupportedMode
-}
-
-// DecodeIntoGray decodes the CCITT-formatted data in r into dst.
-//
-// It returns an error if dst's width and height don't match the implied width
-// and height of CCITT-formatted data.
-func DecodeIntoGray(dst *image.Gray, r io.Reader, order Order, sf SubFormat, opts *Options) error {
- bounds := dst.Bounds()
- if (bounds.Dx() < 0) || (bounds.Dy() < 0) {
- return errInvalidBounds
- }
- if bounds.Dx() > maxWidth {
- return errUnsupportedWidth
- }
-
- z := reader{
- br: bitReader{r: r, order: order},
- subFormat: sf,
- align: (opts != nil) && opts.Align,
- invert: (opts != nil) && opts.Invert,
- width: bounds.Dx(),
- }
- if err := z.startDecode(); err != nil {
- return err
- }
-
- width := bounds.Dx()
- for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
- p := (y - bounds.Min.Y) * dst.Stride
- z.curr = dst.Pix[p : p+width]
- if err := z.decodeRow(y+1 == bounds.Max.Y); err != nil {
- return err
- }
- z.curr, z.prev = nil, z.curr
- }
-
- if err := z.finishDecode(false); err != nil {
- return err
- }
-
- if z.invert {
- for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
- p := (y - bounds.Min.Y) * dst.Stride
- invertBytes(dst.Pix[p : p+width])
- }
- }
-
- return nil
-}
-
-// NewReader returns an io.Reader that decodes the CCITT-formatted data in r.
-// The resultant byte stream is one bit per pixel (MSB first), with 1 meaning
-// white and 0 meaning black. Each row in the result is byte-aligned.
-//
-// A negative height, such as passing AutoDetectHeight, means that the image
-// height is not known in advance. A negative width is invalid.
-func NewReader(r io.Reader, order Order, sf SubFormat, width int, height int, opts *Options) io.Reader {
- readErr := error(nil)
- if width < 0 {
- readErr = errInvalidBounds
- } else if width > maxWidth {
- readErr = errUnsupportedWidth
- }
-
- return &reader{
- br: bitReader{r: r, order: order},
- subFormat: sf,
- align: (opts != nil) && opts.Align,
- invert: (opts != nil) && opts.Invert,
- width: width,
- rowsRemaining: height,
- readErr: readErr,
- }
-}
diff --git a/vendor/golang.org/x/image/ccitt/table.go b/vendor/golang.org/x/image/ccitt/table.go
deleted file mode 100644
index 8b3794bc2..000000000
--- a/vendor/golang.org/x/image/ccitt/table.go
+++ /dev/null
@@ -1,972 +0,0 @@
-// generated by "go run gen.go". DO NOT EDIT.
-
-package ccitt
-
-// Each decodeTable is represented by an array of [2]int16's: a binary tree.
-// Each array element (other than element 0, which means invalid) is a branch
-// node in that tree. The root node is always element 1 (the second element).
-//
-// To walk the tree, look at the next bit in the bit stream, using it to select
-// the first or second element of the [2]int16. If that int16 is 0, we have an
-// invalid code. If it is positive, go to that branch node. If it is negative,
-// then we have a leaf node, whose value is the bitwise complement (the ^
-// operator) of that int16.
-//
-// Comments above each decodeTable also show the same structure visually. The
-// "b123" lines show the 123'rd branch node. The "=XXXXX" lines show an invalid
-// code. The "=v1234" lines show a leaf node with value 1234. When reading the
-// bit stream, a 0 or 1 bit means to go up or down, as you move left to right.
-//
-// For example, in modeDecodeTable, branch node b005 is three steps up from the
-// root node, meaning that we have already seen "000". If the next bit is "0"
-// then we move to branch node b006. Otherwise, the next bit is "1", and we
-// move to the leaf node v0000 (also known as the modePass constant). Indeed,
-// the bits that encode modePass are "0001".
-//
-// Tables 1, 2 and 3 come from the "ITU-T Recommendation T.6: FACSIMILE CODING
-// SCHEMES AND CODING CONTROL FUNCTIONS FOR GROUP 4 FACSIMILE APPARATUS"
-// specification:
-//
-// https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.6-198811-I!!PDF-E&type=items
-
-// modeDecodeTable represents Table 1 and the End-of-Line code.
-//
-// +=XXXXX
-// b009 +-+
-// | +=v0009
-// b007 +-+
-// | | +=v0008
-// b010 | +-+
-// | +=v0005
-// b006 +-+
-// | | +=v0007
-// b008 | +-+
-// | +=v0004
-// b005 +-+
-// | +=v0000
-// b003 +-+
-// | +=v0001
-// b002 +-+
-// | | +=v0006
-// b004 | +-+
-// | +=v0003
-// b001 +-+
-// +=v0002
-var modeDecodeTable = [...][2]int16{
- 0: {0, 0},
- 1: {2, ^2},
- 2: {3, 4},
- 3: {5, ^1},
- 4: {^6, ^3},
- 5: {6, ^0},
- 6: {7, 8},
- 7: {9, 10},
- 8: {^7, ^4},
- 9: {0, ^9},
- 10: {^8, ^5},
-}
-
-// whiteDecodeTable represents Tables 2 and 3 for a white run.
-//
-// +=XXXXX
-// b059 +-+
-// | | +=v1792
-// b096 | | +-+
-// | | | | +=v1984
-// b100 | | | +-+
-// | | | +=v2048
-// b094 | | +-+
-// | | | | +=v2112
-// b101 | | | | +-+
-// | | | | | +=v2176
-// b097 | | | +-+
-// | | | | +=v2240
-// b102 | | | +-+
-// | | | +=v2304
-// b085 | +-+
-// | | +=v1856
-// b098 | | +-+
-// | | | +=v1920
-// b095 | +-+
-// | | +=v2368
-// b103 | | +-+
-// | | | +=v2432
-// b099 | +-+
-// | | +=v2496
-// b104 | +-+
-// | +=v2560
-// b040 +-+
-// | | +=v0029
-// b060 | +-+
-// | +=v0030
-// b026 +-+
-// | | +=v0045
-// b061 | | +-+
-// | | | +=v0046
-// b041 | +-+
-// | +=v0022
-// b016 +-+
-// | | +=v0023
-// b042 | | +-+
-// | | | | +=v0047
-// b062 | | | +-+
-// | | | +=v0048
-// b027 | +-+
-// | +=v0013
-// b008 +-+
-// | | +=v0020
-// b043 | | +-+
-// | | | | +=v0033
-// b063 | | | +-+
-// | | | +=v0034
-// b028 | | +-+
-// | | | | +=v0035
-// b064 | | | | +-+
-// | | | | | +=v0036
-// b044 | | | +-+
-// | | | | +=v0037
-// b065 | | | +-+
-// | | | +=v0038
-// b017 | +-+
-// | | +=v0019
-// b045 | | +-+
-// | | | | +=v0031
-// b066 | | | +-+
-// | | | +=v0032
-// b029 | +-+
-// | +=v0001
-// b004 +-+
-// | | +=v0012
-// b030 | | +-+
-// | | | | +=v0053
-// b067 | | | | +-+
-// | | | | | +=v0054
-// b046 | | | +-+
-// | | | +=v0026
-// b018 | | +-+
-// | | | | +=v0039
-// b068 | | | | +-+
-// | | | | | +=v0040
-// b047 | | | | +-+
-// | | | | | | +=v0041
-// b069 | | | | | +-+
-// | | | | | +=v0042
-// b031 | | | +-+
-// | | | | +=v0043
-// b070 | | | | +-+
-// | | | | | +=v0044
-// b048 | | | +-+
-// | | | +=v0021
-// b009 | +-+
-// | | +=v0028
-// b049 | | +-+
-// | | | | +=v0061
-// b071 | | | +-+
-// | | | +=v0062
-// b032 | | +-+
-// | | | | +=v0063
-// b072 | | | | +-+
-// | | | | | +=v0000
-// b050 | | | +-+
-// | | | | +=v0320
-// b073 | | | +-+
-// | | | +=v0384
-// b019 | +-+
-// | +=v0010
-// b002 +-+
-// | | +=v0011
-// b020 | | +-+
-// | | | | +=v0027
-// b051 | | | | +-+
-// | | | | | | +=v0059
-// b074 | | | | | +-+
-// | | | | | +=v0060
-// b033 | | | +-+
-// | | | | +=v1472
-// b086 | | | | +-+
-// | | | | | +=v1536
-// b075 | | | | +-+
-// | | | | | | +=v1600
-// b087 | | | | | +-+
-// | | | | | +=v1728
-// b052 | | | +-+
-// | | | +=v0018
-// b010 | | +-+
-// | | | | +=v0024
-// b053 | | | | +-+
-// | | | | | | +=v0049
-// b076 | | | | | +-+
-// | | | | | +=v0050
-// b034 | | | | +-+
-// | | | | | | +=v0051
-// b077 | | | | | | +-+
-// | | | | | | | +=v0052
-// b054 | | | | | +-+
-// | | | | | +=v0025
-// b021 | | | +-+
-// | | | | +=v0055
-// b078 | | | | +-+
-// | | | | | +=v0056
-// b055 | | | | +-+
-// | | | | | | +=v0057
-// b079 | | | | | +-+
-// | | | | | +=v0058
-// b035 | | | +-+
-// | | | +=v0192
-// b005 | +-+
-// | | +=v1664
-// b036 | | +-+
-// | | | | +=v0448
-// b080 | | | | +-+
-// | | | | | +=v0512
-// b056 | | | +-+
-// | | | | +=v0704
-// b088 | | | | +-+
-// | | | | | +=v0768
-// b081 | | | +-+
-// | | | +=v0640
-// b022 | | +-+
-// | | | | +=v0576
-// b082 | | | | +-+
-// | | | | | | +=v0832
-// b089 | | | | | +-+
-// | | | | | +=v0896
-// b057 | | | | +-+
-// | | | | | | +=v0960
-// b090 | | | | | | +-+
-// | | | | | | | +=v1024
-// b083 | | | | | +-+
-// | | | | | | +=v1088
-// b091 | | | | | +-+
-// | | | | | +=v1152
-// b037 | | | +-+
-// | | | | +=v1216
-// b092 | | | | +-+
-// | | | | | +=v1280
-// b084 | | | | +-+
-// | | | | | | +=v1344
-// b093 | | | | | +-+
-// | | | | | +=v1408
-// b058 | | | +-+
-// | | | +=v0256
-// b011 | +-+
-// | +=v0002
-// b001 +-+
-// | +=v0003
-// b012 | +-+
-// | | | +=v0128
-// b023 | | +-+
-// | | +=v0008
-// b006 | +-+
-// | | | +=v0009
-// b024 | | | +-+
-// | | | | | +=v0016
-// b038 | | | | +-+
-// | | | | +=v0017
-// b013 | | +-+
-// | | +=v0004
-// b003 +-+
-// | +=v0005
-// b014 | +-+
-// | | | +=v0014
-// b039 | | | +-+
-// | | | | +=v0015
-// b025 | | +-+
-// | | +=v0064
-// b007 +-+
-// | +=v0006
-// b015 +-+
-// +=v0007
-var whiteDecodeTable = [...][2]int16{
- 0: {0, 0},
- 1: {2, 3},
- 2: {4, 5},
- 3: {6, 7},
- 4: {8, 9},
- 5: {10, 11},
- 6: {12, 13},
- 7: {14, 15},
- 8: {16, 17},
- 9: {18, 19},
- 10: {20, 21},
- 11: {22, ^2},
- 12: {^3, 23},
- 13: {24, ^4},
- 14: {^5, 25},
- 15: {^6, ^7},
- 16: {26, 27},
- 17: {28, 29},
- 18: {30, 31},
- 19: {32, ^10},
- 20: {^11, 33},
- 21: {34, 35},
- 22: {36, 37},
- 23: {^128, ^8},
- 24: {^9, 38},
- 25: {39, ^64},
- 26: {40, 41},
- 27: {42, ^13},
- 28: {43, 44},
- 29: {45, ^1},
- 30: {^12, 46},
- 31: {47, 48},
- 32: {49, 50},
- 33: {51, 52},
- 34: {53, 54},
- 35: {55, ^192},
- 36: {^1664, 56},
- 37: {57, 58},
- 38: {^16, ^17},
- 39: {^14, ^15},
- 40: {59, 60},
- 41: {61, ^22},
- 42: {^23, 62},
- 43: {^20, 63},
- 44: {64, 65},
- 45: {^19, 66},
- 46: {67, ^26},
- 47: {68, 69},
- 48: {70, ^21},
- 49: {^28, 71},
- 50: {72, 73},
- 51: {^27, 74},
- 52: {75, ^18},
- 53: {^24, 76},
- 54: {77, ^25},
- 55: {78, 79},
- 56: {80, 81},
- 57: {82, 83},
- 58: {84, ^256},
- 59: {0, 85},
- 60: {^29, ^30},
- 61: {^45, ^46},
- 62: {^47, ^48},
- 63: {^33, ^34},
- 64: {^35, ^36},
- 65: {^37, ^38},
- 66: {^31, ^32},
- 67: {^53, ^54},
- 68: {^39, ^40},
- 69: {^41, ^42},
- 70: {^43, ^44},
- 71: {^61, ^62},
- 72: {^63, ^0},
- 73: {^320, ^384},
- 74: {^59, ^60},
- 75: {86, 87},
- 76: {^49, ^50},
- 77: {^51, ^52},
- 78: {^55, ^56},
- 79: {^57, ^58},
- 80: {^448, ^512},
- 81: {88, ^640},
- 82: {^576, 89},
- 83: {90, 91},
- 84: {92, 93},
- 85: {94, 95},
- 86: {^1472, ^1536},
- 87: {^1600, ^1728},
- 88: {^704, ^768},
- 89: {^832, ^896},
- 90: {^960, ^1024},
- 91: {^1088, ^1152},
- 92: {^1216, ^1280},
- 93: {^1344, ^1408},
- 94: {96, 97},
- 95: {98, 99},
- 96: {^1792, 100},
- 97: {101, 102},
- 98: {^1856, ^1920},
- 99: {103, 104},
- 100: {^1984, ^2048},
- 101: {^2112, ^2176},
- 102: {^2240, ^2304},
- 103: {^2368, ^2432},
- 104: {^2496, ^2560},
-}
-
-// blackDecodeTable represents Tables 2 and 3 for a black run.
-//
-// +=XXXXX
-// b017 +-+
-// | | +=v1792
-// b042 | | +-+
-// | | | | +=v1984
-// b063 | | | +-+
-// | | | +=v2048
-// b029 | | +-+
-// | | | | +=v2112
-// b064 | | | | +-+
-// | | | | | +=v2176
-// b043 | | | +-+
-// | | | | +=v2240
-// b065 | | | +-+
-// | | | +=v2304
-// b022 | +-+
-// | | +=v1856
-// b044 | | +-+
-// | | | +=v1920
-// b030 | +-+
-// | | +=v2368
-// b066 | | +-+
-// | | | +=v2432
-// b045 | +-+
-// | | +=v2496
-// b067 | +-+
-// | +=v2560
-// b013 +-+
-// | | +=v0018
-// b031 | | +-+
-// | | | | +=v0052
-// b068 | | | | +-+
-// | | | | | | +=v0640
-// b095 | | | | | +-+
-// | | | | | +=v0704
-// b046 | | | +-+
-// | | | | +=v0768
-// b096 | | | | +-+
-// | | | | | +=v0832
-// b069 | | | +-+
-// | | | +=v0055
-// b023 | | +-+
-// | | | | +=v0056
-// b070 | | | | +-+
-// | | | | | | +=v1280
-// b097 | | | | | +-+
-// | | | | | +=v1344
-// b047 | | | | +-+
-// | | | | | | +=v1408
-// b098 | | | | | | +-+
-// | | | | | | | +=v1472
-// b071 | | | | | +-+
-// | | | | | +=v0059
-// b032 | | | +-+
-// | | | | +=v0060
-// b072 | | | | +-+
-// | | | | | | +=v1536
-// b099 | | | | | +-+
-// | | | | | +=v1600
-// b048 | | | +-+
-// | | | +=v0024
-// b018 | +-+
-// | | +=v0025
-// b049 | | +-+
-// | | | | +=v1664
-// b100 | | | | +-+
-// | | | | | +=v1728
-// b073 | | | +-+
-// | | | +=v0320
-// b033 | | +-+
-// | | | | +=v0384
-// b074 | | | | +-+
-// | | | | | +=v0448
-// b050 | | | +-+
-// | | | | +=v0512
-// b101 | | | | +-+
-// | | | | | +=v0576
-// b075 | | | +-+
-// | | | +=v0053
-// b024 | +-+
-// | | +=v0054
-// b076 | | +-+
-// | | | | +=v0896
-// b102 | | | +-+
-// | | | +=v0960
-// b051 | | +-+
-// | | | | +=v1024
-// b103 | | | | +-+
-// | | | | | +=v1088
-// b077 | | | +-+
-// | | | | +=v1152
-// b104 | | | +-+
-// | | | +=v1216
-// b034 | +-+
-// | +=v0064
-// b010 +-+
-// | | +=v0013
-// b019 | | +-+
-// | | | | +=v0023
-// b052 | | | | +-+
-// | | | | | | +=v0050
-// b078 | | | | | +-+
-// | | | | | +=v0051
-// b035 | | | | +-+
-// | | | | | | +=v0044
-// b079 | | | | | | +-+
-// | | | | | | | +=v0045
-// b053 | | | | | +-+
-// | | | | | | +=v0046
-// b080 | | | | | +-+
-// | | | | | +=v0047
-// b025 | | | +-+
-// | | | | +=v0057
-// b081 | | | | +-+
-// | | | | | +=v0058
-// b054 | | | | +-+
-// | | | | | | +=v0061
-// b082 | | | | | +-+
-// | | | | | +=v0256
-// b036 | | | +-+
-// | | | +=v0016
-// b014 | +-+
-// | | +=v0017
-// b037 | | +-+
-// | | | | +=v0048
-// b083 | | | | +-+
-// | | | | | +=v0049
-// b055 | | | +-+
-// | | | | +=v0062
-// b084 | | | +-+
-// | | | +=v0063
-// b026 | | +-+
-// | | | | +=v0030
-// b085 | | | | +-+
-// | | | | | +=v0031
-// b056 | | | | +-+
-// | | | | | | +=v0032
-// b086 | | | | | +-+
-// | | | | | +=v0033
-// b038 | | | +-+
-// | | | | +=v0040
-// b087 | | | | +-+
-// | | | | | +=v0041
-// b057 | | | +-+
-// | | | +=v0022
-// b020 | +-+
-// | +=v0014
-// b008 +-+
-// | | +=v0010
-// b015 | | +-+
-// | | | +=v0011
-// b011 | +-+
-// | | +=v0015
-// b027 | | +-+
-// | | | | +=v0128
-// b088 | | | | +-+
-// | | | | | +=v0192
-// b058 | | | | +-+
-// | | | | | | +=v0026
-// b089 | | | | | +-+
-// | | | | | +=v0027
-// b039 | | | +-+
-// | | | | +=v0028
-// b090 | | | | +-+
-// | | | | | +=v0029
-// b059 | | | +-+
-// | | | +=v0019
-// b021 | | +-+
-// | | | | +=v0020
-// b060 | | | | +-+
-// | | | | | | +=v0034
-// b091 | | | | | +-+
-// | | | | | +=v0035
-// b040 | | | | +-+
-// | | | | | | +=v0036
-// b092 | | | | | | +-+
-// | | | | | | | +=v0037
-// b061 | | | | | +-+
-// | | | | | | +=v0038
-// b093 | | | | | +-+
-// | | | | | +=v0039
-// b028 | | | +-+
-// | | | | +=v0021
-// b062 | | | | +-+
-// | | | | | | +=v0042
-// b094 | | | | | +-+
-// | | | | | +=v0043
-// b041 | | | +-+
-// | | | +=v0000
-// b016 | +-+
-// | +=v0012
-// b006 +-+
-// | | +=v0009
-// b012 | | +-+
-// | | | +=v0008
-// b009 | +-+
-// | +=v0007
-// b004 +-+
-// | | +=v0006
-// b007 | +-+
-// | +=v0005
-// b002 +-+
-// | | +=v0001
-// b005 | +-+
-// | +=v0004
-// b001 +-+
-// | +=v0003
-// b003 +-+
-// +=v0002
-var blackDecodeTable = [...][2]int16{
- 0: {0, 0},
- 1: {2, 3},
- 2: {4, 5},
- 3: {^3, ^2},
- 4: {6, 7},
- 5: {^1, ^4},
- 6: {8, 9},
- 7: {^6, ^5},
- 8: {10, 11},
- 9: {12, ^7},
- 10: {13, 14},
- 11: {15, 16},
- 12: {^9, ^8},
- 13: {17, 18},
- 14: {19, 20},
- 15: {^10, ^11},
- 16: {21, ^12},
- 17: {0, 22},
- 18: {23, 24},
- 19: {^13, 25},
- 20: {26, ^14},
- 21: {27, 28},
- 22: {29, 30},
- 23: {31, 32},
- 24: {33, 34},
- 25: {35, 36},
- 26: {37, 38},
- 27: {^15, 39},
- 28: {40, 41},
- 29: {42, 43},
- 30: {44, 45},
- 31: {^18, 46},
- 32: {47, 48},
- 33: {49, 50},
- 34: {51, ^64},
- 35: {52, 53},
- 36: {54, ^16},
- 37: {^17, 55},
- 38: {56, 57},
- 39: {58, 59},
- 40: {60, 61},
- 41: {62, ^0},
- 42: {^1792, 63},
- 43: {64, 65},
- 44: {^1856, ^1920},
- 45: {66, 67},
- 46: {68, 69},
- 47: {70, 71},
- 48: {72, ^24},
- 49: {^25, 73},
- 50: {74, 75},
- 51: {76, 77},
- 52: {^23, 78},
- 53: {79, 80},
- 54: {81, 82},
- 55: {83, 84},
- 56: {85, 86},
- 57: {87, ^22},
- 58: {88, 89},
- 59: {90, ^19},
- 60: {^20, 91},
- 61: {92, 93},
- 62: {^21, 94},
- 63: {^1984, ^2048},
- 64: {^2112, ^2176},
- 65: {^2240, ^2304},
- 66: {^2368, ^2432},
- 67: {^2496, ^2560},
- 68: {^52, 95},
- 69: {96, ^55},
- 70: {^56, 97},
- 71: {98, ^59},
- 72: {^60, 99},
- 73: {100, ^320},
- 74: {^384, ^448},
- 75: {101, ^53},
- 76: {^54, 102},
- 77: {103, 104},
- 78: {^50, ^51},
- 79: {^44, ^45},
- 80: {^46, ^47},
- 81: {^57, ^58},
- 82: {^61, ^256},
- 83: {^48, ^49},
- 84: {^62, ^63},
- 85: {^30, ^31},
- 86: {^32, ^33},
- 87: {^40, ^41},
- 88: {^128, ^192},
- 89: {^26, ^27},
- 90: {^28, ^29},
- 91: {^34, ^35},
- 92: {^36, ^37},
- 93: {^38, ^39},
- 94: {^42, ^43},
- 95: {^640, ^704},
- 96: {^768, ^832},
- 97: {^1280, ^1344},
- 98: {^1408, ^1472},
- 99: {^1536, ^1600},
- 100: {^1664, ^1728},
- 101: {^512, ^576},
- 102: {^896, ^960},
- 103: {^1024, ^1088},
- 104: {^1152, ^1216},
-}
-
-const maxCodeLength = 13
-
-// Each encodeTable is represented by an array of bitStrings.
-
-// bitString is a pair of uint32 values representing a bit code.
-// The nBits low bits of bits make up the actual bit code.
-// Eg. bitString{0x0004, 8} represents the bitcode "00000100".
-type bitString struct {
- bits uint32
- nBits uint32
-}
-
-// modeEncodeTable represents Table 1 and the End-of-Line code.
-var modeEncodeTable = [...]bitString{
- 0: {0x0001, 4}, // "0001"
- 1: {0x0001, 3}, // "001"
- 2: {0x0001, 1}, // "1"
- 3: {0x0003, 3}, // "011"
- 4: {0x0003, 6}, // "000011"
- 5: {0x0003, 7}, // "0000011"
- 6: {0x0002, 3}, // "010"
- 7: {0x0002, 6}, // "000010"
- 8: {0x0002, 7}, // "0000010"
- 9: {0x0001, 7}, // "0000001"
-}
-
-// whiteEncodeTable2 represents Table 2 for a white run.
-var whiteEncodeTable2 = [...]bitString{
- 0: {0x0035, 8}, // "00110101"
- 1: {0x0007, 6}, // "000111"
- 2: {0x0007, 4}, // "0111"
- 3: {0x0008, 4}, // "1000"
- 4: {0x000b, 4}, // "1011"
- 5: {0x000c, 4}, // "1100"
- 6: {0x000e, 4}, // "1110"
- 7: {0x000f, 4}, // "1111"
- 8: {0x0013, 5}, // "10011"
- 9: {0x0014, 5}, // "10100"
- 10: {0x0007, 5}, // "00111"
- 11: {0x0008, 5}, // "01000"
- 12: {0x0008, 6}, // "001000"
- 13: {0x0003, 6}, // "000011"
- 14: {0x0034, 6}, // "110100"
- 15: {0x0035, 6}, // "110101"
- 16: {0x002a, 6}, // "101010"
- 17: {0x002b, 6}, // "101011"
- 18: {0x0027, 7}, // "0100111"
- 19: {0x000c, 7}, // "0001100"
- 20: {0x0008, 7}, // "0001000"
- 21: {0x0017, 7}, // "0010111"
- 22: {0x0003, 7}, // "0000011"
- 23: {0x0004, 7}, // "0000100"
- 24: {0x0028, 7}, // "0101000"
- 25: {0x002b, 7}, // "0101011"
- 26: {0x0013, 7}, // "0010011"
- 27: {0x0024, 7}, // "0100100"
- 28: {0x0018, 7}, // "0011000"
- 29: {0x0002, 8}, // "00000010"
- 30: {0x0003, 8}, // "00000011"
- 31: {0x001a, 8}, // "00011010"
- 32: {0x001b, 8}, // "00011011"
- 33: {0x0012, 8}, // "00010010"
- 34: {0x0013, 8}, // "00010011"
- 35: {0x0014, 8}, // "00010100"
- 36: {0x0015, 8}, // "00010101"
- 37: {0x0016, 8}, // "00010110"
- 38: {0x0017, 8}, // "00010111"
- 39: {0x0028, 8}, // "00101000"
- 40: {0x0029, 8}, // "00101001"
- 41: {0x002a, 8}, // "00101010"
- 42: {0x002b, 8}, // "00101011"
- 43: {0x002c, 8}, // "00101100"
- 44: {0x002d, 8}, // "00101101"
- 45: {0x0004, 8}, // "00000100"
- 46: {0x0005, 8}, // "00000101"
- 47: {0x000a, 8}, // "00001010"
- 48: {0x000b, 8}, // "00001011"
- 49: {0x0052, 8}, // "01010010"
- 50: {0x0053, 8}, // "01010011"
- 51: {0x0054, 8}, // "01010100"
- 52: {0x0055, 8}, // "01010101"
- 53: {0x0024, 8}, // "00100100"
- 54: {0x0025, 8}, // "00100101"
- 55: {0x0058, 8}, // "01011000"
- 56: {0x0059, 8}, // "01011001"
- 57: {0x005a, 8}, // "01011010"
- 58: {0x005b, 8}, // "01011011"
- 59: {0x004a, 8}, // "01001010"
- 60: {0x004b, 8}, // "01001011"
- 61: {0x0032, 8}, // "00110010"
- 62: {0x0033, 8}, // "00110011"
- 63: {0x0034, 8}, // "00110100"
-}
-
-// whiteEncodeTable3 represents Table 3 for a white run.
-var whiteEncodeTable3 = [...]bitString{
- 0: {0x001b, 5}, // "11011"
- 1: {0x0012, 5}, // "10010"
- 2: {0x0017, 6}, // "010111"
- 3: {0x0037, 7}, // "0110111"
- 4: {0x0036, 8}, // "00110110"
- 5: {0x0037, 8}, // "00110111"
- 6: {0x0064, 8}, // "01100100"
- 7: {0x0065, 8}, // "01100101"
- 8: {0x0068, 8}, // "01101000"
- 9: {0x0067, 8}, // "01100111"
- 10: {0x00cc, 9}, // "011001100"
- 11: {0x00cd, 9}, // "011001101"
- 12: {0x00d2, 9}, // "011010010"
- 13: {0x00d3, 9}, // "011010011"
- 14: {0x00d4, 9}, // "011010100"
- 15: {0x00d5, 9}, // "011010101"
- 16: {0x00d6, 9}, // "011010110"
- 17: {0x00d7, 9}, // "011010111"
- 18: {0x00d8, 9}, // "011011000"
- 19: {0x00d9, 9}, // "011011001"
- 20: {0x00da, 9}, // "011011010"
- 21: {0x00db, 9}, // "011011011"
- 22: {0x0098, 9}, // "010011000"
- 23: {0x0099, 9}, // "010011001"
- 24: {0x009a, 9}, // "010011010"
- 25: {0x0018, 6}, // "011000"
- 26: {0x009b, 9}, // "010011011"
- 27: {0x0008, 11}, // "00000001000"
- 28: {0x000c, 11}, // "00000001100"
- 29: {0x000d, 11}, // "00000001101"
- 30: {0x0012, 12}, // "000000010010"
- 31: {0x0013, 12}, // "000000010011"
- 32: {0x0014, 12}, // "000000010100"
- 33: {0x0015, 12}, // "000000010101"
- 34: {0x0016, 12}, // "000000010110"
- 35: {0x0017, 12}, // "000000010111"
- 36: {0x001c, 12}, // "000000011100"
- 37: {0x001d, 12}, // "000000011101"
- 38: {0x001e, 12}, // "000000011110"
- 39: {0x001f, 12}, // "000000011111"
-}
-
-// blackEncodeTable2 represents Table 2 for a black run.
-var blackEncodeTable2 = [...]bitString{
- 0: {0x0037, 10}, // "0000110111"
- 1: {0x0002, 3}, // "010"
- 2: {0x0003, 2}, // "11"
- 3: {0x0002, 2}, // "10"
- 4: {0x0003, 3}, // "011"
- 5: {0x0003, 4}, // "0011"
- 6: {0x0002, 4}, // "0010"
- 7: {0x0003, 5}, // "00011"
- 8: {0x0005, 6}, // "000101"
- 9: {0x0004, 6}, // "000100"
- 10: {0x0004, 7}, // "0000100"
- 11: {0x0005, 7}, // "0000101"
- 12: {0x0007, 7}, // "0000111"
- 13: {0x0004, 8}, // "00000100"
- 14: {0x0007, 8}, // "00000111"
- 15: {0x0018, 9}, // "000011000"
- 16: {0x0017, 10}, // "0000010111"
- 17: {0x0018, 10}, // "0000011000"
- 18: {0x0008, 10}, // "0000001000"
- 19: {0x0067, 11}, // "00001100111"
- 20: {0x0068, 11}, // "00001101000"
- 21: {0x006c, 11}, // "00001101100"
- 22: {0x0037, 11}, // "00000110111"
- 23: {0x0028, 11}, // "00000101000"
- 24: {0x0017, 11}, // "00000010111"
- 25: {0x0018, 11}, // "00000011000"
- 26: {0x00ca, 12}, // "000011001010"
- 27: {0x00cb, 12}, // "000011001011"
- 28: {0x00cc, 12}, // "000011001100"
- 29: {0x00cd, 12}, // "000011001101"
- 30: {0x0068, 12}, // "000001101000"
- 31: {0x0069, 12}, // "000001101001"
- 32: {0x006a, 12}, // "000001101010"
- 33: {0x006b, 12}, // "000001101011"
- 34: {0x00d2, 12}, // "000011010010"
- 35: {0x00d3, 12}, // "000011010011"
- 36: {0x00d4, 12}, // "000011010100"
- 37: {0x00d5, 12}, // "000011010101"
- 38: {0x00d6, 12}, // "000011010110"
- 39: {0x00d7, 12}, // "000011010111"
- 40: {0x006c, 12}, // "000001101100"
- 41: {0x006d, 12}, // "000001101101"
- 42: {0x00da, 12}, // "000011011010"
- 43: {0x00db, 12}, // "000011011011"
- 44: {0x0054, 12}, // "000001010100"
- 45: {0x0055, 12}, // "000001010101"
- 46: {0x0056, 12}, // "000001010110"
- 47: {0x0057, 12}, // "000001010111"
- 48: {0x0064, 12}, // "000001100100"
- 49: {0x0065, 12}, // "000001100101"
- 50: {0x0052, 12}, // "000001010010"
- 51: {0x0053, 12}, // "000001010011"
- 52: {0x0024, 12}, // "000000100100"
- 53: {0x0037, 12}, // "000000110111"
- 54: {0x0038, 12}, // "000000111000"
- 55: {0x0027, 12}, // "000000100111"
- 56: {0x0028, 12}, // "000000101000"
- 57: {0x0058, 12}, // "000001011000"
- 58: {0x0059, 12}, // "000001011001"
- 59: {0x002b, 12}, // "000000101011"
- 60: {0x002c, 12}, // "000000101100"
- 61: {0x005a, 12}, // "000001011010"
- 62: {0x0066, 12}, // "000001100110"
- 63: {0x0067, 12}, // "000001100111"
-}
-
-// blackEncodeTable3 represents Table 3 for a black run.
-var blackEncodeTable3 = [...]bitString{
- 0: {0x000f, 10}, // "0000001111"
- 1: {0x00c8, 12}, // "000011001000"
- 2: {0x00c9, 12}, // "000011001001"
- 3: {0x005b, 12}, // "000001011011"
- 4: {0x0033, 12}, // "000000110011"
- 5: {0x0034, 12}, // "000000110100"
- 6: {0x0035, 12}, // "000000110101"
- 7: {0x006c, 13}, // "0000001101100"
- 8: {0x006d, 13}, // "0000001101101"
- 9: {0x004a, 13}, // "0000001001010"
- 10: {0x004b, 13}, // "0000001001011"
- 11: {0x004c, 13}, // "0000001001100"
- 12: {0x004d, 13}, // "0000001001101"
- 13: {0x0072, 13}, // "0000001110010"
- 14: {0x0073, 13}, // "0000001110011"
- 15: {0x0074, 13}, // "0000001110100"
- 16: {0x0075, 13}, // "0000001110101"
- 17: {0x0076, 13}, // "0000001110110"
- 18: {0x0077, 13}, // "0000001110111"
- 19: {0x0052, 13}, // "0000001010010"
- 20: {0x0053, 13}, // "0000001010011"
- 21: {0x0054, 13}, // "0000001010100"
- 22: {0x0055, 13}, // "0000001010101"
- 23: {0x005a, 13}, // "0000001011010"
- 24: {0x005b, 13}, // "0000001011011"
- 25: {0x0064, 13}, // "0000001100100"
- 26: {0x0065, 13}, // "0000001100101"
- 27: {0x0008, 11}, // "00000001000"
- 28: {0x000c, 11}, // "00000001100"
- 29: {0x000d, 11}, // "00000001101"
- 30: {0x0012, 12}, // "000000010010"
- 31: {0x0013, 12}, // "000000010011"
- 32: {0x0014, 12}, // "000000010100"
- 33: {0x0015, 12}, // "000000010101"
- 34: {0x0016, 12}, // "000000010110"
- 35: {0x0017, 12}, // "000000010111"
- 36: {0x001c, 12}, // "000000011100"
- 37: {0x001d, 12}, // "000000011101"
- 38: {0x001e, 12}, // "000000011110"
- 39: {0x001f, 12}, // "000000011111"
-}
-
-// COPY PASTE table.go BEGIN
-
-const (
- modePass = iota // Pass
- modeH // Horizontal
- modeV0 // Vertical-0
- modeVR1 // Vertical-Right-1
- modeVR2 // Vertical-Right-2
- modeVR3 // Vertical-Right-3
- modeVL1 // Vertical-Left-1
- modeVL2 // Vertical-Left-2
- modeVL3 // Vertical-Left-3
- modeExt // Extension
-)
-
-// COPY PASTE table.go END
diff --git a/vendor/golang.org/x/image/ccitt/writer.go b/vendor/golang.org/x/image/ccitt/writer.go
deleted file mode 100644
index 87130ab04..000000000
--- a/vendor/golang.org/x/image/ccitt/writer.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2019 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 ccitt
-
-import (
- "encoding/binary"
- "io"
-)
-
-type bitWriter struct {
- w io.Writer
-
- // order is whether to process w's bytes LSB first or MSB first.
- order Order
-
- // The high nBits bits of the bits field hold encoded bits to be written to w.
- bits uint64
- nBits uint32
-
- // bytes[:bw] holds encoded bytes not yet written to w.
- // Overflow protection is ensured by using a multiple of 8 as bytes length.
- bw uint32
- bytes [1024]uint8
-}
-
-// flushBits copies 64 bits from b.bits to b.bytes. If b.bytes is then full, it
-// is written to b.w.
-func (b *bitWriter) flushBits() error {
- binary.BigEndian.PutUint64(b.bytes[b.bw:], b.bits)
- b.bits = 0
- b.nBits = 0
- b.bw += 8
- if b.bw < uint32(len(b.bytes)) {
- return nil
- }
- b.bw = 0
- if b.order != MSB {
- reverseBitsWithinBytes(b.bytes[:])
- }
- _, err := b.w.Write(b.bytes[:])
- return err
-}
-
-// close finalizes a bitcode stream by writing any
-// pending bits to bitWriter's underlying io.Writer.
-func (b *bitWriter) close() error {
- // Write any encoded bits to bytes.
- if b.nBits > 0 {
- binary.BigEndian.PutUint64(b.bytes[b.bw:], b.bits)
- b.bw += (b.nBits + 7) >> 3
- }
-
- if b.order != MSB {
- reverseBitsWithinBytes(b.bytes[:b.bw])
- }
-
- // Write b.bw bytes to b.w.
- _, err := b.w.Write(b.bytes[:b.bw])
- return err
-}
-
-// alignToByteBoundary rounds b.nBits up to a multiple of 8.
-// If all 64 bits are used, flush them to bitWriter's bytes.
-func (b *bitWriter) alignToByteBoundary() error {
- if b.nBits = (b.nBits + 7) &^ 7; b.nBits == 64 {
- return b.flushBits()
- }
- return nil
-}
-
-// writeCode writes a variable length bitcode to b's underlying io.Writer.
-func (b *bitWriter) writeCode(bs bitString) error {
- bits := bs.bits
- nBits := bs.nBits
- if 64-b.nBits >= nBits {
- // b.bits has sufficient room for storing nBits bits.
- b.bits |= uint64(bits) << (64 - nBits - b.nBits)
- b.nBits += nBits
- if b.nBits == 64 {
- return b.flushBits()
- }
- return nil
- }
-
- // Number of leading bits that fill b.bits.
- i := 64 - b.nBits
-
- // Fill b.bits then flush and write remaining bits.
- b.bits |= uint64(bits) >> (nBits - i)
- b.nBits = 64
-
- if err := b.flushBits(); err != nil {
- return err
- }
-
- nBits -= i
- b.bits = uint64(bits) << (64 - nBits)
- b.nBits = nBits
- return nil
-}
diff --git a/vendor/golang.org/x/image/tiff/buffer.go b/vendor/golang.org/x/image/tiff/buffer.go
deleted file mode 100644
index d1801be48..000000000
--- a/vendor/golang.org/x/image/tiff/buffer.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// 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 tiff
-
-import "io"
-
-// buffer buffers an io.Reader to satisfy io.ReaderAt.
-type buffer struct {
- r io.Reader
- buf []byte
-}
-
-// fill reads data from b.r until the buffer contains at least end bytes.
-func (b *buffer) fill(end int) error {
- m := len(b.buf)
- if end > m {
- if end > cap(b.buf) {
- newcap := 1024
- for newcap < end {
- newcap *= 2
- }
- newbuf := make([]byte, end, newcap)
- copy(newbuf, b.buf)
- b.buf = newbuf
- } else {
- b.buf = b.buf[:end]
- }
- if n, err := io.ReadFull(b.r, b.buf[m:end]); err != nil {
- end = m + n
- b.buf = b.buf[:end]
- return err
- }
- }
- return nil
-}
-
-func (b *buffer) ReadAt(p []byte, off int64) (int, error) {
- o := int(off)
- end := o + len(p)
- if int64(end) != off+int64(len(p)) {
- return 0, io.ErrUnexpectedEOF
- }
-
- err := b.fill(end)
- return copy(p, b.buf[o:end]), err
-}
-
-// Slice returns a slice of the underlying buffer. The slice contains
-// n bytes starting at offset off.
-func (b *buffer) Slice(off, n int) ([]byte, error) {
- end := off + n
- if err := b.fill(end); err != nil {
- return nil, err
- }
- return b.buf[off:end], nil
-}
-
-// newReaderAt converts an io.Reader into an io.ReaderAt.
-func newReaderAt(r io.Reader) io.ReaderAt {
- if ra, ok := r.(io.ReaderAt); ok {
- return ra
- }
- return &buffer{
- r: r,
- buf: make([]byte, 0, 1024),
- }
-}
diff --git a/vendor/golang.org/x/image/tiff/compress.go b/vendor/golang.org/x/image/tiff/compress.go
deleted file mode 100644
index 3f176f00a..000000000
--- a/vendor/golang.org/x/image/tiff/compress.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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 tiff
-
-import (
- "bufio"
- "io"
-)
-
-type byteReader interface {
- io.Reader
- io.ByteReader
-}
-
-// unpackBits decodes the PackBits-compressed data in src and returns the
-// uncompressed data.
-//
-// The PackBits compression format is described in section 9 (p. 42)
-// of the TIFF spec.
-func unpackBits(r io.Reader) ([]byte, error) {
- buf := make([]byte, 128)
- dst := make([]byte, 0, 1024)
- br, ok := r.(byteReader)
- if !ok {
- br = bufio.NewReader(r)
- }
-
- for {
- b, err := br.ReadByte()
- if err != nil {
- if err == io.EOF {
- return dst, nil
- }
- return nil, err
- }
- code := int(int8(b))
- switch {
- case code >= 0:
- n, err := io.ReadFull(br, buf[:code+1])
- if err != nil {
- return nil, err
- }
- dst = append(dst, buf[:n]...)
- case code == -128:
- // No-op.
- default:
- if b, err = br.ReadByte(); err != nil {
- return nil, err
- }
- for j := 0; j < 1-code; j++ {
- buf[j] = b
- }
- dst = append(dst, buf[:1-code]...)
- }
- }
-}
diff --git a/vendor/golang.org/x/image/tiff/consts.go b/vendor/golang.org/x/image/tiff/consts.go
deleted file mode 100644
index 3e5f7f14d..000000000
--- a/vendor/golang.org/x/image/tiff/consts.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// 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 tiff
-
-// A tiff image file contains one or more images. The metadata
-// of each image is contained in an Image File Directory (IFD),
-// which contains entries of 12 bytes each and is described
-// on page 14-16 of the specification. An IFD entry consists of
-//
-// - a tag, which describes the signification of the entry,
-// - the data type and length of the entry,
-// - the data itself or a pointer to it if it is more than 4 bytes.
-//
-// The presence of a length means that each IFD is effectively an array.
-
-const (
- leHeader = "II\x2A\x00" // Header for little-endian files.
- beHeader = "MM\x00\x2A" // Header for big-endian files.
-
- ifdLen = 12 // Length of an IFD entry in bytes.
-)
-
-// Data types (p. 14-16 of the spec).
-const (
- dtByte = 1
- dtASCII = 2
- dtShort = 3
- dtLong = 4
- dtRational = 5
-)
-
-// The length of one instance of each data type in bytes.
-var lengths = [...]uint32{0, 1, 1, 2, 4, 8}
-
-// Tags (see p. 28-41 of the spec).
-const (
- tImageWidth = 256
- tImageLength = 257
- tBitsPerSample = 258
- tCompression = 259
- tPhotometricInterpretation = 262
-
- tFillOrder = 266
-
- tStripOffsets = 273
- tSamplesPerPixel = 277
- tRowsPerStrip = 278
- tStripByteCounts = 279
-
- tT4Options = 292 // CCITT Group 3 options, a set of 32 flag bits.
- tT6Options = 293 // CCITT Group 4 options, a set of 32 flag bits.
-
- tTileWidth = 322
- tTileLength = 323
- tTileOffsets = 324
- tTileByteCounts = 325
-
- tXResolution = 282
- tYResolution = 283
- tResolutionUnit = 296
-
- tPredictor = 317
- tColorMap = 320
- tExtraSamples = 338
- tSampleFormat = 339
-)
-
-// Compression types (defined in various places in the spec and supplements).
-const (
- cNone = 1
- cCCITT = 2
- cG3 = 3 // Group 3 Fax.
- cG4 = 4 // Group 4 Fax.
- cLZW = 5
- cJPEGOld = 6 // Superseded by cJPEG.
- cJPEG = 7
- cDeflate = 8 // zlib compression.
- cPackBits = 32773
- cDeflateOld = 32946 // Superseded by cDeflate.
-)
-
-// Photometric interpretation values (see p. 37 of the spec).
-const (
- pWhiteIsZero = 0
- pBlackIsZero = 1
- pRGB = 2
- pPaletted = 3
- pTransMask = 4 // transparency mask
- pCMYK = 5
- pYCbCr = 6
- pCIELab = 8
-)
-
-// Values for the tPredictor tag (page 64-65 of the spec).
-const (
- prNone = 1
- prHorizontal = 2
-)
-
-// Values for the tResolutionUnit tag (page 18).
-const (
- resNone = 1
- resPerInch = 2 // Dots per inch.
- resPerCM = 3 // Dots per centimeter.
-)
-
-// imageMode represents the mode of the image.
-type imageMode int
-
-const (
- mBilevel imageMode = iota
- mPaletted
- mGray
- mGrayInvert
- mRGB
- mRGBA
- mNRGBA
- mCMYK
-)
-
-// CompressionType describes the type of compression used in Options.
-type CompressionType int
-
-// Constants for supported compression types.
-const (
- Uncompressed CompressionType = iota
- Deflate
- LZW
- CCITTGroup3
- CCITTGroup4
-)
-
-// specValue returns the compression type constant from the TIFF spec that
-// is equivalent to c.
-func (c CompressionType) specValue() uint32 {
- switch c {
- case LZW:
- return cLZW
- case Deflate:
- return cDeflate
- case CCITTGroup3:
- return cG3
- case CCITTGroup4:
- return cG4
- }
- return cNone
-}
diff --git a/vendor/golang.org/x/image/tiff/fuzz.go b/vendor/golang.org/x/image/tiff/fuzz.go
deleted file mode 100644
index b388b6f42..000000000
--- a/vendor/golang.org/x/image/tiff/fuzz.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build gofuzz
-
-package tiff
-
-import "bytes"
-
-func Fuzz(data []byte) int {
- cfg, err := DecodeConfig(bytes.NewReader(data))
- if err != nil {
- return 0
- }
- if cfg.Width*cfg.Height > 1e6 {
- return 0
- }
- img, err := Decode(bytes.NewReader(data))
- if err != nil {
- return 0
- }
- var w bytes.Buffer
- err = Encode(&w, img, nil)
- if err != nil {
- panic(err)
- }
- return 1
-}
diff --git a/vendor/golang.org/x/image/tiff/lzw/reader.go b/vendor/golang.org/x/image/tiff/lzw/reader.go
deleted file mode 100644
index 0aae475ab..000000000
--- a/vendor/golang.org/x/image/tiff/lzw/reader.go
+++ /dev/null
@@ -1,272 +0,0 @@
-// 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 lzw implements the Lempel-Ziv-Welch compressed data format,
-// described in T. A. Welch, “A Technique for High-Performance Data
-// Compression”, Computer, 17(6) (June 1984), pp 8-19.
-//
-// In particular, it implements LZW as used by the TIFF file format, including
-// an "off by one" algorithmic difference when compared to standard LZW.
-package lzw // import "golang.org/x/image/tiff/lzw"
-
-/*
-This file was branched from src/pkg/compress/lzw/reader.go in the
-standard library. Differences from the original are marked with "NOTE".
-
-The tif_lzw.c file in the libtiff C library has this comment:
-
-----
-The 5.0 spec describes a different algorithm than Aldus
-implements. Specifically, Aldus does code length transitions
-one code earlier than should be done (for real LZW).
-Earlier versions of this library implemented the correct
-LZW algorithm, but emitted codes in a bit order opposite
-to the TIFF spec. Thus, to maintain compatibility w/ Aldus
-we interpret MSB-LSB ordered codes to be images written w/
-old versions of this library, but otherwise adhere to the
-Aldus "off by one" algorithm.
-----
-
-The Go code doesn't read (invalid) TIFF files written by old versions of
-libtiff, but the LZW algorithm in this package still differs from the one in
-Go's standard package library to accommodate this "off by one" in valid TIFFs.
-*/
-
-import (
- "bufio"
- "errors"
- "fmt"
- "io"
-)
-
-// Order specifies the bit ordering in an LZW data stream.
-type Order int
-
-const (
- // LSB means Least Significant Bits first, as used in the GIF file format.
- LSB Order = iota
- // MSB means Most Significant Bits first, as used in the TIFF and PDF
- // file formats.
- MSB
-)
-
-const (
- maxWidth = 12
- decoderInvalidCode = 0xffff
- flushBuffer = 1 << maxWidth
-)
-
-// decoder is the state from which the readXxx method converts a byte
-// stream into a code stream.
-type decoder struct {
- r io.ByteReader
- bits uint32
- nBits uint
- width uint
- read func(*decoder) (uint16, error) // readLSB or readMSB
- litWidth int // width in bits of literal codes
- err error
-
- // The first 1<= 1<>= d.width
- d.nBits -= d.width
- return code, nil
-}
-
-// readMSB returns the next code for "Most Significant Bits first" data.
-func (d *decoder) readMSB() (uint16, error) {
- for d.nBits < d.width {
- x, err := d.r.ReadByte()
- if err != nil {
- return 0, err
- }
- d.bits |= uint32(x) << (24 - d.nBits)
- d.nBits += 8
- }
- code := uint16(d.bits >> (32 - d.width))
- d.bits <<= d.width
- d.nBits -= d.width
- return code, nil
-}
-
-func (d *decoder) Read(b []byte) (int, error) {
- for {
- if len(d.toRead) > 0 {
- n := copy(b, d.toRead)
- d.toRead = d.toRead[n:]
- return n, nil
- }
- if d.err != nil {
- return 0, d.err
- }
- d.decode()
- }
-}
-
-// decode decompresses bytes from r and leaves them in d.toRead.
-// read specifies how to decode bytes into codes.
-// litWidth is the width in bits of literal codes.
-func (d *decoder) decode() {
- // Loop over the code stream, converting codes into decompressed bytes.
-loop:
- for {
- code, err := d.read(d)
- if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- d.err = err
- break
- }
- switch {
- case code < d.clear:
- // We have a literal code.
- d.output[d.o] = uint8(code)
- d.o++
- if d.last != decoderInvalidCode {
- // Save what the hi code expands to.
- d.suffix[d.hi] = uint8(code)
- d.prefix[d.hi] = d.last
- }
- case code == d.clear:
- d.width = 1 + uint(d.litWidth)
- d.hi = d.eof
- d.overflow = 1 << d.width
- d.last = decoderInvalidCode
- continue
- case code == d.eof:
- d.err = io.EOF
- break loop
- case code <= d.hi:
- c, i := code, len(d.output)-1
- if code == d.hi && d.last != decoderInvalidCode {
- // code == hi is a special case which expands to the last expansion
- // followed by the head of the last expansion. To find the head, we walk
- // the prefix chain until we find a literal code.
- c = d.last
- for c >= d.clear {
- c = d.prefix[c]
- }
- d.output[i] = uint8(c)
- i--
- c = d.last
- }
- // Copy the suffix chain into output and then write that to w.
- for c >= d.clear {
- d.output[i] = d.suffix[c]
- i--
- c = d.prefix[c]
- }
- d.output[i] = uint8(c)
- d.o += copy(d.output[d.o:], d.output[i:])
- if d.last != decoderInvalidCode {
- // Save what the hi code expands to.
- d.suffix[d.hi] = uint8(c)
- d.prefix[d.hi] = d.last
- }
- default:
- d.err = errors.New("lzw: invalid code")
- break loop
- }
- d.last, d.hi = code, d.hi+1
- if d.hi+1 >= d.overflow { // NOTE: the "+1" is where TIFF's LZW differs from the standard algorithm.
- if d.width == maxWidth {
- d.last = decoderInvalidCode
- } else {
- d.width++
- d.overflow <<= 1
- }
- }
- if d.o >= flushBuffer {
- break
- }
- }
- // Flush pending output.
- d.toRead = d.output[:d.o]
- d.o = 0
-}
-
-var errClosed = errors.New("lzw: reader/writer is closed")
-
-func (d *decoder) Close() error {
- d.err = errClosed // in case any Reads come along
- return nil
-}
-
-// NewReader creates a new io.ReadCloser.
-// Reads from the returned io.ReadCloser read and decompress data from r.
-// If r does not also implement io.ByteReader,
-// the decompressor may read more data than necessary from r.
-// It is the caller's responsibility to call Close on the ReadCloser when
-// finished reading.
-// The number of bits to use for literal codes, litWidth, must be in the
-// range [2,8] and is typically 8. It must equal the litWidth
-// used during compression.
-func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser {
- d := new(decoder)
- switch order {
- case LSB:
- d.read = (*decoder).readLSB
- case MSB:
- d.read = (*decoder).readMSB
- default:
- d.err = errors.New("lzw: unknown order")
- return d
- }
- if litWidth < 2 || 8 < litWidth {
- d.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth)
- return d
- }
- if br, ok := r.(io.ByteReader); ok {
- d.r = br
- } else {
- d.r = bufio.NewReader(r)
- }
- d.litWidth = litWidth
- d.width = 1 + uint(litWidth)
- d.clear = uint16(1) << uint(litWidth)
- d.eof, d.hi = d.clear+1, d.clear+1
- d.overflow = uint16(1) << d.width
- d.last = decoderInvalidCode
-
- return d
-}
diff --git a/vendor/golang.org/x/image/tiff/reader.go b/vendor/golang.org/x/image/tiff/reader.go
deleted file mode 100644
index 1b8fcb859..000000000
--- a/vendor/golang.org/x/image/tiff/reader.go
+++ /dev/null
@@ -1,785 +0,0 @@
-// 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 tiff implements a TIFF image decoder and encoder.
-//
-// The TIFF specification is at http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
-package tiff // import "golang.org/x/image/tiff"
-
-import (
- "bytes"
- "compress/zlib"
- "encoding/binary"
- "fmt"
- "image"
- "image/color"
- "io"
- "math"
-
- "golang.org/x/image/ccitt"
- "golang.org/x/image/tiff/lzw"
-)
-
-// A FormatError reports that the input is not a valid TIFF image.
-type FormatError string
-
-func (e FormatError) Error() string {
- return "tiff: invalid format: " + string(e)
-}
-
-// An UnsupportedError reports that the input uses a valid but
-// unimplemented feature.
-type UnsupportedError string
-
-func (e UnsupportedError) Error() string {
- return "tiff: unsupported feature: " + string(e)
-}
-
-var (
- errNoPixels = FormatError("not enough pixel data")
- errInvalidColorIndex = FormatError("invalid color index")
-)
-
-const maxChunkSize = 10 << 20 // 10M
-
-// safeReadAt is a verbatim copy of internal/saferio.ReadDataAt from the
-// standard library, which is used to read data from a reader using a length
-// provided by untrusted data, without allocating the entire slice ahead of time
-// if it is large (>maxChunkSize). This allows us to avoid allocating giant
-// slices before learning that we can't actually read that much data from the
-// reader.
-func safeReadAt(r io.ReaderAt, n uint64, off int64) ([]byte, error) {
- if int64(n) < 0 || n != uint64(int(n)) {
- // n is too large to fit in int, so we can't allocate
- // a buffer large enough. Treat this as a read failure.
- return nil, io.ErrUnexpectedEOF
- }
-
- if n < maxChunkSize {
- buf := make([]byte, n)
- _, err := r.ReadAt(buf, off)
- if err != nil {
- // io.SectionReader can return EOF for n == 0,
- // but for our purposes that is a success.
- if err != io.EOF || n > 0 {
- return nil, err
- }
- }
- return buf, nil
- }
-
- var buf []byte
- buf1 := make([]byte, maxChunkSize)
- for n > 0 {
- next := n
- if next > maxChunkSize {
- next = maxChunkSize
- }
- _, err := r.ReadAt(buf1[:next], off)
- if err != nil {
- return nil, err
- }
- buf = append(buf, buf1[:next]...)
- n -= next
- off += int64(next)
- }
- return buf, nil
-}
-
-type decoder struct {
- r io.ReaderAt
- byteOrder binary.ByteOrder
- config image.Config
- mode imageMode
- bpp uint
- features map[int][]uint
- palette []color.Color
-
- buf []byte
- off int // Current offset in buf.
- v uint32 // Buffer value for reading with arbitrary bit depths.
- nbits uint // Remaining number of bits in v.
-}
-
-// firstVal returns the first uint of the features entry with the given tag,
-// or 0 if the tag does not exist.
-func (d *decoder) firstVal(tag int) uint {
- f := d.features[tag]
- if len(f) == 0 {
- return 0
- }
- return f[0]
-}
-
-// ifdUint decodes the IFD entry in p, which must be of the Byte, Short
-// or Long type, and returns the decoded uint values.
-func (d *decoder) ifdUint(p []byte) (u []uint, err error) {
- var raw []byte
- if len(p) < ifdLen {
- return nil, FormatError("bad IFD entry")
- }
-
- datatype := d.byteOrder.Uint16(p[2:4])
- if dt := int(datatype); dt <= 0 || dt >= len(lengths) {
- return nil, UnsupportedError("IFD entry datatype")
- }
-
- count := d.byteOrder.Uint32(p[4:8])
- if count > math.MaxInt32/lengths[datatype] {
- return nil, FormatError("IFD data too large")
- }
- if datalen := lengths[datatype] * count; datalen > 4 {
- // The IFD contains a pointer to the real value.
- raw, err = safeReadAt(d.r, uint64(datalen), int64(d.byteOrder.Uint32(p[8:12])))
- } else {
- raw = p[8 : 8+datalen]
- }
- if err != nil {
- return nil, err
- }
-
- u = make([]uint, count)
- switch datatype {
- case dtByte:
- for i := uint32(0); i < count; i++ {
- u[i] = uint(raw[i])
- }
- case dtShort:
- for i := uint32(0); i < count; i++ {
- u[i] = uint(d.byteOrder.Uint16(raw[2*i : 2*(i+1)]))
- }
- case dtLong:
- for i := uint32(0); i < count; i++ {
- u[i] = uint(d.byteOrder.Uint32(raw[4*i : 4*(i+1)]))
- }
- default:
- return nil, UnsupportedError("data type")
- }
- return u, nil
-}
-
-// parseIFD decides whether the IFD entry in p is "interesting" and
-// stows away the data in the decoder. It returns the tag number of the
-// entry and an error, if any.
-func (d *decoder) parseIFD(p []byte) (int, error) {
- tag := d.byteOrder.Uint16(p[0:2])
- switch tag {
- case tBitsPerSample,
- tExtraSamples,
- tPhotometricInterpretation,
- tCompression,
- tPredictor,
- tStripOffsets,
- tStripByteCounts,
- tRowsPerStrip,
- tTileWidth,
- tTileLength,
- tTileOffsets,
- tTileByteCounts,
- tImageLength,
- tImageWidth,
- tFillOrder,
- tT4Options,
- tT6Options:
- val, err := d.ifdUint(p)
- if err != nil {
- return 0, err
- }
- d.features[int(tag)] = val
- case tColorMap:
- val, err := d.ifdUint(p)
- if err != nil {
- return 0, err
- }
- numcolors := len(val) / 3
- if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 {
- return 0, FormatError("bad ColorMap length")
- }
- d.palette = make([]color.Color, numcolors)
- for i := 0; i < numcolors; i++ {
- d.palette[i] = color.RGBA64{
- uint16(val[i]),
- uint16(val[i+numcolors]),
- uint16(val[i+2*numcolors]),
- 0xffff,
- }
- }
- case tSampleFormat:
- // Page 27 of the spec: If the SampleFormat is present and
- // the value is not 1 [= unsigned integer data], a Baseline
- // TIFF reader that cannot handle the SampleFormat value
- // must terminate the import process gracefully.
- val, err := d.ifdUint(p)
- if err != nil {
- return 0, err
- }
- for _, v := range val {
- if v != 1 {
- return 0, UnsupportedError("sample format")
- }
- }
- }
- return int(tag), nil
-}
-
-// readBits reads n bits from the internal buffer starting at the current offset.
-func (d *decoder) readBits(n uint) (v uint32, ok bool) {
- for d.nbits < n {
- d.v <<= 8
- if d.off >= len(d.buf) {
- return 0, false
- }
- d.v |= uint32(d.buf[d.off])
- d.off++
- d.nbits += 8
- }
- d.nbits -= n
- rv := d.v >> d.nbits
- d.v &^= rv << d.nbits
- return rv, true
-}
-
-// flushBits discards the unread bits in the buffer used by readBits.
-// It is used at the end of a line.
-func (d *decoder) flushBits() {
- d.v = 0
- d.nbits = 0
-}
-
-// minInt returns the smaller of x or y.
-func minInt(a, b int) int {
- if a <= b {
- return a
- }
- return b
-}
-
-// decode decodes the raw data of an image.
-// It reads from d.buf and writes the strip or tile into dst.
-func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
- d.off = 0
-
- // Apply horizontal predictor if necessary.
- // In this case, p contains the color difference to the preceding pixel.
- // See page 64-65 of the spec.
- if d.firstVal(tPredictor) == prHorizontal {
- switch d.bpp {
- case 16:
- var off int
- n := 2 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
- for y := ymin; y < ymax; y++ {
- off += n
- for x := 0; x < (xmax-xmin-1)*n; x += 2 {
- if off+2 > len(d.buf) {
- return errNoPixels
- }
- v0 := d.byteOrder.Uint16(d.buf[off-n : off-n+2])
- v1 := d.byteOrder.Uint16(d.buf[off : off+2])
- d.byteOrder.PutUint16(d.buf[off:off+2], v1+v0)
- off += 2
- }
- }
- case 8:
- var off int
- n := 1 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
- for y := ymin; y < ymax; y++ {
- off += n
- for x := 0; x < (xmax-xmin-1)*n; x++ {
- if off >= len(d.buf) {
- return errNoPixels
- }
- d.buf[off] += d.buf[off-n]
- off++
- }
- }
- case 1:
- return UnsupportedError("horizontal predictor with 1 BitsPerSample")
- }
- }
-
- rMaxX := minInt(xmax, dst.Bounds().Max.X)
- rMaxY := minInt(ymax, dst.Bounds().Max.Y)
- switch d.mode {
- case mGray, mGrayInvert:
- if d.bpp == 16 {
- img := dst.(*image.Gray16)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- if d.off+2 > len(d.buf) {
- return errNoPixels
- }
- v := d.byteOrder.Uint16(d.buf[d.off : d.off+2])
- d.off += 2
- if d.mode == mGrayInvert {
- v = 0xffff - v
- }
- img.SetGray16(x, y, color.Gray16{v})
- }
- if rMaxX == img.Bounds().Max.X {
- d.off += 2 * (xmax - img.Bounds().Max.X)
- }
- }
- } else {
- img := dst.(*image.Gray)
- max := uint32((1 << d.bpp) - 1)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- v, ok := d.readBits(d.bpp)
- if !ok {
- return errNoPixels
- }
- v = v * 0xff / max
- if d.mode == mGrayInvert {
- v = 0xff - v
- }
- img.SetGray(x, y, color.Gray{uint8(v)})
- }
- d.flushBits()
- }
- }
- case mPaletted:
- img := dst.(*image.Paletted)
- pLen := len(d.palette)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- v, ok := d.readBits(d.bpp)
- if !ok {
- return errNoPixels
- }
- idx := uint8(v)
- if int(idx) >= pLen {
- return errInvalidColorIndex
- }
- img.SetColorIndex(x, y, idx)
- }
- d.flushBits()
- }
- case mRGB:
- if d.bpp == 16 {
- img := dst.(*image.RGBA64)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- if d.off+6 > len(d.buf) {
- return errNoPixels
- }
- r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
- g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
- b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
- d.off += 6
- img.SetRGBA64(x, y, color.RGBA64{r, g, b, 0xffff})
- }
- }
- } else {
- img := dst.(*image.RGBA)
- for y := ymin; y < rMaxY; y++ {
- min := img.PixOffset(xmin, y)
- max := img.PixOffset(rMaxX, y)
- off := (y - ymin) * (xmax - xmin) * 3
- for i := min; i < max; i += 4 {
- if off+3 > len(d.buf) {
- return errNoPixels
- }
- img.Pix[i+0] = d.buf[off+0]
- img.Pix[i+1] = d.buf[off+1]
- img.Pix[i+2] = d.buf[off+2]
- img.Pix[i+3] = 0xff
- off += 3
- }
- }
- }
- case mNRGBA:
- if d.bpp == 16 {
- img := dst.(*image.NRGBA64)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- if d.off+8 > len(d.buf) {
- return errNoPixels
- }
- r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
- g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
- b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
- a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8])
- d.off += 8
- img.SetNRGBA64(x, y, color.NRGBA64{r, g, b, a})
- }
- }
- } else {
- img := dst.(*image.NRGBA)
- for y := ymin; y < rMaxY; y++ {
- min := img.PixOffset(xmin, y)
- max := img.PixOffset(rMaxX, y)
- i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
- if i1 > len(d.buf) {
- return errNoPixels
- }
- copy(img.Pix[min:max], d.buf[i0:i1])
- }
- }
- case mRGBA:
- if d.bpp == 16 {
- img := dst.(*image.RGBA64)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- if d.off+8 > len(d.buf) {
- return errNoPixels
- }
- r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
- g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
- b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
- a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8])
- d.off += 8
- img.SetRGBA64(x, y, color.RGBA64{r, g, b, a})
- }
- }
- } else {
- img := dst.(*image.RGBA)
- for y := ymin; y < rMaxY; y++ {
- min := img.PixOffset(xmin, y)
- max := img.PixOffset(rMaxX, y)
- i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
- if i1 > len(d.buf) {
- return errNoPixels
- }
- copy(img.Pix[min:max], d.buf[i0:i1])
- }
- }
- }
-
- return nil
-}
-
-func newDecoder(r io.Reader) (*decoder, error) {
- d := &decoder{
- r: newReaderAt(r),
- features: make(map[int][]uint),
- }
-
- p := make([]byte, 8)
- if _, err := d.r.ReadAt(p, 0); err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return nil, err
- }
- switch string(p[0:4]) {
- case leHeader:
- d.byteOrder = binary.LittleEndian
- case beHeader:
- d.byteOrder = binary.BigEndian
- default:
- return nil, FormatError("malformed header")
- }
-
- ifdOffset := int64(d.byteOrder.Uint32(p[4:8]))
-
- // The first two bytes contain the number of entries (12 bytes each).
- if _, err := d.r.ReadAt(p[0:2], ifdOffset); err != nil {
- return nil, err
- }
- numItems := int(d.byteOrder.Uint16(p[0:2]))
-
- // All IFD entries are read in one chunk.
- var err error
- p, err = safeReadAt(d.r, uint64(ifdLen*numItems), ifdOffset+2)
- if err != nil {
- return nil, err
- }
-
- prevTag := -1
- for i := 0; i < len(p); i += ifdLen {
- tag, err := d.parseIFD(p[i : i+ifdLen])
- if err != nil {
- return nil, err
- }
- if tag <= prevTag {
- return nil, FormatError("tags are not sorted in ascending order")
- }
- prevTag = tag
- }
-
- d.config.Width = int(d.firstVal(tImageWidth))
- d.config.Height = int(d.firstVal(tImageLength))
-
- if _, ok := d.features[tBitsPerSample]; !ok {
- // Default is 1 per specification.
- d.features[tBitsPerSample] = []uint{1}
- }
- d.bpp = d.firstVal(tBitsPerSample)
- switch d.bpp {
- case 0:
- return nil, FormatError("BitsPerSample must not be 0")
- case 1, 8, 16:
- // Nothing to do, these are accepted by this implementation.
- default:
- return nil, UnsupportedError(fmt.Sprintf("BitsPerSample of %v", d.bpp))
- }
-
- // Determine the image mode.
- switch d.firstVal(tPhotometricInterpretation) {
- case pRGB:
- if d.bpp == 16 {
- for _, b := range d.features[tBitsPerSample] {
- if b != 16 {
- return nil, FormatError("wrong number of samples for 16bit RGB")
- }
- }
- } else {
- for _, b := range d.features[tBitsPerSample] {
- if b != 8 {
- return nil, FormatError("wrong number of samples for 8bit RGB")
- }
- }
- }
- // RGB images normally have 3 samples per pixel.
- // If there are more, ExtraSamples (p. 31-32 of the spec)
- // gives their meaning (usually an alpha channel).
- //
- // This implementation does not support extra samples
- // of an unspecified type.
- switch len(d.features[tBitsPerSample]) {
- case 3:
- d.mode = mRGB
- if d.bpp == 16 {
- d.config.ColorModel = color.RGBA64Model
- } else {
- d.config.ColorModel = color.RGBAModel
- }
- case 4:
- switch d.firstVal(tExtraSamples) {
- case 1:
- d.mode = mRGBA
- if d.bpp == 16 {
- d.config.ColorModel = color.RGBA64Model
- } else {
- d.config.ColorModel = color.RGBAModel
- }
- case 2:
- d.mode = mNRGBA
- if d.bpp == 16 {
- d.config.ColorModel = color.NRGBA64Model
- } else {
- d.config.ColorModel = color.NRGBAModel
- }
- default:
- return nil, FormatError("wrong number of samples for RGB")
- }
- default:
- return nil, FormatError("wrong number of samples for RGB")
- }
- case pPaletted:
- d.mode = mPaletted
- d.config.ColorModel = color.Palette(d.palette)
- case pWhiteIsZero:
- d.mode = mGrayInvert
- if d.bpp == 16 {
- d.config.ColorModel = color.Gray16Model
- } else {
- d.config.ColorModel = color.GrayModel
- }
- case pBlackIsZero:
- d.mode = mGray
- if d.bpp == 16 {
- d.config.ColorModel = color.Gray16Model
- } else {
- d.config.ColorModel = color.GrayModel
- }
- default:
- return nil, UnsupportedError("color model")
- }
- if d.firstVal(tPhotometricInterpretation) != pRGB {
- if len(d.features[tBitsPerSample]) != 1 {
- return nil, UnsupportedError("extra samples")
- }
- }
-
- return d, nil
-}
-
-// DecodeConfig returns the color model and dimensions of a TIFF image without
-// decoding the entire image.
-func DecodeConfig(r io.Reader) (image.Config, error) {
- d, err := newDecoder(r)
- if err != nil {
- return image.Config{}, err
- }
- return d.config, nil
-}
-
-func ccittFillOrder(tiffFillOrder uint) ccitt.Order {
- if tiffFillOrder == 2 {
- return ccitt.LSB
- }
- return ccitt.MSB
-}
-
-// Decode reads a TIFF image from r and returns it as an image.Image.
-// The type of Image returned depends on the contents of the TIFF.
-func Decode(r io.Reader) (img image.Image, err error) {
- d, err := newDecoder(r)
- if err != nil {
- return
- }
-
- blockPadding := false
- blockWidth := d.config.Width
- blockHeight := d.config.Height
- blocksAcross := 1
- blocksDown := 1
-
- if d.config.Width == 0 {
- blocksAcross = 0
- }
- if d.config.Height == 0 {
- blocksDown = 0
- }
-
- var blockOffsets, blockCounts []uint
-
- if int(d.firstVal(tTileWidth)) != 0 {
- blockPadding = true
-
- blockWidth = int(d.firstVal(tTileWidth))
- blockHeight = int(d.firstVal(tTileLength))
-
- // The specification says that tile widths and lengths must be a multiple of 16.
- // We currently permit invalid sizes, but reject anything too small to limit the
- // amount of work a malicious input can force us to perform.
- if blockWidth < 8 || blockHeight < 8 {
- return nil, FormatError("tile size is too small")
- }
-
- if blockWidth != 0 {
- blocksAcross = (d.config.Width + blockWidth - 1) / blockWidth
- }
- if blockHeight != 0 {
- blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
- }
-
- blockCounts = d.features[tTileByteCounts]
- blockOffsets = d.features[tTileOffsets]
-
- } else {
- if int(d.firstVal(tRowsPerStrip)) != 0 {
- blockHeight = int(d.firstVal(tRowsPerStrip))
- }
-
- if blockHeight != 0 {
- blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
- }
-
- blockOffsets = d.features[tStripOffsets]
- blockCounts = d.features[tStripByteCounts]
- }
-
- // Check if we have the right number of strips/tiles, offsets and counts.
- if n := blocksAcross * blocksDown; len(blockOffsets) < n || len(blockCounts) < n {
- return nil, FormatError("inconsistent header")
- }
-
- imgRect := image.Rect(0, 0, d.config.Width, d.config.Height)
- switch d.mode {
- case mGray, mGrayInvert:
- if d.bpp == 16 {
- img = image.NewGray16(imgRect)
- } else {
- img = image.NewGray(imgRect)
- }
- case mPaletted:
- img = image.NewPaletted(imgRect, d.palette)
- case mNRGBA:
- if d.bpp == 16 {
- img = image.NewNRGBA64(imgRect)
- } else {
- img = image.NewNRGBA(imgRect)
- }
- case mRGB, mRGBA:
- if d.bpp == 16 {
- img = image.NewRGBA64(imgRect)
- } else {
- img = image.NewRGBA(imgRect)
- }
- }
-
- if blocksAcross == 0 || blocksDown == 0 {
- return
- }
- // Maximum data per pixel is 8 bytes (RGBA64).
- blockMaxDataSize := int64(blockWidth) * int64(blockHeight) * 8
- for i := 0; i < blocksAcross; i++ {
- blkW := blockWidth
- if !blockPadding && i == blocksAcross-1 && d.config.Width%blockWidth != 0 {
- blkW = d.config.Width % blockWidth
- }
- for j := 0; j < blocksDown; j++ {
- blkH := blockHeight
- if !blockPadding && j == blocksDown-1 && d.config.Height%blockHeight != 0 {
- blkH = d.config.Height % blockHeight
- }
- offset := int64(blockOffsets[j*blocksAcross+i])
- n := int64(blockCounts[j*blocksAcross+i])
- switch d.firstVal(tCompression) {
-
- // According to the spec, Compression does not have a default value,
- // but some tools interpret a missing Compression value as none so we do
- // the same.
- case cNone, 0:
- if b, ok := d.r.(*buffer); ok {
- d.buf, err = b.Slice(int(offset), int(n))
- } else {
- d.buf, err = safeReadAt(d.r, uint64(n), offset)
- }
- case cG3:
- inv := d.firstVal(tPhotometricInterpretation) == pWhiteIsZero
- order := ccittFillOrder(d.firstVal(tFillOrder))
- r := ccitt.NewReader(io.NewSectionReader(d.r, offset, n), order, ccitt.Group3, blkW, blkH, &ccitt.Options{Invert: inv, Align: false})
- d.buf, err = readBuf(r, d.buf, blockMaxDataSize)
- case cG4:
- inv := d.firstVal(tPhotometricInterpretation) == pWhiteIsZero
- order := ccittFillOrder(d.firstVal(tFillOrder))
- r := ccitt.NewReader(io.NewSectionReader(d.r, offset, n), order, ccitt.Group4, blkW, blkH, &ccitt.Options{Invert: inv, Align: false})
- d.buf, err = readBuf(r, d.buf, blockMaxDataSize)
- case cLZW:
- r := lzw.NewReader(io.NewSectionReader(d.r, offset, n), lzw.MSB, 8)
- d.buf, err = readBuf(r, d.buf, blockMaxDataSize)
- r.Close()
- case cDeflate, cDeflateOld:
- var r io.ReadCloser
- r, err = zlib.NewReader(io.NewSectionReader(d.r, offset, n))
- if err != nil {
- return nil, err
- }
- d.buf, err = readBuf(r, d.buf, blockMaxDataSize)
- r.Close()
- case cPackBits:
- d.buf, err = unpackBits(io.NewSectionReader(d.r, offset, n))
- default:
- err = UnsupportedError(fmt.Sprintf("compression value %d", d.firstVal(tCompression)))
- }
- if err != nil {
- return nil, err
- }
-
- xmin := i * blockWidth
- ymin := j * blockHeight
- xmax := xmin + blkW
- ymax := ymin + blkH
- err = d.decode(img, xmin, ymin, xmax, ymax)
- if err != nil {
- return nil, err
- }
- }
- }
- return
-}
-
-func readBuf(r io.Reader, buf []byte, lim int64) ([]byte, error) {
- b := bytes.NewBuffer(buf[:0])
- _, err := b.ReadFrom(io.LimitReader(r, lim))
- return b.Bytes(), err
-}
-
-func init() {
- image.RegisterFormat("tiff", leHeader, Decode, DecodeConfig)
- image.RegisterFormat("tiff", beHeader, Decode, DecodeConfig)
-}
diff --git a/vendor/golang.org/x/image/tiff/writer.go b/vendor/golang.org/x/image/tiff/writer.go
deleted file mode 100644
index 5d461841c..000000000
--- a/vendor/golang.org/x/image/tiff/writer.go
+++ /dev/null
@@ -1,441 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package tiff
-
-import (
- "bytes"
- "compress/zlib"
- "encoding/binary"
- "errors"
- "image"
- "io"
- "sort"
-)
-
-// The TIFF format allows to choose the order of the different elements freely.
-// The basic structure of a TIFF file written by this package is:
-//
-// 1. Header (8 bytes).
-// 2. Image data.
-// 3. Image File Directory (IFD).
-// 4. "Pointer area" for larger entries in the IFD.
-
-// We only write little-endian TIFF files.
-var enc = binary.LittleEndian
-
-// An ifdEntry is a single entry in an Image File Directory.
-// A value of type dtRational is composed of two 32-bit values,
-// thus data contains two uints (numerator and denominator) for a single number.
-type ifdEntry struct {
- tag int
- datatype int
- data []uint32
-}
-
-func (e ifdEntry) putData(p []byte) {
- for _, d := range e.data {
- switch e.datatype {
- case dtByte, dtASCII:
- p[0] = byte(d)
- p = p[1:]
- case dtShort:
- enc.PutUint16(p, uint16(d))
- p = p[2:]
- case dtLong, dtRational:
- enc.PutUint32(p, uint32(d))
- p = p[4:]
- }
- }
-}
-
-type byTag []ifdEntry
-
-func (d byTag) Len() int { return len(d) }
-func (d byTag) Less(i, j int) bool { return d[i].tag < d[j].tag }
-func (d byTag) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
-
-func encodeGray(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
- if !predictor {
- return writePix(w, pix, dy, dx, stride)
- }
- buf := make([]byte, dx)
- for y := 0; y < dy; y++ {
- min := y*stride + 0
- max := y*stride + dx
- off := 0
- var v0 uint8
- for i := min; i < max; i++ {
- v1 := pix[i]
- buf[off] = v1 - v0
- v0 = v1
- off++
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-func encodeGray16(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
- buf := make([]byte, dx*2)
- for y := 0; y < dy; y++ {
- min := y*stride + 0
- max := y*stride + dx*2
- off := 0
- var v0 uint16
- for i := min; i < max; i += 2 {
- // An image.Gray16's Pix is in big-endian order.
- v1 := uint16(pix[i])<<8 | uint16(pix[i+1])
- if predictor {
- v0, v1 = v1, v1-v0
- }
- // We only write little-endian TIFF files.
- buf[off+0] = byte(v1)
- buf[off+1] = byte(v1 >> 8)
- off += 2
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
- if !predictor {
- return writePix(w, pix, dy, dx*4, stride)
- }
- buf := make([]byte, dx*4)
- for y := 0; y < dy; y++ {
- min := y*stride + 0
- max := y*stride + dx*4
- off := 0
- var r0, g0, b0, a0 uint8
- for i := min; i < max; i += 4 {
- r1, g1, b1, a1 := pix[i+0], pix[i+1], pix[i+2], pix[i+3]
- buf[off+0] = r1 - r0
- buf[off+1] = g1 - g0
- buf[off+2] = b1 - b0
- buf[off+3] = a1 - a0
- off += 4
- r0, g0, b0, a0 = r1, g1, b1, a1
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-func encodeRGBA64(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
- buf := make([]byte, dx*8)
- for y := 0; y < dy; y++ {
- min := y*stride + 0
- max := y*stride + dx*8
- off := 0
- var r0, g0, b0, a0 uint16
- for i := min; i < max; i += 8 {
- // An image.RGBA64's Pix is in big-endian order.
- r1 := uint16(pix[i+0])<<8 | uint16(pix[i+1])
- g1 := uint16(pix[i+2])<<8 | uint16(pix[i+3])
- b1 := uint16(pix[i+4])<<8 | uint16(pix[i+5])
- a1 := uint16(pix[i+6])<<8 | uint16(pix[i+7])
- if predictor {
- r0, r1 = r1, r1-r0
- g0, g1 = g1, g1-g0
- b0, b1 = b1, b1-b0
- a0, a1 = a1, a1-a0
- }
- // We only write little-endian TIFF files.
- buf[off+0] = byte(r1)
- buf[off+1] = byte(r1 >> 8)
- buf[off+2] = byte(g1)
- buf[off+3] = byte(g1 >> 8)
- buf[off+4] = byte(b1)
- buf[off+5] = byte(b1 >> 8)
- buf[off+6] = byte(a1)
- buf[off+7] = byte(a1 >> 8)
- off += 8
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-func encode(w io.Writer, m image.Image, predictor bool) error {
- bounds := m.Bounds()
- buf := make([]byte, 4*bounds.Dx())
- for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
- off := 0
- if predictor {
- var r0, g0, b0, a0 uint8
- for x := bounds.Min.X; x < bounds.Max.X; x++ {
- r, g, b, a := m.At(x, y).RGBA()
- r1 := uint8(r >> 8)
- g1 := uint8(g >> 8)
- b1 := uint8(b >> 8)
- a1 := uint8(a >> 8)
- buf[off+0] = r1 - r0
- buf[off+1] = g1 - g0
- buf[off+2] = b1 - b0
- buf[off+3] = a1 - a0
- off += 4
- r0, g0, b0, a0 = r1, g1, b1, a1
- }
- } else {
- for x := bounds.Min.X; x < bounds.Max.X; x++ {
- r, g, b, a := m.At(x, y).RGBA()
- buf[off+0] = uint8(r >> 8)
- buf[off+1] = uint8(g >> 8)
- buf[off+2] = uint8(b >> 8)
- buf[off+3] = uint8(a >> 8)
- off += 4
- }
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-// writePix writes the internal byte array of an image to w. It is less general
-// but much faster then encode. writePix is used when pix directly
-// corresponds to one of the TIFF image types.
-func writePix(w io.Writer, pix []byte, nrows, length, stride int) error {
- if length == stride {
- _, err := w.Write(pix[:nrows*length])
- return err
- }
- for ; nrows > 0; nrows-- {
- if _, err := w.Write(pix[:length]); err != nil {
- return err
- }
- pix = pix[stride:]
- }
- return nil
-}
-
-func writeIFD(w io.Writer, ifdOffset int, d []ifdEntry) error {
- var buf [ifdLen]byte
- // Make space for "pointer area" containing IFD entry data
- // longer than 4 bytes.
- parea := make([]byte, 1024)
- pstart := ifdOffset + ifdLen*len(d) + 6
- var o int // Current offset in parea.
-
- // The IFD has to be written with the tags in ascending order.
- sort.Sort(byTag(d))
-
- // Write the number of entries in this IFD.
- if err := binary.Write(w, enc, uint16(len(d))); err != nil {
- return err
- }
- for _, ent := range d {
- enc.PutUint16(buf[0:2], uint16(ent.tag))
- enc.PutUint16(buf[2:4], uint16(ent.datatype))
- count := uint32(len(ent.data))
- if ent.datatype == dtRational {
- count /= 2
- }
- enc.PutUint32(buf[4:8], count)
- datalen := int(count * lengths[ent.datatype])
- if datalen <= 4 {
- ent.putData(buf[8:12])
- } else {
- if (o + datalen) > len(parea) {
- newlen := len(parea) + 1024
- for (o + datalen) > newlen {
- newlen += 1024
- }
- newarea := make([]byte, newlen)
- copy(newarea, parea)
- parea = newarea
- }
- ent.putData(parea[o : o+datalen])
- enc.PutUint32(buf[8:12], uint32(pstart+o))
- o += datalen
- }
- if _, err := w.Write(buf[:]); err != nil {
- return err
- }
- }
- // The IFD ends with the offset of the next IFD in the file,
- // or zero if it is the last one (page 14).
- if err := binary.Write(w, enc, uint32(0)); err != nil {
- return err
- }
- _, err := w.Write(parea[:o])
- return err
-}
-
-// Options are the encoding parameters.
-type Options struct {
- // Compression is the type of compression used.
- Compression CompressionType
- // Predictor determines whether a differencing predictor is used;
- // if true, instead of each pixel's color, the color difference to the
- // preceding one is saved. This improves the compression for certain
- // types of images and compressors. For example, it works well for
- // photos with Deflate compression.
- Predictor bool
-}
-
-// Encode writes the image m to w. opt determines the options used for
-// encoding, such as the compression type. If opt is nil, an uncompressed
-// image is written.
-func Encode(w io.Writer, m image.Image, opt *Options) error {
- d := m.Bounds().Size()
-
- compression := uint32(cNone)
- predictor := false
- if opt != nil {
- compression = opt.Compression.specValue()
- // The predictor field is only used with LZW. See page 64 of the spec.
- predictor = opt.Predictor && compression == cLZW
- }
-
- _, err := io.WriteString(w, leHeader)
- if err != nil {
- return err
- }
-
- // Compressed data is written into a buffer first, so that we
- // know the compressed size.
- var buf bytes.Buffer
- // dst holds the destination for the pixel data of the image --
- // either w or a writer to buf.
- var dst io.Writer
- // imageLen is the length of the pixel data in bytes.
- // The offset of the IFD is imageLen + 8 header bytes.
- var imageLen int
-
- switch compression {
- case cNone:
- dst = w
- // Write IFD offset before outputting pixel data.
- switch m.(type) {
- case *image.Paletted:
- imageLen = d.X * d.Y * 1
- case *image.Gray:
- imageLen = d.X * d.Y * 1
- case *image.Gray16:
- imageLen = d.X * d.Y * 2
- case *image.RGBA64:
- imageLen = d.X * d.Y * 8
- case *image.NRGBA64:
- imageLen = d.X * d.Y * 8
- default:
- imageLen = d.X * d.Y * 4
- }
- err = binary.Write(w, enc, uint32(imageLen+8))
- if err != nil {
- return err
- }
- case cDeflate:
- dst = zlib.NewWriter(&buf)
- default:
- return errors.New("tiff: unsupported compression")
- }
-
- pr := uint32(prNone)
- photometricInterpretation := uint32(pRGB)
- samplesPerPixel := uint32(4)
- bitsPerSample := []uint32{8, 8, 8, 8}
- extraSamples := uint32(0)
- colorMap := []uint32{}
-
- if predictor {
- pr = prHorizontal
- }
- switch m := m.(type) {
- case *image.Paletted:
- photometricInterpretation = pPaletted
- samplesPerPixel = 1
- bitsPerSample = []uint32{8}
- colorMap = make([]uint32, 256*3)
- for i := 0; i < 256 && i < len(m.Palette); i++ {
- r, g, b, _ := m.Palette[i].RGBA()
- colorMap[i+0*256] = uint32(r)
- colorMap[i+1*256] = uint32(g)
- colorMap[i+2*256] = uint32(b)
- }
- err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.Gray:
- photometricInterpretation = pBlackIsZero
- samplesPerPixel = 1
- bitsPerSample = []uint32{8}
- err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.Gray16:
- photometricInterpretation = pBlackIsZero
- samplesPerPixel = 1
- bitsPerSample = []uint32{16}
- err = encodeGray16(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.NRGBA:
- extraSamples = 2 // Unassociated alpha.
- err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.NRGBA64:
- extraSamples = 2 // Unassociated alpha.
- bitsPerSample = []uint32{16, 16, 16, 16}
- err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.RGBA:
- extraSamples = 1 // Associated alpha.
- err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.RGBA64:
- extraSamples = 1 // Associated alpha.
- bitsPerSample = []uint32{16, 16, 16, 16}
- err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- default:
- extraSamples = 1 // Associated alpha.
- err = encode(dst, m, predictor)
- }
- if err != nil {
- return err
- }
-
- if compression != cNone {
- if err = dst.(io.Closer).Close(); err != nil {
- return err
- }
- imageLen = buf.Len()
- if err = binary.Write(w, enc, uint32(imageLen+8)); err != nil {
- return err
- }
- if _, err = buf.WriteTo(w); err != nil {
- return err
- }
- }
-
- ifd := []ifdEntry{
- {tImageWidth, dtShort, []uint32{uint32(d.X)}},
- {tImageLength, dtShort, []uint32{uint32(d.Y)}},
- {tBitsPerSample, dtShort, bitsPerSample},
- {tCompression, dtShort, []uint32{compression}},
- {tPhotometricInterpretation, dtShort, []uint32{photometricInterpretation}},
- {tStripOffsets, dtLong, []uint32{8}},
- {tSamplesPerPixel, dtShort, []uint32{samplesPerPixel}},
- {tRowsPerStrip, dtShort, []uint32{uint32(d.Y)}},
- {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}},
- // There is currently no support for storing the image
- // resolution, so give a bogus value of 72x72 dpi.
- {tXResolution, dtRational, []uint32{72, 1}},
- {tYResolution, dtRational, []uint32{72, 1}},
- {tResolutionUnit, dtShort, []uint32{resPerInch}},
- }
- if pr != prNone {
- ifd = append(ifd, ifdEntry{tPredictor, dtShort, []uint32{pr}})
- }
- if len(colorMap) != 0 {
- ifd = append(ifd, ifdEntry{tColorMap, dtShort, colorMap})
- }
- if extraSamples > 0 {
- ifd = append(ifd, ifdEntry{tExtraSamples, dtShort, []uint32{extraSamples}})
- }
-
- return writeIFD(w, imageLen+8, ifd)
-}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 612d8a0f7..52a61a714 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -175,9 +175,6 @@ github.com/coreos/go-systemd/v22/dbus
# github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
## explicit
github.com/davecgh/go-spew/spew
-# github.com/disintegration/imaging v1.6.2
-## explicit
-github.com/disintegration/imaging
# github.com/docker/go-units v0.5.0
## explicit
github.com/docker/go-units
@@ -1095,11 +1092,7 @@ golang.org/x/exp/slog/internal
golang.org/x/exp/slog/internal/buffer
# golang.org/x/image v0.19.0
## explicit; go 1.18
-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