diff --git a/.vscode/settings.json b/.vscode/settings.json index e9e1230..51b7639 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,8 +7,15 @@ "hacky", "hilbertify", "kbinani", + "manifoldco", "mapcap", + "nfnt", "noita", - "schollz" + "schollz", + "tcnksm", + "xmax", + "xmin", + "ymax", + "ymin" ] } \ No newline at end of file diff --git a/README.md b/README.md index 2193466..605f3c1 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,21 @@ Addon that captures the map and saves it as image. ![](images/example1.png) +A resulting image with close to 3 gigapixels can be [seen here](https://easyzoom.com/image/158284/album/0/4). + ## State Works somewhat, still in development. **To-Do:** -- [ ] Reduce memory usage of stitching program +- [x] Reduce memory usage of stitching program - [x] Make stitching multi threaded -- [ ] Add parameters to stitching program +- [x] Add parameters to stitching program - [x] Show progress while stitching - [x] Improve image quality, reduce artifacts - [ ] Travis or similar for automatic builds, right now there are no executables -- [ ] Fix crash while taking screenshots +- [x] Fix crash while taking screenshots ## Usage @@ -35,7 +37,7 @@ Works somewhat, still in development. ## Advanced usage -If you use `noita_dev.exe`, you can enable the debug mode by pressing `F5`. Once in debug mode, you can use `F8` to toggle shaders (Includes fog of war), and you can use `F7` to disable the UI. +If you use `noita_dev.exe`, you can enable the debug mode by pressing `F5`. Once in debug mode, you can use `F8` to toggle shaders (Includes fog of war), and you can use `F12` to disable the UI. There are some more options in the `F7` and `Shift + F7` menu. ## License diff --git a/bin/stitch/README.md b/bin/stitch/README.md new file mode 100644 index 0000000..44ae7d5 --- /dev/null +++ b/bin/stitch/README.md @@ -0,0 +1,62 @@ +# Stitch + +A program to stitch (overlapping) image tiles of pixel-art to one big image. + +The program will use median filtering for overlapping images. +That means that all moving object will completely disappear, and only the static pixels will be outputted. +But this has the disadvantage of being slower, and objects that move only a little bit may become blurred. + +You can also use this program to remove moving objects from a series of photographs taken with a tripod. +But as this tool is designed for pixel art, it only accepts png as input. + +## Source images + +The source images need to contain their coordinates in the filename, as this program doesn't align the images: + +`%d,%d.png` + +example list of files: + +``` Shell Session +0,0.png +512,0.png +-512,0.png +512,-512.png +``` + +## Usage + +- Run the program and follow the interactive prompt. +- Run the program with parameters: + - `divide int` + A downscaling factor. 2 will produce an image with half the side lengths. (default 2) + - `input string`The source path of the image tiles to be stitched. (default "..\\..\\output") + - `output string` + The path and filename of the resulting stitched image. (default "output.png") + - `xmax int` + Right bound of the output rectangle. This coordinate is not included in the output. + - `xmin int` + Left bound of the output rectangle. This coordinate is included in the output. + - `ymax int` + Lower bound of the output rectangle. This coordinate is not included in the output. + - `ymin int` + Upper bound of the output rectangle. This coordinate is included in the output. + +Example of usage: + +``` Shell Session +./stitch -divide 2 +``` + +Example of output: + +``` Shell Session +2019/10/25 16:02:25 Starting to read tile information at "..\..\output" +2019/10/25 16:02:34 Got 43338 tiles +2019/10/25 16:02:34 Total size of the possible output space is (-19968,-36864)-(21184,35100) +2019/10/25 16:02:34 Creating output image with a size of (41152,71964) +2019/10/25 16:02:46 Stitching 43338 tiles into an image at (-19968,-36864)-(21184,35100) + 100% |████████████████████████████████████████| [33m13s:0s] +2019/10/25 16:35:59 Creating output file "output.png" +2019/10/25 16:44:17 Created output file "output.png" +``` diff --git a/bin/stitch/imagetiles.go b/bin/stitch/imagetiles.go index 943298b..ab3189e 100644 --- a/bin/stitch/imagetiles.go +++ b/bin/stitch/imagetiles.go @@ -44,7 +44,7 @@ func loadImages(path string, scaleDivider int) ([]imageTile, error) { return nil, fmt.Errorf("Invalid scale of %v", scaleDivider) } - files, err := filepath.Glob(filepath.Join(inputPath, "*.png")) + files, err := filepath.Glob(filepath.Join(path, "*.png")) if err != nil { return nil, err } @@ -267,7 +267,7 @@ func (tp tilePairs) StitchGrid(tiles []imageTile, destImage *image.RGBA, gridSiz // Start worker threads wc := make(chan image.Rectangle) wg := sync.WaitGroup{} - for i := 0; i < runtime.NumCPU(); i++ { + for i := 0; i < runtime.NumCPU()*2; i++ { wg.Add(1) go func() { defer wg.Done() diff --git a/bin/stitch/stitch.go b/bin/stitch/stitch.go index 7375d04..aa27498 100644 --- a/bin/stitch/stitch.go +++ b/bin/stitch/stitch.go @@ -6,21 +6,78 @@ package main import ( + "flag" + "fmt" "image" "image/png" "log" "os" "path/filepath" + + "github.com/manifoldco/promptui" ) -var inputPath = filepath.Join(".", "..", "..", "output") +var flagInputPath = flag.String("input", filepath.Join(".", "..", "..", "output"), "The source path of the image tiles to be stitched.") +var flagOutputPath = flag.String("output", filepath.Join(".", "output.png"), "The path and filename of the resulting stitched image.") +var flagScaleDivider = flag.Int("divide", 2, "A downscaling factor. 2 will produce an image with half the side lengths.") +var flagXMin = flag.Int("xmin", 0, "Left bound of the output rectangle. This coordinate is included in the output.") +var flagYMin = flag.Int("ymin", 0, "Upper bound of the output rectangle. This coordinate is included in the output.") +var flagXMax = flag.Int("xmax", 0, "Right bound of the output rectangle. This coordinate is not included in the output.") +var flagYMax = flag.Int("ymax", 0, "Lower bound of the output rectangle. This coordinate is not included in the output.") func main() { - log.Printf("Starting to read tile information at \"%v\"", inputPath) - tiles, err := loadImages(inputPath, 2) + flag.Parse() + + // Query the user, if there were no cmd arguments given + if flag.NFlag() == 0 { + prompt := promptui.Prompt{ + Label: "Enter downscaling factor:", + Default: fmt.Sprint(*flagScaleDivider), + AllowEdit: true, + Validate: func(s string) error { + var num int + _, err := fmt.Sscanf(s, "%d", &num) + if err != nil { + return err + } + if int(num) < 1 { + return fmt.Errorf("Number must be larger than 0") + } + + return nil + }, + } + + result, err := prompt.Run() + if err != nil { + log.Panicf("Error while getting user input: %v", err) + } + fmt.Sscanf(result, "%d", flagScaleDivider) + } + + // Query the user, if there were no cmd arguments given + if flag.NFlag() == 0 { + prompt := promptui.Prompt{ + Label: "Enter input path:", + Default: *flagInputPath, + AllowEdit: true, + } + + result, err := prompt.Run() + if err != nil { + log.Panicf("Error while getting user input: %v", err) + } + *flagInputPath = result + } + + log.Printf("Starting to read tile information at \"%v\"", *flagInputPath) + tiles, err := loadImages(*flagInputPath, *flagScaleDivider) if err != nil { log.Panic(err) } + if len(tiles) == 0 { + log.Panicf("Got no tiles inside of %v", *flagInputPath) + } log.Printf("Got %v tiles", len(tiles)) totalBounds := image.Rectangle{} @@ -43,9 +100,58 @@ func main() { } defer pprof.StopCPUProfile()*/ - // TODO: Flags / Program arguments + // If the output rect is empty, use the rectangle that encloses all tiles + outputRect := image.Rect(*flagXMin, *flagYMin, *flagXMax, *flagYMax) + if outputRect.Empty() { + outputRect = totalBounds + } - outputRect := image.Rect(-1900*2, -1900*2, 1900*2, 1900*2) + // Query the user, if there were no cmd arguments given + if flag.NFlag() == 0 { + prompt := promptui.Prompt{ + Label: "Enter output rectangle (xMin,yMin;xMax,yMax):", + Default: fmt.Sprintf("%d,%d;%d,%d", outputRect.Min.X, outputRect.Min.Y, outputRect.Max.X, outputRect.Max.Y), + AllowEdit: true, + Validate: func(s string) error { + var xMin, yMin, xMax, yMax int + _, err := fmt.Sscanf(s, "%d,%d;%d,%d", &xMin, &yMin, &xMax, &yMax) + if err != nil { + return err + } + rect := image.Rect(xMin, yMin, xMax, yMax) + if rect.Empty() { + return fmt.Errorf("Rectangle must not be empty") + } + + outputRect = rect + + return nil + }, + } + + result, err := prompt.Run() + if err != nil { + log.Panicf("Error while getting user input: %v", err) + } + var xMin, yMin, xMax, yMax int + fmt.Sscanf(result, "%d,%d;%d,%d", &xMin, &yMin, &xMax, &yMax) + outputRect = image.Rect(xMin, yMin, xMax, yMax) + } + + // Query the user, if there were no cmd arguments given + if flag.NFlag() == 0 { + prompt := promptui.Prompt{ + Label: "Enter output filename and path:", + Default: *flagOutputPath, + AllowEdit: true, + } + + result, err := prompt.Run() + if err != nil { + log.Panicf("Error while getting user input: %v", err) + } + *flagOutputPath = result + } log.Printf("Creating output image with a size of %v", outputRect.Size()) outputImage := image.NewRGBA(outputRect) diff --git a/go.mod b/go.mod index 82e9b5f..29b0308 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,15 @@ go 1.13 require ( github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 // indirect + github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect github.com/gen2brain/shm v0.0.0-20180314170312-6c18ff7f8b90 // indirect github.com/google/hilbert v0.0.0-20181122061418-320f2e35a565 github.com/kbinani/screenshot v0.0.0-20190719135742-f06580e30cdc github.com/lxn/win v0.0.0-20190919090605-24c5960b03d8 // indirect + github.com/manifoldco/promptui v0.3.2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/schollz/progressbar/v2 v2.14.0 + github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8 // indirect golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 + gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c // indirect ) diff --git a/go.sum b/go.sum index 93cb8be..cb4adb5 100644 --- a/go.sum +++ b/go.sum @@ -1,29 +1,82 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/alecthomas/gometalinter v2.0.11+incompatible h1:ENdXMllZNSVDTJUUVIzBW9CSEpntTrQa76iRsEFLX/M= +github.com/alecthomas/gometalinter v2.0.11+incompatible/go.mod h1:qfIpQGGz3d+NmgyPBqv+LSh50emm1pt72EtcX2vKYQk= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gen2brain/shm v0.0.0-20180314170312-6c18ff7f8b90 h1:QagTG5rauLt6pVVEhnVSrlIX4ifhVIZOwmw6x6D8TUw= github.com/gen2brain/shm v0.0.0-20180314170312-6c18ff7f8b90/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= +github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3 h1:I4BOK3PBMjhWfQM2zPJKK7lOBGsrsvOB7kBELP33hiE= +github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/google/hilbert v0.0.0-20181122061418-320f2e35a565 h1:KBAlCAY6eLC44FiEwbzEbHnpVlw15iVM4ZK8QpRIp4U= github.com/google/hilbert v0.0.0-20181122061418-320f2e35a565/go.mod h1:xn6EodFfRzV6j8NXQRPjngeHWlrpOrsZPKuuLRThU1k= +github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= +github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= +github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc h1:cJlkeAx1QYgO5N80aF5xRGstVsRQwgLR7uA2FnP1ZjY= +github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/kbinani/screenshot v0.0.0-20190719135742-f06580e30cdc h1:kGFotla6Dyr6a2ILeExAHlttPgJtnoP/GIw2uVN/4h4= github.com/kbinani/screenshot v0.0.0-20190719135742-f06580e30cdc/go.mod h1:f8GY5V3lRzakvEyr49P7hHRYoHtPr8zvj/7JodCoRzw= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lxn/win v0.0.0-20190919090605-24c5960b03d8 h1:RVMGIuuNgrpGB7I79f6xfhGCkpN47IaEGh8VTM0p7Xc= github.com/lxn/win v0.0.0-20190919090605-24c5960b03d8/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA= +github.com/manifoldco/promptui v0.3.2 h1:rir7oByTERac6jhpHUPErHuopoRDvO3jxS+FdadEns8= +github.com/manifoldco/promptui v0.3.2/go.mod h1:8JU+igZ+eeiiRku4T5BjtKh2ms8sziGpSYl1gN8Bazw= +github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/nicksnyder/go-i18n v2.0.2+incompatible h1:Xt6dluut3s2zBUha8/3sj6atWMQbFioi9OMqUGH9khg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/schollz/progressbar/v2 v2.14.0 h1:vo7bdkI9E4/CIk9DnL5uVIaybLQiVtiCC2vO+u9j5IM= github.com/schollz/progressbar/v2 v2.14.0/go.mod h1:6YZjqdthH6SCZKv2rqGryrxPtfmRB/DWZxSMfCXPyD8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8 h1:RB0v+/pc8oMzPsN97aZYEwNuJ6ouRJ2uhjxemJ9zvrY= +github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8/go.mod h1:IlWNj9v/13q7xFbaK4mbyzMNwrZLaWSHx/aibKIZuIg= +github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9 h1:vY5WqiEon0ZSTGM3ayVVi+twaHKHDFUVloaQ/wug9/c= +github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9/go.mod h1:q+QjxYvZ+fpjMXqs+XEriussHjSYqeXVnAdSV1tkMYk= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 h1:x/bBzNauLQAlE3fLku/xy92Y8QwKX5HZymrMz2IiKFc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20181122213734-04b5d21e00f1 h1:bsEj/LXbv3BCtkp/rBj9Wi/0Nde4OMaraIZpndHAhdI= +golang.org/x/tools v0.0.0-20181122213734-04b5d21e00f1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c h1:vTxShRUnK60yd8DZU+f95p1zSLj814+5CuEh7NjF2/Y= +gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=