package epubimageprocessor import ( "archive/zip" "bytes" "fmt" "image" "image/jpeg" "image/png" "io" "io/fs" "os" "path/filepath" "slices" "sort" "strings" "github.com/celogeek/go-comic-converter/v3/internal/pkg/epubimage" "github.com/celogeek/go-comic-converter/v3/internal/pkg/epubprogress" "github.com/celogeek/go-comic-converter/v3/internal/pkg/epubzip" "github.com/celogeek/go-comic-converter/v3/internal/pkg/sortpath" ) func (e EPUBImageProcessor) PassThrough() (images []epubimage.EPUBImage, err error) { fi, err := os.Stat(e.Input) if err != nil { return } if fi.IsDir() { return e.passThroughDir() } else { switch ext := strings.ToLower(filepath.Ext(e.Input)); ext { case ".cbz", ".zip": return e.passThroughCbz() case ".cbr", ".rar": return e.passThroughCbr() default: return nil, fmt.Errorf("unknown file format (%s): support .cbz, .zip, .cbr, .rar", ext) } } } func (e EPUBImageProcessor) passThroughDir() (images []epubimage.EPUBImage, err error) { imagesPath := make([]string, 0) input := filepath.Clean(e.Input) err = filepath.WalkDir(input, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if filterCopyPath(d.IsDir(), path) { imagesPath = append(imagesPath, path) } return nil }) if err != nil { return } if len(imagesPath) == 0 { err = errNoImagesFound return } sort.Sort(sortpath.By(imagesPath, e.SortPathMode)) var imgStorage epubzip.StorageImageWriter imgStorage, err = epubzip.NewStorageImageWriter(e.ImgStorage(), e.Image.Format) if err != nil { return } defer imgStorage.Close() // processing bar := epubprogress.New(epubprogress.Options{ Quiet: e.Quiet, Json: e.Json, Max: len(imagesPath), Description: "Copying", CurrentJob: 1, TotalJob: 2, }) defer bar.Close() for i, imgPath := range imagesPath { var f *os.File f, err = os.Open(imgPath) if err != nil { return } var img epubimage.EPUBImage img, err = copyRawDataToStorage( imgStorage, f, i, input, imgPath, ) if err != nil { return } images = append(images, img) _ = bar.Add(1) } if len(images) == 0 { err = errNoImagesFound } return } func (e EPUBImageProcessor) passThroughCbz() (images []epubimage.EPUBImage, err error) { images = make([]epubimage.EPUBImage, 0) input := filepath.Clean(e.Input) r, err := zip.OpenReader(input) if err != nil { return } defer r.Close() imagesZip := make([]*zip.File, 0) for _, f := range r.File { if filterCopyPath(f.FileInfo().IsDir(), f.Name) { imagesZip = append(imagesZip, f) } } if len(imagesZip) == 0 { err = errNoImagesFound return } var names []string for _, img := range imagesZip { names = append(names, img.Name) } sort.Sort(sortpath.By(names, e.SortPathMode)) indexedNames := make(map[string]int) for i, name := range names { indexedNames[name] = i } var imgStorage epubzip.StorageImageWriter imgStorage, err = epubzip.NewStorageImageWriter(e.ImgStorage(), e.Image.Format) if err != nil { return } defer imgStorage.Close() // processing bar := epubprogress.New(epubprogress.Options{ Quiet: e.Quiet, Json: e.Json, Max: len(imagesZip), Description: "Copying", CurrentJob: 1, TotalJob: 2, }) defer bar.Close() for _, imgZip := range imagesZip { var f io.ReadCloser f, err = imgZip.Open() if err != nil { return } var img epubimage.EPUBImage img, err = copyRawDataToStorage( imgStorage, f, indexedNames[imgZip.Name], "", imgZip.Name, ) if err != nil { return } images = append(images, img) _ = bar.Add(1) } if len(images) == 0 { err = errNoImagesFound } return } func (e EPUBImageProcessor) passThroughCbr() (images []epubimage.EPUBImage, err error) { images = make([]epubimage.EPUBImage, 0) err = errNoImagesFound return } func filterCopyPath(isDir bool, filename string) bool { return !isDir && !strings.HasPrefix(filepath.Base(filename), ".") && slices.Contains([]string{".jpeg", ".jpg", ".png"}, strings.ToLower(filepath.Ext(filename))) } func copyRawDataToStorage( imgStorage epubzip.StorageImageWriter, f io.ReadCloser, id int, dirname string, filename string, ) (img epubimage.EPUBImage, err error) { var uncompressedData []byte uncompressedData, err = io.ReadAll(f) if err != nil { return } err = f.Close() if err != nil { return } p, fn := filepath.Split(filepath.Clean(filename)) if p == dirname { p = "" } else { p = p[len(dirname)+1:] } var ( format string decodeConfig func(r io.Reader) (image.Config, error) decode func(r io.Reader) (image.Image, error) ) switch filepath.Ext(fn) { case ".png": format = "png" decodeConfig = png.DecodeConfig decode = png.Decode case ".jpg", ".jpeg": format = "jpeg" decodeConfig = jpeg.DecodeConfig decode = jpeg.Decode } var config image.Config config, err = decodeConfig(bytes.NewReader(uncompressedData)) if err != nil { return } var rawImage image.Image if id == 0 { rawImage, err = decode(bytes.NewReader(uncompressedData)) if err != nil { return } } img = epubimage.EPUBImage{ Id: id, Part: 0, Raw: rawImage, Width: config.Width, Height: config.Height, IsBlank: false, DoublePage: config.Width > config.Height, Path: p, Name: fn, Format: format, OriginalAspectRatio: float64(config.Height) / float64(config.Width), } err = imgStorage.AddRaw(img.EPUBImgPath(), uncompressedData) return }