add cbz support

This commit is contained in:
2025-06-04 10:40:21 -04:00
parent 4afe1bfb18
commit 60c269ad35
3 changed files with 173 additions and 21 deletions

120
main.go
View File

@@ -1,9 +1,11 @@
package main
import (
"archive/zip"
_ "embed"
"fmt"
"image"
"io"
"log"
"os"
"path/filepath"
@@ -22,7 +24,12 @@ import (
type state struct {
dir string
i int
images []string
images []imagefile
}
type imagefile struct {
contents *image.Image
filename string
}
//go:embed media/noise.png
@@ -41,7 +48,20 @@ var fileListBindVar = tk.Variable("FileList")
var directoryState state
func (d state) pathToImageAtIndex(i int) string {
return filepath.Join(directoryState.dir, directoryState.images[i])
return filepath.Join(directoryState.dir, directoryState.images[i].filename)
}
func (d state) imageWithFilename(s string) (imagefile, int, error) {
for i, f := range directoryState.images {
if f.filename == s {
return directoryState.images[i], i, nil
}
}
return imagefile{}, 0, fmt.Errorf("not found")
}
func (d state) setImage(i int, img *image.Image) {
d.images[i].contents = img
}
func must[T any](t T, err error) T {
@@ -62,7 +82,49 @@ func newFileInDirectory() {
return
}
// GetOpenFile returns an array split on spaces!
newBrowse(strings.Join(files, " "))
file := strings.Join(files, " ")
if filepath.Ext(file) == ".cbr" || filepath.Ext(file) == ".cbz" {
log.Println("Comic Book Archive!")
openArchive(file)
return
}
newBrowse(file)
}
func openArchive(path string) {
r, err := zip.OpenReader(path)
if err != nil {
log.Println(err)
return
}
clearFileList()
directoryState.images = []imagefile{}
for _, f := range r.File {
log.Println(f.FileInfo().Name())
if f.FileInfo().IsDir() {
continue
}
if f.FileInfo().Name()[0] == '.' {
continue
}
reader, err := f.Open()
if err != nil {
log.Println(err)
continue
}
i, err := decode(reader, f.FileInfo().Name())
if err != nil {
log.Println(err)
continue
}
directoryState.images = append(directoryState.images, imagefile{
contents: &i,
filename: f.FileInfo().Name(),
})
insertIntoFileList(f.FileInfo().Name())
}
moveSelectionInFileList(0)
updateImage(directoryState.images[0].filename)
}
func newDirectory() {
@@ -102,12 +164,12 @@ func newBrowse(file string) {
})
// ...that way we only have to do this loop once.
clearFileList()
directoryState.images = []string{}
directoryState.images = []imagefile{}
i := 0
for _, v := range dirfiles {
if filetypes.IsImage(v) {
directoryState.images = append(directoryState.images, v.Name())
insertIntoFileList(directoryState.images[i])
directoryState.images = append(directoryState.images, imagefile{filename: v.Name()})
insertIntoFileList(directoryState.images[i].filename)
if v.Name() == filepath.Base(file) {
directoryState.i = i
moveSelectionInFileList(i)
@@ -121,24 +183,28 @@ func newBrowse(file string) {
func updateImage(file string) {
var i image.Image
f, err := os.Open(file)
entry, index, err := directoryState.imageWithFilename(filepath.Base(file))
if err != nil {
log.Printf("error opening image: %v", err)
log.Println(err.Error())
return
}
defer f.Close()
if entry.contents != nil {
fmt.Printf("loaded %s from cache\n", file)
i = *entry.contents
} else {
f, err := os.Open(file)
if err != nil {
log.Printf("error opening image: %v", err)
return
}
defer f.Close()
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(file), "."))
if checkErr(imaging.FormatFromExtension(ext)) {
i, err = imaging.Decode(f, imaging.AutoOrientation(true))
} else if ext == "webp" {
i, err = webp.Decode(f)
} else if ext == "tga" {
i, err = tga.Decode(f)
}
if err != nil {
log.Printf("error decoding image: %v", err)
return
i, err = decode(f, file)
if err != nil {
log.Printf("error decoding image: %v", err)
return
}
directoryState.setImage(index, &i)
}
i = imaging.Fit(i,
// -50 to give some space to breathe around the edges
@@ -149,6 +215,18 @@ func updateImage(file string) {
repaint(filepath.Base(file), tk.Data(i))
}
func decode(f io.Reader, name string) (image.Image, error) {
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(name), "."))
if checkErr(imaging.FormatFromExtension(ext)) {
return imaging.Decode(f, imaging.AutoOrientation(true))
} else if ext == "webp" {
return webp.Decode(f)
} else if ext == "tga" {
return tga.Decode(f)
}
return image.Black, fmt.Errorf("could not parse image")
}
func repaint(name string, data tk.Opt) {
// TODO: sometimes, when going from a big image to a smaller one,
// the window remains the same height as the big image,
@@ -229,7 +307,7 @@ func constructFileList() {
}))
clearFileList()
for i := range directoryState.images {
insertIntoFileList(directoryState.images[i])
insertIntoFileList(directoryState.images[i].filename)
if directoryState.i == i {
moveSelectionInFileList(i)
}