Skip to content
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

Support graphical banners #40226

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

Conversation

dmlloyd
Copy link
Member

@dmlloyd dmlloyd commented Apr 23, 2024

Support graphical banners with a separate configuration.
Only render a graphical banner if the console supports it at run time, else fall back on the text banner.

Why?

It looks really cool.

And, I needed a break from more difficult work. This has been on my back burner for years so I thought I'd put something together to see if it was feasible, and it is!

image

How?

Many modern terminals support inline image output. It's a matter of image encoding and escape codes, pretty much. There are multiple ways to transfer images to the terminal including temporary files and shared memory, but I opted for the simplest and most direct route: translating the image directly into base64 and transmitting it in line.

What works?

Any PNG image should work (including transparent). The image is currently hard-coded to have a height of 4 character rows. The width is then calculated based on the aspect ratio of the image. The image is scaled to fit these dimensions.

If the terminal is detected to not support graphics, the image is not displayed (otherwise it appears as a huge blob of base64 text).

What doesn't work?

Any kind of dark/light mode detection. Best results will be with images which look good on any background. In my test (see image) I just used a Quarkus "dark mode" logo.

My terminal of choice, kitty, does not properly compute the aspect ratio automatically as it should, so I compute the columns/rows aspect ratio by hand using an estimate of 1.8 for the font height-to-width aspect ratio. It looks OK on my terminal but will probably look weird if you use a different font than I do. I'll probably remove this hack once the bug is fixed. The bug is kitty#7380. Once this is solved, using ImageIO would no longer be needed for analyzing the image.

More?

There are all kinds of things we can do with terminal image support, up to and including a complete graphical terminal-based console. But, printing a banner is spiffy enough for now I think.

Several other image types could easily be supported as well. I think PNG is the logical starting point though due to its support for transparency.

@aloubyansky
Copy link
Member

Glamorous :)

@Sanne
Copy link
Member

Sanne commented Apr 24, 2024

Cool :)

@geoand
Copy link
Contributor

geoand commented Apr 24, 2024

It looks really cool.

This is the coolest thing I've seen in a while!

@gastaldi
Copy link
Contributor

gastaldi commented Apr 25, 2024

Holy crap, that's amazing!

Screenshot 2024-04-25 at 17 11 39

@gastaldi
Copy link
Contributor

@dmlloyd I've tested locally and it looks great. What's missing to make this PR Ready for Review?

@gastaldi
Copy link
Contributor

Interesting that it doesn't work with quarkus dev

@dmlloyd
Copy link
Member Author

dmlloyd commented Apr 25, 2024

A few things (I'll make it a checklist):

  • Wait for a new release of kitty to be out for a little while and drop the ImageIO stuff (This was replaced by configuration options to override the scale factor)
  • Have a fallback so if graphics are not supported, it can fall back to xxxx.txt from xxxx.png
  • Maybe some kind of dark mode detection? (This is kind of hard/expensive to do though)
  • Maybe columns/rows configuration?
  • Come up with a nice default banner that looks good on both light and dark screens (maybe the default Quarkus logo, optimized for dark mode but with black outlines around the white letters so they are visible on a light screen? Maybe @insectengine has an idea...)

@maxandersen
Copy link
Contributor

Neat.

Is the idea to have a default PNG or just to let users provide one?
Asking sinde at least historically for me the PNG rendering makes console output slower so would need convincing to make it the default.

Anyone tested this on windows and when running inside a container yet ? :)

@holly-cummins
Copy link
Contributor

So I love this, but I have a suggestion. It'd be cute to auto-convert the png to ascii art for the cases where this doesn't work. That saves people having to provide a fallback, and ascii art is just awesome anyway.

@aloubyansky
Copy link
Member

That will be a part of boot time that users may use for comparisons though.

@holly-cummins
Copy link
Contributor

That will be a part of boot time that users may use for comparisons though.

The conversion could be build-time, right? And we just package up the fallback.txt.

@dmlloyd
Copy link
Member Author

dmlloyd commented Apr 26, 2024

Neat.

Is the idea to have a default PNG or just to let users provide one?

As stated above, I think it would be nifty to have a default one.

Asking since at least historically for me the PNG rendering makes console output slower so would need convincing to make it the default.

Yeah it'll definitely have some amount of overhead, but I never observed anything I would call "slow" using kitty even on my 10-year-old Linux workhorse.

The potential performance impacts would include:

  • Data transfer - I transfer the image in-line presently, but it's also possible to write the image to a file and tell the terminal to find it there. Obviously this won't work across an SSH link without some kind of magic though. There's also a shared-memory option.
  • The terminal program itself - though as I said I never observed a performance issue with kitty.

Anyone tested this on windows and when running inside a container yet ? :)

While it is possible that there is a Windows terminal which supports graphics, if such a terminal is not detected, then image display is disabled as stated above. For example, no banner is displayed when running Maven integration tests (at least in my test program).

There should of course be a manual override switch though.

@dmlloyd
Copy link
Member Author

dmlloyd commented Apr 26, 2024

So I love this, but I have a suggestion. It'd be cute to auto-convert the png to ascii art for the cases where this doesn't work. That saves people having to provide a fallback, and ascii art is just awesome anyway.

That's a cool idea. Are you thinking e.g. interpolating to RGB unicode half-blocks, or actually interpolating to ascii like e.g. https://www.asciiart.eu/image-to-ascii to get something like:

+++++++++++++++                                                                                     
++   --  +   ++        @@@@@@@@    @@     @@      @@@      @@@@@@@    @@   @@    @@     @@   @@@@@@@
++   +#@%*   ++       @@      @@   @@     @@     @@@@@     @@   @@@   @@ @@@     @@     @@   @@     
++ ++@@@@@---++      @@       @@   @@     @@    @@@ @@@    @@@@@@@    @@@@@      @@     @@    @@@@@ 
++   *@@@#   ++       @@      @@   @@     @@    @@@@@@@    @@  @@     @@ @@@     @@     @@        @@
++   --+++   ++       @@@   @@@    @@@   @@@   @@     @@   @@   @@    @@   @@    @@@   @@@   @    @@
++    +++    ++         @@@@@        @@@@@     @@      @@  @@    @@   @@    @@     @@@@@     @@@@@@ 
+++++++++++++++             @@@                                                                     

?

@dmlloyd
Copy link
Member Author

dmlloyd commented Apr 26, 2024

In terms of startup time, according to my highly unscientific measurements, my simple getting-started example starts in about ~320ms with the banner and ~310ms without it. So, there probably is some kind of impact but I don't think that the banner is likely "it". Note that the banner is "loaded" via the recorder even if it isn't displayed. I wouldn't expect this to have much overhead though.

@holly-cummins
Copy link
Contributor

That's a cool idea. Are you thinking e.g. interpolating to RGB unicode half-blocks, or actually interpolating to ascii like e.g. https://www.asciiart.eu/image-to-ascii to get something like:

I hadn't really got that far. I was assuming there was a library we could use, although once you add the requirement that it's a Java library, the selection is limited. And, ideally, it would use terminal colours to replicate the colours in the image, and use a wide range of characters to achieve different segment intensities and shapes. Or you could use emojis to get colours. And to do all that, it might be you'll have to take a longer break from the difficult work in order to write a best-of-breed Java ascii art converter. :)

@dmlloyd
Copy link
Member Author

dmlloyd commented May 1, 2024

So for some reason I spent some time tinkering with an alternative text-based banner.

I started with this analysis:

quarkus-grid

I wrote a crappy image interpolator which gave me this text (ignore github's bad formatting):

 ▟▀▀▀▄   ▐▌   ▐     █▖    █▀▀▚▖  ▐▌ ▗▞▘  █    ▌  ▗▛▀▀▘
▟▘   ▝▌  ▐▌   ▐    ▟ ▙    █  ▐▌  ▐▌▄▀    █   ▝▌  ▐▌   
█     ▛  ▐▌   ▐   ▗▙▄▟▌   █▀▜▛   ▐▛▀▖    █   ▝▌    ▀▚▖
▝▙   ▟▘  ▝▙   █   ▛   ▜▖  █  ▜▖  ▐▌ ▝▙   ▜▖  ▟▘     ▗▛
  ▀▀█      ▀▀▀   ▝▘    ▘  ▀   ▀  ▝▘  ▝▘   ▀▀▀▘   ▝▀▀▀ 

I cleaned it up manually to get this:

image

I'm not sure where I'm going with this. It might be a bit plain-looking to be a good replacement the default banner. Maybe it can be spiced up somehow.

@insectengine
Copy link
Contributor

Do we have a target width for this ascii banner? I've converted the Kroxylicious logo to ascii and it was important to have the optimum target width since you can't scale them.

@dmlloyd
Copy link
Member Author

dmlloyd commented May 1, 2024

I just determined the width as a function of the original image aspect ratio, based on 5 rows and a font aspect ratio of 3:5 (which appears to be more or less standard for most monospace fonts). Since we generally cannot know the correct maximum banner width, it might be a good idea to send the proper escape code to prevent line wrap for those lines. That way if it overflows, it'll get chopped instead of causing a mess on the screen. I could add that...

@gsmet
Copy link
Member

gsmet commented May 1, 2024

Just keep in mind that the current banner is ugly because Windows was really hard to get right.

@insectengine
Copy link
Contributor

insectengine commented May 1, 2024

Having a logo be ascii art friendly was NEVER discussed at design school. LOL! Honestly, trying to do the full logo is very problematic as it forces the counter forms of the logo mark to fill in horribly.

I've tweaked the logomark (icon) and rendered it at 100 characters (and adjusted the density sliders to get the best result).

quarkus_icon_ascii_100

quarkus_icon_ascii_100.txt

@dmlloyd
Copy link
Member Author

dmlloyd commented May 1, 2024

Yeah, it's tricky when it's scaled down. I'd be hesitant to go much higher than five rows of text let alone 100 😉. Even just doing the letters, it doesn't look amazing at that scale. Definite retro PC vibes. :)

@quarkus-bot quarkus-bot bot added area/devtools Issues/PR related to maven, gradle, platform and cli tooling/plugins area/documentation area/graphics area/kubernetes area/maven labels May 1, 2024
@quarkus-bot quarkus-bot bot added this to To do in Quarkus Documentation May 1, 2024
@dmlloyd
Copy link
Member Author

dmlloyd commented May 1, 2024

Pushed. Now we have separate config for graphical banners, plus a separate switch. Also some knobs for adjusting the size, and a default graphical banner.

I've also updated the text banner, but as @gsmet says it probably will look bad on windows. I'm going to boot up my windows vm and have a look.

Update: it appears I have vaporized my Windows VM. So, it's on the back burner again.

Copy link

github-actions bot commented May 1, 2024

🎊 PR Preview c02cafb has been successfully built and deployed to https://quarkus-pr-main-40226-preview.surge.sh/version/main/guides/

  • Images of blog posts older than 3 months are not available.
  • Newsletters older than 3 months are not available.

@dmlloyd
Copy link
Member Author

dmlloyd commented May 1, 2024

Oh, to enable at run time use -Dquarkus.banner.image.enabled=true. Maybe we should make it the default? (It'll still be disabled if the console does not appear to support graphics though...)

@dmlloyd
Copy link
Member Author

dmlloyd commented May 2, 2024

The above text banner does indeed look bad on Windows (missing Unicode characters).

This one looks OK in cmd.exe, though it's even lower resolution:

▄█▀▀█▄  █    █    ▐█▌    █▀▀▀▄   █  ▄█  █    █  ▄▀▀▀▄
█    █  █    █   ▐▌ ▐▌   █   █   █▄█▀   █    █  █    
█    █  █    █   █▄▄▄█   █▀█▀    ██▄    █    █   ▀▀▀▄
█▄  ▄█  ▐▌  ▐▌  ▐▌   ▐▌  █  █    █ ▀█▄  ▐▌  ▐▌  ▄   █
 ▀▀▀█▄   ▀▀▀▀   ▀     ▀  ▀   ▀   ▀   ▀   ▀▀▀▀    ▀▀▀ 

Screenshot_2024-05-02_12-56-19
image

@dmlloyd dmlloyd force-pushed the graphical-banner branch 2 times, most recently from 83cae92 to f2a40a0 Compare May 2, 2024 19:00
Comment on lines +1 to +8
██░░██ ░██ ░██ ░███ ░██░░░██ ░██ ██ ░██ ░██ ██░░░██
██ ░░██ ░██ ░██ ██░██ ░██ ░██ ░██ ██ ░██ ░██ ░██ ░░
░██ ░██ ░██ ░██ ░██░██ ░██████ ░█████ ░██ ░██ ░░█████
░██ ░██ ░██ ░██ ███████ ░██░██ ░██░░██ ░██ ░██ ░░░░░██
░░██ ██ ░██ ░██ ░██░░░██ ░██░░██ ░██ ░░██ ░██ ░██ ██ ░██
░░███░██ ░█████ ██ ░░██ ░██ ░░██ ░██ ░░█ ░█████ ░░█████
░░░ ░░ ░░░░ ░░ ░░ ░░ ░░ ░░ ░ ░░░░ ░░░░░
Copy link
Member Author

@dmlloyd dmlloyd May 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latest idea. Only uses three characters, all of which appear in Latin-1 the original IBM PC code page. It's tall though, 8 characters.

@maxandersen
Copy link
Contributor

Please please dont enable this by default.

@maxandersen
Copy link
Contributor

maxandersen commented May 3, 2024

It's fine to have as an option - but consistency is important and having to deal with the amount of different fonts and behaviors across all crazy combos of windows, osx, Linux and containers in and outside proper set of OS and just rendering inside let's say GitHub actions is going to not make this worth having it by default.

@dmlloyd
Copy link
Member Author

dmlloyd commented May 3, 2024

Don't worry @maxandersen, as I said before, it won't attempt to display the banner unless there is a high confidence that it will work, even if it is explicitly enabled.

@dmlloyd dmlloyd removed area/maven area/kubernetes area/devtools Issues/PR related to maven, gradle, platform and cli tooling/plugins labels May 3, 2024
@dmlloyd
Copy link
Member Author

dmlloyd commented May 6, 2024

@insectengine did you have any thoughts about a transparent-background, PNG-format version of the banner that looks good on both light and dark backgrounds?

Alternatively we could have separate config for light-mode and dark-mode banner PNG images.

@insectengine
Copy link
Contributor

@dmlloyd - I take it we can only have one .PNG that will be accessible (we can't pull a version for light and a version for dark)? If that's the case, then we'd be better off picking one direction and doing an non-transparent version with either a filled light or dark background.

Additionally, we need a minimum amount of space around the logo (as per our branding guidelines).
https://quarkus.io/brand/

I'm attaching two versions of the logo with in built in spacing and white or black backgrounds.
quarkus_logo_horizontal_default_black
quarkus_logo_horizontal_default_white

@dmlloyd
Copy link
Member Author

dmlloyd commented May 6, 2024

Ah, well that's unfortunate. We can't realistically provide the extra surrounding padding on the console (we're pretty space-constrained), and using a non-transparent version is definitely not as nice aesthetically. So, I'm not sure where that leaves us.

@insectengine
Copy link
Contributor

We could roll the dice on the transparency. It's my complete guess but I'd imagine the vast majority of developers use dark mode for their consoles so we could use the one designed for a dark background. I've also fudged the padding a bit to give the more of the intended effect.

quarkus_logo_horizontal_reverse

Support graphical banners with a separate configuration.
Only render a graphical banner if the console supports it at run time, else fall back on the text banner.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

9 participants