Add Lossless option

This commit is contained in:
Milan Nikolic
2026-06-23 18:16:11 +02:00
parent b7c422fe33
commit a5817c3ba5
4 changed files with 205 additions and 161 deletions
+2
View File
@@ -27,6 +27,8 @@ type Options struct {
Quality int Quality int
// Encoder speed/effort, format-specific: webp method 0-6, avif speed 0-10, jxl effort 1-10; -1 uses the format default // Encoder speed/effort, format-specific: webp method 0-6, avif speed 0-10, jxl effort 1-10; -1 uses the format default
Effort int Effort int
// Lossless enables lossless compression (webp, avif, jxl), ignores quality
Lossless bool
// Image width // Image width
Width int Width int
// Image height // Image height
+3 -3
View File
@@ -402,19 +402,19 @@ func (c *Converter) imageEncode(img image.Image, w io.Writer) error {
if c.Opts.Effort >= 0 { if c.Opts.Effort >= 0 {
method = min(max(c.Opts.Effort, 0), 6) method = min(max(c.Opts.Effort, 0), 6)
} }
err = webp.Encode(w, img, webp.Options{Quality: c.Opts.Quality, Method: method}) err = webp.Encode(w, img, webp.Options{Quality: c.Opts.Quality, Method: method, Lossless: c.Opts.Lossless})
case "avif": case "avif":
speed := avif.DefaultSpeed speed := avif.DefaultSpeed
if c.Opts.Effort >= 0 { if c.Opts.Effort >= 0 {
speed = min(max(c.Opts.Effort, 0), 10) speed = min(max(c.Opts.Effort, 0), 10)
} }
err = avif.Encode(w, img, avif.Options{Quality: c.Opts.Quality, Speed: speed}) err = avif.Encode(w, img, avif.Options{Quality: c.Opts.Quality, Speed: speed, Lossless: c.Opts.Lossless})
case "jxl": case "jxl":
effort := jpegxl.DefaultEffort effort := jpegxl.DefaultEffort
if c.Opts.Effort >= 0 { if c.Opts.Effort >= 0 {
effort = min(max(c.Opts.Effort, 1), 10) effort = min(max(c.Opts.Effort, 1), 10)
} }
err = jpegxl.Encode(w, img, jpegxl.Options{Quality: c.Opts.Quality, Effort: effort}) err = jpegxl.Encode(w, img, jpegxl.Options{Quality: c.Opts.Quality, Effort: effort, Lossless: c.Opts.Lossless})
case "bmp": case "bmp":
opts := &gobmp.EncoderOptions{} opts := &gobmp.EncoderOptions{}
opts.SupportTransparency(false) opts.SupportTransparency(false)
+101 -61
View File
@@ -146,6 +146,7 @@ func options() cbconvert.Options {
default: default:
opts.Effort = -1 opts.Effort = -1
} }
opts.Lossless = iup.GetHandle("Lossless").GetAttribute("VALUE") == "ON"
opts.Grayscale = iup.GetHandle("Grayscale").GetAttribute("VALUE") == "ON" opts.Grayscale = iup.GetHandle("Grayscale").GetAttribute("VALUE") == "ON"
opts.Brightness = iup.GetHandle("Brightness").GetInt("VALUE") opts.Brightness = iup.GetHandle("Brightness").GetInt("VALUE")
opts.Contrast = iup.GetHandle("Contrast").GetInt("VALUE") opts.Contrast = iup.GetHandle("Contrast").GetInt("VALUE")
@@ -171,24 +172,30 @@ func setActive() {
iup.GetHandle("RemoveAll").SetAttribute("ACTIVE", "YES") iup.GetHandle("RemoveAll").SetAttribute("ACTIVE", "YES")
} }
if opts.OutDir == "" { active := "YES"
iup.GetHandle("Thumbnail").SetAttributes(`ACTIVE=NO`) var tip string
iup.GetHandle("Cover").SetAttributes(`ACTIVE=NO`) switch {
iup.GetHandle("Convert").SetAttributes(`ACTIVE=NO`) case count == 0 && opts.OutDir == "":
if count > 0 { active, tip = "NO", "Add files and set output directory"
iup.GetHandle("Thumbnail").SetAttributes(`ACTIVE=NO, TIP="Set Output Directory"`) case count == 0:
iup.GetHandle("Cover").SetAttributes(`ACTIVE=NO, TIP="Set Output Directory"`) active, tip = "NO", "Add files"
iup.GetHandle("Convert").SetAttributes(`ACTIVE=NO, TIP="Set Output Directory"`) case opts.OutDir == "":
active, tip = "NO", "Set output directory"
} }
enabledTip := map[string]string{
"Thumbnail": "Extract cover thumbnails",
"Cover": "Extract covers",
"Convert": "Convert files to the selected format",
}
for _, h := range []string{"Thumbnail", "Cover", "Convert"} {
b := iup.GetHandle(h)
b.SetAttribute("ACTIVE", active)
if active == "YES" {
b.SetAttribute("TIP", enabledTip[h])
} else { } else {
if count > 0 { b.SetAttribute("TIP", tip)
iup.GetHandle("Thumbnail").SetAttributes(`ACTIVE=YES, TIP=""`)
iup.GetHandle("Cover").SetAttributes(`ACTIVE=YES, TIP=""`)
iup.GetHandle("Convert").SetAttributes(`ACTIVE=YES, TIP=""`)
} else {
iup.GetHandle("Thumbnail").SetAttributes(`ACTIVE=NO`)
iup.GetHandle("Cover").SetAttributes(`ACTIVE=NO`)
iup.GetHandle("Convert").SetAttributes(`ACTIVE=NO`)
} }
} }
@@ -200,16 +207,21 @@ func setActive() {
iup.GetHandle("VboxTransform").SetAttribute("ACTIVE", "YES") iup.GetHandle("VboxTransform").SetAttribute("ACTIVE", "YES")
} }
if (opts.Format == "jpeg" || opts.Format == "webp" || opts.Format == "avif" || opts.Format == "jxl") && !opts.NoConvert { canLossless := opts.Format == "webp" || opts.Format == "avif" || opts.Format == "jxl"
losslessOn := canLossless && opts.Lossless
if (opts.Format == "jpeg" || canLossless) && !opts.NoConvert && !losslessOn {
iup.GetHandle("VboxQuality").SetAttribute("ACTIVE", "YES") iup.GetHandle("VboxQuality").SetAttribute("ACTIVE", "YES")
} else { } else {
iup.GetHandle("VboxQuality").SetAttribute("ACTIVE", "NO") iup.GetHandle("VboxQuality").SetAttribute("ACTIVE", "NO")
} }
if (opts.Format == "webp" || opts.Format == "avif" || opts.Format == "jxl") && !opts.NoConvert { if canLossless && !opts.NoConvert {
iup.GetHandle("VboxEffort").SetAttribute("ACTIVE", "YES") iup.GetHandle("VboxEffort").SetAttribute("ACTIVE", "YES")
iup.GetHandle("Lossless").SetAttribute("ACTIVE", "YES")
} else { } else {
iup.GetHandle("VboxEffort").SetAttribute("ACTIVE", "NO") iup.GetHandle("VboxEffort").SetAttribute("ACTIVE", "NO")
iup.GetHandle("Lossless").SetAttribute("ACTIVE", "NO")
} }
if opts.Width != 0 && opts.Height != 0 && !opts.NoConvert { if opts.Width != 0 && opts.Height != 0 && !opts.NoConvert {
@@ -243,6 +255,7 @@ func setEffort(format string) {
val.SetAttribute("EFFORTNAME", name) val.SetAttribute("EFFORTNAME", name)
iup.GetHandle("LabelEffort").SetAttribute("TITLE", fmt.Sprintf("%s: %d", name, val.GetInt("VALUE"))) iup.GetHandle("LabelEffort").SetAttribute("TITLE", fmt.Sprintf("%s: %d", name, val.GetInt("VALUE")))
iup.Refresh(iup.GetHandle("LabelEffort"))
} }
func layout() iup.Ihandle { func layout() iup.Ihandle {
@@ -401,7 +414,7 @@ func tabs() iup.Ihandle {
SetAttributes(`TIP="Process only files larger than minimum size"`), SetAttributes(`TIP="Process only files larger than minimum size"`),
), ),
iup.Space().SetAttributes("EXPAND=HORIZONTAL"), iup.Space().SetAttributes("EXPAND=HORIZONTAL"),
).SetHandle("VboxInput").SetAttributes("MARGIN=5x5, GAP=5") ).SetHandle("VboxInput").SetAttributes("NGAP=10")
vboxOutput := iup.Vbox( vboxOutput := iup.Vbox(
iup.Vbox( iup.Vbox(
@@ -430,9 +443,10 @@ func tabs() iup.Ihandle {
"2": "TAR", "2": "TAR",
}).SetHandle("Archive"), }).SetHandle("Archive"),
), ),
).SetHandle("VboxOutput").SetAttributes("MARGIN=5x5, GAP=5") ).SetHandle("VboxOutput").SetAttributes("NGAP=10")
vboxImage := iup.Vbox( vboxImage := iup.Hbox(
iup.Vbox(
iup.Vbox( iup.Vbox(
iup.Label("Format:"), iup.Label("Format:"),
iup.List().SetAttributes(map[string]string{ iup.List().SetAttributes(map[string]string{
@@ -457,7 +471,7 @@ func tabs() iup.Ihandle {
iup.Vbox( iup.Vbox(
iup.Label("Size:"), iup.Label("Size:"),
iup.Hbox( iup.Hbox(
iup.Text().SetAttributes(`CUEBANNER=" width", VISIBLECOLUMNS=4, MASK="/d*"`).SetHandle("Width"). iup.Text().SetAttributes(`CUEBANNER="width", VISIBLECOLUMNS=6, MASK="/d*"`).SetHandle("Width").
SetAttribute("TIP", "If one of, width or height is not set, the image aspect ratio is preserved"). SetAttribute("TIP", "If one of, width or height is not set, the image aspect ratio is preserved").
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
setActive() setActive()
@@ -473,8 +487,10 @@ func tabs() iup.Ihandle {
return iup.DEFAULT return iup.DEFAULT
})), })),
iup.Space().SetAttribute("SIZE", "2"),
iup.Label("x"), iup.Label("x"),
iup.Text().SetAttributes(`CUEBANNER=" height", VISIBLECOLUMNS=4, MASK="/d*"`).SetHandle("Height"). iup.Space().SetAttribute("SIZE", "2"),
iup.Text().SetAttributes(`CUEBANNER="height", VISIBLECOLUMNS=6, MASK="/d*"`).SetHandle("Height").
SetAttribute("TIP", "If one of, width or height is not set, the image aspect ratio is preserved"). SetAttribute("TIP", "If one of, width or height is not set, the image aspect ratio is preserved").
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
setActive() setActive()
@@ -490,7 +506,7 @@ func tabs() iup.Ihandle {
return iup.DEFAULT return iup.DEFAULT
})), })),
).SetAttributes("ALIGNMENT=ACENTER, MARGIN=0"), ).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=0"),
), ),
iup.Vbox( iup.Vbox(
iup.Toggle(" Best Fit").SetHandle("Fit"). iup.Toggle(" Best Fit").SetHandle("Fit").
@@ -511,15 +527,19 @@ func tabs() iup.Ihandle {
"7": "Lanczos", "7": "Lanczos",
}).SetHandle("Filter").SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(onFilterChanged)), }).SetHandle("Filter").SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(onFilterChanged)),
), ),
).SetAttributes("NGAP=10"),
iup.Space().SetAttribute("SIZE", "15"),
iup.Vbox(
iup.Vbox( iup.Vbox(
iup.Hbox( iup.Hbox(
iup.Label("Quality: "), iup.Label("Quality: "),
iup.Label("75").SetHandle("LabelQuality"), iup.Label("75").SetHandle("LabelQuality"),
).SetAttributes("MARGIN=0"), ).SetAttributes("NMARGIN=0"),
iup.Val("").SetAttributes(`MIN=0, MAX=100, VALUE=75, SHOWTICKS=10`).SetHandle("Quality"). iup.Val("").SetAttributes(`MIN=0, MAX=100, VALUE=75, SHOWTICKS=10`).SetHandle("Quality").
SetAttribute("TIP", "Quality affects JPEG, WEBP, AVIF and JXL"). SetAttribute("TIP", "Quality affects JPEG, WEBP, AVIF and JXL").
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
iup.GetHandle("LabelQuality").SetAttribute("TITLE", ih.GetInt("VALUE")) iup.GetHandle("LabelQuality").SetAttribute("TITLE", ih.GetInt("VALUE"))
iup.Refresh(iup.GetHandle("LabelQuality"))
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
return iup.DEFAULT return iup.DEFAULT
@@ -534,11 +554,12 @@ func tabs() iup.Ihandle {
})), })),
).SetHandle("VboxQuality"), ).SetHandle("VboxQuality"),
iup.Vbox( iup.Vbox(
iup.Label("").SetHandle("LabelEffort"), iup.Label("Effort:").SetHandle("LabelEffort"),
iup.Val("").SetAttributes(`MIN=0, MAX=10, VALUE=0, SHOWTICKS=11`).SetHandle("Effort"). iup.Val("").SetAttributes(`MIN=0, MAX=10, VALUE=0, SHOWTICKS=11`).SetHandle("Effort").
SetAttribute("TIP", "Encoder speed/effort (WEBP, AVIF, JXL)"). SetAttribute("TIP", "Encoder speed/effort (WEBP, AVIF, JXL)").
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
iup.GetHandle("LabelEffort").SetAttribute("TITLE", fmt.Sprintf("%s: %d", ih.GetAttribute("EFFORTNAME"), ih.GetInt("VALUE"))) iup.GetHandle("LabelEffort").SetAttribute("TITLE", fmt.Sprintf("%s: %d", ih.GetAttribute("EFFORTNAME"), ih.GetInt("VALUE")))
iup.Refresh(iup.GetHandle("LabelEffort"))
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
return iup.DEFAULT return iup.DEFAULT
@@ -552,6 +573,16 @@ func tabs() iup.Ihandle {
return iup.DEFAULT return iup.DEFAULT
})), })),
).SetHandle("VboxEffort"), ).SetHandle("VboxEffort"),
iup.Vbox(
iup.Toggle(" Lossless").SetHandle("Lossless").
SetAttributes(`TIP="Lossless compression (WEBP, AVIF, JXL), ignores quality"`).
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
setActive()
previewPost()
return iup.DEFAULT
})),
),
iup.Vbox( iup.Vbox(
iup.Toggle(" Grayscale").SetHandle("Grayscale"). iup.Toggle(" Grayscale").SetHandle("Grayscale").
SetAttributes(`TIP="Convert images to grayscale (monochromatic)"`). SetAttributes(`TIP="Convert images to grayscale (monochromatic)"`).
@@ -561,18 +592,20 @@ func tabs() iup.Ihandle {
return iup.DEFAULT return iup.DEFAULT
})), })),
), ),
).SetHandle("VboxImage").SetAttributes("MARGIN=5x5, GAP=5") ).SetAttributes("NGAP=10"),
).SetHandle("VboxImage")
vboxTransform := iup.Vbox( vboxTransform := iup.Vbox(
iup.Vbox( iup.Vbox(
iup.Hbox( iup.Hbox(
iup.Label("Brightness: "), iup.Label("Brightness: "),
iup.Label("0").SetHandle("LabelBrightness"), iup.Label("0").SetHandle("LabelBrightness"),
).SetAttributes("ALIGNMENT=ACENTER, MARGIN=0"), ).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=0"),
iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Brightness"). iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Brightness").
SetAttributes(`TIP="Adjust the brightness of the images"`). SetAttributes(`TIP="Adjust the brightness of the images"`).
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
iup.GetHandle("LabelBrightness").SetAttribute("TITLE", iup.GetHandle("Brightness").GetInt("VALUE")) iup.GetHandle("LabelBrightness").SetAttribute("TITLE", iup.GetHandle("Brightness").GetInt("VALUE"))
iup.Refresh(iup.GetHandle("LabelBrightness"))
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
return iup.DEFAULT return iup.DEFAULT
@@ -590,11 +623,12 @@ func tabs() iup.Ihandle {
iup.Hbox( iup.Hbox(
iup.Label("Contrast: "), iup.Label("Contrast: "),
iup.Label("0").SetHandle("LabelContrast"), iup.Label("0").SetHandle("LabelContrast"),
).SetAttributes("ALIGNMENT=ACENTER, MARGIN=0"), ).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=0"),
iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Contrast"). iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Contrast").
SetAttributes(`TIP="Adjust the contrast of the images"`). SetAttributes(`TIP="Adjust the contrast of the images"`).
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
iup.GetHandle("LabelContrast").SetAttribute("TITLE", iup.GetHandle("Contrast").GetInt("VALUE")) iup.GetHandle("LabelContrast").SetAttribute("TITLE", iup.GetHandle("Contrast").GetInt("VALUE"))
iup.Refresh(iup.GetHandle("LabelContrast"))
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
return iup.DEFAULT return iup.DEFAULT
@@ -624,45 +658,51 @@ func tabs() iup.Ihandle {
return iup.DEFAULT return iup.DEFAULT
})), })),
), ),
).SetHandle("VboxTransform").SetAttributes("MARGIN=5x5, GAP=5") ).SetHandle("VboxTransform").SetAttributes("NGAP=10")
return iup.Tabs( return iup.Tabs(
vboxInput.SetAttributes("TABTITLE=Input"), vboxInput.SetAttributes("TABTITLE=Input, NMARGIN=10x10"),
vboxOutput.SetAttributes("TABTITLE=Output"), vboxOutput.SetAttributes("TABTITLE=Output, NMARGIN=10x10"),
vboxImage.SetAttributes("TABTITLE=Image"), vboxImage.SetAttributes("TABTITLE=Image, NMARGIN=10x10"),
vboxTransform.SetAttributes("TABTITLE=Transform"), vboxTransform.SetAttributes("TABTITLE=Transform, NMARGIN=10x10"),
).SetHandle("Tabs").SetAttributes("MINSIZE=320x400, EXPAND=HORIZONTAL, MULTILINE=YES") ).SetHandle("Tabs")
} }
func buttons() iup.Ihandle { func buttons() iup.Ihandle {
addFiles := iup.Button("Add &Files...").SetHandle("AddFiles").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
SetCallback("ACTION", iup.ActionFunc(onAddFiles))
addDir := iup.Button("Add &Dir...").SetHandle("AddDir").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
SetCallback("ACTION", iup.ActionFunc(onAddDir))
remove := iup.Button("Remove").SetHandle("Remove").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
SetCallback("ACTION", iup.ActionFunc(onRemove))
removeAll := iup.Button("Remove All").SetHandle("RemoveAll").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
SetCallback("ACTION", iup.ActionFunc(onRemoveAll))
thumbnail := iup.Button("Thumbnail").SetHandle("Thumbnail").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
SetCallback("ACTION", iup.ActionFunc(onThumbnail))
cover := iup.Button("Cover").SetHandle("Cover").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
SetCallback("ACTION", iup.ActionFunc(onCover))
convert := iup.Button("&Convert").SetHandle("Convert").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
SetCallback("ACTION", iup.ActionFunc(onConvert))
iup.Normalizer(addFiles, addDir, remove, removeAll, thumbnail, cover, convert).SetAttribute("NORMALIZE", "BOTH")
return iup.Vbox( return iup.Vbox(
iup.Frame(
iup.Vbox( iup.Vbox(
iup.Button("Add &Files...").SetHandle("AddFiles").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). addFiles,
SetCallback("ACTION", iup.ActionFunc(onAddFiles)), addDir,
iup.Button("Add &Dir...").SetHandle("AddDir").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). remove,
SetCallback("ACTION", iup.ActionFunc(onAddDir)), removeAll,
iup.Button("Remove").SetHandle("Remove").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). ).SetAttribute("NGAP", "2"),
SetCallback("ACTION", iup.ActionFunc(onRemove)), iup.Space().SetAttribute("SIZE", "x5"),
iup.Button("Remove All").SetHandle("RemoveAll").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING").
SetCallback("ACTION", iup.ActionFunc(onRemoveAll)),
).SetAttributes("NGAP=5"),
),
iup.Frame(
iup.Vbox( iup.Vbox(
iup.Button("Thumbnail").SetHandle("Thumbnail").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). thumbnail,
SetCallback("ACTION", iup.ActionFunc(onThumbnail)), cover,
iup.Button("Cover").SetHandle("Cover").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). ).SetAttribute("NGAP", "2"),
SetCallback("ACTION", iup.ActionFunc(onCover)), iup.Space().SetAttribute("SIZE", "x5"),
).SetAttributes("NGAP=5"),
),
iup.Frame(
iup.Vbox( iup.Vbox(
iup.Button("&Convert").SetHandle("Convert").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). convert,
SetCallback("ACTION", iup.ActionFunc(onConvert)),
), ),
), ).SetHandle("Buttons").SetAttributes("ALIGNMENT=ACENTER")
).SetHandle("Buttons").SetAttributes("ALIGNMENT=ACENTER, NGAP=10")
} }
func status() iup.Ihandle { func status() iup.Ihandle {
@@ -670,10 +710,10 @@ func status() iup.Ihandle {
loading(), loading(),
iup.Fill(), iup.Fill(),
iup.Label("File 1 of 1").SetHandle("LabelStatus1").SetAttributes("VISIBLE=NO"), iup.Label("File 1 of 1").SetHandle("LabelStatus1").SetAttributes("VISIBLE=NO"),
iup.Space().SetAttribute("SIZE", "5x0"), iup.Space().SetAttribute("SIZE", "5"),
iup.Label("(000/000)").SetHandle("LabelStatus2").SetAttributes("VISIBLE=NO"), iup.Label("(000/000)").SetHandle("LabelStatus2").SetAttributes("VISIBLE=NO"),
iup.Space().SetAttribute("SIZE", "5x0"), iup.Space().SetAttribute("SIZE", "5"),
iup.ProgressBar().SetAttributes("RASTERSIZE=200x15, VISIBLE=NO").SetHandle("ProgressBar"). iup.ProgressBar().SetAttributes("RASTERSIZE=200x, VISIBLE=NO").SetHandle("ProgressBar").
SetCallback("POSTMESSAGE_CB", iup.PostMessageFunc(func(ih iup.Ihandle, s string, i int, p any) int { SetCallback("POSTMESSAGE_CB", iup.PostMessageFunc(func(ih iup.Ihandle, s string, i int, p any) int {
switch s { switch s {
case "convert": case "convert":
+4 -2
View File
@@ -168,6 +168,7 @@ func parseFlags() (cbconvert.Options, []string) {
convert.StringVar(&opts.Archive, "archive", "zip", "Archive format, valid values are zip, tar") convert.StringVar(&opts.Archive, "archive", "zip", "Archive format, valid values are zip, tar")
convert.IntVar(&opts.Quality, "quality", 75, "Image quality") convert.IntVar(&opts.Quality, "quality", 75, "Image quality")
convert.IntVar(&opts.Effort, "effort", -1, "Encoder speed/effort, format-specific (webp method 0-6, avif speed 0-10, jxl effort 1-10), -1 uses the format default") convert.IntVar(&opts.Effort, "effort", -1, "Encoder speed/effort, format-specific (webp method 0-6, avif speed 0-10, jxl effort 1-10), -1 uses the format default")
convert.BoolVar(&opts.Lossless, "lossless", false, "Lossless compression (webp, avif, jxl), ignores quality")
convert.IntVar(&opts.Filter, "filter", 2, "0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos") convert.IntVar(&opts.Filter, "filter", 2, "0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos")
convert.BoolVar(&opts.NoCover, "no-cover", false, "Do not convert the cover image") convert.BoolVar(&opts.NoCover, "no-cover", false, "Do not convert the cover image")
convert.BoolVar(&opts.NoRGB, "no-rgb", false, "Do not convert images that have RGB colorspace") convert.BoolVar(&opts.NoRGB, "no-rgb", false, "Do not convert images that have RGB colorspace")
@@ -190,6 +191,7 @@ func parseFlags() (cbconvert.Options, []string) {
cover.StringVar(&opts.Format, "format", "jpeg", "Image format, valid values are jpeg, png, tiff, bmp, webp, avif") cover.StringVar(&opts.Format, "format", "jpeg", "Image format, valid values are jpeg, png, tiff, bmp, webp, avif")
cover.IntVar(&opts.Quality, "quality", 75, "Image quality") cover.IntVar(&opts.Quality, "quality", 75, "Image quality")
cover.IntVar(&opts.Effort, "effort", -1, "Encoder speed/effort, format-specific (webp method 0-6, avif speed 0-10, jxl effort 1-10), -1 uses the format default") cover.IntVar(&opts.Effort, "effort", -1, "Encoder speed/effort, format-specific (webp method 0-6, avif speed 0-10, jxl effort 1-10), -1 uses the format default")
cover.BoolVar(&opts.Lossless, "lossless", false, "Lossless compression (webp, avif, jxl), ignores quality")
cover.IntVar(&opts.Filter, "filter", 2, "0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos") cover.IntVar(&opts.Filter, "filter", 2, "0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos")
cover.StringVar(&opts.OutDir, "outdir", ".", "Output directory") cover.StringVar(&opts.OutDir, "outdir", ".", "Output directory")
cover.IntVar(&opts.Size, "size", 0, "Process only files larger than size (in MB)") cover.IntVar(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
@@ -220,7 +222,7 @@ func parseFlags() (cbconvert.Options, []string) {
fmt.Fprintf(os.Stderr, "Usage: %s <command> [<flags>] [file1 dir1 ... fileOrDirN]\n\n", filepath.Base(os.Args[0])) fmt.Fprintf(os.Stderr, "Usage: %s <command> [<flags>] [file1 dir1 ... fileOrDirN]\n\n", filepath.Base(os.Args[0]))
fmt.Fprintf(os.Stderr, "\nCommands:\n") fmt.Fprintf(os.Stderr, "\nCommands:\n")
fmt.Fprintf(os.Stderr, "\n convert\n \tConvert archive or document\n\n") fmt.Fprintf(os.Stderr, "\n convert\n \tConvert archive or document\n\n")
order := []string{"width", "height", "fit", "format", "archive", "quality", "effort", "filter", "no-cover", "no-rgb", order := []string{"width", "height", "fit", "format", "archive", "quality", "effort", "lossless", "filter", "no-cover", "no-rgb",
"no-nonimage", "no-convert", "grayscale", "rotate", "brightness", "contrast", "suffix", "outdir", "size", "recursive", "quiet"} "no-nonimage", "no-convert", "grayscale", "rotate", "brightness", "contrast", "suffix", "outdir", "size", "recursive", "quiet"}
for _, name := range order { for _, name := range order {
f := convert.Lookup(name) f := convert.Lookup(name)
@@ -228,7 +230,7 @@ func parseFlags() (cbconvert.Options, []string) {
fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue) fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
} }
fmt.Fprintf(os.Stderr, "\n cover\n \tExtract cover\n\n") fmt.Fprintf(os.Stderr, "\n cover\n \tExtract cover\n\n")
order = []string{"width", "height", "fit", "format", "quality", "effort", "filter", "outdir", "size", "recursive", "quiet"} order = []string{"width", "height", "fit", "format", "quality", "effort", "lossless", "filter", "outdir", "size", "recursive", "quiet"}
for _, name := range order { for _, name := range order {
f := cover.Lookup(name) f := cover.Lookup(name)
fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name) fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)