23

I used to use full-screen consoles (those opened with Ctrl+Alt+F1...F6) actively and have come to an idea that I would like to try decorating it with a "wallpaper" of a sort (a rather dark and monotonous one of course so that it wouldn't decrease readability), perhaps this could look and feel nice (or not, but I need to try). It would even better if I could set different pictures as different console's background (one for Ctrl+Alt+F1, another for Ctrl+Alt+F2 etc).

The fact the consoles have much higher resolution that pure text mode provides suggests that full-fledged graphical mode is used for them and everything is possible. But how?

terdon
  • 100,812
Ivan
  • 57,065
  • 3
    Impossible. Virtual Consoles are text only. – Sergiy Kolodyazhnyy Nov 24 '15 at 08:34
  • 8
    @Serg I have been using text-only modes since the time Linux didn't even exist - believe me, I can distinguish real text mode from its graphical emulation. Many people can hardly imagine this nowadays but I have even been watching movies in the consoles with no X server installed at all during the Linux 2.4 days. This makes me doubt this actually is impossible. – Ivan Nov 24 '15 at 09:24
  • 3
    OK, well let me correct myself: I do believe in viewing images and movies in console, because of something know as framebuffer device, but with that screen is occupied with output of some program, such as fbi. TTY in and of itself is still a text-only device – Sergiy Kolodyazhnyy Nov 24 '15 at 09:42
  • 3
    I'll put a bounty on your question once it's eligible. I got interested actually – Sergiy Kolodyazhnyy Nov 24 '15 at 09:45
  • 1
    Check this out : https://code.google.com/p/fbterm/ – Sergiy Kolodyazhnyy Nov 24 '15 at 09:55

4 Answers4

15

I'm pretty sure that the Linux console driver does not have this ability built in, however there is an application called fbterm which can do this. In order to make background images work, you will also need a utility which can display an image on the framebuffer such as fbi:

sudo apt-get install fbterm fbi

fbterm does not actually read or display background images itself, it expects some other program to set up the background image on the screen before it starts. There are instructions in the fbterm man page on how to do this using fbv, an absolutely antiquated and unsupported utility I couldn't even get to compile on a modern Ubuntu system. fbi is a much cleaner and nicer image viewer for the framebuffer, but unfortunately does not have the "set it and exit" functionality of the simpler fbv, and thus interferes with fbterm if you try to use it directly. However, I was able to come up with an alternative which works:

First, you will need to use fbi and cat to display the image you want and then dump it to a "framebuffer raw format" image file. As root, in a framebuffer console, run:

( sleep 1; cat /dev/fb0 > nifty-background.fbimg ) & fbi -t 2 -1 --noverbose -a nifty-background.png

(This will display the image for a couple of seconds and then exit, having saved the result in the file nifty-background.fbimg. Replace nifty-background.fbimg and nifty-background.png with whatever filenames you wish, of course.)

The first part of the command waits for 1 second before catting the framebuffer contents to a file. At the same time, the second part (after the &) launches fbi to display the image on the framebuffer, so that when the cat command gets around to executing (1 second later), there's an image there to dump. The reason they're in that order is because I found that fbi had issues if it wasn't running in the foreground, which means it has to be the last command in the list.

From then on, whenever you want to run fbterm, you can start it like so (you may want to create a little wrapper script):

export FBTERM_BACKGROUND_IMAGE=1
cat nifty-background.fbimg > /dev/fb0; fbterm
terdon
  • 100,812
Foogod
  • 315
11

I can distinguish real text mode from its graphical emulation.

… which is one of the ways in which the observant could distinguish a real BSOD on Windows from the actions of the joke BSOD screen-saver that did the rounds a decade or so ago. The display of block graphics characters using the display adapter hardware in graphics mode was subtly different from the characters generated by the display adapter hardware in text mode.

Yes, the display adapter is in graphics mode. It has been this way for quite some while, now. It was always this way on systems without PC display adapter hardware. In the early years of Linux, on PC compatibles the console would have the display adapter hardware in text mode. But this use has quietly eroded to pretty much nothing. Unicode support for most users nowadays requires a bigger glyph set than the text-mode hardware has. The machine firmware (of course) uses graphics mode for splash screens (with pretty pictures and company logos), as does the Linux loader and system initialization.

There's a terminal emulator program built into the Linux kernel. It's layered on top of the framebuffer and the input event subsystem, which it uses internal kernel interfaces to access. It presents itself to application-mode systems as a series of kernel virtual terminal devices, /dev/tty1 and so forth.

This program is fairly limited compared to terminal emulators that run outwith the Linux kernel, as ordinary applications programs. It only emulates a limited subset of a real terminal's functionality, and it lacks the added features of the latter terminal emulators.

It is those that you need to look to for this. You may be familiar with the terminal emulators that use X for their input/output, such as xterm, lxterminal, gnome-console, konsole, eterm, wterm, and the rest. Less well known are the ones that use the framebuffer device(s) and the input event devices for their input/output. providing user-space virtual terminals:

Some of these latter can do what you want.

fbterm can be configured to use whatever is in the framebuffer at startup as a background image, for example. So all that one needs to do is use one of the several other utilities for displaying images directly to a Linux framebuffer deviceto set up a background image before running fbterm. There are several such tools, including:

fbvis and fbi clear the screen at exit, and require the convolutions that are explained in more detail in Foogod's answer. dfbg, though, doesn't clean up after itself, making it more suitable for this particular task.

Further reading

JdeBP
  • 3,959
  • The question asked on how to create background image for console. Your answer only lists potential solutions. Hence I award bounty to the other answer, however, I do thank you for the wealth of info you've provided. You have my upvote. – Sergiy Kolodyazhnyy Dec 05 '15 at 08:47
5

Although Foogod's answer didn't work for me, it did lead me into the right direction, by providing half of the solution (namely, reading framebuffer data, while fbi is showing an image on TTY screen). Therefore I've awarded his answer the bounty.

Bellow is a script that makes it easy to launch fbterm with partial path to image as a single command line argument

Usage

Script must be saved in a directory that is listed in your $PATH variable. Preferably it must be in your personal $HOME/bin folder. Refer to How to add a directory to the PATH? on explanation how to add your personal bin to $PATH, but creating a directory called bin in your home directory is sufficient to add it to PATH on re-login.

The script also must have executable permission; you can set it with chmod +x /path/to/script.sh.

Finally, it must be ran with sudo, to allow root access for reading and writing to /dev/fb0.

Script Source

Also available on my Github repository.

#!/bin/bash
# Author : Serg Kolo
# Date: Dec 5, 2015
# Description: Script to render image and set it as background
# in conjunction with fbterm
# Depends: fbterm,fbi, awk
# Written for: https://askubuntu.com/q/701874/295286

function printUsage
{
  echo "<<< Script to set background image in TTY console"
  echo "<<< Written by Serg Kolo, Dec 5 , 2015"
  echo "<<< Usage: scriptName.sh /path/to/image"
  echo "<<< Must be ran with root privileges, in TTY only"
  echo "exiting"

}

# check if we're root, if there's at least one ARG, and it is a TTY

if [ "$(whoami)" != "root"   ] || [ "$#" -eq 0  ] ||  [ "$( tty | awk '{gsub(/[[:digit:]]/,""); gsub(/\/dev\//,"");print}' )" != "tty"  ] ;then

   printUsage
   exit 1
fi



# read the full path of the image

IMAGE="$( readlink -f "$@" )"

# Launch fbi with whatever image was supplied as command line arg
# then take out whatever is the data in framebuffer;
# Store that data to /tmp folder

( sleep 1; cat /dev/fb0 > /tmp/BACKGROUND.fbimg ; sleep 1; pkill fbi ) & fbi -t 2 -1 --noverbose -a  "$IMAGE"

# This portion is really optional; you can comment it out 
# if you choose so

echo "LAUNCH FBTERM ?(y/n)"
read ANSWER

if [ "$ANSWER" != "y"  ] ; then
   echo exiting
   exit 1
fi

# The man page states that fbterm takes screenshot of 
# what is currently in framebuffer and sets it as background
# if FBTERM_BACKGROUND_IMAGE is set to 1
# Therefore the trick is to send the framebuffer data captured
# in the last step (which will display the image on screen)
# and then launch fbterm. Note, that I send output from the command
# send to background in order to avoid the extra text displayed on 
# screen. That way we have clear image in framebuffer, without 
# the shell text, when we launch fbterm

export FBTERM_BACKGROUND_IMAGE=1 
clear
( cat /tmp/BACKGROUND.fbimg  > /dev/fb0 &) > /dev/null; sleep 0.25; fbterm 

Additional info

It turns out that user doesn't necessarily need to use sudo; /dev/fb0 belongs to video group, so users could just add themselves to that group using

sudo usermod -a -G video $USER

Thus, the checks for root in the above script become obsolete, specifically [ "$(whoami)" != "root" ] || part.

muru
  • 197,895
  • 55
  • 485
  • 740
Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
0

Answers above worked for me

But need to specify device for fbi:

fbi -d /dev/fb0

In my case fbi was trying dri: /dev/dri/card0

For readability possible to use imagemagick:

convert -fill '#202020' -colorize 80% "$1" /tmp/background

This will imitate transparent background by converting image to overlayed with color #202020 with 80% visibility