mirror of
https://github.com/celogeek/go-comic-converter.git
synced 2025-05-25 00:02:37 +02:00
Compare commits
6 Commits
3f874dc43e
...
abf3b8facf
Author | SHA1 | Date | |
---|---|---|---|
abf3b8facf | |||
728129aba2 | |||
a816350c97 | |||
58cd5f5399 | |||
ee00ed2615 | |||
13103b0eba |
@ -110,7 +110,6 @@ func (c *Converter) InitParse() {
|
||||
c.AddIntParam(&c.Options.Brightness, "brightness", c.Options.Brightness, "Brightness readjustement: between -100 and 100, > 0 lighter, < 0 darker")
|
||||
c.AddIntParam(&c.Options.Contrast, "contrast", c.Options.Contrast, "Contrast readjustement: between -100 and 100, > 0 more contrast, < 0 less contrast")
|
||||
c.AddBoolParam(&c.Options.AutoRotate, "autorotate", c.Options.AutoRotate, "Auto Rotate page when width > height")
|
||||
c.AddBoolParam(&c.Options.Auto, "auto", false, "Activate all automatic options")
|
||||
c.AddBoolParam(&c.Options.AutoSplitDoublePage, "autosplitdoublepage", c.Options.AutoSplitDoublePage, "Auto Split double page when width > height")
|
||||
c.AddBoolParam(&c.Options.NoBlankImage, "noblankimage", c.Options.NoBlankImage, "Remove blank image")
|
||||
c.AddBoolParam(&c.Options.Manga, "manga", c.Options.Manga, "Manga mode (right to left)")
|
||||
@ -120,12 +119,22 @@ func (c *Converter) InitParse() {
|
||||
c.AddIntParam(&c.Options.SortPathMode, "sort", c.Options.SortPathMode, "Sort path mode\n0 = alpha for path and file\n1 = alphanum for path and alpha for file\n2 = alphanum for path and file")
|
||||
c.AddStringParam(&c.Options.ForegroundColor, "foreground-color", c.Options.ForegroundColor, "Foreground color in hexa format RGB. Black=000, White=FFF")
|
||||
c.AddStringParam(&c.Options.BackgroundColor, "background-color", c.Options.BackgroundColor, "Background color in hexa format RGB. Black=000, White=FFF, Light Gray=DDD, Dark Gray=777")
|
||||
c.AddBoolParam(&c.Options.NoResize, "noresize", c.Options.NoResize, "Do not reduce image size if exceed device size")
|
||||
c.AddStringParam(&c.Options.Format, "format", c.Options.Format, "Format of output images: jpeg (lossy), png (lossless)")
|
||||
|
||||
c.AddSection("Default config")
|
||||
c.AddBoolParam(&c.Options.Show, "show", false, "Show your default parameters")
|
||||
c.AddBoolParam(&c.Options.Save, "save", false, "Save your parameters as default")
|
||||
c.AddBoolParam(&c.Options.Reset, "reset", false, "Reset your parameters to default")
|
||||
|
||||
c.AddSection("Shortcut")
|
||||
c.AddBoolParam(&c.Options.Auto, "auto", false, "Activate all automatic options")
|
||||
c.AddBoolParam(&c.Options.NoFilter, "nofilter", false, "Deactivate all filters")
|
||||
c.AddBoolParam(&c.Options.MaxQuality, "maxquality", false, "Max quality: color png + noresize")
|
||||
c.AddBoolParam(&c.Options.BestQuality, "bestquality", false, "Max quality: color jpg q100 + noresize")
|
||||
c.AddBoolParam(&c.Options.GreatQuality, "greatquality", false, "Max quality: grayscale jpg q90 + noresize")
|
||||
c.AddBoolParam(&c.Options.GoodQuality, "goodquality", false, "Max quality: grayscale jpg q90")
|
||||
|
||||
c.AddSection("Other")
|
||||
c.AddIntParam(&c.Options.Workers, "workers", runtime.NumCPU(), "Number of workers")
|
||||
c.AddBoolParam(&c.Options.Dry, "dry", false, "Dry run to show all options")
|
||||
@ -211,6 +220,36 @@ func (c *Converter) Parse() {
|
||||
c.Options.AutoRotate = true
|
||||
c.Options.AutoSplitDoublePage = true
|
||||
}
|
||||
|
||||
if c.Options.MaxQuality {
|
||||
c.Options.Format = "png"
|
||||
c.Options.Grayscale = false
|
||||
c.Options.NoResize = true
|
||||
} else if c.Options.BestQuality {
|
||||
c.Options.Format = "jpeg"
|
||||
c.Options.Quality = 100
|
||||
c.Options.Grayscale = false
|
||||
c.Options.NoResize = true
|
||||
} else if c.Options.GreatQuality {
|
||||
c.Options.Format = "jpeg"
|
||||
c.Options.Quality = 90
|
||||
c.Options.Grayscale = true
|
||||
c.Options.NoResize = true
|
||||
} else if c.Options.GoodQuality {
|
||||
c.Options.Format = "jpeg"
|
||||
c.Options.Quality = 90
|
||||
c.Options.Grayscale = true
|
||||
c.Options.NoResize = false
|
||||
}
|
||||
|
||||
if c.Options.NoFilter {
|
||||
c.Options.Crop = false
|
||||
c.Options.Brightness = 0
|
||||
c.Options.Contrast = 0
|
||||
c.Options.AutoRotate = false
|
||||
c.Options.NoBlankImage = false
|
||||
c.Options.NoResize = true
|
||||
}
|
||||
}
|
||||
|
||||
// Check parameters
|
||||
@ -307,6 +346,11 @@ func (c *Converter) Validate() error {
|
||||
return errors.New("background color must have color format in hexa: [0-9A-F]{3}")
|
||||
}
|
||||
|
||||
// Format
|
||||
if !(c.Options.Format == "jpeg" || c.Options.Format == "png") {
|
||||
return errors.New("format should be jpeg or png")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,6 @@ type Options struct {
|
||||
CropRatioBottom int `yaml:"crop_ratio_bottom"`
|
||||
Brightness int `yaml:"brightness"`
|
||||
Contrast int `yaml:"contrast"`
|
||||
Auto bool `yaml:"-"`
|
||||
AutoRotate bool `yaml:"auto_rotate"`
|
||||
AutoSplitDoublePage bool `yaml:"auto_split_double_page"`
|
||||
NoBlankImage bool `yaml:"no_blank_image"`
|
||||
@ -42,12 +41,22 @@ type Options struct {
|
||||
SortPathMode int `yaml:"sort_path_mode"`
|
||||
ForegroundColor string `yaml:"foreground_color"`
|
||||
BackgroundColor string `yaml:"background_color"`
|
||||
NoResize bool `yaml:"noresize"`
|
||||
Format string `yaml:"format"`
|
||||
|
||||
// Default Config
|
||||
Show bool `yaml:"-"`
|
||||
Save bool `yaml:"-"`
|
||||
Reset bool `yaml:"-"`
|
||||
|
||||
// Shortcut
|
||||
Auto bool `yaml:"-"`
|
||||
NoFilter bool `yaml:"-"`
|
||||
MaxQuality bool `yaml:"-"`
|
||||
BestQuality bool `yaml:"-"`
|
||||
GreatQuality bool `yaml:"-"`
|
||||
GoodQuality bool `yaml:"-"`
|
||||
|
||||
// Other
|
||||
Workers int `yaml:"-"`
|
||||
Dry bool `yaml:"-"`
|
||||
@ -83,6 +92,8 @@ func New() *Options {
|
||||
SortPathMode: 1,
|
||||
ForegroundColor: "000",
|
||||
BackgroundColor: "FFF",
|
||||
NoResize: false,
|
||||
Format: "jpeg",
|
||||
profiles: profiles.New(),
|
||||
}
|
||||
}
|
||||
@ -152,10 +163,6 @@ func (o *Options) ShowConfig() string {
|
||||
perfectHeight,
|
||||
)
|
||||
}
|
||||
limitmb := "nolimit"
|
||||
if o.LimitMb > 0 {
|
||||
limitmb = fmt.Sprintf("%d Mb", o.LimitMb)
|
||||
}
|
||||
|
||||
sortpathmode := ""
|
||||
switch o.SortPathMode {
|
||||
@ -169,30 +176,35 @@ func (o *Options) ShowConfig() string {
|
||||
|
||||
var b strings.Builder
|
||||
for _, v := range []struct {
|
||||
K string
|
||||
V any
|
||||
Key string
|
||||
Value any
|
||||
Condition bool
|
||||
}{
|
||||
{"Profile", profileDesc},
|
||||
{"ViewRatio", fmt.Sprintf("1:%s", strings.TrimRight(fmt.Sprintf("%f", profiles.PerfectRatio), "0"))},
|
||||
{"View", viewDesc},
|
||||
{"Quality", o.Quality},
|
||||
{"Grayscale", o.Grayscale},
|
||||
{"Crop", o.Crop},
|
||||
{"CropRatio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom)},
|
||||
{"Brightness", o.Brightness},
|
||||
{"Contrast", o.Contrast},
|
||||
{"AutoRotate", o.AutoRotate},
|
||||
{"AutoSplitDoublePage", o.AutoSplitDoublePage},
|
||||
{"NoBlankImage", o.NoBlankImage},
|
||||
{"Manga", o.Manga},
|
||||
{"HasCover", o.HasCover},
|
||||
{"LimitMb", limitmb},
|
||||
{"StripFirstDirectoryFromToc", o.StripFirstDirectoryFromToc},
|
||||
{"SortPathMode", sortpathmode},
|
||||
{"Foreground Color", fmt.Sprintf("#%s", o.ForegroundColor)},
|
||||
{"Background Color", fmt.Sprintf("#%s", o.BackgroundColor)},
|
||||
{"Profile", profileDesc, true},
|
||||
{"ViewRatio", fmt.Sprintf("1:%s", strings.TrimRight(fmt.Sprintf("%f", profiles.PerfectRatio), "0")), true},
|
||||
{"View", viewDesc, true},
|
||||
{"Format", o.Format, true},
|
||||
{"Quality", o.Quality, o.Format == "jpeg"},
|
||||
{"Grayscale", o.Grayscale, true},
|
||||
{"Crop", o.Crop, true},
|
||||
{"CropRatio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom), o.Crop},
|
||||
{"Brightness", o.Brightness, o.Brightness != 0},
|
||||
{"Contrast", o.Contrast, o.Contrast != 0},
|
||||
{"AutoRotate", o.AutoRotate, true},
|
||||
{"AutoSplitDoublePage", o.AutoSplitDoublePage, true},
|
||||
{"NoBlankImage", o.NoBlankImage, true},
|
||||
{"Manga", o.Manga, true},
|
||||
{"HasCover", o.HasCover, true},
|
||||
{"LimitMb", fmt.Sprintf("%d Mb", o.LimitMb), o.LimitMb != 0},
|
||||
{"StripFirstDirectoryFromToc", o.StripFirstDirectoryFromToc, true},
|
||||
{"SortPathMode", sortpathmode, true},
|
||||
{"Foreground Color", fmt.Sprintf("#%s", o.ForegroundColor), true},
|
||||
{"Background Color", fmt.Sprintf("#%s", o.BackgroundColor), true},
|
||||
{"Resize", !o.NoResize, true},
|
||||
} {
|
||||
b.WriteString(fmt.Sprintf("\n %-26s: %v", v.K, v.V))
|
||||
if v.Condition {
|
||||
b.WriteString(fmt.Sprintf("\n %-26s: %v", v.Key, v.Value))
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ func (e *ePub) Write() error {
|
||||
{"OEBPS/Text/title.xhtml", e.render(epubtemplates.Text, map[string]any{
|
||||
"Title": title,
|
||||
"ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height),
|
||||
"ImagePath": "Images/title.jpg",
|
||||
"ImagePath": fmt.Sprintf("Images/title.%s", e.Image.Format),
|
||||
"ImageStyle": part.Cover.ImgStyle(e.Image.View.Width, e.Image.View.Height, titleAlign),
|
||||
})},
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ package epubimage
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Image struct {
|
||||
@ -20,6 +21,7 @@ type Image struct {
|
||||
Path string
|
||||
Name string
|
||||
Position string
|
||||
Format string
|
||||
}
|
||||
|
||||
// key name of the blank plage after the image
|
||||
@ -59,7 +61,7 @@ func (i *Image) ImgKey() string {
|
||||
|
||||
// image path
|
||||
func (i *Image) ImgPath() string {
|
||||
return fmt.Sprintf("Images/%s.jpg", i.ImgKey())
|
||||
return fmt.Sprintf("Images/%s.%s", i.ImgKey(), i.Format)
|
||||
}
|
||||
|
||||
// image path into the EPUB
|
||||
@ -72,24 +74,48 @@ func (i *Image) EPUBImgPath() string {
|
||||
// center by default.
|
||||
// align to left or right if it's part of the splitted double page.
|
||||
func (i *Image) ImgStyle(viewWidth, viewHeight int, align string) string {
|
||||
marginW, marginH := float64(viewWidth-i.Width)/2, float64(viewHeight-i.Height)/2
|
||||
relWidth, relHeight := i.RelSize(viewWidth, viewHeight)
|
||||
marginW, marginH := float64(viewWidth-relWidth)/2, float64(viewHeight-relHeight)/2
|
||||
|
||||
style := []string{}
|
||||
|
||||
style = append(style, fmt.Sprintf("width:%dpx", relWidth))
|
||||
style = append(style, fmt.Sprintf("height:%dpx", relHeight))
|
||||
style = append(style, fmt.Sprintf("top:%.2f%%", marginH*100/float64(viewHeight)))
|
||||
if align == "" {
|
||||
switch i.Position {
|
||||
case "rendition:page-spread-left":
|
||||
align = "right:0"
|
||||
style = append(style, "right:0")
|
||||
case "rendition:page-spread-right":
|
||||
align = "left:0"
|
||||
style = append(style, "left:0")
|
||||
default:
|
||||
align = fmt.Sprintf("left:%.2f%%", marginW*100/float64(viewWidth))
|
||||
style = append(style, fmt.Sprintf("left:%.2f%%", marginW*100/float64(viewWidth)))
|
||||
}
|
||||
} else {
|
||||
style = append(style, align)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
"width:%dpx; height:%dpx; top:%.2f%%; %s;",
|
||||
i.Width,
|
||||
i.Height,
|
||||
marginH*100/float64(viewHeight),
|
||||
align,
|
||||
)
|
||||
return strings.Join(style, "; ")
|
||||
}
|
||||
|
||||
func (i *Image) RelSize(viewWidth, viewHeight int) (relWidth, relHeight int) {
|
||||
w, h := viewWidth, viewHeight
|
||||
srcw, srch := i.Width, i.Height
|
||||
|
||||
if w <= 0 || h <= 0 || srcw <= 0 || srch <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
wratio := float64(srcw) / float64(w)
|
||||
hratio := float64(srch) / float64(h)
|
||||
|
||||
if wratio > hratio {
|
||||
relWidth = w
|
||||
relHeight = int(float64(srch)/wratio + 0.5)
|
||||
} else {
|
||||
relHeight = h
|
||||
relWidth = int(float64(srcw)/hratio + 0.5)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -1,48 +0,0 @@
|
||||
package epubimagefilters
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/draw"
|
||||
|
||||
"github.com/disintegration/gift"
|
||||
)
|
||||
|
||||
// Resize image by keeping aspect ratio.
|
||||
// This will reduce or enlarge image to fit into the viewWidth and viewHeight.
|
||||
func Resize(viewWidth, viewHeight int, resampling gift.Resampling) gift.Filter {
|
||||
return &resizeFilter{
|
||||
viewWidth, viewHeight, resampling,
|
||||
}
|
||||
}
|
||||
|
||||
type resizeFilter struct {
|
||||
viewWidth, viewHeight int
|
||||
resampling gift.Resampling
|
||||
}
|
||||
|
||||
func (p *resizeFilter) Bounds(srcBounds image.Rectangle) image.Rectangle {
|
||||
w, h := p.viewWidth, p.viewHeight
|
||||
srcw, srch := srcBounds.Dx(), srcBounds.Dy()
|
||||
|
||||
if w <= 0 || h <= 0 || srcw <= 0 || srch <= 0 {
|
||||
return image.Rect(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
wratio := float64(srcw) / float64(w)
|
||||
hratio := float64(srch) / float64(h)
|
||||
|
||||
var dstw, dsth int
|
||||
if wratio > hratio {
|
||||
dstw = w
|
||||
dsth = int(float64(srch)/wratio + 0.5)
|
||||
} else {
|
||||
dsth = h
|
||||
dstw = int(float64(srcw)/hratio + 0.5)
|
||||
}
|
||||
|
||||
return image.Rect(0, 0, dstw, dsth)
|
||||
}
|
||||
|
||||
func (p *resizeFilter) Draw(dst draw.Image, src image.Image, options *gift.Options) {
|
||||
gift.Resize(dst.Bounds().Dx(), dst.Bounds().Dy(), p.resampling).Draw(dst, src, options)
|
||||
}
|
@ -38,9 +38,10 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) {
|
||||
if e.Dry {
|
||||
for img := range imageInput {
|
||||
images = append(images, &epubimage.Image{
|
||||
Id: img.Id,
|
||||
Path: img.Path,
|
||||
Name: img.Name,
|
||||
Id: img.Id,
|
||||
Path: img.Path,
|
||||
Name: img.Name,
|
||||
Format: e.Image.Format,
|
||||
})
|
||||
}
|
||||
|
||||
@ -59,13 +60,17 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) {
|
||||
})
|
||||
wg := &sync.WaitGroup{}
|
||||
|
||||
imgStorage, err := epubzip.NewEPUBZipStorageImageWriter(e.ImgStorage())
|
||||
imgStorage, err := epubzip.NewEPUBZipStorageImageWriter(e.ImgStorage(), e.Image.Format)
|
||||
if err != nil {
|
||||
bar.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < e.WorkersRatio(50); i++ {
|
||||
wr := 50
|
||||
if e.Image.Format == "png" {
|
||||
wr = 100
|
||||
}
|
||||
for i := 0; i < e.WorkersRatio(wr); i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
@ -90,6 +95,7 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) {
|
||||
DoublePage: part == 0 && src.Bounds().Dx() > src.Bounds().Dy(),
|
||||
Path: input.Path,
|
||||
Name: input.Name,
|
||||
Format: e.Image.Format,
|
||||
}
|
||||
|
||||
if err = imgStorage.Add(img.EPUBImgPath(), dst, e.Image.Quality); err != nil {
|
||||
@ -201,10 +207,12 @@ func (e *EPUBImageProcessor) transformImage(src image.Image, srcId int) []image.
|
||||
splitFilter = append(splitFilter, f)
|
||||
}
|
||||
|
||||
filters = append(filters,
|
||||
epubimagefilters.Resize(e.Image.View.Width, e.Image.View.Height, gift.LanczosResampling),
|
||||
epubimagefilters.Pixel(),
|
||||
)
|
||||
if e.Image.Resize {
|
||||
f := gift.ResizeToFit(e.Image.View.Width, e.Image.View.Height, gift.LanczosResampling)
|
||||
filters = append(filters, f)
|
||||
}
|
||||
|
||||
filters = append(filters, epubimagefilters.Pixel())
|
||||
|
||||
// convert
|
||||
{
|
||||
@ -232,10 +240,10 @@ func (e *EPUBImageProcessor) transformImage(src image.Image, srcId int) []image.
|
||||
// convert double page
|
||||
for _, b := range []bool{e.Image.Manga, !e.Image.Manga} {
|
||||
g := gift.New(splitFilter...)
|
||||
g.Add(
|
||||
epubimagefilters.CropSplitDoublePage(b),
|
||||
epubimagefilters.Resize(e.Image.View.Width, e.Image.View.Height, gift.LanczosResampling),
|
||||
)
|
||||
g.Add(epubimagefilters.CropSplitDoublePage(b))
|
||||
if e.Image.Resize {
|
||||
g.Add(gift.ResizeToFit(e.Image.View.Width, e.Image.View.Height, gift.LanczosResampling))
|
||||
}
|
||||
dst := e.createImage(src, g.Bounds(src.Bounds()))
|
||||
g.Draw(dst, src)
|
||||
images = append(images, dst)
|
||||
@ -251,5 +259,10 @@ func (e *EPUBImageProcessor) CoverTitleData(src image.Image, title string) (*epu
|
||||
dst := e.createImage(src, g.Bounds(src.Bounds()))
|
||||
g.Draw(dst, src)
|
||||
|
||||
return epubzip.CompressImage("OEBPS/Images/title.jpg", dst, e.Image.Quality)
|
||||
return epubzip.CompressImage(
|
||||
fmt.Sprintf("OEBPS/Images/title.%s", e.Image.Format),
|
||||
e.Image.Format,
|
||||
dst,
|
||||
e.Image.Quality,
|
||||
)
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ type Image struct {
|
||||
HasCover bool
|
||||
View *View
|
||||
GrayScale bool
|
||||
Resize bool
|
||||
Format string
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
|
@ -127,7 +127,7 @@ func getManifest(o *ContentOptions) []tag {
|
||||
var imageTags, pageTags, spaceTags []tag
|
||||
addTag := func(img *epubimage.Image, withSpace bool) {
|
||||
imageTags = append(imageTags,
|
||||
tag{"item", tagAttrs{"id": img.ImgKey(), "href": img.ImgPath(), "media-type": "image/jpeg"}, ""},
|
||||
tag{"item", tagAttrs{"id": img.ImgKey(), "href": img.ImgPath(), "media-type": fmt.Sprintf("image/%s", o.ImageOptions.Format)}, ""},
|
||||
)
|
||||
pageTags = append(pageTags,
|
||||
tag{"item", tagAttrs{"id": img.PageKey(), "href": img.PagePath(), "media-type": "application/xhtml+xml"}, ""},
|
||||
@ -144,7 +144,7 @@ func getManifest(o *ContentOptions) []tag {
|
||||
{"item", tagAttrs{"id": "css", "href": "Text/style.css", "media-type": "text/css"}, ""},
|
||||
{"item", tagAttrs{"id": "space_title", "href": "Text/space_title.xhtml", "media-type": "application/xhtml+xml"}, ""},
|
||||
{"item", tagAttrs{"id": "page_title", "href": "Text/title.xhtml", "media-type": "application/xhtml+xml"}, ""},
|
||||
{"item", tagAttrs{"id": "img_title", "href": "Images/title.jpg", "media-type": "image/jpeg"}, ""},
|
||||
{"item", tagAttrs{"id": "img_title", "href": fmt.Sprintf("Images/title.%s", o.ImageOptions.Format), "media-type": fmt.Sprintf("image/%s", o.ImageOptions.Format)}, ""},
|
||||
}
|
||||
|
||||
if o.ImageOptions.HasCover || o.Current > 1 {
|
||||
|
@ -8,8 +8,6 @@
|
||||
<meta name="viewport" content="{{ .ViewPort }}"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<img src="../{{ .ImagePath }}" alt="{{ .Title }}" style="{{ .ImageStyle }}"/>
|
||||
</div>
|
||||
<img src="../{{ .ImagePath }}" alt="{{ .Title }}" style="{{ .ImageStyle }}"/>
|
||||
</body>
|
||||
</html>
|
@ -4,9 +4,11 @@ import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"compress/flate"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -16,13 +18,20 @@ type ZipImage struct {
|
||||
}
|
||||
|
||||
// create gzip encoded jpeg
|
||||
func CompressImage(filename string, img image.Image, quality int) (*ZipImage, error) {
|
||||
func CompressImage(filename string, format string, img image.Image, quality int) (*ZipImage, error) {
|
||||
var (
|
||||
data, cdata bytes.Buffer
|
||||
err error
|
||||
)
|
||||
|
||||
err = jpeg.Encode(&data, img, &jpeg.Options{Quality: quality})
|
||||
switch format {
|
||||
case "png":
|
||||
err = png.Encode(&data, img)
|
||||
case "jpeg":
|
||||
err = jpeg.Encode(&data, img, &jpeg.Options{Quality: quality})
|
||||
default:
|
||||
err = fmt.Errorf("unknown format %q", format)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -8,19 +8,19 @@ import (
|
||||
)
|
||||
|
||||
type EPUBZipStorageImageWriter struct {
|
||||
fh *os.File
|
||||
fz *zip.Writer
|
||||
|
||||
mut *sync.Mutex
|
||||
fh *os.File
|
||||
fz *zip.Writer
|
||||
format string
|
||||
mut *sync.Mutex
|
||||
}
|
||||
|
||||
func NewEPUBZipStorageImageWriter(filename string) (*EPUBZipStorageImageWriter, error) {
|
||||
func NewEPUBZipStorageImageWriter(filename string, format string) (*EPUBZipStorageImageWriter, error) {
|
||||
fh, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fz := zip.NewWriter(fh)
|
||||
return &EPUBZipStorageImageWriter{fh, fz, &sync.Mutex{}}, nil
|
||||
return &EPUBZipStorageImageWriter{fh, fz, format, &sync.Mutex{}}, nil
|
||||
}
|
||||
|
||||
func (e *EPUBZipStorageImageWriter) Close() error {
|
||||
@ -32,7 +32,7 @@ func (e *EPUBZipStorageImageWriter) Close() error {
|
||||
}
|
||||
|
||||
func (e *EPUBZipStorageImageWriter) Add(filename string, img image.Image, quality int) error {
|
||||
zipImage, err := CompressImage(filename, img, quality)
|
||||
zipImage, err := CompressImage(filename, e.format, img, quality)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user