diff --git a/README.md b/README.md index a24c662..faf687d 100644 --- a/README.md +++ b/README.md @@ -191,10 +191,10 @@ This table maps quality settings for JPEG to the respective AVIF and WEBP qualit ### Compile -Install ImageMagick7 (with libheif/libjxl support) and MuPDF libraries and headers and then install to GOBIN: +Install to `GOBIN`: -`go install -tags extlib github.com/gen2brain/cbconvert/cmd/cbconvert@latest` +`go install github.com/gen2brain/cbconvert/cmd/cbconvert@latest` For GUI app, check [IUP requirements](https://github.com/gen2brain/iup-go), and then install: -`go install -tags extlib github.com/gen2brain/cbconvert/cmd/cbconvert-gui@latest` +`go install github.com/gen2brain/cbconvert/cmd/cbconvert-gui@latest` diff --git a/cbconvert.go b/cbconvert.go index 408dffa..240731d 100644 --- a/cbconvert.go +++ b/cbconvert.go @@ -6,6 +6,10 @@ import ( "crypto/md5" "errors" "fmt" + "image" + _ "image/gif" + "image/jpeg" + "image/png" "io" "os" "path/filepath" @@ -15,12 +19,9 @@ import ( "strings" "sync/atomic" - "image" - _ "image/gif" // allow gif decoding - "image/jpeg" - "image/png" - - "git.sr.ht/~jackmordaunt/go-libwebp/webp" + "github.com/gen2brain/avif" + "github.com/gen2brain/jpegxl" + "github.com/gen2brain/webp" "golang.org/x/image/tiff" "github.com/disintegration/imaging" @@ -30,7 +31,6 @@ import ( "github.com/gen2brain/go-fitz" "github.com/gen2brain/go-unarr" "golang.org/x/sync/errgroup" - "gopkg.in/gographics/imagick.v3/imagick" ) // Resample filters. @@ -310,11 +310,7 @@ func (c *Converter) convertArchive(ctx context.Context, fileName string) error { var img image.Image img, err = c.imageDecode(bytes.NewReader(data)) if err != nil { - e := err - img, err = c.imDecode(bytes.NewReader(data), pathName) - if err != nil { - return fmt.Errorf("convertArchive: %w: %w", e, err) - } + return fmt.Errorf("convertArchive: %w", err) } if c.Opts.NoRGB && !isGrayScale(img) { @@ -406,16 +402,7 @@ func (c *Converter) convertDirectory(ctx context.Context, dirPath string) error var i image.Image i, err = c.imageDecode(file) if err != nil { - e := err - _, err = file.Seek(0, io.SeekStart) - if err != nil { - return fmt.Errorf("convertDirectory: %w: %w", e, err) - } - - i, err = c.imDecode(file, img) - if err != nil { - return fmt.Errorf("convertDirectory: %w: %w", e, err) - } + return fmt.Errorf("convertDirectory: %w", err) } if c.Opts.NoRGB && !isGrayScale(i) { @@ -480,15 +467,8 @@ func (c *Converter) imageConvert(ctx context.Context, img image.Image, index int } defer w.Close() - switch c.Opts.Format { - case "jpeg", "png", "tiff", "webp": - if err := c.imageEncode(img, w); err != nil { - return fmt.Errorf("imageConvert: %w", err) - } - case "bmp", "avif", "jxl": - if err := c.imEncode(img, w); err != nil { - return fmt.Errorf("imageConvert: %w", err) - } + if err := c.imageEncode(img, w); err != nil { + return fmt.Errorf("imageConvert: %w", err) } return nil @@ -542,45 +522,6 @@ func (c *Converter) imageDecode(reader io.Reader) (image.Image, error) { return img, nil } -// imDecode decodes image from reader (ImageMagick). -func (c *Converter) imDecode(reader io.Reader, fileName string) (image.Image, error) { - mw := imagick.NewMagickWand() - defer mw.Destroy() - - var img image.Image - - b, err := io.ReadAll(reader) - if err != nil { - return img, fmt.Errorf("imDecode: %w", err) - } - - if err = mw.SetFilename(fileName); err != nil { - return img, fmt.Errorf("imDecode: %w", err) - } - - if err = mw.ReadImageBlob(b); err != nil { - return img, fmt.Errorf("imDecode: %w", err) - } - - w := mw.GetImageWidth() - h := mw.GetImageHeight() - - out, err := mw.ExportImagePixels(0, 0, w, h, "RGBA", imagick.PIXEL_CHAR) - if err != nil { - return img, fmt.Errorf("imDecode: %w", err) - } - - data, ok := out.([]byte) - - if ok { - rgba := image.NewRGBA(image.Rect(0, 0, int(w), int(h))) - rgba.Pix = data - img = rgba - } - - return img, nil -} - // imageEncode encodes image to file. func (c *Converter) imageEncode(img image.Image, w io.Writer) error { var err error @@ -593,7 +534,11 @@ func (c *Converter) imageEncode(img image.Image, w io.Writer) error { case "jpeg": err = jpeg.Encode(w, img, &jpeg.Options{Quality: c.Opts.Quality}) case "webp": - err = webp.Encode(w, img, webp.Quality(float32(c.Opts.Quality))) + err = webp.Encode(w, img, webp.Options{Quality: c.Opts.Quality, Method: webp.DefaultMethod}) + case "avif": + err = avif.Encode(w, img, avif.Options{Quality: c.Opts.Quality, Speed: avif.DefaultSpeed}) + case "jxl": + err = jpegxl.Encode(w, img, jpegxl.Options{Quality: c.Opts.Quality, Effort: jpegxl.DefaultEffort}) } if err != nil { @@ -603,82 +548,6 @@ func (c *Converter) imageEncode(img image.Image, w io.Writer) error { return nil } -// imEncode encodes image to file (ImageMagick). -func (c *Converter) imEncode(i image.Image, w io.Writer) error { - mw := imagick.NewMagickWand() - defer mw.Destroy() - - if err := mw.ConstituteImage(uint(i.Bounds().Dx()), uint(i.Bounds().Dy()), - "RGBA", imagick.PIXEL_CHAR, imageToRGBA(i).Pix); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - - switch c.Opts.Format { - case "png": - if err := mw.SetImageFormat("PNG"); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - case "tiff": - if err := mw.SetImageFormat("TIFF"); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - case "jpeg": - if err := mw.SetImageFormat("JPEG"); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - if err := mw.SetImageCompressionQuality(uint(c.Opts.Quality)); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - case "bmp": - pw := imagick.NewPixelWand() - pw.SetColor("black") - defer pw.Destroy() - - if err := mw.SetImageFormat("BMP3"); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - if err := mw.SetImageBackgroundColor(pw); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - if err := mw.SetImageAlphaChannel(imagick.ALPHA_CHANNEL_REMOVE); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - if err := mw.SetImageAlphaChannel(imagick.ALPHA_CHANNEL_DEACTIVATE); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - if err := mw.SetImageMatte(false); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - if err := mw.SetImageCompression(imagick.COMPRESSION_NO); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - if err := mw.QuantizeImage(16, mw.GetImageColorspace(), 1, imagick.DITHER_METHOD_NO, true); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - case "avif": - if err := mw.SetImageFormat("AVIF"); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - if err := mw.SetImageCompressionQuality(uint(c.Opts.Quality)); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - case "jxl": - if err := mw.SetImageFormat("JXL"); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - if err := mw.SetImageCompressionQuality(uint(c.Opts.Quality)); err != nil { - return fmt.Errorf("imEncode: %w", err) - } - } - - _, err := w.Write(mw.GetImageBlob()) - if err != nil { - return fmt.Errorf("imEncode: %w", err) - } - - return nil -} - // coverArchive extracts cover from archive. func (c *Converter) coverArchive(fileName string) (image.Image, error) { var images []string @@ -714,11 +583,7 @@ func (c *Converter) coverArchive(fileName string) (image.Image, error) { var img image.Image img, err = c.imageDecode(bytes.NewReader(data)) if err != nil { - e := err - img, err = c.imDecode(bytes.NewReader(data), cover) - if err != nil { - return nil, fmt.Errorf("coverArchive: %w: %w", e, err) - } + return nil, fmt.Errorf("coverArchive: %w", err) } return img, nil @@ -759,16 +624,7 @@ func (c *Converter) coverDirectory(dir string) (image.Image, error) { var img image.Image img, err = c.imageDecode(file) if err != nil { - e := err - _, err = file.Seek(0, io.SeekStart) - if err != nil { - return nil, fmt.Errorf("coverDirectory: %w: %w", e, err) - } - - img, err = c.imDecode(file, cover) - if err != nil { - return nil, fmt.Errorf("coverDirectory: %w: %w", e, err) - } + return nil, fmt.Errorf("coverDirectory: %w", err) } return img, nil @@ -830,16 +686,6 @@ func (c *Converter) coverImage(fileName string, fileInfo os.FileInfo) (image.Ima return cover, nil } -// Initialize inits ImageMagick. -func (c *Converter) Initialize() { - imagick.Initialize() -} - -// Terminate terminates ImageMagick. -func (c *Converter) Terminate() { - imagick.Terminate() -} - // Cancel cancels the operation. func (c *Converter) Cancel() { if c.OnCancel != nil { @@ -989,15 +835,8 @@ func (c *Converter) Cover(fileName string, fileInfo os.FileInfo) error { } defer w.Close() - switch c.Opts.Format { - case "jpeg", "png", "tiff", "webp": - if err := c.imageEncode(cover, w); err != nil { - return fmt.Errorf("%s: %w", fileName, err) - } - case "bmp", "avif", "jxl": - if err := c.imEncode(cover, w); err != nil { - return fmt.Errorf("%s: %w", fileName, err) - } + if err := c.imageEncode(cover, w); err != nil { + return fmt.Errorf("%s: %w", fileName, err) } return nil @@ -1164,15 +1003,8 @@ func (c *Converter) Preview(fileName string, fileInfo os.FileInfo, width, height var w bytes.Buffer - switch c.Opts.Format { - case "jpeg", "png", "tiff", "webp": - if err := c.imageEncode(i, &w); err != nil { - return img, fmt.Errorf("%s: %w", fileName, err) - } - case "bmp", "avif", "jxl": - if err := c.imEncode(i, &w); err != nil { - return img, fmt.Errorf("%s: %w", fileName, err) - } + if err := c.imageEncode(i, &w); err != nil { + return img, fmt.Errorf("%s: %w", fileName, err) } img.Width = i.Bounds().Dx() @@ -1183,16 +1015,7 @@ func (c *Converter) Preview(fileName string, fileInfo os.FileInfo, width, height dec, err := c.imageDecode(r) if err != nil { - e := err - _, err = r.Seek(0, io.SeekStart) - if err != nil { - return img, fmt.Errorf("%s: %w: %w", fileName, e, err) - } - - dec, err = c.imDecode(r, "cbc."+c.Opts.Format) - if err != nil { - return img, fmt.Errorf("%s: %w: %w", fileName, e, err) - } + return img, fmt.Errorf("%s: %w", fileName, err) } if width != 0 && height != 0 { diff --git a/cmd/cbconvert-gui/main.go b/cmd/cbconvert-gui/main.go index f79e2be..eca3b3d 100644 --- a/cmd/cbconvert-gui/main.go +++ b/cmd/cbconvert-gui/main.go @@ -260,9 +260,6 @@ func previewPost() { go func(opts cbconvert.Options) { conv := cbconvert.New(opts) - conv.Initialize() - defer conv.Terminate() - file := files[index] img, err := conv.Preview(file.Path, file.Stat, width, height) if err != nil { @@ -765,9 +762,6 @@ func onThumbnail(ih iup.Ihandle) int { iup.PostMessage(iup.GetHandle("ProgressBar"), "start", 0, conv) go func(c *cbconvert.Converter) { - c.Initialize() - defer c.Terminate() - for _, file := range files { if canceled { break @@ -811,9 +805,6 @@ func onCover(ih iup.Ihandle) int { iup.PostMessage(iup.GetHandle("ProgressBar"), "start", 0, conv) go func(c *cbconvert.Converter) { - c.Initialize() - defer c.Terminate() - for _, file := range files { if canceled { break @@ -860,9 +851,6 @@ func onConvert(ih iup.Ihandle) int { })) go func(c *cbconvert.Converter) { - c.Initialize() - defer c.Terminate() - for _, file := range files { if err := c.Convert(file.Path, file.Stat); err != nil { if errors.Is(err, context.Canceled) { diff --git a/cmd/cbconvert/main.go b/cmd/cbconvert/main.go index 156f1a6..b287214 100644 --- a/cmd/cbconvert/main.go +++ b/cmd/cbconvert/main.go @@ -72,9 +72,6 @@ func main() { os.Exit(1) } - conv.Initialize() - defer conv.Terminate() - files, err := conv.Files(args) if err != nil { fmt.Println(err) diff --git a/go.mod b/go.mod index c301222..acd01c6 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,17 @@ module github.com/gen2brain/cbconvert go 1.23 require ( - git.sr.ht/~jackmordaunt/go-libwebp v1.8.0 github.com/disintegration/imaging v1.6.2 github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d github.com/dustin/go-humanize v1.0.1 github.com/fvbommel/sortorder v1.1.0 + github.com/gen2brain/avif v0.4.0 github.com/gen2brain/go-fitz v1.24.14 github.com/gen2brain/go-unarr v0.2.3 + github.com/gen2brain/jpegxl v0.4.1 + github.com/gen2brain/webp v0.5.0 golang.org/x/image v0.21.0 - gopkg.in/gographics/imagick.v3 v3.5.1 + golang.org/x/sync v0.8.0 ) require ( @@ -21,16 +23,8 @@ require ( github.com/ebitengine/purego v0.8.1 // indirect github.com/go-errors/errors v1.1.1 // indirect github.com/golang/geo v0.0.0-20200319012246-673a6f80352d // indirect - github.com/google/uuid v1.6.0 // indirect github.com/jupiterrider/ffi v0.2.1 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/ncruces/go-strftime v0.1.9 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect + github.com/tetratelabs/wazero v1.8.1 // indirect golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 // indirect - golang.org/x/sys v0.26.0 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect - modernc.org/libc v1.61.0 // indirect - modernc.org/mathutil v1.6.0 // indirect - modernc.org/memory v1.8.0 // indirect ) diff --git a/go.sum b/go.sum index 860ee12..6142e78 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -git.sr.ht/~jackmordaunt/go-libwebp v1.8.0 h1:05YWkouuQnR6CTPz/TlN0J9hXQiZDFk+bWeIbd73c7M= -git.sr.ht/~jackmordaunt/go-libwebp v1.8.0/go.mod h1:rXiwpxkkOe8OEvhh9g+HIvtPpBxgZXQyB6s+HXQUFyI= 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/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E= @@ -21,10 +19,16 @@ github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/ github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/gen2brain/avif v0.4.0 h1:JuwAX2rVrkAzQrZx9lpIKx/ovCO35gCUquarfJ6uhHc= +github.com/gen2brain/avif v0.4.0/go.mod h1:oePci7KPleKZ8X/2rjZ3FlVm2JFYjPwXiQpNgq9wrzs= github.com/gen2brain/go-fitz v1.24.14 h1:09weRkjVtLYNGo7l0J7DyOwBExbwi8SJ9h8YPhw9WEo= github.com/gen2brain/go-fitz v1.24.14/go.mod h1:0KaZeQgASc20Yp5R/pFzyy7SmP01XcoHKNF842U2/S4= github.com/gen2brain/go-unarr v0.2.3 h1:VwZg0P6Dc/8Uh51McjVhzUMg4wHwwbiyqjEFsFELc0c= github.com/gen2brain/go-unarr v0.2.3/go.mod h1:hoHheVuf0KT8/hfvkEL7GMwj2h7fq0lF72NdyySdr3c= +github.com/gen2brain/jpegxl v0.4.1 h1:jWaVp5GkXLJXjRvC+g0R9+uo+xoWiS7DYKxJ3n5gHL4= +github.com/gen2brain/jpegxl v0.4.1/go.mod h1:zIIDnzh7WqG+z66zyzLWQ0M4AS5xi//pyJLgu32GB1o= +github.com/gen2brain/webp v0.5.0 h1:nn3o0BtKltoFKX9rlDZG/Y/aWqNzUZVyXdB815yVNfU= +github.com/gen2brain/webp v0.5.0/go.mod h1:Nb3xO5sy6MeUAHhru9H3GT7nlOQO5dKRNNlE92CZrJw= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= github.com/go-errors/errors v1.1.1 h1:ljK/pL5ltg3qoN+OtN6yCv9HWSfMwxSx90GJCZQxYNg= @@ -32,25 +36,15 @@ github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWE github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/geo v0.0.0-20200319012246-673a6f80352d h1:C/hKUcHT483btRbeGkrRjJz+Zbcj8audldIi9tRJDCc= github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jupiterrider/ffi v0.2.1 h1:08GJVDqz4eoQq7cKT1T0kwb9MB58XEAGjgxDvz80yBs= github.com/jupiterrider/ffi v0.2.1/go.mod h1:tJ7Q8p/3blFjdWt5qJU4W5oDE0xloImvrViE+0td0Rk= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= -github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550= +github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s= golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -61,38 +55,9 @@ golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/gographics/imagick.v3 v3.5.1 h1:58JqK0UCx5RfvbRggF5FKuK6jHwAtTQopUxK8mzFa40= -gopkg.in/gographics/imagick.v3 v3.5.1/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= -modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.21.0 h1:kKPI3dF7RIag8YcToh5ZwDcVMIv6VGa0ED5cvh0LMW4= -modernc.org/ccgo/v4 v4.21.0/go.mod h1:h6kt6H/A2+ew/3MW/p6KEoQmrq/i3pr0J/SiwiaF/g0= -modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= -modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= -modernc.org/gc/v2 v2.5.0 h1:bJ9ChznK1L1mUtAQtxi0wi5AtAs5jQuw4PrPHO5pb6M= -modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= -modernc.org/libc v1.61.0 h1:eGFcvWpqlnoGwzZeZe3PWJkkKbM/3SUGyk1DVZQ0TpE= -modernc.org/libc v1.61.0/go.mod h1:DvxVX89wtGTu+r72MLGhygpfi3aUGgZRdAYGCAVVud0= -modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= -modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= -modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= -modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= -modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= -modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= -modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= -modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=