This repository has been archived on 2025-03-01. You can view files and clone it, but cannot push or open issues or pull requests.
trantor/lib/cover.go

189 lines
4.1 KiB
Go
Raw Normal View History

2016-05-02 21:36:49 -04:00
package trantor
import (
2014-08-30 13:17:50 -05:00
_ "image/gif"
_ "image/jpeg"
_ "image/png"
log "github.com/cihub/seelog"
"bytes"
"image"
"image/jpeg"
2013-04-01 14:05:04 +02:00
"io"
"io/ioutil"
"regexp"
"strings"
2014-08-30 13:17:50 -05:00
"github.com/gorilla/mux"
2015-04-21 21:32:01 -04:00
"github.com/meskio/epubgo"
2014-08-30 13:17:50 -05:00
"github.com/nfnt/resize"
2016-05-02 21:36:49 -04:00
"gitlab.com/trantor/trantor/lib/storage"
)
const (
imgWidthBig = 300
imgWidthSmall = 60
imgQuality = 80
coverFile = "cover.jpg"
coverSmallFile = "coverSmall.jpg"
)
func coverHandler(h handler) {
vars := mux.Vars(h.r)
2013-04-15 22:10:48 +02:00
file := coverFile
2013-04-15 22:10:48 +02:00
if vars["size"] == "small" {
file = coverSmallFile
2013-04-15 22:10:48 +02:00
}
2021-04-26 18:16:44 +00:00
f, err := h.store.Get(vars["id"], file)
2013-04-15 22:10:48 +02:00
if err != nil {
2014-02-11 13:13:43 +01:00
log.Error("Error while opening image: ", err)
notFound(h)
2013-04-15 22:10:48 +02:00
return
}
defer f.Close()
headers := h.w.Header()
2013-04-15 22:10:48 +02:00
headers["Content-Type"] = []string{"image/jpeg"}
addCacheControlHeader(h.w, false)
2013-04-15 22:10:48 +02:00
2014-08-21 19:24:23 -05:00
_, err = io.Copy(h.w, f)
if err != nil {
log.Error("Error while copying image: ", err)
notFound(h)
return
}
2013-04-15 22:10:48 +02:00
}
2017-05-21 10:16:16 +00:00
func GetCover(e *epubgo.Epub, id string, store storage.Store) bool {
2014-08-21 19:24:23 -05:00
if coverFromMetadata(e, id, store) {
return true
2013-07-18 21:08:22 +02:00
}
2014-08-21 19:24:23 -05:00
if searchCommonCoverNames(e, id, store) {
return true
}
/* search for img on the text */
2013-07-18 20:28:35 +02:00
exp, _ := regexp.Compile("<.*ima?g.*[(src)(href)]=[\"']([^\"']*(\\.[^\\.\"']*))[\"']")
2013-04-01 14:05:04 +02:00
it, errNext := e.Spine()
for errNext == nil {
file, err := it.Open()
if err != nil {
break
}
defer file.Close()
txt, err := ioutil.ReadAll(file)
if err != nil {
break
}
res := exp.FindSubmatch(txt)
if res != nil {
2013-04-01 14:05:04 +02:00
href := string(res[1])
2013-06-04 21:30:37 +02:00
urlPart := strings.Split(it.URL(), "/")
url := strings.Join(urlPart[:len(urlPart)-1], "/")
2013-04-01 14:05:04 +02:00
if href[:3] == "../" {
href = href[3:]
url = strings.Join(urlPart[:len(urlPart)-2], "/")
}
2013-04-01 14:05:04 +02:00
href = strings.Replace(href, "%20", " ", -1)
href = strings.Replace(href, "%27", "'", -1)
href = strings.Replace(href, "%28", "(", -1)
href = strings.Replace(href, "%29", ")", -1)
if url == "" {
2013-04-01 14:05:04 +02:00
url = href
} else {
2013-04-01 14:05:04 +02:00
url = url + "/" + href
}
2013-04-01 14:05:04 +02:00
img, err := e.OpenFile(url)
if err == nil {
defer img.Close()
2014-08-21 19:24:23 -05:00
return storeImg(img, id, store)
}
}
2013-04-01 14:05:04 +02:00
errNext = it.Next()
}
2014-08-21 19:24:23 -05:00
return false
2013-04-01 14:05:04 +02:00
}
2017-05-21 10:16:16 +00:00
func coverFromMetadata(e *epubgo.Epub, id string, store storage.Store) bool {
2013-07-18 21:08:22 +02:00
metaList, _ := e.MetadataAttr("meta")
for _, meta := range metaList {
if meta["name"] == "cover" {
img, err := e.OpenFileId(meta["content"])
if err == nil {
defer img.Close()
2014-08-21 19:24:23 -05:00
return storeImg(img, id, store)
2013-07-18 21:08:22 +02:00
}
}
}
2014-08-21 19:24:23 -05:00
return false
2013-07-18 21:08:22 +02:00
}
2017-05-21 10:16:16 +00:00
func searchCommonCoverNames(e *epubgo.Epub, id string, store storage.Store) bool {
2013-07-18 21:08:22 +02:00
for _, p := range []string{"cover.jpg", "Images/cover.jpg", "images/cover.jpg", "cover.jpeg", "cover1.jpg", "cover1.jpeg"} {
2013-04-01 14:05:04 +02:00
img, err := e.OpenFile(p)
if err == nil {
defer img.Close()
2014-08-21 19:24:23 -05:00
return storeImg(img, id, store)
2013-04-01 14:05:04 +02:00
}
}
2014-08-21 19:24:23 -05:00
return false
}
2017-05-21 10:16:16 +00:00
func storeImg(img io.Reader, id string, store storage.Store) bool {
/* open the files */
fBig, err := store.Create(id, coverFile)
if err != nil {
2014-08-21 19:24:23 -05:00
log.Error("Error creating cover ", id, ": ", err.Error())
return false
}
defer fBig.Close()
fSmall, err := store.Create(id, coverSmallFile)
if err != nil {
2014-08-21 19:24:23 -05:00
log.Error("Error creating small cover ", id, ": ", err.Error())
return false
}
defer fSmall.Close()
/* resize img */
2013-04-01 14:05:04 +02:00
var img2 bytes.Buffer
img1 := io.TeeReader(img, &img2)
jpgOptions := jpeg.Options{imgQuality}
imgResized, err := resizeImg(img1, imgWidthBig)
if err != nil {
2014-02-11 13:13:43 +01:00
log.Error("Error resizing big image: ", err.Error())
2014-08-21 19:24:23 -05:00
return false
}
err = jpeg.Encode(fBig, imgResized, &jpgOptions)
if err != nil {
2014-02-11 13:13:43 +01:00
log.Error("Error encoding big image: ", err.Error())
2014-08-21 19:24:23 -05:00
return false
}
imgSmallResized, err := resizeImg(&img2, imgWidthSmall)
if err != nil {
2014-02-11 13:13:43 +01:00
log.Error("Error resizing small image: ", err.Error())
2014-08-21 19:24:23 -05:00
return false
}
err = jpeg.Encode(fSmall, imgSmallResized, &jpgOptions)
if err != nil {
2014-02-11 13:13:43 +01:00
log.Error("Error encoding small image: ", err.Error())
2014-08-21 19:24:23 -05:00
return false
}
2014-08-21 19:24:23 -05:00
return true
}
2013-04-01 14:05:04 +02:00
func resizeImg(imgReader io.Reader, width uint) (image.Image, error) {
img, _, err := image.Decode(imgReader)
if err != nil {
return nil, err
}
return resize.Resize(width, 0, img, resize.NearestNeighbor), nil
}