| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 | package metadataimport (	"errors"	"image"	"image/draw"	"image/jpeg"	"image/png"	"log"	"os"	"path/filepath"	"strings"	"github.com/nfnt/resize")/*	Generate folder thumbnail from the containing files	The preview is generated by overlapping 2 - 3 layers of images*/func generateThumbnailForFolder(cacheFolder string, file string, generateOnly bool) (string, error) {	//Check if this folder has cache image folder	cacheFolderInsideThisFolder := filepath.Join(file, "/.cache")	if !fileExists(cacheFolderInsideThisFolder) {		//This folder do not have a cache folder		return "", errors.New("No previewable files")	}	//Load the base template	if !fileExists("web/img/system/folder-preview.png") {		//Missing system files. Skip rendering		return "", errors.New("Missing system template image file")	}	image1, err := os.Open("web/img/system/folder-preview.png")	if err != nil {		return "", err	}	baseTemplate, err := png.Decode(image1)	if err != nil {		return "", err	}	image1.Close()	//Generate the base image	b := baseTemplate.Bounds()	resultThumbnail := image.NewRGBA(b)	draw.Draw(resultThumbnail, b, baseTemplate, image.ZP, draw.Over)	//Get cached file inside this folder, only include jpg (non folder)	contentCache, _ := wGlob(filepath.Join(cacheFolderInsideThisFolder, "/*.jpg"))	//Check if there are more than 1 file inside this folder that is cached	if len(contentCache) > 1 {		//More than 1 files. Render the image at the back		image2, err := os.Open(contentCache[1])		if err != nil {			return "", err		}		backImage, err := jpeg.Decode(image2)		if err != nil {			return "", err		}		backImgOffset := image.Pt(155, 110)		defer image2.Close()		resizedBackImg := resize.Resize(250, 250, backImage, resize.Lanczos3)		draw.Draw(resultThumbnail, resizedBackImg.Bounds().Add(backImgOffset), resizedBackImg, image.ZP, draw.Over)	} else if len(contentCache) == 0 {		//Nothing to preview inside this folder		return "", errors.New("No previewable files")	}	//Render the top image	image3, err := os.Open(contentCache[0])	if err != nil {		log.Fatalf("failed to open: %s", err)	}	topImage, err := jpeg.Decode(image3)	if err != nil {		log.Fatalf("failed to decode: %s", err)	}	defer image3.Close()	topImageOffset := image.Pt(210, 210)	resizedTopImage := resize.Resize(260, 260, topImage, resize.Lanczos3)	draw.Draw(resultThumbnail, resizedTopImage.Bounds().Add(topImageOffset), resizedTopImage, image.ZP, draw.Over)	outfile, err := os.Create(filepath.Join(cacheFolder, filepath.Base(file)+".png"))	if err != nil {		log.Fatalf("failed to create: %s", err)	}	png.Encode(outfile, resultThumbnail)	outfile.Close()	ctx, err := getImageAsBase64(cacheFolder + filepath.Base(file) + ".png")	return ctx, err}//Special glob function to handle file name containing wildcard charactersfunc wGlob(path string) ([]string, error) {	files, err := filepath.Glob(path)	if err != nil {		return []string{}, err	}	if strings.Contains(path, "[") == true || strings.Contains(path, "]") == true {		if len(files) == 0 {			//Handle reverse check. Replace all [ and ] with ?			newSearchPath := strings.ReplaceAll(path, "[", "?")			newSearchPath = strings.ReplaceAll(newSearchPath, "]", "?")			//Scan with all the similar structure except [ and ]			tmpFilelist, _ := filepath.Glob(newSearchPath)			for _, file := range tmpFilelist {				file = filepath.ToSlash(file)				if strings.Contains(file, filepath.ToSlash(filepath.Dir(path))) {					files = append(files, file)				}			}		}	}	//Convert all filepaths to slash	for i := 0; i < len(files); i++ {		files[i] = filepath.ToSlash(files[i])	}	return files, nil}
 |