Skip to content

Instantly share code, notes, and snippets.

@lepinkainen
Last active June 12, 2024 09:41
Show Gist options
  • Save lepinkainen/5900f81b6d30f00e696a90523e2435a2 to your computer and use it in GitHub Desktop.
Save lepinkainen/5900f81b6d30f00e696a90523e2435a2 to your computer and use it in GitHub Desktop.
Grab all png's from defined directory, convert it to jpeg and webp, keep the smallest
package main
import (
"bufio"
"bytes"
"fmt"
"image"
"image/jpeg"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/chai2010/webp"
"github.com/disintegration/imaging"
)
func convertToJPG(img image.Image) ([]byte, error) {
var buf bytes.Buffer
err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: 80})
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func convertToWebP(img image.Image) ([]byte, error) {
var buf bytes.Buffer
err := webp.Encode(&buf, img, &webp.Options{Quality: 80})
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func getImageSize(data []byte) int64 {
return int64(len(data))
}
func main() {
if len(os.Args) != 2 {
fmt.Println("Usage: go run convert_images.go <directory>")
return
}
directory := os.Args[1]
files, err := ioutil.ReadDir(directory)
if err != nil {
fmt.Println("Error reading directory:", err)
return
}
smallestFiles := make(map[string]struct{})
for _, file := range files {
if strings.HasSuffix(file.Name(), ".png") {
filepath := filepath.Join(directory, file.Name())
fmt.Println("Processing:", filepath)
img, err := imaging.Open(filepath)
if err != nil {
fmt.Println("Error opening file:", err)
continue
}
jpgData, err := convertToJPG(img)
if err != nil {
fmt.Println("Error converting to JPG:", err)
continue
}
webpData, err := convertToWebP(img)
if err != nil {
fmt.Println("Error converting to WebP:", err)
continue
}
pngSize := file.Size()
jpgSize := getImageSize(jpgData)
webpSize := getImageSize(webpData)
jpgPercentage := float64(jpgSize) / float64(pngSize) * 100
webpPercentage := float64(webpSize) / float64(pngSize) * 100
fmt.Printf(" PNG size: %10d bytes\n", pngSize)
fmt.Printf(" JPG size: %10d bytes (%.2f%% of original)\n", jpgSize, jpgPercentage)
fmt.Printf(" WebP size: %10d bytes (%.2f%% of original)\n", webpSize, webpPercentage)
smallestSize := pngSize
smallestData := []byte{}
extension := "png"
originalIsSmallest := true
if jpgSize < smallestSize {
smallestSize = jpgSize
smallestData = jpgData
extension = "jpg"
originalIsSmallest = false
}
if webpSize < smallestSize {
smallestSize = webpSize
smallestData = webpData
extension = "webp"
originalIsSmallest = false
}
outputFilepath := strings.TrimSuffix(filepath, ".png") + "." + extension
if !originalIsSmallest {
err = ioutil.WriteFile(outputFilepath, smallestData, 0644)
if err != nil {
fmt.Println("Error writing file:", err)
continue
}
}
fmt.Printf("Chosen format: %s\n\n", extension)
// Add the chosen format to the list of smallest files
smallestFiles[outputFilepath] = struct{}{}
if originalIsSmallest {
smallestFiles[filepath] = struct{}{}
}
}
}
reader := bufio.NewReader(os.Stdin)
fmt.Print("Do you want to delete the original PNG files that were not the smallest? (y/n): ")
choice, _ := reader.ReadString('\n')
choice = strings.TrimSpace(choice)
if choice == "y" {
for _, file := range files {
if strings.HasSuffix(file.Name(), ".png") {
filepath := filepath.Join(directory, file.Name())
if _, exists := smallestFiles[filepath]; !exists {
err := os.Remove(filepath)
if err != nil {
fmt.Println("Error deleting file:", err)
} else {
fmt.Println("Deleted:", filepath)
}
}
}
}
fmt.Println("Original PNG files that were not the smallest have been deleted.")
} else {
fmt.Println("Original PNG files have been kept.")
}
fmt.Println("Conversion complete.")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment