Originally created by: endernoke
Related to [#104]
This PR introduces a new modular and extensible image rendering system for terminal UIs, supporting multiple protocols for displaying images using different techniques.
Changes (high level:
- Added a unified
Image component interface
- implemented two new image rendering protocols (
HalfBlock and Braille)
- Introduced a protocol factory for easy extensibility,
Image component
<Image> handles image fetching, resizing, and conversion to terminal-friendly output.
Props:
src: file path or URL to image
- Accepts png/jpg, webp, possibly svg and tif but haven't tested
width, height (optional): display width and height of the image (in terminal cells).
- If not set, width and height will be inferred from available space in parent component and the aspect ratio of the original image.
- Note that on most terminals the cell height is roughly twice the cell width, so for example a square image should have its height set to half its width to maintain aspect ratio
protocol (optional): the rendering backend to use, currently either halfBlock or braille.
New image rendering protocols
halfBlock:
- Uses the unicode lower half block character ("▄",, U+2584) with ANSI escape sequences for text color and background color
- Resolution: 1x2 pixels per terminal cell
Braille:
- Uses eight dot braille characters (U+2800 to U+2899) to render a monochrome image
- Resolution: 2x4 pixels per terminal cell
To-do / technical debt
- Convert image protocol factory from class-based to functional for better compatibility with React
- Implement ASCII rendering based on original feed display
- Keep experimenting with iterm2, kitty, sixel, and other native terminal image protocols which allows full resolution.
Since Ink doesn't support custom terminal rendering natively we need to manually figure out the correct coordinates in the terminal where the image should be rendered, then render the image via a side-effect, then clean up / redraw the image when component moves or unmounts (At this point I'm not very optimistic about this 💀 The code for rendering sixel is in ts-migration/image-sixel)
Originally posted by: endernoke
Should we convert this into a npm library and install back to this project, thinking this would give it more robust community support and our repo won't be cluttered with terminal compatibility issues lmao
Ticket changed by: endernoke
Originally posted by: endernoke
Sorry pushed to the wrong branch 😅 , reverted