mirror of
https://github.com/9001/copyparty.git
synced 2025-12-27 13:46:42 -05:00
option to set thumbnail quality (#1092);
plus these fixes: * adds a previously missed libvips optimization, giving much smaller files at the same quality * try to align the quality-scale of each backend (pillow, libvips, ffmpeg) by filesize
This commit is contained in:
@@ -1646,6 +1646,7 @@ def add_thumbnail(ap):
|
||||
ap2.add_argument("--th-ram-max", metavar="GB", type=float, default=th_ram, help="max memory usage (GiB) permitted by thumbnailer; not very accurate")
|
||||
ap2.add_argument("--th-crop", metavar="TXT", type=u, default="y", help="crop thumbnails to 4:3 or keep dynamic height; client can override in UI unless force. [\033[32my\033[0m]=crop, [\033[32mn\033[0m]=nocrop, [\033[32mfy\033[0m]=force-y, [\033[32mfn\033[0m]=force-n (volflag=crop)")
|
||||
ap2.add_argument("--th-x3", metavar="TXT", type=u, default="n", help="show thumbs at 3x resolution; client can override in UI unless force. [\033[32my\033[0m]=yes, [\033[32mn\033[0m]=no, [\033[32mfy\033[0m]=force-yes, [\033[32mfn\033[0m]=force-no (volflag=th3x)")
|
||||
ap2.add_argument("--th-qv", metavar="N", type=int, default=40, help="thumbnail quality (10~90); higher is larger filesize and better quality (volflag=th_qv)")
|
||||
ap2.add_argument("--th-dec", metavar="LIBS", default="vips,pil,raw,ff", help="image decoders, in order of preference")
|
||||
ap2.add_argument("--th-no-jpg", action="store_true", help="disable jpg output")
|
||||
ap2.add_argument("--th-no-webp", action="store_true", help="disable webp output")
|
||||
|
||||
@@ -2384,7 +2384,7 @@ class AuthSrv(object):
|
||||
if vf not in vol.flags:
|
||||
vol.flags[vf] = getattr(self.args, ga)
|
||||
|
||||
zs = "forget_ip gid nrand tail_who th_spec_p u2abort u2ow uid unp_who ups_who zip_who"
|
||||
zs = "forget_ip gid nrand tail_who th_qv th_spec_p u2abort u2ow uid unp_who ups_who zip_who"
|
||||
for k in zs.split():
|
||||
if k in vol.flags:
|
||||
vol.flags[k] = int(vol.flags[k])
|
||||
|
||||
@@ -133,6 +133,7 @@ def vf_vmap() -> dict[str, str]:
|
||||
"tail_tmax",
|
||||
"tail_who",
|
||||
"tcolor",
|
||||
"th_qv",
|
||||
"th_spec_p",
|
||||
"txt_eol",
|
||||
"unlist",
|
||||
@@ -289,6 +290,7 @@ flagcats = {
|
||||
"thsize": "thumbnail res; WxH",
|
||||
"crop": "center-cropping (y/n/fy/fn)",
|
||||
"th3x": "3x resolution (y/n/fy/fn)",
|
||||
"th_qv=40": "thumbnail quality (10~90)",
|
||||
"convt": "convert-to-image timeout in seconds",
|
||||
"aconvt": "convert-to-audio timeout in seconds",
|
||||
"th_spec_p=1": "make spectrograms? 0=never 1=fallback 2=always",
|
||||
|
||||
@@ -14,7 +14,7 @@ import time
|
||||
|
||||
from queue import Queue
|
||||
|
||||
from .__init__ import ANYWIN, PY2, TYPE_CHECKING
|
||||
from .__init__ import ANYWIN, PY2, TYPE_CHECKING, unicode
|
||||
from .authsrv import VFS
|
||||
from .bos import bos
|
||||
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, au_unpk, ffprobe
|
||||
@@ -56,6 +56,56 @@ EXTS_SPEC_SAFE = set("aif aiff flac mp3 opus wav".split())
|
||||
|
||||
PTN_TS = re.compile("^-?[0-9a-f]{8,10}$")
|
||||
|
||||
# for n in {1..100}; do rm -rf /home/ed/Pictures/wp/.hist/th/ ; python3 -m copyparty -qv /home/ed/Pictures/wp/::r --th-no-webp --th-qv $n --th-dec pil >/dev/null 2>&1 & p=$!; printf '\033[A\033[J%3d ' $n; while true; do sleep 0.1; curl -s 127.1:3923 >/dev/null && break; done; curl -s '127.1:3923/?tar=j' >/dev/null ; cat /home/ed/Pictures/wp/.hist/th/1n/bs/1nBsjDetfie1iDq3y2D4YzF5/*.* | wc -c; kill $p; wait >/dev/null 2>&1; done
|
||||
# filesize-equivalent, not quality (ff looks much shittier)
|
||||
FF_JPG_Q = {
|
||||
0: b"30", # 0
|
||||
1: b"30", # 5
|
||||
2: b"30", # 10
|
||||
3: b"30", # 15
|
||||
4: b"28", # 20
|
||||
5: b"21", # 25
|
||||
6: b"17", # 30
|
||||
7: b"15", # 35
|
||||
8: b"13", # 40
|
||||
9: b"12", # 45
|
||||
10: b"11", # 50
|
||||
11: b"10", # 55
|
||||
12: b"9", # 60
|
||||
13: b"8", # 65
|
||||
14: b"7", # 70
|
||||
15: b"6", # 75
|
||||
16: b"5", # 80
|
||||
17: b"4", # 85
|
||||
18: b"3", # 90
|
||||
19: b"2", # 95
|
||||
20: b"2", # 100
|
||||
}
|
||||
# FF_JPG_Q = {xn: ("%d" % (xn,)).encode("ascii") for xn in range(2, 33)}
|
||||
VIPS_JPG_Q = {
|
||||
0: 4, # 0
|
||||
1: 7, # 5
|
||||
2: 12, # 10
|
||||
3: 17, # 15
|
||||
4: 22, # 20
|
||||
5: 27, # 25
|
||||
6: 32, # 30
|
||||
7: 37, # 35
|
||||
8: 42, # 40
|
||||
9: 47, # 45
|
||||
10: 52, # 50
|
||||
11: 56, # 55
|
||||
12: 61, # 60
|
||||
13: 66, # 65
|
||||
14: 71, # 70
|
||||
15: 75, # 75
|
||||
16: 80, # 80
|
||||
17: 85, # 85
|
||||
18: 89, # 90 (vips explodes past this point)
|
||||
19: 91, # 95
|
||||
20: 97, # 100
|
||||
}
|
||||
|
||||
|
||||
try:
|
||||
if os.environ.get("PRTY_NO_PIL"):
|
||||
@@ -529,7 +579,7 @@ class ThumbSrv(object):
|
||||
im.thumbnail(self.getres(vn, fmt))
|
||||
|
||||
fmts = ["RGB", "L"]
|
||||
args = {"quality": 40}
|
||||
args = {"quality": vn.flags["th_qv"]}
|
||||
|
||||
if tpath.endswith(".webp"):
|
||||
# quality 80 = pillow-default
|
||||
@@ -573,7 +623,12 @@ class ThumbSrv(object):
|
||||
raise
|
||||
|
||||
assert img # type: ignore # !rm
|
||||
img.write_to_file(tpath, Q=40)
|
||||
args = {}
|
||||
qv = vn.flags["th_qv"]
|
||||
if tpath.endswith("jpg"):
|
||||
qv = VIPS_JPG_Q[qv // 5]
|
||||
args["optimize_coding"] = True
|
||||
img.write_to_file(tpath, Q=qv, strip=True, **args)
|
||||
|
||||
def conv_raw(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||
self.wait4ram(0.2, tpath)
|
||||
@@ -607,7 +662,12 @@ class ThumbSrv(object):
|
||||
raise
|
||||
|
||||
assert img # type: ignore # !rm
|
||||
img.write_to_file(tpath, Q=40)
|
||||
args = {}
|
||||
qv = vn.flags["th_qv"]
|
||||
if tpath.endswith("jpg"):
|
||||
qv = VIPS_JPG_Q[qv // 5]
|
||||
args["optimize_coding"] = True
|
||||
img.write_to_file(tpath, Q=qv, strip=True, **args)
|
||||
elif HAVE_PIL:
|
||||
if thumb.format == rawpy.ThumbFormat.BITMAP:
|
||||
im = Image.fromarray(thumb.data, "RGB")
|
||||
@@ -671,12 +731,12 @@ class ThumbSrv(object):
|
||||
if tpath.endswith(".jpg"):
|
||||
cmd += [
|
||||
b"-q:v",
|
||||
b"6", # default=??
|
||||
FF_JPG_Q[vn.flags["th_qv"] // 5], # default=??
|
||||
]
|
||||
else:
|
||||
cmd += [
|
||||
b"-q:v",
|
||||
b"50", # default=75
|
||||
unicode(vn.flags["th_qv"]).encode("ascii"), # default=75
|
||||
b"-compression_level:v",
|
||||
b"6", # default=4, 0=fast, 6=max
|
||||
]
|
||||
@@ -722,7 +782,7 @@ class ThumbSrv(object):
|
||||
if len(lines) > 50:
|
||||
lines = lines[:25] + ["[...]"] + lines[-25:]
|
||||
|
||||
txt = "\n".join(["ff: " + str(x) for x in lines])
|
||||
txt = "\n".join(["ff: " + unicode(x) for x in lines])
|
||||
if len(txt) > 5000:
|
||||
txt = txt[:2500] + "...\nff: [...]\nff: ..." + txt[-2500:]
|
||||
|
||||
@@ -880,12 +940,12 @@ class ThumbSrv(object):
|
||||
if tpath.endswith(".jpg"):
|
||||
cmd += [
|
||||
b"-q:v",
|
||||
b"6", # default=??
|
||||
FF_JPG_Q[vn.flags["th_qv"] // 5], # default=??
|
||||
]
|
||||
else:
|
||||
cmd += [
|
||||
b"-q:v",
|
||||
b"50", # default=75
|
||||
unicode(vn.flags["th_qv"]).encode("ascii"), # default=75
|
||||
b"-compression_level:v",
|
||||
b"6", # default=4, 0=fast, 6=max
|
||||
]
|
||||
@@ -1143,7 +1203,7 @@ class ThumbSrv(object):
|
||||
ret = []
|
||||
for k, vs in raw_tags.items():
|
||||
for v in vs:
|
||||
if len(str(v)) >= 1024:
|
||||
if len(unicode(v)) >= 1024:
|
||||
bv = k.encode("utf-8", "replace")
|
||||
ret += [b"-metadata", bv + b"="]
|
||||
break
|
||||
|
||||
@@ -158,7 +158,7 @@ class Cfg(Namespace):
|
||||
ex = "hash_mt hsortn qdel safe_dedup scan_pr_r scan_pr_s scan_st_r srch_time tail_fd tail_rate th_spec_p u2abort u2j u2sz unp_who"
|
||||
ka.update(**{k: 1 for k in ex.split()})
|
||||
|
||||
ex = "ac_convt au_vol dl_list du_iwho mtab_age reg_cap s_thead s_tbody tail_tmax tail_who th_convt ups_who ver_iwho zip_who"
|
||||
ex = "ac_convt au_vol dl_list du_iwho mtab_age reg_cap s_thead s_tbody tail_tmax tail_who th_convt th_qv ups_who ver_iwho zip_who"
|
||||
ka.update(**{k: 9 for k in ex.split()})
|
||||
|
||||
ex = "ctl_re db_act forget_ip idp_cookie idp_store k304 loris no304 nosubtle qr_pin qr_wait re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo u2ow zipmaxn zipmaxs"
|
||||
|
||||
Reference in New Issue
Block a user