8000 Add support for block printing using more characters. by veggiebob · Pull Request #62 · atanunq/viuer · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add support for block printing using more characters. #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

veggiebob
Copy link

Started to add support for additional block characters in unicode, including:
▁▂▃▄▅▆▇▉▊▋▌▍▎▏▖▗▘▚▝🭇🭈🭉🭊🭋🭆🭑🭀🬿🬾🬽🬼🭢🭣🭤🭥🭦🭧🭜🭛🭚🭙🭘🭗
and their inversions.

This PR needs a lot of work, and I don't even know if it's within the scope of the project, but I saw some interest for it in #22 so @rosekunkel here you go!
Current issues:

  1. Speed (not fast enough for gifs without caching)
  2. Some bias in the representation of characters, and maybe compatibility issues? (I have only tested on GNOME terminal)

The current structure could easily accomodate the sextants in #22 which I just found out about. The block characters I have been using are from this repo.
An appropriate option has been added to Config: sub_blocks: bool which toggles between regular block printing, and this block printing, which uses the additional characters.
It also properly acknowledges the transparency modes.
Screenshot from 2024-11-24 16-51-19
Screenshot from 2024-11-24 16-52-35

@atanunq
Copy link
Owner
8000
atanunq commented Dec 1, 2024

Wow, thank you so much for the PR! I am happy to work on it and eventually merge as printing does look significantly better. Though, can you please describe on a high level how the new Traits and color math functions work together? I am having a hard time understanding the approach

@veggiebob
Copy link
Author

Sorry, I don't know why I didn't see this earlier. Certainly! I have no problem adding documentation to everything as well.
The approach is as simple and brute as possible, which is why it is slow.
First, imagine that each terminal cell is split into an 8x16 grid, or 8x8 "subpixel" for each "pixel" in the original block render. This comes from the precision of these characters: ▁▂▃▄▅▆▇▉ and ▉▊▋▌▍▎▏ - these represent 8 heights and 8 widths. These numbers are defined as constants.

A "Masker" has a method that samples one cell (by row, column) in the grid and tells whether it is black or white (bool).
A "Mask" represents all of the white (and consequently, the black) regions of each character in a [[bool; 8]; 16] and connects it to a specific char that it is supposed to represent.
The rest of the structs and trait impls in maskers.rs are just there to make it easy to construct masks by using linear functions, etc. (these have no reason to be public; just one of the many things that should be cleaned up).

The rendering process looks like this:

  1. Rescale input image so that it is a whole number of terminal cells (1).
  2. Make another copy of the input image that is 8x bigger than (1) so that an image pixel aligns with each terminal "subpixel"
  3. For each terminal cell:
    • Propose a mask (for example, the mask representing 🭆) used to render this part of the image.
    • Calculate the error:
      • Suppose the color to be used in the white area (foreground) is the average of the colors of the image pixels that are within white area of the mask.
      • Calculate the mean squared error (MSE) for all pixels in that region.
      • Repeat process for black region, and add them together. This is the "error". It is also the sum of the standard deviation of the colors in their own regions.
    • Record the mask and its error, and its foreground and background colors.
    • Repeat for all masks. Choose the mask with the smallest error. Print the corresponding unicode character.

Due to this repetitive process of mask selection, I'm sure that it can be sped up, either by improving the algorithm or just parallelizing all of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0