mirror of
https://github.com/axllent/goptimize.git
synced 2025-07-05 16:38:25 -04:00
Refactor function names to follow camelCase convention and improve error handling in file operations
This commit is contained in:
parent
99756efb02
commit
c6ccb45a25
@ -115,21 +115,21 @@ func copyMetadata(outImagePath, imagePath, metadataImagePath string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outFile.Close()
|
||||
defer func() { _ = outFile.Close() }()
|
||||
writer := bufio.NewWriter(outFile)
|
||||
|
||||
imageFile, err := os.Open(imagePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer imageFile.Close()
|
||||
defer func() { _ = imageFile.Close() }()
|
||||
imageReader := bufio.NewReader(imageFile)
|
||||
|
||||
metaFile, err := os.Open(metadataImagePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer metaFile.Close()
|
||||
defer func() { _ = metaFile.Close() }()
|
||||
metaReader := bufio.NewReader(metaFile)
|
||||
|
||||
_, err = writer.Write([]byte{0xFF, soi})
|
||||
@ -166,6 +166,6 @@ func exifCopy(fromPath, toPath string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(copyPath)
|
||||
defer func() { _ = os.Remove(copyPath) }()
|
||||
return copyMetadata(toPath, copyPath, fromPath)
|
||||
}
|
||||
|
73
goptimize.go
73
goptimize.go
@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
// Goptimize downscales and optimizes an existing image
|
||||
func Goptimize(file string) {
|
||||
func goptimize(file string) {
|
||||
info, err := os.Stat(file)
|
||||
|
||||
if err != nil {
|
||||
@ -57,7 +57,7 @@ func Goptimize(file string) {
|
||||
|
||||
if format.String() == "GIF" {
|
||||
// return if GIF is animated - unsupported
|
||||
if err := IsGIFAnimated(file); err != nil {
|
||||
if err := isGIFAnimated(file); err != nil {
|
||||
fmt.Printf("Error: animated GIF not supported (%v)\n", file)
|
||||
return
|
||||
}
|
||||
@ -99,7 +99,7 @@ func Goptimize(file string) {
|
||||
return
|
||||
}
|
||||
|
||||
defer os.Remove(tmpFile.Name())
|
||||
defer func() { _ = os.Remove(tmpFile.Name()) }()
|
||||
|
||||
switch imgType := format.String(); imgType {
|
||||
case "JPEG":
|
||||
@ -127,15 +127,18 @@ func Goptimize(file string) {
|
||||
|
||||
// immediately close the temp file to release pointers
|
||||
// so we can modify it with system processes
|
||||
tmpFile.Close()
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
fmt.Printf("Error closing temporary file: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// run through optimizers
|
||||
if format.String() == "JPEG" {
|
||||
// run one or the other, running both has no advantage
|
||||
if jpegtran != "" {
|
||||
RunOptimizer(tmpFilename, true, jpegtran, "-optimize", "-outfile")
|
||||
runOptimizer(tmpFilename, true, jpegtran, "-optimize", "-outfile")
|
||||
} else if jpegoptim != "" {
|
||||
RunOptimizer(tmpFilename, false, jpegoptim, "-f", "-s", "-o")
|
||||
runOptimizer(tmpFilename, false, jpegoptim, "-f", "-s", "-o")
|
||||
}
|
||||
|
||||
if copyExif {
|
||||
@ -146,13 +149,13 @@ func Goptimize(file string) {
|
||||
}
|
||||
} else if format.String() == "PNG" {
|
||||
if pngquant != "" {
|
||||
RunOptimizer(tmpFilename, true, pngquant, "-f", "--output")
|
||||
runOptimizer(tmpFilename, true, pngquant, "-f", "--output")
|
||||
}
|
||||
if optipng != "" {
|
||||
RunOptimizer(tmpFilename, true, optipng, "-out")
|
||||
runOptimizer(tmpFilename, true, optipng, "-out")
|
||||
}
|
||||
} else if format.String() == "GIF" && gifsicle != "" {
|
||||
RunOptimizer(tmpFilename, true, gifsicle, "-o")
|
||||
runOptimizer(tmpFilename, true, gifsicle, "-o")
|
||||
}
|
||||
|
||||
// re-open modified temporary file
|
||||
@ -162,7 +165,7 @@ func Goptimize(file string) {
|
||||
return
|
||||
}
|
||||
|
||||
defer tmpFile.Close()
|
||||
defer func() { _ = tmpFile.Close() }()
|
||||
|
||||
// get th eoriginal file stats
|
||||
srcStat, _ := os.Stat(file)
|
||||
@ -187,7 +190,7 @@ func Goptimize(file string) {
|
||||
return
|
||||
}
|
||||
|
||||
defer out.Close()
|
||||
defer func() { _ = out.Close() }()
|
||||
|
||||
if _, err := io.Copy(out, tmpFile); err != nil {
|
||||
fmt.Printf("Error overwriting original file: %v\n", err)
|
||||
@ -201,22 +204,26 @@ func Goptimize(file string) {
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Goptimized %s (%dx%d %s > %s %v%%)\n", dstFile, resultW, resultH, ByteCountSI(srcSize), ByteCountSI(dstSize), savedPercent)
|
||||
fmt.Printf("Optimized %s (%dx%d %s > %s %v%%)\n", dstFile, resultW, resultH, byteCountSI(srcSize), byteCountSI(dstSize), savedPercent)
|
||||
} else {
|
||||
// if the output directory is not the same,
|
||||
// then write a copy of the original file
|
||||
if outputDir != "" {
|
||||
out, err := os.Create(dstFile)
|
||||
if err != nil {
|
||||
fmt.Printf("Error creating new file: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() { _ = out.Close() }()
|
||||
|
||||
orig, err := os.Open(file)
|
||||
if err != nil {
|
||||
fmt.Printf("Error opening original file: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer out.Close()
|
||||
|
||||
orig, _ := os.Open(file)
|
||||
|
||||
defer orig.Close()
|
||||
defer func() { _ = orig.Close() }()
|
||||
|
||||
if _, err := io.Copy(out, orig); err != nil {
|
||||
fmt.Printf("Error ovewriting original file: %v\n", err)
|
||||
@ -230,36 +237,35 @@ func Goptimize(file string) {
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Copied %s (%dx%d %s %v%%)\n", dstFile, srcW, srcH, ByteCountSI(srcSize), 0)
|
||||
fmt.Printf("Copied %s (%dx%d %s %v%%)\n", dstFile, srcW, srcH, byteCountSI(srcSize), 0)
|
||||
} else {
|
||||
// we didn't actually change anything
|
||||
fmt.Printf("Skipped %s (%dx%d %s %v%%)\n", dstFile, srcW, srcH, ByteCountSI(srcSize), 0)
|
||||
fmt.Printf("Skipped %s (%dx%d %s %v%%)\n", dstFile, srcW, srcH, byteCountSI(srcSize), 0)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// RunOptimizer 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 RunOptimizer(src string, outFileArg bool, args ...string) {
|
||||
func runOptimizer(src string, outFileArg bool, args ...string) {
|
||||
// create a new temp file
|
||||
tmpFile, err := os.CreateTemp(os.TempDir(), "Goptimized-")
|
||||
tmpFile, err := os.CreateTemp(os.TempDir(), "goptimize-")
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Cannot create temporary file: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer os.Remove(tmpFile.Name())
|
||||
defer func() { _ = os.Remove(tmpFile.Name()) }()
|
||||
|
||||
source, err := os.Open(src)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Cannot open temporary file: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer source.Close()
|
||||
defer func() { _ = source.Close() }()
|
||||
|
||||
if _, err := io.Copy(tmpFile, source); err != nil {
|
||||
fmt.Printf("Cannot copy source file: %v\n", err)
|
||||
@ -289,8 +295,8 @@ func RunOptimizer(src string, outFileArg bool, args ...string) {
|
||||
dstSize := dstStat.Size()
|
||||
|
||||
// ensure file pointers are closed before renaming
|
||||
tmpFile.Close()
|
||||
source.Close()
|
||||
func() { _ = tmpFile.Close() }()
|
||||
func() { _ = source.Close() }()
|
||||
|
||||
if dstSize < srcSize {
|
||||
if err := os.Rename(tmpFilename, src); err != nil {
|
||||
@ -301,7 +307,7 @@ func RunOptimizer(src string, outFileArg bool, args ...string) {
|
||||
}
|
||||
|
||||
// ByteCountSI returns a human readable size from int64 bytes
|
||||
func ByteCountSI(b int64) string {
|
||||
func byteCountSI(b int64) string {
|
||||
const unit = 1000
|
||||
if b < unit {
|
||||
return fmt.Sprintf("%dB", b)
|
||||
@ -315,9 +321,12 @@ func ByteCountSI(b int64) string {
|
||||
}
|
||||
|
||||
// IsGIFAnimated will return an error if the GIF file has more than 1 frame
|
||||
func IsGIFAnimated(gifFile string) error {
|
||||
file, _ := os.Open(gifFile)
|
||||
defer file.Close()
|
||||
func isGIFAnimated(gifFile string) error {
|
||||
file, err := os.Open(gifFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot open GIF file: %v", err)
|
||||
}
|
||||
defer func() { _ = file.Close() }()
|
||||
|
||||
g, err := gif.DecodeAll(file)
|
||||
if err != nil {
|
||||
@ -329,5 +338,5 @@ func IsGIFAnimated(gifFile string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("Animated gif")
|
||||
return fmt.Errorf("cannot optimize an animated gif")
|
||||
}
|
||||
|
14
main.go
14
main.go
@ -55,11 +55,11 @@ func main() {
|
||||
|
||||
fmt.Println("\nDetected optimizers:")
|
||||
if err := displayDetectedOptimizer("jpegtran ", jpegtran); err != nil {
|
||||
displayDetectedOptimizer("jpegoptim", jpegoptim)
|
||||
_ = displayDetectedOptimizer("jpegoptim", jpegoptim)
|
||||
}
|
||||
displayDetectedOptimizer("optipng ", optipng)
|
||||
displayDetectedOptimizer("pngquant ", pngquant)
|
||||
displayDetectedOptimizer("gifsicle ", gifsicle)
|
||||
_ = displayDetectedOptimizer("optipng ", optipng)
|
||||
_ = displayDetectedOptimizer("pngquant ", pngquant)
|
||||
_ = displayDetectedOptimizer("gifsicle ", gifsicle)
|
||||
}
|
||||
|
||||
var maxSizes string
|
||||
@ -85,7 +85,9 @@ func main() {
|
||||
flag.SortFlags = false
|
||||
|
||||
// parse args excluding os.Args[0]
|
||||
flag.Parse(os.Args[1:])
|
||||
if err := flag.Parse(os.Args[1:]); err != nil {
|
||||
fmt.Printf("Error parsing flags: %s\n", err.Error())
|
||||
}
|
||||
|
||||
// detect optimizer paths
|
||||
gifsicle, _ = exec.LookPath(gifsicle)
|
||||
@ -179,7 +181,7 @@ func main() {
|
||||
for i := 0; i < threads; i++ {
|
||||
go func() {
|
||||
for nextFile := range processChan {
|
||||
Goptimize(nextFile)
|
||||
goptimize(nextFile)
|
||||
}
|
||||
// Channel was closed, so we finished this goroutine.
|
||||
wg.Done() // Let main goroutine know we are done.
|
||||
|
Loading…
x
Reference in New Issue
Block a user