Skip to content

Commit

Permalink
Merge pull request #13 from AnonymouX47/rendering
Browse files Browse the repository at this point in the history
Improvements to Image and Image Grid Rendering
  • Loading branch information
AnonymouX47 authored May 3, 2024
2 parents c2c8577 + 328d504 commit b3650b2
Show file tree
Hide file tree
Showing 12 changed files with 841 additions and 206 deletions.
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Fixed
- tui: Crash on image grid view ([c64f195]).
- cli,tui: Sorting of top-level (command line) entries ([9ea0572])
- cli,tui: Sorting of top-level (command line) entries ([9ea0572]).

### Added
- tui: Thumbnail generation (with deduplication) and caching for the image grid ([#13]).
- config: `thumbnail`, `thumbnail cache` and `thumbnail size` config options.
- args: `--thumbnail/--no-thumbnail` command-line option.
- tui: `Force Render` action to the `menu` context ([#13]).

### Changed
- cli,tui: Revamped the *max pixels* setting ([#13]).
- It is now **opt-in** i.e by default, all images are now rendered regardless of resolution.
- config: Changed the default value of the `max pixels` config option to `0` (disabled).
- tui: It no longer applies in the `full-grid-image` context.
- tui: In the `image-grid` context, images with more pixels than *max pixels* (**if non-zero**) are now distinguished by a yellow title and border.

### Removed
- args: `--max-pixels-cli` command-line option ([#13]).

[#13]: https://github.com/AnonymouX47/termvisage/pull/13
[c64f195]: https://github.com/AnonymouX47/termvisage/commit/c64f195a79557fdf5a9323db907a5716a12d6440
[9ea0572]: https://github.com/AnonymouX47/termvisage/commit/9ea0572e6db35984a4ae0af1691edfd179e5d393

Expand Down
29 changes: 16 additions & 13 deletions default-termvisage.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
"grid renderers": 1,
"log file": "~/.local/state/termvisage/termvisage.log",
"max notifications": 2,
"max pixels": 4194304,
"max pixels": 0,
"multi": true,
"query timeout": 0.1,
"style": "auto",
"swap win size": false,
"thumbnail": true,
"thumbnail cache": 0,
"thumbnail size": 256,
"keys": {
"navigation": {
"Left": [
Expand Down Expand Up @@ -81,13 +84,13 @@
"Switch Pane": [
"tab",
"\u21b9"
]
},
"image": {
],
"Force Render": [
"F",
"\u21e7F"
],
]
},
"image": {
"Maximize": [
"f",
"f"
Expand All @@ -99,6 +102,10 @@
"Switch Pane": [
"tab",
"\u21b9"
],
"Force Render": [
"F",
"\u21e7F"
]
},
"image-grid": {
Expand All @@ -124,23 +131,19 @@
"esc",
"\u238b"
],
"Force Render": [
"F",
"\u21e7F"
],
"Delete": [
"d",
"d"
],
"Force Render": [
"F",
"\u21e7F"
]
},
"full-grid-image": {
"Back": [
"esc",
"\u238b"
],
"Force Render": [
"F",
"\u21e7F"
]
},
"confirmation": {
Expand Down
11 changes: 0 additions & 11 deletions docs/source/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,6 @@ Options and Arguments
:option:`--original-size` is used if not larger than the :term:`available size`,
else :option:`--fit`.
.. [#] Any image having more pixels than the specified maximum will be:
- skipped, in CLI mode, if :option:`--max-pixels-cli` is specified.
- replaced, in TUI mode, with a placeholder when displayed but can still be
explicitly made to display.
Note that increasing this should not have any effect on general performance
(i.e navigation, etc) but the larger an image is, the more the time and memory
it'll take to render it. Thus, a large image might delay the rendering of other
images to be rendered immediately after it.
.. [#] Any event with a level lower than the specified one is not reported.
.. [#] 0 -> worst quality; smallest data size, 95 -> best quality; largest data size.
Expand Down
65 changes: 54 additions & 11 deletions docs/source/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,21 +130,22 @@ These are top-level fields whose values control various settings of the viewer.
Adjusts the height of the :ref:`notification bar <notif-bar>`.

.. confval:: max pixels
:synopsis: The maximum amount of pixels in images to be displayed in the TUI.
:synopsis: The maximum pixel-count for images that should be rendered.
:type: integer
:valid: *x* > ``0``
:default: ``4194304`` (2 ** 22)
:valid: *x* >= ``0``
:default: ``0``

Any image having more pixels than the specified value will be:
If zero, all images will be rendered normally, regardless of their resolution.
Otherwise, any image having more pixels than the specified value will be:

* skipped, in CLI mode, if :option:`--max-pixels-cli` is specified.
* replaced, in TUI mode, with a placeholder when displayed but can still be forced
to display or viewed externally.
* **skipped** in CLI mode.
* **replaced** in TUI mode (except in the ``full-grid-image``
:ref:`context <contexts>`), with a placeholder (filled with exclamation marks)
but can be forced to render using the ``Force Render`` :ref:`action <actions>`
in :ref:`contexts <contexts>` with a full-sized image view.

Note that increasing this should not have any effect on general performance (i.e
navigation, etc) but the larger an image is, the more the time and memory it'll take
to render it. Thus, a large image might delay the rendering of other images to be
rendered immediately after it.
In the ``image-grid`` :ref:`context <contexts>`, such images have a **yellow**
border (when selected) and title.

.. note:: Overridden by :option:`--max-pixels`.

Expand Down Expand Up @@ -191,6 +192,48 @@ These are top-level fields whose values control various settings of the viewer.
* Overridden by :option:`--swap-win-size` and :option:`--no-swap-win-size`.
* Affects *auto* :term:`cell ratio` computation.

.. confval:: thumbnail
:synopsis: Enable or disable thumbnailing for the image grid.
:type: boolean
:valid: ``true``, ``false``
:default: ``true``

If ``true``, thumbnails are generated for some images (based on their resolution),
cached on disk and cleaned up upon exit. Otherwise, all images in the grid are
rendered directly from the original image files.

.. note::

- Overridden by :option:`--thumbnail` and :option:`--no-thumbnail`.
- Thumbnails are generated **on demand** i.e a thumbnail will be generated for
an image only if its grid cell has come into view at least once.
- Thumbnails are **deduplicated** i.e only one thumbnail is cached and used for
different images having exactly identical thumbnails.

.. confval:: thumbnail cache
:synopsis: The maximum amount of thumbnails that can be cached per time.
:type: integer
:valid: *x* >= ``0``
:default: ``0``

If ``0``, the cache size is infinite i.e no eviction. Otherwise, older thumbnails
will be evicted to accommodate newer ones when the cache is full (i.e the specified
size limit is reached).

.. note:: Unused if :confval:`thumbnail` is ``false`` or :option:`--no-thumbnail`
is specified.

.. confval:: thumbnail size
:synopsis: Maxiumum thumbnail dimension.
:type: integer
:valid: ``32`` <= *x* <= ``512``
:default: ``256``

Thumbnails generated will have a maximum of *x* pixels in the long dimension.

.. note:: Unused if :confval:`thumbnail` is ``false`` or :option:`--no-thumbnail`
is specified.


Keybindings
-----------
Expand Down
2 changes: 1 addition & 1 deletion src/termvisage/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,7 @@ def main() -> None:
show_name = len(args.sources) > 1
for entry in images:
image = entry[1]._ti_image
if args.max_pixels_cli and mul(*image._original_size) > args.max_pixels:
if 0 < args.max_pixels < mul(*image._original_size):
log(
f"Has more than the maximum pixel-count, skipping: {entry[0]!r}",
logger,
Expand Down
39 changes: 27 additions & 12 deletions src/termvisage/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,9 +592,9 @@ def update_context_nav(
"must be an integer between 0 and 5 (both inclusive)",
),
"max pixels": Option(
2**22, # 2048x2048
lambda x: isinstance(x, int) and x > 0,
"must be an integer greater than zero",
0,
lambda x: isinstance(x, int) and x >= 0,
"must be a non-negative integer",
),
"multi": Option(
True,
Expand All @@ -616,6 +616,21 @@ def update_context_nav(
lambda x: isinstance(x, bool),
"must be a boolean",
),
"thumbnail": Option(
True,
lambda x: isinstance(x, bool),
"must be a boolean",
),
"thumbnail cache": Option(
0,
lambda x: isinstance(x, int) and x >= 0,
"must be a non-negative integer",
),
"thumbnail size": Option(
256,
lambda x: isinstance(x, int) and 32 <= x <= 512,
"must be an integer between 32 and 512 (both inclusive)",
),
}
config_options = ConfigOptions(config_options)

Expand Down Expand Up @@ -647,6 +662,11 @@ def update_context_nav(
"Back": ["backspace", "\u27f5 ", "Return to the previous directory"],
"Delete": ["d", "d", "Delete selected image"],
"Switch Pane": ["tab", "\u21b9", "Switch to image pane"],
"Force Render": [
"F",
"\u21e7F",
"Force an image, with more pixels than the set maximum, to be displayed",
],
"Page Up": ["page up", "", "Jump up one page"],
"Page Down": ["page down", "", "Jump down one page"],
"Top": ["home", "", "Jump to the top of the list"],
Expand All @@ -655,14 +675,14 @@ def update_context_nav(
"image": {
"Prev": ["left", "", "Move to the previous image"],
"Next": ["right", "", "Move to the next image"],
"Maximize": ["f", "f", "Maximize the current image"],
"Delete": ["d", "d", "Delete current image"],
"Switch Pane": ["tab", "\u21b9", "Switch to list pane"],
"Force Render": [
"F",
"\u21e7F",
"Force an image, with more pixels than the set maximum, to be displayed",
],
"Maximize": ["f", "f", "Maximize the current image"],
"Delete": ["d", "d", "Delete current image"],
"Switch Pane": ["tab", "\u21b9", "Switch to list pane"],
},
"image-grid": {
"Open": ["enter", "\u23ce", "Maximize the selected image"],
Expand All @@ -682,20 +702,15 @@ def update_context_nav(
"Restore": ["esc", "\u238b", "Exit maximized view"],
"Prev": ["left", "", "Move to the previous image"],
"Next": ["right", "", "Move to the next image"],
"Delete": ["d", "d", "Delete current image"],
"Force Render": [
"F",
"\u21e7F",
"Force an image, with more pixels than the set maximum, to be displayed",
],
"Delete": ["d", "d", "Delete current image"],
},
"full-grid-image": {
"Back": ["esc", "\u238b", "Back to grid view"],
"Force Render": [
"F",
"\u21e7F",
"Force an image, with more pixels than the set maximum, to be displayed",
],
},
"confirmation": {
"Confirm": ["enter", "\u23ce", ""],
Expand Down
19 changes: 12 additions & 7 deletions src/termvisage/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,16 @@ def strip_markup(string: str) -> str:
default=sys.getrecursionlimit() - 50,
help=f"Maximum recursion depth (default: {sys.getrecursionlimit() - 50})",
)
tui_options.add_argument(
"--thumbnail",
action=BooleanOptionalAction,
default=None,
help=(
"Enable or disable thumbnail generation for the image grid; if enabled, "
"thumbnails are cached on disk and cleaned up upon exit "
"(default: :confval:`thumbnail` config)"
),
)

# Performance
perf_options = parser.add_argument_group("Performance Options")
Expand All @@ -601,15 +611,10 @@ def strip_markup(string: str) -> str:
type=int,
metavar="N",
help=(
"Maximum amount of pixels in images to be displayed "
"(default: :confval:`max pixels` config) [#]_"
"The maximum pixel-count for images that should be rendered "
"(default: :confval:`max pixels` config)"
),
)
perf_options.add_argument(
"--max-pixels-cli",
action="store_true",
help="Apply :option:`--max-pixels` in CLI mode",
)
perf_options.add_argument(
"--multi",
action=BooleanOptionalAction,
Expand Down
Loading

0 comments on commit b3650b2

Please sign in to comment.