textual-image


Nametextual-image JSON
Version 0.7.0 PyPI version JSON
download
home_pageNone
SummaryRender images via Kitty's Terminal Graphics Protocol with Rich and Textual
upload_time2024-12-28 21:54:19
maintainerNone
docs_urlNone
authorNone
requires_pythonNone
licenseNone
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # textual-image
[![PyPI - Version](https://img.shields.io/pypi/v/textual-image)](https://pypi.org/project/textual-image/)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/textual-image)](https://pypi.org/project/textual-image/)
[![GitHub deployments](https://img.shields.io/github/deployments/lnqs/textual-image/pypi)](https://github.com/lnqs/textual-image/actions/workflows/publish.yml)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/textual-image)](https://www.pepy.tech/projects/textual-image)

**Render images directly in your terminal using [Textual](https://www.textualize.io/) and [Rich](https://github.com/Textualize/rich).**

![Demo App](./demo.gif)

_textual-image_ offers both Rich renderables and Textual Widgets that leverage the [Terminal Graphics Protocol (TGP)](https://sw.kovidgoyal.net/kitty/graphics-protocol/) and [Sixel](https://en.wikipedia.org/wiki/Sixel) protocols to display images in your terminal. For terminals that don't support these protocols, fallback rendering using Unicode characters is available.

## Supported Terminals

- **Terminal Graphics Protocol (TGP)**: Initially introduced by the [Kitty](https://sw.kovidgoyal.net/kitty/) terminal emulator. While support is partially available in other terminals, it doesn't seem to be really usable there.
- **Sixel Graphics**: Supported by various terminal emulators including [xterm](https://invisible-island.net/xterm/) and a lot of others.

_Note_: As implementation of these protocols differ a lot feedback on different terminal emulators is very welcome.

See the Support Matrix below on what was tested already.

### Support Matrix [^1]

[^1]: Based on [Are We Sixel Yet?](https://www.arewesixelyet.com/)

| Terminal            | TGP support | Sixel support | Works with textual-image |
|---------------------|:-----------:|:-------------:|:------------------------:|
| Black Box           |          ❌ |            ✅ |                       ✅ |
| foot                |          ❌ |            ✅ |                       ✅ |
| GNOME Terminal      |          ❌ |            ❌ |                          |
| iTerm2              |          ❌ |            ✅ |                       ✅ |
| kitty               |          ✅ |            ❌ |                       ✅ |
| konsole             |          ✅ |            ✅ |                       ✅ |
| tmux                |          ❌ |            ✅ |                       ✅ |
| Visual Studio Code  |          ❌ |            ✅ |                       ✅ |
| wezterm             |          ✅ |            ✅ |                       ✅ |
| Windows Console     |          ❌ |            ❌ |                          |
| Windows Terminal    |          ❌ |            ✅ |                       ✅ |
| xterm               |          ❌ |            ✅ |                       ✅ |

✅ = Supported; ❌ = Not Supported

### BlackBox

**Homepage**: https://gitlab.gnome.org/raggesilver/blackbox  
**TGP support**: No  
**Sixel support**: Yes  
**Works**: Yes

**Notes**:  
*Preferences -> Advanced -> Sixel Support* has to be enabled.

Needs to be linked against a version of VTE with Sixel support enabled.
This is the case for the Flatpak version of BlackBox, but not on most Linux distribution's native packages.

### foot

**Homepage**: https://codeberg.org/dnkl/foot  
**TGP support**: No  
**Sixel support**: Yes  
**Works**: Yes

**Notes:**  
Works out of the box, no known issues.

### GNOME Terminal

**Homepage**: https://gitlab.gnome.org/GNOME/gnome-terminal  
**TGP support**: No  
**Sixel support**: No  
**Works**: No

**Notes:**  
Relies on VTE Sixel implementation (<https://gitlab.gnome.org/GNOME/vte/-/issues/253>). While that one is available in an experimental state, I didn't find any resources if it's somehow possible to enable Sixel support on the terminal.

### iTerm2

**Homepage**: https://iterm2.com/  
**TGP support**: No  
**Sixel support**: Yes  
**Works**: Yes

**Notes:**  
Works out of the box.

### Kitty

**Homepage**: https://sw.kovidgoyal.net/kitty/  
**TGP support**: Yes  
**Sixel support**: No  
**Works**: Yes

**Notes:**  
Works out of the box.

### Konsole

**Homepage**: https://konsole.kde.org/  
**TGP support**: Partially  
**Sixel support**: Yes  
**Works**: Yes

**Notes:**  
TGP support is not in a usable state. However, Sixel is working out of the box with a few minor graphical glitches in Textual.

### tmux

**Homepage**: https://github.com/tmux/tmux/wiki  
**TGP support**: No  
**Sixel support**: Yes  
**Works**: Partially

**Notes:**  
tmux doesn't support TGP, even on a TGP enabled terminal nothing will render. Sixel generally works, but heavily depends on the underlying terminal. In some terminals it works great, in others major bugs occur, even if the terminal without tmux works.

### Visual Studio Code

**Homepage**: https://code.visualstudio.com/  
**TGP support**: No  
**Sixel support**: Yes  
**Works**: Yes

**Notes:**  
The `terminal.integrated.enableImages` setting has to be enabled.

### WezTerm

**Homepage**: https://wezfurlong.org/wezterm/index.html  
**TGP support**: No  
**Sixel support**: Yes  
**Works**: Yes

**Notes:**  
Works out of the box.

### Windows Console

**TGP support**: No  
**Sixel support**: No  
**Works**: No

**Notes:**  
Windows Console and Windows Terminal are two different pieces of software. The latter one is supported.

### Windows Terminal

**Homepage**: https://github.com/microsoft/terminal  
**TGP support**: No  
**Sixel support**: Yes  
**Works**: Yes

**Notes:**  
Sixel support was added in version 1.22, which is currently the pre-release.

### xterm

**Homepage**: https://invisible-island.net/xterm/  
**TGP support**: No  
**Sixel support**: Yes  
**Works**: Yes

**Notes:**  
Sixel on xterm is disabled by default. To enable it, add `+lc` and `-ti vt340` options when launching xterm:

```sh
xterm +lc -ti vt340
```

Alternatively, you can add these options to your xterm configuration file (`~/.Xresources` or `~/.Xdefaults`) to make the change permanent:

```sh
echo 'XTerm*decTerminalID: vt340' >> ~/.Xresources
xrdb -merge ~/.Xresources
```

## Installation

Install _textual-image_ using pip with the following commands:

For the basic installation:
```sh
pip install textual-image
```

To include the Textual Widget's dependencies:
```sh
pip install textual-image[textual]
```

## Demonstration

Once installed, run the demo application to see the module in action.

For a demonstration of the Rich renderable, use:
```sh
python -m textual_image rich
```

For a demonstration of the Textual Widget, use:
```sh
python -m textual_image textual
```

The module will automatically select the best available rendering option. If you wish to specify a particular rendering method, use the `-p` argument with one of the following values: `tgp`, `sixel`, `halfcell`, or `unicode`.

For more information, use:
```sh
python -m textual_image --help
```

## Usage

### Rich Integration

To use the Rich renderable, simply pass an instance of `textual_image.renderable.Image` to a Rich function that renders data:

```python
from rich.console import Console
from textual_image.renderable import Image

console = Console()
console.print(Image("path/to/image.png"))
```

The `Image` constructor accepts either a string, a `pathlib.Path` representing the file path of an image readable by [Pillow](https://python-pillow.org/), or a Pillow `Image` instance directly.

By default, the image is rendered in its original dimensions. You can modify this behavior by specifying the `width` and/or `height` parameters. These can be defined as an integer (number of cells), a percentage string (e.g., `50%`), or the literal `auto` to automatically scale while maintaining the aspect ratio.

`textual_image.renderable.Image` defaults to the best available rendering method. To specify an explicit rendering method, use one of the following classes: `textual_image.renderable.tgp.Image`, `textual_image.renderable.sixel.Image`, `textual_image.renderable.halfcell.Image`, or `textual_image.renderable.unicode.Image`.

### Textual Integration

For integration with Textual, _textual-image_ offers a Textual `Widget` to render images:

```python
from textual.app import App, ComposeResult
from textual_image.widget import Image

class ImageApp(App[None]):
    def compose(self) -> ComposeResult:
        yield Image("path/to/image.png")

ImageApp().run()
```

The `Image` constructor accepts either a string or a `pathlib.Path` with the file path of an image readable by [Pillow](https://python-pillow.org/), or a Pillow `Image` instance directly.

You can also set the image using the `image` property of an `Image` instance:

```python
from textual.app import App, ComposeResult
from textual_image.textual import Image

class ImageApp(App[None]):
    def compose(self) -> ComposeResult:
        image = Image()
        image.image = "path/to/image.png"
        yield image

ImageApp().run()
```

If a different image is set, the Widget will update to display the new image.

By default, the best available rendering option is used. To override this, you can instantiate `textual_image.widget.TGPImage`, `textual_image.widget.SixelImage`, `textual_image.widget.HalfcellImage`, or `textual_image.widget.UnicodeImage` directly.

_*Note*_: The process of determining the best available rendering option involves querying the terminal, which means sending and receiving data. Since Textual starts threads to handle input and output, this query will **not work** once the Textual app has started. Therefore, make sure that `textual_image.renderable` is imported **before** running the Textual app (which is typically the case in most use cases).

## Limitations

- **High Sixel images in Rich**: As terminal emulators don't implement the Sixel protocol exactly consistent, a workaround to get the cursor position in Rich right had to be implemented. This breaks as soon as the image is higher that the terminal window itself. Rendering will still happen, but the image may be displaced and borders around it may be broken.
- **Sixel Support in Textual**: Sixel support in Textual is not particularly performant due to the way Textual handles rendering. The Sixel graphics are injected into the rendering process in a somewhat hacky manner, which affects performance. Scrolling and changing styles of images can lead to a lot of flickering. But for mostly static images it should work fine. If not, please file an issue on GitHub.

## Contribution

If you find this module useful, please consider starring the repository on GitHub.

This project began by moving some TGP functionality from a private project to a public GitHub repository and PyPI package, with some additional code added along the way to support Sixel graphics. If you encounter any issues, please file an issue on GitHub.

Contributions via pull requests are welcome and encouraged.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "textual-image",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": null,
    "author": null,
    "author_email": "Simon Hayessen <simon@lnqs.io>",
    "download_url": "https://files.pythonhosted.org/packages/62/81/ca6f886d489c94ed5cf9f4c4b178828e3d30fb12276338e641691fad9eb8/textual_image-0.7.0.tar.gz",
    "platform": null,
    "description": "# textual-image\n[![PyPI - Version](https://img.shields.io/pypi/v/textual-image)](https://pypi.org/project/textual-image/)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/textual-image)](https://pypi.org/project/textual-image/)\n[![GitHub deployments](https://img.shields.io/github/deployments/lnqs/textual-image/pypi)](https://github.com/lnqs/textual-image/actions/workflows/publish.yml)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/textual-image)](https://www.pepy.tech/projects/textual-image)\n\n**Render images directly in your terminal using [Textual](https://www.textualize.io/) and [Rich](https://github.com/Textualize/rich).**\n\n![Demo App](./demo.gif)\n\n_textual-image_ offers both Rich renderables and Textual Widgets that leverage the [Terminal Graphics Protocol (TGP)](https://sw.kovidgoyal.net/kitty/graphics-protocol/) and [Sixel](https://en.wikipedia.org/wiki/Sixel) protocols to display images in your terminal. For terminals that don't support these protocols, fallback rendering using Unicode characters is available.\n\n## Supported Terminals\n\n- **Terminal Graphics Protocol (TGP)**: Initially introduced by the [Kitty](https://sw.kovidgoyal.net/kitty/) terminal emulator. While support is partially available in other terminals, it doesn't seem to be really usable there.\n- **Sixel Graphics**: Supported by various terminal emulators including [xterm](https://invisible-island.net/xterm/) and a lot of others.\n\n_Note_: As implementation of these protocols differ a lot feedback on different terminal emulators is very welcome.\n\nSee the Support Matrix below on what was tested already.\n\n### Support Matrix [^1]\n\n[^1]: Based on [Are We Sixel Yet?](https://www.arewesixelyet.com/)\n\n| Terminal            | TGP support | Sixel support | Works with textual-image |\n|---------------------|:-----------:|:-------------:|:------------------------:|\n| Black Box           |          \u274c |            \u2705 |                       \u2705 |\n| foot                |          \u274c |            \u2705 |                       \u2705 |\n| GNOME Terminal      |          \u274c |            \u274c |                          |\n| iTerm2              |          \u274c |            \u2705 |                       \u2705 |\n| kitty               |          \u2705 |            \u274c |                       \u2705 |\n| konsole             |          \u2705 |            \u2705 |                       \u2705 |\n| tmux                |          \u274c |            \u2705 |                       \u2705 |\n| Visual Studio Code  |          \u274c |            \u2705 |                       \u2705 |\n| wezterm             |          \u2705 |            \u2705 |                       \u2705 |\n| Windows Console     |          \u274c |            \u274c |                          |\n| Windows Terminal    |          \u274c |            \u2705 |                       \u2705 |\n| xterm               |          \u274c |            \u2705 |                       \u2705 |\n\n\u2705 = Supported; \u274c = Not Supported\n\n### BlackBox\n\n**Homepage**: https://gitlab.gnome.org/raggesilver/blackbox  \n**TGP support**: No  \n**Sixel support**: Yes  \n**Works**: Yes\n\n**Notes**:  \n*Preferences -> Advanced -> Sixel Support* has to be enabled.\n\nNeeds to be linked against a version of VTE with Sixel support enabled.\nThis is the case for the Flatpak version of BlackBox, but not on most Linux distribution's native packages.\n\n### foot\n\n**Homepage**: https://codeberg.org/dnkl/foot  \n**TGP support**: No  \n**Sixel support**: Yes  \n**Works**: Yes\n\n**Notes:**  \nWorks out of the box, no known issues.\n\n### GNOME Terminal\n\n**Homepage**: https://gitlab.gnome.org/GNOME/gnome-terminal  \n**TGP support**: No  \n**Sixel support**: No  \n**Works**: No\n\n**Notes:**  \nRelies on VTE Sixel implementation (<https://gitlab.gnome.org/GNOME/vte/-/issues/253>). While that one is available in an experimental state, I didn't find any resources if it's somehow possible to enable Sixel support on the terminal.\n\n### iTerm2\n\n**Homepage**: https://iterm2.com/  \n**TGP support**: No  \n**Sixel support**: Yes  \n**Works**: Yes\n\n**Notes:**  \nWorks out of the box.\n\n### Kitty\n\n**Homepage**: https://sw.kovidgoyal.net/kitty/  \n**TGP support**: Yes  \n**Sixel support**: No  \n**Works**: Yes\n\n**Notes:**  \nWorks out of the box.\n\n### Konsole\n\n**Homepage**: https://konsole.kde.org/  \n**TGP support**: Partially  \n**Sixel support**: Yes  \n**Works**: Yes\n\n**Notes:**  \nTGP support is not in a usable state. However, Sixel is working out of the box with a few minor graphical glitches in Textual.\n\n### tmux\n\n**Homepage**: https://github.com/tmux/tmux/wiki  \n**TGP support**: No  \n**Sixel support**: Yes  \n**Works**: Partially\n\n**Notes:**  \ntmux doesn't support TGP, even on a TGP enabled terminal nothing will render. Sixel generally works, but heavily depends on the underlying terminal. In some terminals it works great, in others major bugs occur, even if the terminal without tmux works.\n\n### Visual Studio Code\n\n**Homepage**: https://code.visualstudio.com/  \n**TGP support**: No  \n**Sixel support**: Yes  \n**Works**: Yes\n\n**Notes:**  \nThe `terminal.integrated.enableImages` setting has to be enabled.\n\n### WezTerm\n\n**Homepage**: https://wezfurlong.org/wezterm/index.html  \n**TGP support**: No  \n**Sixel support**: Yes  \n**Works**: Yes\n\n**Notes:**  \nWorks out of the box.\n\n### Windows Console\n\n**TGP support**: No  \n**Sixel support**: No  \n**Works**: No\n\n**Notes:**  \nWindows Console and Windows Terminal are two different pieces of software. The latter one is supported.\n\n### Windows Terminal\n\n**Homepage**: https://github.com/microsoft/terminal  \n**TGP support**: No  \n**Sixel support**: Yes  \n**Works**: Yes\n\n**Notes:**  \nSixel support was added in version 1.22, which is currently the pre-release.\n\n### xterm\n\n**Homepage**: https://invisible-island.net/xterm/  \n**TGP support**: No  \n**Sixel support**: Yes  \n**Works**: Yes\n\n**Notes:**  \nSixel on xterm is disabled by default. To enable it, add `+lc` and `-ti vt340` options when launching xterm:\n\n```sh\nxterm +lc -ti vt340\n```\n\nAlternatively, you can add these options to your xterm configuration file (`~/.Xresources` or `~/.Xdefaults`) to make the change permanent:\n\n```sh\necho 'XTerm*decTerminalID: vt340' >> ~/.Xresources\nxrdb -merge ~/.Xresources\n```\n\n## Installation\n\nInstall _textual-image_ using pip with the following commands:\n\nFor the basic installation:\n```sh\npip install textual-image\n```\n\nTo include the Textual Widget's dependencies:\n```sh\npip install textual-image[textual]\n```\n\n## Demonstration\n\nOnce installed, run the demo application to see the module in action.\n\nFor a demonstration of the Rich renderable, use:\n```sh\npython -m textual_image rich\n```\n\nFor a demonstration of the Textual Widget, use:\n```sh\npython -m textual_image textual\n```\n\nThe module will automatically select the best available rendering option. If you wish to specify a particular rendering method, use the `-p` argument with one of the following values: `tgp`, `sixel`, `halfcell`, or `unicode`.\n\nFor more information, use:\n```sh\npython -m textual_image --help\n```\n\n## Usage\n\n### Rich Integration\n\nTo use the Rich renderable, simply pass an instance of `textual_image.renderable.Image` to a Rich function that renders data:\n\n```python\nfrom rich.console import Console\nfrom textual_image.renderable import Image\n\nconsole = Console()\nconsole.print(Image(\"path/to/image.png\"))\n```\n\nThe `Image` constructor accepts either a string, a `pathlib.Path` representing the file path of an image readable by [Pillow](https://python-pillow.org/), or a Pillow `Image` instance directly.\n\nBy default, the image is rendered in its original dimensions. You can modify this behavior by specifying the `width` and/or `height` parameters. These can be defined as an integer (number of cells), a percentage string (e.g., `50%`), or the literal `auto` to automatically scale while maintaining the aspect ratio.\n\n`textual_image.renderable.Image` defaults to the best available rendering method. To specify an explicit rendering method, use one of the following classes: `textual_image.renderable.tgp.Image`, `textual_image.renderable.sixel.Image`, `textual_image.renderable.halfcell.Image`, or `textual_image.renderable.unicode.Image`.\n\n### Textual Integration\n\nFor integration with Textual, _textual-image_ offers a Textual `Widget` to render images:\n\n```python\nfrom textual.app import App, ComposeResult\nfrom textual_image.widget import Image\n\nclass ImageApp(App[None]):\n    def compose(self) -> ComposeResult:\n        yield Image(\"path/to/image.png\")\n\nImageApp().run()\n```\n\nThe `Image` constructor accepts either a string or a `pathlib.Path` with the file path of an image readable by [Pillow](https://python-pillow.org/), or a Pillow `Image` instance directly.\n\nYou can also set the image using the `image` property of an `Image` instance:\n\n```python\nfrom textual.app import App, ComposeResult\nfrom textual_image.textual import Image\n\nclass ImageApp(App[None]):\n    def compose(self) -> ComposeResult:\n        image = Image()\n        image.image = \"path/to/image.png\"\n        yield image\n\nImageApp().run()\n```\n\nIf a different image is set, the Widget will update to display the new image.\n\nBy default, the best available rendering option is used. To override this, you can instantiate `textual_image.widget.TGPImage`, `textual_image.widget.SixelImage`, `textual_image.widget.HalfcellImage`, or `textual_image.widget.UnicodeImage` directly.\n\n_*Note*_: The process of determining the best available rendering option involves querying the terminal, which means sending and receiving data. Since Textual starts threads to handle input and output, this query will **not work** once the Textual app has started. Therefore, make sure that `textual_image.renderable` is imported **before** running the Textual app (which is typically the case in most use cases).\n\n## Limitations\n\n- **High Sixel images in Rich**: As terminal emulators don't implement the Sixel protocol exactly consistent, a workaround to get the cursor position in Rich right had to be implemented. This breaks as soon as the image is higher that the terminal window itself. Rendering will still happen, but the image may be displaced and borders around it may be broken.\n- **Sixel Support in Textual**: Sixel support in Textual is not particularly performant due to the way Textual handles rendering. The Sixel graphics are injected into the rendering process in a somewhat hacky manner, which affects performance. Scrolling and changing styles of images can lead to a lot of flickering. But for mostly static images it should work fine. If not, please file an issue on GitHub.\n\n## Contribution\n\nIf you find this module useful, please consider starring the repository on GitHub.\n\nThis project began by moving some TGP functionality from a private project to a public GitHub repository and PyPI package, with some additional code added along the way to support Sixel graphics. If you encounter any issues, please file an issue on GitHub.\n\nContributions via pull requests are welcome and encouraged.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Render images via Kitty's Terminal Graphics Protocol with Rich and Textual",
    "version": "0.7.0",
    "project_urls": {
        "Documentation": "https://github.com/lnqs/textual-image",
        "Homepage": "https://github.com/lnqs/textual-image",
        "Issues": "https://github.com/lnqs/textual-image/issues",
        "Repository": "https://github.com/lnqs/textual-image"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2562da4f7d1a078ceb4eecf90102b255b5e47c07c69d17a3fd28b8deac57c356",
                "md5": "c9ef8f7dbecb0f1b77a86387565f7617",
                "sha256": "920ca6ae67fae015136896aaa3641033ac1ccc86e9313a430f01ceec4455384f"
            },
            "downloads": -1,
            "filename": "textual_image-0.7.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c9ef8f7dbecb0f1b77a86387565f7617",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 108443,
            "upload_time": "2024-12-28T21:54:16",
            "upload_time_iso_8601": "2024-12-28T21:54:16.778028Z",
            "url": "https://files.pythonhosted.org/packages/25/62/da4f7d1a078ceb4eecf90102b255b5e47c07c69d17a3fd28b8deac57c356/textual_image-0.7.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6281ca6f886d489c94ed5cf9f4c4b178828e3d30fb12276338e641691fad9eb8",
                "md5": "4dcd353fa2c9ae75ab998a6e0d4cce10",
                "sha256": "5cd4a0808c3455afeb836a62443bc292723576a96346ef7a06666f1b2b8752e0"
            },
            "downloads": -1,
            "filename": "textual_image-0.7.0.tar.gz",
            "has_sig": false,
            "md5_digest": "4dcd353fa2c9ae75ab998a6e0d4cce10",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 107720,
            "upload_time": "2024-12-28T21:54:19",
            "upload_time_iso_8601": "2024-12-28T21:54:19.524694Z",
            "url": "https://files.pythonhosted.org/packages/62/81/ca6f886d489c94ed5cf9f4c4b178828e3d30fb12276338e641691fad9eb8/textual_image-0.7.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-28 21:54:19",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "lnqs",
    "github_project": "textual-image",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "textual-image"
}
        
Elapsed time: 1.30582s