Skip to content

Instantly share code, notes, and snippets.

@robrotheram
Last active September 7, 2019 21:46
Show Gist options
  • Save robrotheram/7b397242370daa70d44db926a4981789 to your computer and use it in GitHub Desktop.
Save robrotheram/7b397242370daa70d44db926a4981789 to your computer and use it in GitHub Desktop.
Produce thumbnails
package worker
import (
"crypto/md5"
"encoding/hex"
"fmt"
"image"
"image/jpeg"
"log"
"os"
"runtime"
"github.com/disintegration/gift"
)
var thumbnailChan = make(chan string, 800)
func QueSize() int {
return len(thumbnailChan)
}
func SendToThumbnail(image string) {
if !CheckCacheFolder(image) {
thumbnailChan <- image
}
}
func GetMD5Hash(text string) string {
hasher := md5.New()
hasher.Write([]byte(text))
return hex.EncodeToString(hasher.Sum(nil))
}
var img image.Image
func loadImage(filename string) image.Image {
f, err := os.Open(filename)
if err != nil {
log.Fatalf("os.Open failed: %v", err)
}
defer f.Close()
img, _, err := image.Decode(f)
if err != nil {
log.Printf("image.Decode failed on image: %s with err: %v \n", filename, err)
return nil
}
return img
}
func saveImage(filename string, img image.Image) {
f, err := os.Create(filename)
if err != nil {
log.Fatalf("os.Create failed: %v", err)
}
defer f.Close()
err = jpeg.Encode(f, img, nil)
if err != nil {
log.Fatalf("image encode failed: %v", err)
}
}
func generateThumbnail(path string, size int, prefix string) {
cachePath := fmt.Sprintf("cache/%s%s.jpg", prefix, GetMD5Hash(path))
src := loadImage(path)
if src == nil {
return
}
g := gift.New(gift.Resize(size, 0, gift.LanczosResampling))
dst := image.NewNRGBA(g.Bounds(src.Bounds()))
g.Draw(dst, src)
saveImage(cachePath, dst)
}
func makeCacheFolder() {
os.MkdirAll("cache", os.ModePerm)
}
func doesThumbExists(path string, prefix string) bool {
cachePath := fmt.Sprintf("cache/%s%s.jpg", prefix, GetMD5Hash(path))
if _, err := os.Stat(cachePath); err == nil {
return true
}
return false
}
// CheckCacheFolder Lets check to see if a cache image has already been made before adding it to the channel
func CheckCacheFolder(path string) bool {
return doesThumbExists(path, "") && doesThumbExists(path, "large_")
}
func worker(id int, jobs <-chan string) {
log.Printf("Strarting Worker: %d \n", id)
makeCacheFolder()
for j := range jobs {
generateThumbnail(j, 400, "")
runtime.GC()
}
}
func StartWorkers() {
for w := 1; w <= runtime.NumCPU(); w++ {
go worker(w, thumbnailChan)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment