Skip to content

Instantly share code, notes, and snippets.

@BjoernSchilberg
Forked from s-l-teichmann/blindtiffs.go
Created November 1, 2017 12:37
Show Gist options
  • Save BjoernSchilberg/b8dbd7c273ff5e3cd15bbd83ed790ef0 to your computer and use it in GitHub Desktop.
Save BjoernSchilberg/b8dbd7c273ff5e3cd15bbd83ed790ef0 to your computer and use it in GitHub Desktop.
A small tool to create a copy of a directory tree with all GeoTIFFs 'blinded' (all values zero) by gdal_calc.py preserving the meta data.
// blindtiffs
// ----------
// Usage: blindtiffs <src> <dst>
// Recursively copies folder <src> to folder <dst>.
// All GeoTIFFs in the source tree are 'blinded' by
// gdal_calc.py to have zero channels but still contain
// all the meta data.
//
// (c) 2017 by Sascha L. Teichmann
// This is Free Software covered by the terms of the Apache 2 license.
// See http://www.apache.org/licenses/LICENSE-2.0.txt for Details.
package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"sync"
)
func copyTiff(dst, src string) error {
cmd := exec.Command(
"gdal_calc.py",
"-A", src,
"--outfile="+dst,
"--calc=A*0",
"--co=COMPRESS=DEFLATE",
"--co=PREDICTOR=2",
"--co=ZLEVEL=9",
"--allBands=A")
out, err := cmd.CombinedOutput()
if err != nil {
log.Printf("error: %s -> %s\n%s\n", src, dst, out)
} else {
fmt.Printf("%s\n", out)
}
return err
}
func copyFile(dst, src string) error {
s, err := os.Open(src)
if err != nil {
return err
}
defer s.Close()
d, err := os.Create(dst)
if err != nil {
return err
}
if _, err = io.Copy(d, s); err != nil {
d.Close()
return err
}
return d.Close()
}
func copyAll(dst, src string, jobs chan<- [2]string) error {
sfi, err := os.Stat(src)
if err != nil {
return err
}
if sfi.IsDir() {
return copyDir(dst, src, jobs)
}
jobs <- [2]string{dst, src}
return nil
}
func copyDir(dst, src string, jobs chan<- [2]string) error {
d, err := os.Open(src)
if err != nil {
return err
}
names, err := d.Readdirnames(0)
d.Close()
if err != nil {
return nil
}
if dfi, err := os.Stat(dst); err != nil {
if os.IsNotExist(err) {
if err := os.MkdirAll(dst, 0777); err != nil {
return err
}
} else {
return err
}
} else if !dfi.IsDir() {
return fmt.Errorf("'%s' is not a directory.", dst)
}
for _, name := range names {
fname := filepath.Join(src, name)
fi, err := os.Stat(fname)
if err != nil {
return nil
}
if fi.IsDir() {
if err := copyDir(fname, filepath.Join(dst, name), jobs); err != nil {
return err
}
} else {
jobs <- [2]string{filepath.Join(dst, name), fname}
}
}
return nil
}
func main() {
flag.Parse()
if flag.NArg() < 2 {
log.Fatalln("Need two arguments.")
}
jobs := make(chan [2]string)
var wg sync.WaitGroup
for i := runtime.NumCPU(); i > 0; i-- {
wg.Add(1)
go func() {
defer wg.Done()
for pair := range jobs {
dst, src := pair[0], pair[1]
fmt.Printf("%s -> %s\n", src, dst)
cpy := copyFile
if l := strings.ToLower(filepath.Ext(src)); l == ".tif" || l == ".tiff" {
cpy = copyTiff
}
if err := cpy(dst, src); err != nil {
log.Printf("error: %v\n", err)
}
}
}()
}
copyAll(flag.Arg(1), flag.Arg(0), jobs)
close(jobs)
wg.Wait()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment