forked from mirror/oddmu
90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
//go:build !openbsd
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"image/jpeg"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/disintegration/imaging"
|
|
"github.com/edwvee/exiffix"
|
|
"github.com/gen2brain/webp"
|
|
)
|
|
|
|
// staticFile is used to walk the file trees and do the right thing for the destination directory: create
|
|
// subdirectories, link files, render HTML files.
|
|
func staticFile(source, target string, info fs.FileInfo, shrink bool) error {
|
|
// render pages
|
|
if strings.HasSuffix(source, ".md") {
|
|
// target already has ".html" extension
|
|
p, err := staticPage(source[:len(source)-3], target)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return staticFeed(source[:len(source)-3], target[:len(target)-5]+".rss", p, info.ModTime())
|
|
}
|
|
if shrink {
|
|
switch filepath.Ext(source) {
|
|
case ".jpg", ".jpeg", ".webp":
|
|
return shrinkImage(source, target, info)
|
|
}
|
|
}
|
|
// delete before linking, ignore errors
|
|
os.Remove(target)
|
|
err := os.Link(source, target)
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
// in case of invalid cross-device link error, copy file instead
|
|
src, err := os.Open(source)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer src.Close()
|
|
dst, err := os.Create(target)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer dst.Close()
|
|
_, err = io.Copy(dst, src)
|
|
return err
|
|
}
|
|
|
|
// shrink Image shrinks images down and reduces the quality dramatically.
|
|
func shrinkImage(source, target string, info fs.FileInfo) error {
|
|
file, err := os.Open(source)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
img, _, err := exiffix.Decode(file)
|
|
if err != nil {
|
|
return fmt.Errorf("%s cannot be decoded", source)
|
|
}
|
|
if img.Bounds().Dx() > shrinkWidth {
|
|
res := imaging.Resize(img, shrinkWidth, 0, imaging.Lanczos) // preserve aspect ratio
|
|
// imaging functions don't return errors but empty images…
|
|
if res.Rect.Empty() {
|
|
return fmt.Errorf("%s cannot be resized", source)
|
|
}
|
|
img = res
|
|
}
|
|
dst, err := os.Create(target)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer dst.Close()
|
|
switch filepath.Ext(source) {
|
|
case ".jpg", ".jpeg":
|
|
err = jpeg.Encode(dst, img, &jpeg.Options{Quality: shrinkQuality})
|
|
case ".webp":
|
|
err = webp.Encode(dst, img, webp.Options{Quality: shrinkQuality})
|
|
}
|
|
return err
|
|
}
|