mirror of
https://github.com/gen2brain/cbconvert
synced 2026-07-24 12:25:38 +02:00
Compare commits
2
Commits
7b71fdae99
...
6a54e4d5e8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a54e4d5e8 | ||
|
|
629d569667 |
@@ -102,6 +102,8 @@ type Converter struct {
|
||||
prefix string
|
||||
// Input root for the current file, used to build recursive output paths
|
||||
root string
|
||||
// Target size for fast previews; when set, JPEG covers are IDCT-downscaled while decoding
|
||||
previewWidth, previewHeight int
|
||||
// Number of files
|
||||
Nfiles int
|
||||
// Index of the current file
|
||||
@@ -554,6 +556,27 @@ func (c *Converter) Preview(fileName string, fileInfo os.FileInfo, width, height
|
||||
return c.previewImage(fileName, i, width, height)
|
||||
}
|
||||
|
||||
// CoverPreview returns the cover fitted into width x height, skipping the output-codec round-trip.
|
||||
func (c *Converter) CoverPreview(fileName string, fileInfo os.FileInfo, width, height int) (Image, error) {
|
||||
c.previewWidth, c.previewHeight = width, height
|
||||
|
||||
i, err := c.coverImage(fileName, fileInfo)
|
||||
if err != nil {
|
||||
return Image{}, fmt.Errorf("%s: %w", fileName, err)
|
||||
}
|
||||
|
||||
if width != 0 && height != 0 {
|
||||
i = fit(i, width, height, resampleFilter(c.Opts.Filter))
|
||||
}
|
||||
|
||||
var img Image
|
||||
img.Image = i
|
||||
img.Width = i.Bounds().Dx()
|
||||
img.Height = i.Bounds().Dy()
|
||||
|
||||
return img, nil
|
||||
}
|
||||
|
||||
// PreviewPage returns the page-th image (0-based) as an image preview.
|
||||
func (c *Converter) PreviewPage(fileName string, fileInfo os.FileInfo, page, width, height int) (Image, error) {
|
||||
i, err := c.pageImage(fileName, fileInfo, page)
|
||||
|
||||
+48
-1
@@ -1,6 +1,7 @@
|
||||
package cbconvert
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
@@ -16,6 +17,7 @@ import (
|
||||
"github.com/gen2brain/avif"
|
||||
"github.com/gen2brain/go-fitz"
|
||||
"github.com/gen2brain/jpegli"
|
||||
"github.com/gen2brain/jpegn"
|
||||
"github.com/gen2brain/jpegxl"
|
||||
"github.com/gen2brain/webp"
|
||||
"github.com/jsummers/gobmp"
|
||||
@@ -356,8 +358,42 @@ func (c *Converter) imageTransform(img image.Image) image.Image {
|
||||
}
|
||||
|
||||
// imageDecode decodes image from reader.
|
||||
// jpegnOptions decodes straight to RGBA with high-quality chroma upsampling.
|
||||
var jpegnOptions = jpegn.Options{ToRGBA: true, UpsampleMethod: jpegn.CatmullRom}
|
||||
|
||||
func (c *Converter) imageDecode(reader io.Reader) (image.Image, error) {
|
||||
img, _, err := image.Decode(reader)
|
||||
br := bufio.NewReader(reader)
|
||||
|
||||
if magic, err := br.Peek(2); err == nil && magic[0] == 0xff && magic[1] == 0xd8 {
|
||||
opts := jpegnOptions
|
||||
|
||||
if c.previewWidth > 0 && c.previewHeight > 0 {
|
||||
data, err := io.ReadAll(br)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("imageDecode: %w", err)
|
||||
}
|
||||
|
||||
if cfg, err := jpegn.DecodeConfig(bytes.NewReader(data)); err == nil {
|
||||
opts.ScaleDenom = scaleDenom(cfg.Width, cfg.Height, c.previewWidth, c.previewHeight)
|
||||
}
|
||||
|
||||
img, err := jpegn.Decode(bytes.NewReader(data), &opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("imageDecode: %w", err)
|
||||
}
|
||||
|
||||
return img, nil
|
||||
}
|
||||
|
||||
img, err := jpegn.Decode(br, &opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("imageDecode: %w", err)
|
||||
}
|
||||
|
||||
return img, nil
|
||||
}
|
||||
|
||||
img, _, err := image.Decode(br)
|
||||
if err != nil {
|
||||
return img, fmt.Errorf("imageDecode: %w", err)
|
||||
}
|
||||
@@ -365,6 +401,17 @@ func (c *Converter) imageDecode(reader io.Reader) (image.Image, error) {
|
||||
return img, nil
|
||||
}
|
||||
|
||||
// scaleDenom returns the largest JPEG IDCT denominator (1, 2, 4, 8) that keeps w x h at or above tw x th.
|
||||
func scaleDenom(w, h, tw, th int) int {
|
||||
for _, d := range []int{8, 4, 2} {
|
||||
if w/d >= tw && h/d >= th {
|
||||
return d
|
||||
}
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
// imageEncode encodes image to file.
|
||||
func (c *Converter) imageEncode(img image.Image, w io.Writer) error {
|
||||
var err error
|
||||
|
||||
@@ -70,10 +70,37 @@ func fileDlg(title string, multiple, directory bool, dirKey string) ([]string, e
|
||||
|
||||
const dlgPreviewName = "_FILEDLGPREVIEW_"
|
||||
|
||||
// previewPad insets the cover from the preview pane edges, in pixels per side.
|
||||
const previewPad = 8
|
||||
|
||||
// previewCover returns a FILE_CB handler that draws the highlighted comic's cover in the dialog preview pane.
|
||||
// Extracted covers are cached by path so re-highlighting a file doesn't re-extract it.
|
||||
func previewCover() iup.FileFunc {
|
||||
var image iup.Ihandle
|
||||
var lastFile string
|
||||
const maxCache = 32
|
||||
|
||||
cache := make(map[string]iup.Ihandle)
|
||||
order := make([]string, 0, maxCache)
|
||||
|
||||
cover := func(path string, w, h int) iup.Ihandle {
|
||||
if img, ok := cache[path]; ok {
|
||||
return img
|
||||
}
|
||||
|
||||
img := loadCover(path, w, h)
|
||||
cache[path] = img
|
||||
order = append(order, path)
|
||||
|
||||
if len(order) > maxCache {
|
||||
old := order[0]
|
||||
order = order[1:]
|
||||
if oi := cache[old]; oi != 0 {
|
||||
oi.Destroy()
|
||||
}
|
||||
delete(cache, old)
|
||||
}
|
||||
|
||||
return img
|
||||
}
|
||||
|
||||
return func(ih iup.Ihandle, filename, status string) int {
|
||||
switch status {
|
||||
@@ -82,19 +109,8 @@ func previewCover() iup.FileFunc {
|
||||
cw, ch := iup.DrawGetSize(ih)
|
||||
iup.DrawParentBackground(ih)
|
||||
|
||||
if filename != lastFile {
|
||||
lastFile = filename
|
||||
if image != 0 {
|
||||
image.Destroy()
|
||||
image = 0
|
||||
}
|
||||
if img := loadCover(filename, cw, ch); img != 0 {
|
||||
image = img
|
||||
iup.SetHandle(dlgPreviewName, image)
|
||||
}
|
||||
}
|
||||
|
||||
if image != 0 {
|
||||
if image := cover(filename, cw-2*previewPad, ch-2*previewPad); image != 0 {
|
||||
iup.SetHandle(dlgPreviewName, image)
|
||||
iw, iih, _ := iup.DrawGetImageInfo(dlgPreviewName)
|
||||
iup.DrawImage(ih, dlgPreviewName, (cw-iw)/2, (ch-iih)/2, iw, iih)
|
||||
} else {
|
||||
@@ -106,11 +122,13 @@ func previewCover() iup.FileFunc {
|
||||
|
||||
iup.DrawEnd(ih)
|
||||
case "FINISH":
|
||||
if image != 0 {
|
||||
image.Destroy()
|
||||
image = 0
|
||||
for _, img := range cache {
|
||||
if img != 0 {
|
||||
img.Destroy()
|
||||
}
|
||||
}
|
||||
lastFile = ""
|
||||
cache = make(map[string]iup.Ihandle)
|
||||
order = order[:0]
|
||||
}
|
||||
|
||||
return iup.DEFAULT
|
||||
@@ -131,7 +149,7 @@ func loadCover(path string, w, h int) iup.Ihandle {
|
||||
opts := cbconvert.NewOptions()
|
||||
opts.DPI = 96
|
||||
|
||||
img, err := cbconvert.New(opts).Preview(path, fi, w, h)
|
||||
img, err := cbconvert.New(opts).CoverPreview(path, fi, w, h)
|
||||
if err != nil || img.Image == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ require (
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/ebitengine/purego v0.10.1 // indirect
|
||||
github.com/gen2brain/avif v0.5.1 // indirect
|
||||
github.com/gen2brain/go-fitz v1.24.15 // indirect
|
||||
github.com/gen2brain/go-fitz v1.28.0 // indirect
|
||||
github.com/gen2brain/jpegli v0.4.1 // indirect
|
||||
github.com/gen2brain/jpegxl v0.5.1 // indirect
|
||||
github.com/gen2brain/webp v0.6.1 // indirect
|
||||
@@ -31,7 +31,6 @@ require (
|
||||
github.com/golang/geo v0.0.0-20260625163123-7c0e84413537 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
|
||||
github.com/jupiterrider/ffi v0.7.0 // indirect
|
||||
github.com/klauspost/compress v1.18.6 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/mholt/archives v0.1.5 // indirect
|
||||
|
||||
@@ -42,8 +42,7 @@ github.com/gen2brain/avif v0.5.1 h1:LQzLsJpWyGlsa4wuZ3D57qEbCiICIK7Yidz5ZPEwzTk=
|
||||
github.com/gen2brain/avif v0.5.1/go.mod h1:QgrYqdVE9y40PCfArK9VakcMIpYeDYpZmCSLkW6C1n8=
|
||||
github.com/gen2brain/cbconvert v1.0.5-0.20260626071631-8155626dbb42 h1:p1K1jOk+rKDhTgh6fiYMKSqXJdIVUWFLK5jodTtwPOU=
|
||||
github.com/gen2brain/cbconvert v1.0.5-0.20260626071631-8155626dbb42/go.mod h1:qHzMhKZ7VBTffwDQ/9rc4yZ9FO5677ZSjSFZ7QNfaLw=
|
||||
github.com/gen2brain/go-fitz v1.24.15 h1:sJNB1MOWkqnzzENPHggFpgxTwW0+S5WF/rM5wUBpJWo=
|
||||
github.com/gen2brain/go-fitz v1.24.15/go.mod h1:SftkiVbTHqF141DuiLwBBM65zP7ig6AVDQpf2WlHamo=
|
||||
github.com/gen2brain/go-fitz v1.28.0 h1:RovqgQPAcOuyv5HZrWsTWl8qwlwbAHSKcAZXZUw0Vlk=
|
||||
github.com/gen2brain/iup-go/iup v0.32.1-0.20260626100855-f328861e3291 h1:ad/nhBGhknOGDpiHnQ0ZLltZccG82t4tAKK94SrQ8OY=
|
||||
github.com/gen2brain/iup-go/iup v0.32.1-0.20260626100855-f328861e3291/go.mod h1:V4f7tHOJAeHtjQ+ju795QKv6DGdLEb4L5cmWB1sjSzU=
|
||||
github.com/gen2brain/jpegli v0.4.1 h1:qc11IQU0jTYFltroulT4MXmbu9YRftqHV0YBZ0Bqz5o=
|
||||
@@ -69,8 +68,6 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
|
||||
github.com/jupiterrider/ffi v0.7.0 h1:RKsl6Ascal+3kyAqR5Qcbp83LceQMLc1VZbPfHWoNzs=
|
||||
github.com/jupiterrider/ffi v0.7.0/go.mod h1:9dauhpOfNqrqk28fxuu0kkdeFtT9Qr4vbfigiuIXN7c=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
|
||||
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
|
||||
@@ -148,6 +148,8 @@ func settingsApply(group string) {
|
||||
}
|
||||
}
|
||||
|
||||
userLossless = iup.GetHandle("Lossless").GetAttribute("VALUE") == "ON"
|
||||
|
||||
syncLabels()
|
||||
setActive()
|
||||
previewPost()
|
||||
|
||||
@@ -1,10 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n"
|
||||
"github.com/gen2brain/iup-go/iup"
|
||||
)
|
||||
|
||||
// jxlLosslessBuild reports whether wasm2go and nodynamic leave zune-jpegxl (lossless-only) as the only jxl encoder.
|
||||
var jxlLosslessBuild = func() bool {
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
var wasm2go, nodynamic bool
|
||||
for _, kv := range info.Settings {
|
||||
if kv.Key != "-tags" {
|
||||
continue
|
||||
}
|
||||
for _, t := range strings.Split(kv.Value, ",") {
|
||||
switch t {
|
||||
case "wasm2go":
|
||||
wasm2go = true
|
||||
case "nodynamic":
|
||||
nodynamic = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return wasm2go && nodynamic
|
||||
}()
|
||||
|
||||
// userLossless is the user's Lossless preference, tracked separately because a jxl
|
||||
// wasm2go build force-sets the widget on.
|
||||
var userLossless bool
|
||||
|
||||
func setActive() {
|
||||
if busy {
|
||||
return
|
||||
@@ -68,7 +98,15 @@ func setActive() {
|
||||
}
|
||||
|
||||
canLossless := opts.Format == "webp" || opts.Format == "avif" || opts.Format == "jxl"
|
||||
losslessOn := canLossless && opts.Lossless
|
||||
jxlLossless := jxlLosslessBuild && opts.Format == "jxl"
|
||||
|
||||
// jxl wasm2go forces lossless on; otherwise show the user's preference so it doesn't stay stuck on.
|
||||
losslessVal := "OFF"
|
||||
if jxlLossless || userLossless {
|
||||
losslessVal = "ON"
|
||||
}
|
||||
iup.GetHandle("Lossless").SetAttribute("VALUE", losslessVal)
|
||||
losslessOn := jxlLossless || (canLossless && userLossless)
|
||||
|
||||
if (opts.Format == "jpeg" || canLossless) && !opts.NoConvert && !losslessOn {
|
||||
iup.GetHandle("VboxQuality").SetAttribute("ACTIVE", "YES")
|
||||
@@ -84,6 +122,11 @@ func setActive() {
|
||||
iup.GetHandle("Lossless").SetAttribute("ACTIVE", "NO")
|
||||
}
|
||||
|
||||
if jxlLossless {
|
||||
iup.GetHandle("Lossless").SetAttribute("ACTIVE", "NO")
|
||||
iup.GetHandle("VboxEffort").SetAttribute("ACTIVE", "NO")
|
||||
}
|
||||
|
||||
if opts.Width != 0 && opts.Height != 0 && !opts.NoConvert {
|
||||
iup.GetHandle("Fit").SetAttribute("ACTIVE", "YES")
|
||||
} else {
|
||||
|
||||
@@ -60,7 +60,7 @@ func list() iup.Ihandle {
|
||||
"TITLE1": i18n.Lng(i18n.ColTitle),
|
||||
"TITLE2": i18n.Lng(i18n.ColType),
|
||||
"TITLE3": i18n.Lng(i18n.ColSize),
|
||||
"WIDTH1": "300",
|
||||
"WIDTH1": "250",
|
||||
"WIDTH2": "50",
|
||||
"WIDTH3": "100",
|
||||
"ALIGNMENT2": "ACENTER",
|
||||
@@ -568,6 +568,7 @@ func tabImage() iup.Ihandle {
|
||||
iup.Toggle(i18n.Lng(i18n.TglLossless)).SetHandle("Lossless").
|
||||
SetAttribute("TIP", i18n.Lng(i18n.TipLossless)).
|
||||
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
||||
userLossless = ih.GetAttribute("VALUE") == "ON"
|
||||
setActive()
|
||||
previewPost()
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ require (
|
||||
github.com/ebitengine/purego v0.10.1 // indirect
|
||||
github.com/fvbommel/sortorder v1.1.0 // indirect
|
||||
github.com/gen2brain/avif v0.5.1 // indirect
|
||||
github.com/gen2brain/go-fitz v1.24.15 // indirect
|
||||
github.com/gen2brain/go-fitz v1.28.0 // indirect
|
||||
github.com/gen2brain/jpegli v0.4.1 // indirect
|
||||
github.com/gen2brain/jpegxl v0.5.1 // indirect
|
||||
github.com/gen2brain/webp v0.6.1 // indirect
|
||||
@@ -32,7 +32,6 @@ require (
|
||||
github.com/golang/geo v0.0.0-20260625163123-7c0e84413537 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
|
||||
github.com/jupiterrider/ffi v0.7.0 // indirect
|
||||
github.com/klauspost/compress v1.18.6 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.24 // indirect
|
||||
|
||||
@@ -46,8 +46,7 @@ github.com/gen2brain/avif v0.5.1 h1:LQzLsJpWyGlsa4wuZ3D57qEbCiICIK7Yidz5ZPEwzTk=
|
||||
github.com/gen2brain/avif v0.5.1/go.mod h1:QgrYqdVE9y40PCfArK9VakcMIpYeDYpZmCSLkW6C1n8=
|
||||
github.com/gen2brain/cbconvert v1.0.5-0.20260626071631-8155626dbb42 h1:p1K1jOk+rKDhTgh6fiYMKSqXJdIVUWFLK5jodTtwPOU=
|
||||
github.com/gen2brain/cbconvert v1.0.5-0.20260626071631-8155626dbb42/go.mod h1:qHzMhKZ7VBTffwDQ/9rc4yZ9FO5677ZSjSFZ7QNfaLw=
|
||||
github.com/gen2brain/go-fitz v1.24.15 h1:sJNB1MOWkqnzzENPHggFpgxTwW0+S5WF/rM5wUBpJWo=
|
||||
github.com/gen2brain/go-fitz v1.24.15/go.mod h1:SftkiVbTHqF141DuiLwBBM65zP7ig6AVDQpf2WlHamo=
|
||||
github.com/gen2brain/go-fitz v1.28.0 h1:RovqgQPAcOuyv5HZrWsTWl8qwlwbAHSKcAZXZUw0Vlk=
|
||||
github.com/gen2brain/jpegli v0.4.1 h1:qc11IQU0jTYFltroulT4MXmbu9YRftqHV0YBZ0Bqz5o=
|
||||
github.com/gen2brain/jpegli v0.4.1/go.mod h1:zJ++s4symmKCN1CLkrY0dGXTY3s0NWbd94Rz9KLdCzk=
|
||||
github.com/gen2brain/jpegxl v0.5.1 h1:UuBUIkZ35DErImU3bTA6rltfV5zSgVNOA/K5a6JibfE=
|
||||
@@ -71,8 +70,6 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
|
||||
github.com/jupiterrider/ffi v0.7.0 h1:RKsl6Ascal+3kyAqR5Qcbp83LceQMLc1VZbPfHWoNzs=
|
||||
github.com/jupiterrider/ffi v0.7.0/go.mod h1:9dauhpOfNqrqk28fxuu0kkdeFtT9Qr4vbfigiuIXN7c=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
|
||||
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
|
||||
@@ -10,6 +10,7 @@ require (
|
||||
github.com/gen2brain/avif v0.5.1
|
||||
github.com/gen2brain/go-fitz v1.28.0
|
||||
github.com/gen2brain/jpegli v0.4.1
|
||||
github.com/gen2brain/jpegn v0.4.2
|
||||
github.com/gen2brain/jpegxl v0.5.1
|
||||
github.com/gen2brain/webp v0.6.1
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25
|
||||
|
||||
@@ -44,6 +44,8 @@ github.com/gen2brain/go-fitz v1.28.0 h1:RovqgQPAcOuyv5HZrWsTWl8qwlwbAHSKcAZXZUw0
|
||||
github.com/gen2brain/go-fitz v1.28.0/go.mod h1:pY2hqAjp9Zy7qfPI2gwbJMHBFAdZpVXOLrRxD82l3Bs=
|
||||
github.com/gen2brain/jpegli v0.4.1 h1:qc11IQU0jTYFltroulT4MXmbu9YRftqHV0YBZ0Bqz5o=
|
||||
github.com/gen2brain/jpegli v0.4.1/go.mod h1:zJ++s4symmKCN1CLkrY0dGXTY3s0NWbd94Rz9KLdCzk=
|
||||
github.com/gen2brain/jpegn v0.4.2 h1:sxy2yolV1eNA02uYtnqBFm4EIC3ETnars98aG7Dc4LM=
|
||||
github.com/gen2brain/jpegn v0.4.2/go.mod h1:YvcVOmVPSAsefH6yn9HBW3uY0EHlZwCMoiJXoAWfgL0=
|
||||
github.com/gen2brain/jpegxl v0.5.1 h1:UuBUIkZ35DErImU3bTA6rltfV5zSgVNOA/K5a6JibfE=
|
||||
github.com/gen2brain/jpegxl v0.5.1/go.mod h1:Wlc6lqx03RJfhiQRyHa2e+8VQwT4/qv7zSRsNv9T+yE=
|
||||
github.com/gen2brain/webp v0.6.1 h1:ei7Y1SWpQcdqz3YNDNyn4y2nQanxs9WLzwW5/2DKS64=
|
||||
|
||||
@@ -95,6 +95,7 @@ golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
|
||||
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
|
||||
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
|
||||
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
|
||||
|
||||
Reference in New Issue
Block a user