diff -Nru imgp-2.7/auto-completion/bash/imgp-completion.bash imgp-2.8/auto-completion/bash/imgp-completion.bash --- imgp-2.7/auto-completion/bash/imgp-completion.bash 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/auto-completion/bash/imgp-completion.bash 2020-11-30 19:54:14.000000000 +0000 @@ -13,26 +13,28 @@ opts=( -a --adapt -c --convert - -d --dot -e --eraseexif -f --force - -h --help + -H --hidden -i --includeimgp -k --keep -m --mute + -M --minres -n --enlarge - --nn + -N --nearest -o --rotate - -p --optimize - --pr --progressive + -O --optimize + -P --progressive -q --quality -r --recurse -s --size -w --overwrite -x --res - -z --debug + -d --debug + -h --help ) opts_with_arg=( + -M --minres -o --rotate -q --quality -s --size diff -Nru imgp-2.7/auto-completion/fish/imgp.fish imgp-2.8/auto-completion/fish/imgp.fish --- imgp-2.7/auto-completion/fish/imgp.fish 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/auto-completion/fish/imgp.fish 2020-11-30 19:54:14.000000000 +0000 @@ -6,21 +6,22 @@ # complete -c imgp -s a -l adapt --description 'adapt to resolution by orientation' complete -c imgp -s c -l convert --description 'convert PNG to JPG format' -complete -c imgp -s d -l dot --description 'include hidden files (on Linux)' complete -c imgp -s e -l eraseexif --description 'erase exif metadata' complete -c imgp -s f -l force --description 'force to exact specified resolution' -complete -c imgp -s h -l help --description 'show help' +complete -c imgp -s H -l hidden --description 'include hidden (dot) files' complete -c imgp -s i -l includeimgp --description 're-process _IMGP files' complete -c imgp -s k -l keep --description 'skip images with matching hres or vres' complete -c imgp -s m -l mute --description 'operate silently' +complete -c imgp -s M -l minres -r --description 'minimum resolution in HxV or %' complete -c imgp -s n -l enlarge --description 'enlarge smaller images' -complete -c imgp -l nn --description 'use nearest neighbour interpolation for PNG' +complete -c imgp -s N -l nearest --description 'use nearest neighbour interpolation for PNG' complete -c imgp -s o -l rotate -r --description 'rotate clockwise by angle (in degrees)' -complete -c imgp -s p -l optimize --description 'optimize the output images' -complete -c imgp -l pr -l progressive --description 'save JPEG as progressive' +complete -c imgp -s O -l optimize --description 'optimize the output images' +complete -c imgp -l P -l progressive --description 'save JPEG as progressive' complete -c imgp -s q -l quality -r --description 'specify quality factor (1-95)' complete -c imgp -s r -l recurse --description 'process directories recursively' complete -c imgp -s s -l size -r --description 'min byte size to process an image' complete -c imgp -s w -l overwrite --description 'overwrite source images' complete -c imgp -s x -l res -r --description 'output resolution in HxV or %' -complete -c imgp -s z -l debug --description 'enable debug logs' +complete -c imgp -s d -l debug --description 'enable debug logs' +complete -c imgp -s h -l help --description 'show help' diff -Nru imgp-2.7/auto-completion/zsh/_imgp imgp-2.8/auto-completion/zsh/_imgp --- imgp-2.7/auto-completion/zsh/_imgp 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/auto-completion/zsh/_imgp 2020-11-30 19:54:14.000000000 +0000 @@ -11,23 +11,24 @@ args=( '(-a --adapt)'{-a,--adapt}'[adapt to resolution by orientation]' '(-c --convert)'{-c,--convert}'[convert PNG to JPG format]' - '(-d --dot)'{-d,--dot}'[include hidden files (on Linux)]' '(-e --eraseexif)'{-e,--eraseexif}'[erase exif metadata]' '(-f --force)'{-f,--force}'[force to exact specified resolution]' - '(-h --help)'{-h,--help}'[show help]' + '(-H --hidden)'{-H,--hidden}'[include hidden (dot) files]' '(-i --includeimgp)'{-i,--includeimgp}'[re-process _IMGP files]' '(-k --keep)'{-k,--keep}'[skip images with matching hres or vres]' '(-m --mute)'{-m,--mute}'[operate silently]' + '(-M --minres)'{-M,--minres}'[minimum resolution]:HxV or %' '(-n --enlarge)'{-n,--enlarge}'[enlarge smaller images]' - '(--nn)--n[use nearest neighbour interpolation for PNG]' + '(-N --nearest)'{-N,--nearest}'[use nearest neighbour interpolation for PNG]' '(-o --rotate)'{-o,--rotate}'[rotate clockwise by angle]:degree' - '(-p --optimize)'{-p,--optimize}'[optimize the output images]' - '(--pr --progressive)'{--pr,--progressive}'[save JPEG as progressive]' + '(-O --optimize)'{-p,--optimize}'[optimize the output images]' + '(-P --progressive)'{-P,--progressive}'[save JPEG as progressive]' '(-q --quiet)'{-q,--quality}'[specify quality factor (1-95)]:factor' '(-r --recurse)'{-r,--recurse}'[process directories recursively]' '(-s --size)'{-s,--size}'[min byte size to process an image]:bytes' '(-w --overwrite)'{-w,--overwrite}'[overwrite source images]' '(-x --res)'{-x,--res}'[output resolution]:HxV or %' - '(-z --debug)'{-z,--debug}'[enable debug logs]' + '(-d --debug)'{-z,--debug}'[enable debug logs]' + '(-h --help)'{-h,--help}'[show help]' ) _arguments -S -s $args diff -Nru imgp-2.7/CHANGELOG imgp-2.8/CHANGELOG --- imgp-2.7/CHANGELOG 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/CHANGELOG 2020-11-30 19:54:14.000000000 +0000 @@ -1,3 +1,14 @@ +imgp v2.8 +2020-12-01 + +- option `-M` to specify minimum resolution of iamges to process +- option `-H` (process hidden files) replaces `-d` +- option `-d` (debug mode) replaces `-z` +- option `-N` and `--nearest` (nearest neighbour for PNG) replace `--nn` +- option `-P` (save JPEG as progressive) replaces `--pr` + +------------------------------------------------------------------------------- + imgp v2.7 2019-12-21 diff -Nru imgp-2.7/.circleci/config.yml imgp-2.8/.circleci/config.yml --- imgp-2.7/.circleci/config.yml 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/.circleci/config.yml 2020-11-30 19:54:14.000000000 +0000 @@ -17,11 +17,6 @@ make test jobs: - py35: - docker: - - image: python:3.5-slim - <<: *test-template - py36: docker: - image: python:3.6-slim @@ -37,6 +32,11 @@ - image: python:3.8-slim <<: *test-template + py39: + docker: + - image: python:3.9-slim + <<: *test-template + package-and-publish: machine: true working_directory: ~/imgp @@ -60,10 +60,10 @@ test: jobs: &all-tests - - py35 - py36 - py37 - py38 + - py39 nightly: triggers: diff -Nru imgp-2.7/debian/changelog imgp-2.8/debian/changelog --- imgp-2.7/debian/changelog 2020-10-29 03:16:49.000000000 +0000 +++ imgp-2.8/debian/changelog 2020-12-01 05:25:26.000000000 +0000 @@ -1,3 +1,11 @@ +imgp (2.8-1) unstable; urgency=medium + + * Import new upstream release + * d/control: + - Bump Standards-Version to 4.5.1 + + -- SZ Lin (林上智) Tue, 01 Dec 2020 13:25:26 +0800 + imgp (2.7-2) unstable; urgency=medium * d/control: diff -Nru imgp-2.7/debian/control imgp-2.8/debian/control --- imgp-2.7/debian/control 2020-10-29 03:16:29.000000000 +0000 +++ imgp-2.8/debian/control 2020-12-01 05:10:29.000000000 +0000 @@ -6,7 +6,7 @@ python3 (>= 3.5), python3-setuptools, dh-python -Standards-Version: 4.5.0 +Standards-Version: 4.5.1 Rules-Requires-Root: no Homepage: https://github.com/jarun/imgp Vcs-Git: https://salsa.debian.org/debian/imgp.git diff -Nru imgp-2.7/.github/workflows/lock.yml imgp-2.8/.github/workflows/lock.yml --- imgp-2.7/.github/workflows/lock.yml 1970-01-01 00:00:00.000000000 +0000 +++ imgp-2.8/.github/workflows/lock.yml 2020-11-30 19:54:14.000000000 +0000 @@ -0,0 +1,17 @@ +name: 'Lock threads' + +on: + schedule: + - cron: '0 0 * * *' + +jobs: + lock: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v2 + with: + github-token: ${{ github.token }} + issue-lock-inactive-days: '30' + issue-lock-reason: '' + pr-lock-inactive-days: '30' + pr-lock-reason: '' diff -Nru imgp-2.7/imgp imgp-2.8/imgp --- imgp-2.7/imgp 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/imgp 2020-11-30 19:54:14.000000000 +0000 @@ -18,6 +18,7 @@ # along with this program. If not, see . import argparse +import textwrap from multiprocessing import Pool, Lock import os import sys @@ -32,12 +33,14 @@ rotate = None # specified rotation in degree adapt = False # use adaptive resolution convert = False # convert PNG to JPG -dot = False # process hidden files starting with . +hidden = False # process hidden files eraseexif = False # erase EXIF metadata progressive = False # save as a progressive image force = False # forced to exact specified resolution includeimgp = False # process _IMGP files keep = False # ignore images with matching hres or vres +minH = 0 # min horizontal resolution to convert +minV = 0 # min vertical resolution to convert enlarge = False # enlarge images with smaller hres or vres optimal = False # apply PIL library optimization when saving mute = False # suppress additional information @@ -51,7 +54,7 @@ png_ip = PIL.Image.ANTIALIAS # default interpolation for PNG fill_color = '#ffffff' # BG color to strip alpha channel init_time = time.time() # profile the total time taken -_VERSION_ = '2.7' # current program version +_VERSION_ = '2.8' # current program version # Globals for multiprocessing pool = None @@ -101,7 +104,7 @@ try: for entry in os.scandir(path): # Add check for hidden here - if not dot and entry.name.startswith('.'): + if not hidden and entry.name.startswith('.'): continue if entry.is_dir(follow_symlinks=False): @@ -208,7 +211,7 @@ def resize_image(src): '''Resize a source image''' - global HRES, VRES, lock + global HRES, VRES, minH, minV, lock converted = False _progressive = progressive @@ -269,6 +272,11 @@ antialias = png_ip if _format == 'PNG' else PIL.Image.ANTIALIAS + if hres < minH or vres < minV: + if debug: + lock_print('resize_image: hres < minH or vres < minV') + return + if keep and (HRES == hres or VRES == vres or scale == 100): if progressive and _format not in ['JPEG', 'MPO']: return @@ -462,7 +470,7 @@ # Help def print_help(self, file=None): - super(ExtendedArgumentParser, self).print_help(file) + super().print_help(file) self.print_extended_help(file) @@ -480,7 +488,8 @@ Namespace with parsed arguments / options. ''' - argparser = ExtendedArgumentParser(description='Resize, rotate JPEG and PNG images.') + argparser = ExtendedArgumentParser(description='Resize, rotate JPEG and PNG images.', + formatter_class=argparse.RawTextHelpFormatter) addarg = argparser.add_argument addarg('-x', '--res', nargs=1, metavar='res', help='output resolution in HxV or percentage') @@ -490,37 +499,39 @@ help='adapt to resolution by orientation [default: off]') addarg('-c', '--convert', action='store_true', help='convert PNG to JPG format [default: off]') - addarg('-d', '--dot', action='store_true', - help='include hidden files (on Linux) [default: off]') addarg('-e', '--eraseexif', action='store_true', help='erase exif metadata [default: off]') addarg('-f', '--force', action='store_true', help='force to exact specified resolution [default: off]') + addarg('-H', '--hidden', action='store_true', + help='include hidden (dot) files [default: off]') addarg('-i', '--includeimgp', action='store_true', help='re-process _IMGP files. * RISKY: refer to docs') addarg('-k', '--keep', action='store_true', - help='skip (honors -c or --pr) images matching specified \ - hres or vres or --res=100 [default: off]') + help=textwrap.dedent('''\ + skip (honors -c or --pr) images matching specified + H or V or --res=100 [default: off]''')) addarg('-m', '--mute', action='store_true', help='operate silently [default: informative]') + addarg('-M', '--minres', nargs=1, metavar='res', + help='min resolution in HxV or percentage of --res to resize') addarg('-n', '--enlarge', action='store_true', help='enlarge smaller images [default: off]') - addarg('--nn', action='store_true', - help='use nearest neighbour interpolation for PNG images [default: antialias]') - addarg('-p', '--optimize', action='store_true', + addarg('-N', '--nearest', action='store_true', + help='use nearest neighbour interpolation for PNG [default: antialias]') + addarg('-O', '--optimize', action='store_true', help='optimize the output images [default: off]') - addarg('--pr', '--progressive', action='store_true', + addarg('-P', '--progressive', action='store_true', help='save JPEG images as progressive [default: off]') addarg('-q', '--quality', type=int, metavar='N', choices=range(1, 96), help='quality factor (N=1-95, JPEG only) [default: 75]') addarg('-r', '--recurse', action='store_true', - help='process directories recursively [default: off] \ - symbolic links are ignored') + help='process non-symbolic dirs recursively [default: off]') addarg('-s', '--size', type=int, metavar='byte', help='minimum size to process an image [default: 1024]') addarg('-w', '--overwrite', action='store_true', help='overwrite source images [default: off]') - addarg('-z', '--debug', action='store_true', + addarg('-d', '--debug', action='store_true', help='enable debug logs [default: off]') addarg('keywords', nargs='*', metavar='PATH', help='source file or dir [default: current dir]') @@ -534,9 +545,9 @@ def main(): - global HRES, VRES, scale, rotate, adapt, convert, dot, eraseexif, force, \ + global HRES, VRES, scale, rotate, adapt, convert, hidden, eraseexif, force, \ includeimgp, keep, enlarge, optimal, progressive, mute, recurse, size, \ - qual, overwrite, debug, no_res_opt, pool, init_time, count, png_ip + qual, overwrite, debug, no_res_opt, pool, init_time, count, png_ip, minH, minV args = parse_args() @@ -548,7 +559,7 @@ if 'x' in args.res[0]: HRES, VRES = getres(args.res[0]) if HRES == 0 and VRES == 0: - print('-ve values not allowed, \ + print('-ve values not allowed in --res, \ hres and vres cannot be 0 together') return else: @@ -572,23 +583,51 @@ if not rotate: print('cannot rotate by 0 degree') return - elif args.convert or args.pr or args.optimize: + elif args.convert or args.progressive or args.optimize: no_res_opt = True scale = 100 else: print('missing image transformation') return + if args.minres is not None: + if 'x' in args.minres[0]: + minH, minV = getres(args.minres[0]) + if minH == 0 or minV == 0: + print('-ve values not allowed in --minres, \ + H or V cannot be 0') + return + else: + if scale is not None: + print('both --res and --minres cannot be in percentage') + return + + try: + if args.minres[0].endswith('%'): + minscale = int(args.minres[0][:-1]) + else: + minscale = int(args.minres[0]) + + if minscale <= 0: + print('--minres should be > 0%') + return + + minH = (HRES * minscale) / 100 + minV = (VRES * minscale) / 100 + except Exception: + print('invalid value for --minres') + return + adapt = args.adapt convert = args.convert - dot = args.dot + hidden = args.hidden eraseexif = args.eraseexif force = args.force includeimgp = args.includeimgp keep = args.keep enlarge = args.enlarge optimal = args.optimize - progressive = args.pr + progressive = args.progressive mute = args.mute recurse = args.recurse if args.size is not None: @@ -597,7 +636,7 @@ qual = args.quality overwrite = args.overwrite debug = args.debug - if args.nn: + if args.nearest: png_ip = PIL.Image.NEAREST pool = Pool() diff -Nru imgp-2.7/imgp.1 imgp-2.8/imgp.1 --- imgp-2.7/imgp.1 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/imgp.1 2020-11-30 19:54:14.000000000 +0000 @@ -1,4 +1,4 @@ -.TH "IMGP" "1" "21 Dec 2019" "Version 2.7" "User Commands" +.TH "IMGP" "1" "01 Dec 2020" "Version 2.8" "User Commands" .SH NAME imgp \- Resize, rotate JPEG and PNG images. .SH SYNOPSIS @@ -64,15 +64,15 @@ .BI "-c, --convert" Convert PNG images to JPEG to save on space. The output image is saved with '.jpg' extension. .TP -.BI "-d, --dot" -Include hidden files (Linux-specific). By default hidden files are skipped on Linux. -.TP .BI "-e, --eraseexif" Erase EXIF metadata of JPEG images. Preserved by default. .TP .BI "-f, --force" Force to the exact specified resolution. Disabled by default. .TP +.TP +.BI "-H, --hidden" +Include hidden (dot) files. By default hidden files are skipped. .BI "-i, --includeimgp" Process \fI_IMGP\fR files. Risky due to potential race conditions. .TP @@ -82,13 +82,13 @@ .BI "-n, --enlarge" Enlarge smaller images. By default smaller images are not scaled if specified resolution is greater. .TP -.BI "--nn" +.BI "-N --nearest" Use nearest neighbour interpolation for PNG images instead of default antialias. .TP .BI "-p, --optimize" Optimize output images using PIL library optimization algorithm. Disabled by default. .TP -.BI "--pr, --progressive" +.BI "-P, --progressive" Save all output JPEG images as progressive, even if the source is not. .TP .BI "-q, --quality=" N @@ -97,6 +97,9 @@ .BI "-m, --mute" Do not show any operational output. .TP +.BI "-M, --minres" res +minimum resolution in HxV or percentage of --res to resize +.TP .BI "-r, --recurse" Recursively process sub-directories. By default only the specified directory is processed. Symbolic links are ignored to avoid recursive loops. .TP @@ -109,7 +112,7 @@ .B NOTE: If overwrite and convert options are used together, source PNG images are deleted. .TP -.BI "-z, --debug" +.BI "-d, --debug" Enable debugging. .SH EXAMPLES .PP diff -Nru imgp-2.7/packagecore.yaml imgp-2.8/packagecore.yaml --- imgp-2.7/packagecore.yaml 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/packagecore.yaml 2020-11-30 19:54:14.000000000 +0000 @@ -1,20 +1,22 @@ name: imgp maintainer: Arun Prakash Jana license: GPLv3 -summary: Multi-core batch image resizer and rotator. +summary: High-performance cli batch image resizer and rotator. homepage: https://github.com/jarun/imgp commands: install: - make PREFIX="/usr" install DESTDIR="${BP_DESTDIR}" packages: - archlinux: + centos7.5: builddeps: - make deps: - python-pillow - python - container: "archlinux/base" - centos7.5: + commands: + pre: + - yum install epel-release + centos7.6: builddeps: - make deps: @@ -23,7 +25,7 @@ commands: pre: - yum install epel-release - centos7.6: + centos7.7: builddeps: - make deps: @@ -32,15 +34,15 @@ commands: pre: - yum install epel-release -# centos8.0: -# builddeps: -# - make -# deps: -# - python-pillow -# - python -# commands: -# pre: -# - yum install epel-release + centos8.0: + builddeps: + - make + deps: + - python3-pillow + - python3 + commands: + precompile: + - dnf install python3 debian9: builddeps: - make @@ -53,19 +55,31 @@ deps: - python3-pillow - python3 - fedora30: + fedora31: builddeps: - make deps: - python3-pillow - python3 - fedora31: + fedora32: builddeps: - make deps: - python3-pillow - python3 - opensuse42.3: + opensuse15.1: + builddeps: + - make + deps: + - python3-Pillow + - python3 + opensuse15.2: + builddeps: + - make + deps: + - python3-Pillow + - python3 + opensuse.tumbleweed: builddeps: - make deps: @@ -81,5 +95,11 @@ builddeps: - make deps: + - python3-pillow + - python3 + ubuntu20.04: + builddeps: + - make + deps: - python3-pillow - python3 diff -Nru imgp-2.7/README.md imgp-2.8/README.md --- imgp-2.7/README.md 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/README.md 2020-11-30 19:54:14.000000000 +0000 @@ -5,11 +5,11 @@ Availability PyPI Build Status -License +License

-imgp_asciicast +imgp_asciicast

Watch imgp resize a directory of images in lightning speed!

@@ -23,7 +23,7 @@ *Love smart and efficient utilities? Explore [my repositories](https://github.com/jarun?tab=repositories). Buy me a cup of coffee if they help you.*

-Donate via PayPal! +Donate via PayPal!

### Table of Contents @@ -81,7 +81,7 @@ #### Dependencies -`imgp` requires Python 3.5 or later. +`imgp` requires Python 3.6 or later. To install PIL library on Ubuntu, run: @@ -144,9 +144,8 @@ #### cmdline options ``` -usage: imgp [-h] [-x res] [-o deg] [-a] [-c] [-d] [-e] [-f] [-i] [-k] [-m] - [-n] [--nn] [-p] [--pr] [-q N] [-r] [-s byte] [-w] [-z] - [PATH [PATH ...]] +usage: imgp [-h] [-x res] [-o deg] [-a] [-c] [-e] [-f] [-H] [-i] [-k] [-m] [-M res] + [-n] [-N] [-O] [-P] [-q N] [-r] [-s byte] [-w] [-d] [PATH [PATH ...]] Resize, rotate JPEG and PNG images. @@ -159,24 +158,23 @@ -o deg, --rotate deg rotate clockwise by angle (in degrees) -a, --adapt adapt to resolution by orientation [default: off] -c, --convert convert PNG to JPG format [default: off] - -d, --dot include hidden files (on Linux) [default: off] -e, --eraseexif erase exif metadata [default: off] -f, --force force to exact specified resolution [default: off] + -H, --hidden include hidden (dot) files [default: off] -i, --includeimgp re-process _IMGP files. * RISKY: refer to docs -k, --keep skip (honors -c or --pr) images matching specified - hres or vres or --res=100 [default: off] + H or V or --res=100 [default: off] -m, --mute operate silently [default: informative] + -M res, --minres res min resolution in HxV or percentage of --res to resize -n, --enlarge enlarge smaller images [default: off] - --nn use nearest neighbour interpolation for PNG images - [default: antialias] - -p, --optimize optimize the output images [default: off] - --pr, --progressive save JPEG images as progressive [default: off] + -N, --nearest use nearest neighbour interpolation for PNG [default: antialias] + -O, --optimize optimize the output images [default: off] + -P, --progressive save JPEG images as progressive [default: off] -q N, --quality N quality factor (N=1-95, JPEG only) [default: 75] - -r, --recurse process directories recursively [default: off] - symbolic links are ignored + -r, --recurse process non-symbolic dirs recursively [default: off] -s byte, --size byte minimum size to process an image [default: 1024] -w, --overwrite overwrite source images [default: off] - -z, --debug enable debug logs [default: off] + -d, --debug enable debug logs [default: off] ``` #### Operational notes diff -Nru imgp-2.7/setup.py imgp-2.8/setup.py --- imgp-2.7/setup.py 2019-12-21 09:29:54.000000000 +0000 +++ imgp-2.8/setup.py 2020-11-30 19:54:14.000000000 +0000 @@ -34,7 +34,7 @@ url='https://github.com/jarun/imgp', license='GPLv3', license_file='LICENSE', - python_requires='>=3.5', # requires pip>=9.0.0 + python_requires='>=3.6', # requires pip>=9.0.0 platforms=['any'], py_modules=['imgp'], install_requires=requirements, @@ -56,10 +56,10 @@ 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', 'Topic :: Utilities' ] )