mirror of
				https://github.com/axllent/goptimize.git
				synced 2025-10-30 18:17:25 -04:00 
			
		
		
		
	Compare commits
	
		
			12 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ee6aa69087 | ||
|  | 8362617920 | ||
|  | b157fcd72b | ||
|  | 0c000fe262 | ||
|  | 97fa6c94c5 | ||
|  | 36e9b4c8fa | ||
|  | 5df486c53e | ||
|  | 120e5fefde | ||
|  | d2a591a6d9 | ||
|  | 8e5e7b6098 | ||
|  | 47024e030b | ||
|  | 45915d4b42 | 
| @@ -1,5 +1,10 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## [dev] | ||||
|  | ||||
| - Switch to [pflag](https://github.com/spf13/pflag) for better flag management | ||||
|  | ||||
|  | ||||
| ## [0.0.1] | ||||
|  | ||||
| - Initial release | ||||
|   | ||||
							
								
								
									
										3
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
									
									
									
									
								
							| @@ -6,7 +6,7 @@ build = echo "\n\nBuilding $(1)-$(2)" && GOOS=$(1) GOARCH=$(2) go build ${LDFLAG | ||||
| 	&& bzip2 dist/goptimize_${VERSION}_$(1)_$(2) | ||||
|  | ||||
| goptimize: *.go | ||||
| 	go get github.com/disintegration/imaging | ||||
| 	go get github.com/disintegration/imaging golang.org/x/image/bmp golang.org/x/image/tiff github.com/axllent/gitrel github.com/spf13/pflag | ||||
| 	go build ${LDFLAGS} -o goptimize | ||||
| 	rm -rf /tmp/go-* | ||||
|  | ||||
| @@ -16,6 +16,7 @@ clean: | ||||
| release: | ||||
| 	mkdir -p dist | ||||
| 	rm -f dist/goptimize_${VERSION}_* | ||||
| 	go get github.com/disintegration/imaging golang.org/x/image/bmp golang.org/x/image/tiff github.com/axllent/gitrel github.com/spf13/pflag | ||||
| 	$(call build,linux,amd64) | ||||
| 	$(call build,linux,386) | ||||
| 	$(call build,linux,arm) | ||||
|   | ||||
							
								
								
									
										49
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | ||||
| # Goptimizer - downscales and optimizes images | ||||
|  | ||||
| Goptimizer is a commandline utility written in Golang. It downscales and optimize existing images JPEG, PNG and Gif files. | ||||
| Goptimizer is a commandline utility written in Golang. It downscales and optimizes JPEG, PNG and Gif files. | ||||
|  | ||||
| Image downscaling is done within Goptimize (`-m <width>x<height>`, see [Usage](#usage-options)), however optimization is done using the following additional tools (if they are installed): | ||||
| Image downscaling/rotation is done within goptimize (`-m <width>x<height>`, see [Usage](#usage-options)), however optimization is done using the following additional tools (if they are installed): | ||||
|  | ||||
| - jpegoptim | ||||
| - jpegtran (`libjpeg-turbo-progs`) | ||||
| @@ -28,23 +28,18 @@ It will also preserve (by default) the file's original modification times (`-p=f | ||||
| Usage: ./goptimize [options] <images> | ||||
|  | ||||
| Options: | ||||
|   -gifsicle string | ||||
|         gifsicle binary (default "gifsicle") | ||||
|   -jpegoptim string | ||||
|         jpegoptim binary (default "jpegoptim") | ||||
|   -jpegtran string | ||||
|         jpegtran binary (default "jpegtran") | ||||
|   -m string | ||||
|         downscale to a maximum width & height in pixels (<width>x<height>) | ||||
|   -o string | ||||
|         output directory (default overwrites original) | ||||
|   -optipng string | ||||
|         optipng binary (default "optipng") | ||||
|   -p    preserve file modification times (default true) | ||||
|   -pngquant string | ||||
|         pngquant binary (default "pngquant") | ||||
|   -q int | ||||
|         quality - JPEG only (default 75) | ||||
|   -q, --quality int        quality, JPEG only (default 75) | ||||
|   -m, --max string         downscale to a maximum width & height in pixels (<width>x<height>) | ||||
|   -o, --out string         output directory (default overwrites original) | ||||
|   -p, --preserve           preserve file modification times (default true) | ||||
|   -u, --update             update to latest release | ||||
|   -v, --version            show version number | ||||
|   -h, --help               show help | ||||
|       --jpegtran string    jpegtran binary (default "jpegtran") | ||||
|       --jpegoptim string   jpegoptim binary (default "jpegoptim") | ||||
|       --gifsicle string    gifsicle binary (default "gifsicle") | ||||
|       --pngquant string    pngquant binary (default "pngquant") | ||||
|       --optipng string     optipng binary (default "optipng") | ||||
| ``` | ||||
|  | ||||
|  | ||||
| @@ -54,3 +49,19 @@ Options: | ||||
| - `./goptimize -m 800x800 *` - optimize and downscale all image files to a maximum size of 800x800px | ||||
| - `./goptimize -m 1200x0 image.jpg` - optimize and downscale a JPG file to a maximum size of width of 1200px | ||||
| - `./goptimize -o out/ image.jpg` - optimize a JPG file and save it to `out/` | ||||
|  | ||||
|  | ||||
| ## Install | ||||
|  | ||||
| Download the appropriate binary from the [releases](https://github.com/axllent/goptimize/releases/latest), or if you have golang installed  | ||||
| ``` | ||||
| go get github.com/axllent/goptimize | ||||
| ``` | ||||
|  | ||||
|  | ||||
| ## TODO | ||||
|  | ||||
| Some ideas for the future: | ||||
|  | ||||
| - Dry run | ||||
| - Option to copy exif data (how?) | ||||
|   | ||||
							
								
								
									
										18
									
								
								goptimize.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								goptimize.go
									
									
									
									
									
								
							| @@ -32,7 +32,7 @@ func Goptimize(file string) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// open original, rotate if neccesary | ||||
| 	// open original, rotate if necessary | ||||
| 	src, err := imaging.Open(file, imaging.AutoOrientation(true)) | ||||
|  | ||||
| 	if err != nil { | ||||
| @@ -116,19 +116,19 @@ func Goptimize(file string) { | ||||
| 	if format.String() == "JPEG" { | ||||
| 		// run one or the other, running both has no advantage | ||||
| 		if jpegtran != "" { | ||||
| 			RunOptimiser(tmpFilename, true, jpegtran, "-optimize", "-outfile") | ||||
| 			RunOptimizer(tmpFilename, true, jpegtran, "-optimize", "-outfile") | ||||
| 		} else if jpegoptim != "" { | ||||
| 			RunOptimiser(tmpFilename, false, jpegoptim, "-f", "-s", "-o") | ||||
| 			RunOptimizer(tmpFilename, false, jpegoptim, "-f", "-s", "-o") | ||||
| 		} | ||||
| 	} else if format.String() == "PNG" { | ||||
| 		if pngquant != "" { | ||||
| 			RunOptimiser(tmpFilename, true, pngquant, "-f", "--output") | ||||
| 			RunOptimizer(tmpFilename, true, pngquant, "-f", "--output") | ||||
| 		} | ||||
| 		if optipng != "" { | ||||
| 			RunOptimiser(tmpFilename, true, optipng, "-out") | ||||
| 			RunOptimizer(tmpFilename, true, optipng, "-out") | ||||
| 		} | ||||
| 	} else if format.String() == "GIF" && gifsicle != "" { | ||||
| 		RunOptimiser(tmpFilename, true, gifsicle, "-o") | ||||
| 		RunOptimizer(tmpFilename, true, gifsicle, "-o") | ||||
| 	} | ||||
|  | ||||
| 	// re-open modified temporary file | ||||
| @@ -166,7 +166,7 @@ func Goptimize(file string) { | ||||
| 		defer out.Close() | ||||
|  | ||||
| 		if _, err := io.Copy(out, tmpFile); err != nil { | ||||
| 			fmt.Printf("Error ovewriting original file: %v\n", err) | ||||
| 			fmt.Printf("Error overwriting original file: %v\n", err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| @@ -215,9 +215,9 @@ func Goptimize(file string) { | ||||
|  | ||||
| } | ||||
|  | ||||
| // RunOptimiser will run the specified command on a copy of the temporary file, | ||||
| // RunOptimizer will run the specified command on a copy of the temporary file, | ||||
| // and overwrite it if the output is smaller than the original | ||||
| func RunOptimiser(src string, outFileArg bool, args ...string) { | ||||
| func RunOptimizer(src string, outFileArg bool, args ...string) { | ||||
| 	// create a new temp file | ||||
| 	tmpFile, err := ioutil.TempFile(os.TempDir(), "Goptimized-") | ||||
|  | ||||
|   | ||||
							
								
								
									
										40
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								main.go
									
									
									
									
									
								
							| @@ -1,7 +1,6 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| @@ -9,6 +8,7 @@ import ( | ||||
| 	"strconv" | ||||
|  | ||||
| 	"github.com/axllent/gitrel" | ||||
| 	"github.com/spf13/pflag" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -26,11 +26,15 @@ var ( | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	// set up new flag instance | ||||
| 	flag := pflag.NewFlagSet(os.Args[0], pflag.ExitOnError) | ||||
|  | ||||
| 	// set the default help | ||||
| 	flag.Usage = func() { | ||||
| 		fmt.Println("Goptimize - downscales and optimizes images") | ||||
| 		fmt.Printf("\nUsage: %s [options] <images>\n", os.Args[0]) | ||||
| 		fmt.Println("\nOptions:") | ||||
| 		flag.SortFlags = false | ||||
| 		flag.PrintDefaults() | ||||
| 		fmt.Println("\nExamples:") | ||||
| 		fmt.Printf("  %s image.png\n", os.Args[0]) | ||||
| @@ -47,24 +51,27 @@ func main() { | ||||
| 	} | ||||
|  | ||||
| 	var maxSizes string | ||||
| 	var update, showversion bool | ||||
| 	var update, showversion, showhelp bool | ||||
|  | ||||
| 	flag.IntVar(&quality, "q", 75, "quality - JPEG only") | ||||
| 	flag.StringVar(&outputDir, "o", "", "output directory (default overwrites original)") | ||||
| 	flag.BoolVar(&preserveModTimes, "p", true, "preserve file modification times") | ||||
| 	flag.StringVar(&maxSizes, "m", "", "downscale to a maximum width & height in pixels (<width>x<height>)") | ||||
| 	flag.BoolVar(&update, "u", false, "update to latest release") | ||||
| 	flag.BoolVar(&showversion, "v", false, "show version number") | ||||
| 	flag.IntVarP(&quality, "quality", "q", 75, "quality, JPEG only") | ||||
| 	flag.StringVarP(&maxSizes, "max", "m", "", "downscale to a maximum width & height in pixels (<width>x<height>)") | ||||
| 	flag.StringVarP(&outputDir, "out", "o", "", "output directory (default overwrites original)") | ||||
| 	flag.BoolVarP(&preserveModTimes, "preserve", "p", true, "preserve file modification times") | ||||
| 	flag.BoolVarP(&update, "update", "u", false, "update to latest release") | ||||
| 	flag.BoolVarP(&showversion, "version", "v", false, "show version number") | ||||
| 	flag.BoolVarP(&showhelp, "help", "h", false, "show help") | ||||
|  | ||||
| 	// third-party optimizers | ||||
| 	flag.StringVar(&gifsicle, "gifsicle", "gifsicle", "gifsicle binary") | ||||
| 	flag.StringVar(&jpegoptim, "jpegoptim", "jpegoptim", "jpegoptim binary") | ||||
| 	flag.StringVar(&jpegtran, "jpegtran", "jpegtran", "jpegtran binary") | ||||
| 	flag.StringVar(&optipng, "optipng", "optipng", "optipng binary") | ||||
| 	flag.StringVar(&jpegoptim, "jpegoptim", "jpegoptim", "jpegoptim binary") | ||||
| 	flag.StringVar(&gifsicle, "gifsicle", "gifsicle", "gifsicle binary") | ||||
| 	flag.StringVar(&pngquant, "pngquant", "pngquant", "pngquant binary") | ||||
| 	flag.StringVar(&optipng, "optipng", "optipng", "optipng binary") | ||||
|  | ||||
| 	// parse flags | ||||
| 	flag.Parse() | ||||
| 	flag.SortFlags = false | ||||
|  | ||||
| 	// parse args excluding os.Args[0] | ||||
| 	flag.Parse(os.Args[1:]) | ||||
|  | ||||
| 	// detect optimizer paths | ||||
| 	gifsicle, _ = exec.LookPath(gifsicle) | ||||
| @@ -73,6 +80,11 @@ func main() { | ||||
| 	optipng, _ = exec.LookPath(optipng) | ||||
| 	pngquant, _ = exec.LookPath(pngquant) | ||||
|  | ||||
| 	if showhelp { | ||||
| 		flag.Usage() | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
|  | ||||
| 	if showversion { | ||||
| 		fmt.Println(fmt.Sprintf("Version: %s", version)) | ||||
| 		latest, _, _, err := gitrel.Latest("axllent/goptimize", "goptimize") | ||||
| @@ -88,7 +100,7 @@ func main() { | ||||
| 			fmt.Println(err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 		fmt.Printf("Updated %s to version %s", os.Args[0], rel) | ||||
| 		fmt.Printf("Updated %s to version %s\n", os.Args[0], rel) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user