|
|
@ -2,11 +2,15 @@ package pic
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/estebangarcia21/subprocess"
|
|
|
|
//"github.com/jmoiron/sqlx"
|
|
|
|
//"github.com/jmoiron/sqlx"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
//Picture - работа с картинками
|
|
|
|
// Picture - работа с картинками
|
|
|
|
type Picture struct {
|
|
|
|
type Picture struct {
|
|
|
|
ID int `db:"id" json:"id"`
|
|
|
|
ID int `db:"id" json:"id"`
|
|
|
|
Album string `db:"album" json:"album"`
|
|
|
|
Album string `db:"album" json:"album"`
|
|
|
@ -18,18 +22,19 @@ type Picture struct {
|
|
|
|
ThumbHeight int `db:"thumb_height" json:"imgtHeight"`
|
|
|
|
ThumbHeight int `db:"thumb_height" json:"imgtHeight"`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Hello - приветствие и комментарии к модулю
|
|
|
|
// Hello - приветствие и комментарии к модулю
|
|
|
|
func Hello() {
|
|
|
|
func Hello() {
|
|
|
|
fmt.Printf("pic - пакет для работы с картинками\n")
|
|
|
|
fmt.Printf("pic - пакет для работы с картинками\n")
|
|
|
|
fmt.Printf("v0.0.1 - начальная версия\n")
|
|
|
|
fmt.Printf("v0.0.1 - начальная версия\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func NewPicture(album string) Picture {
|
|
|
|
func NewPicture(album string) Picture {
|
|
|
|
pic := Picture {Album: album}
|
|
|
|
pic := Picture{Album: album}
|
|
|
|
return pic
|
|
|
|
return pic
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// возвращает имя файла без расширения
|
|
|
|
// возвращает имя файла без расширения
|
|
|
|
|
|
|
|
// т.е. из test/filename.jpg получаем filename
|
|
|
|
func baseName(filename string) string {
|
|
|
|
func baseName(filename string) string {
|
|
|
|
// на всякий случай заменим обратный слэш
|
|
|
|
// на всякий случай заменим обратный слэш
|
|
|
|
filename = strings.ReplaceAll(filename, "\\", "/")
|
|
|
|
filename = strings.ReplaceAll(filename, "\\", "/")
|
|
|
@ -39,8 +44,89 @@ func baseName(filename string) string {
|
|
|
|
if len(items) > 0 {
|
|
|
|
if len(items) > 0 {
|
|
|
|
// есть каталоги, уберем
|
|
|
|
// есть каталоги, уберем
|
|
|
|
filename = items[len(items)-1]
|
|
|
|
filename = items[len(items)-1]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn := strings.Split(filename, ".")
|
|
|
|
fn := strings.Split(filename, ".")
|
|
|
|
return fn[0]
|
|
|
|
return fn[0]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// cmdFfmpeg формирует команду ffmpeg для последующего исполнения
|
|
|
|
|
|
|
|
// ffmpeg - увеличивает gif в 2 раза и сразу преобразует в .webp
|
|
|
|
|
|
|
|
// filename - сам файл gif
|
|
|
|
|
|
|
|
// Возвращает команду ffmpeg и выходной файл webp
|
|
|
|
|
|
|
|
func cmdFfmpeg(src string) (string, string, error) {
|
|
|
|
|
|
|
|
if !strings.HasSuffix(src, ".gif") {
|
|
|
|
|
|
|
|
return "", "", fmt.Errorf("файл не .gif")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
webp := strings.ReplaceAll(src, ".gif", "-2x.webp")
|
|
|
|
|
|
|
|
cmd := fmt.Sprintf("ffmpeg -i \"%s\" -vf scale=iw*2:ih*2 -loop 0 \"%s\"", src, webp)
|
|
|
|
|
|
|
|
return cmd, webp, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type WebpFile struct {
|
|
|
|
|
|
|
|
filename string
|
|
|
|
|
|
|
|
width string
|
|
|
|
|
|
|
|
height string
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// конвертация из .gif в .webp с изменением размеров файла
|
|
|
|
|
|
|
|
// filename - исходный файл gif
|
|
|
|
|
|
|
|
func convert(filename string) (WebpFile, error) {
|
|
|
|
|
|
|
|
webpfile := WebpFile{}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd, webp, err := cmdFfmpeg(filename)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return webpfile, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s := subprocess.New(cmd, subprocess.HideStderr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if err := s.Exec(); err != nil {
|
|
|
|
|
|
|
|
return webpfile, fmt.Errorf("(%s) ffmpeg: %v", filename, err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ExitCode() != 0 {
|
|
|
|
|
|
|
|
return webpfile, fmt.Errorf("(%s): ffmpeg exit code: %d", filename, s.ExitCode())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// из вывода команды ffmpeg получим новый размер файла webp
|
|
|
|
|
|
|
|
w, h := getSize(s.StderrText())
|
|
|
|
|
|
|
|
webpfile = WebpFile{
|
|
|
|
|
|
|
|
filename: webp,
|
|
|
|
|
|
|
|
width: w,
|
|
|
|
|
|
|
|
height: h,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// fid := upload(newname)
|
|
|
|
|
|
|
|
// println(fid)
|
|
|
|
|
|
|
|
return webpfile, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// получает размер файла из вывода команды ffmpeg
|
|
|
|
|
|
|
|
// если пустая строка - бросаем панику
|
|
|
|
|
|
|
|
func getSize(out string) (string, string) {
|
|
|
|
|
|
|
|
if out == "" {
|
|
|
|
|
|
|
|
panic("пустая строка вывода ffmpeg")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
lines := strings.Split(out, "\n")
|
|
|
|
|
|
|
|
for _, s := range lines {
|
|
|
|
|
|
|
|
if strings.Contains(s, "Stream #0:0: Video: webp") {
|
|
|
|
|
|
|
|
// fmt.Printf("== %s\n", s)
|
|
|
|
|
|
|
|
re := regexp.MustCompile(`(\d*)x(\d*)`)
|
|
|
|
|
|
|
|
matches := re.FindAllStringSubmatch(s, -1)
|
|
|
|
|
|
|
|
// fmt.Printf("matches: %v\n", matches)
|
|
|
|
|
|
|
|
return matches[0][1], matches[0][2]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return "0", "0"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func copyFile(src, dst string) error {
|
|
|
|
|
|
|
|
input, err := ioutil.ReadFile(src)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
err = ioutil.WriteFile(dst, input, 0644)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|