Skip to content

Display images on a screen without X. Use a Raspberry Pi to show a slideshow on your TV, controlled by a shell script.

License

Notifications You must be signed in to change notification settings

ryanrsrs/console-jpeg

Repository files navigation

console-jpeg
============

Console-jpeg is a simple program to display images on a screen, without X.
It can be used to make a digital picture frame or show a slideshow.

When console-jpeg exits, the screen reverts to whatever it was showing before,
such as a login prompt or a bunch of printks. Console-jpeg never leaves an
image on the screen after it exits.

Capabilities:
 - Show an image on the screen.
 - Fill the screen with a solid color.
 - Sleep/wake the display on command.

Requires:
    libdrm-dev
    libturbojpeg0-dev
    libspng-dev
    libheif-dev[*]

* libheif is optional. Uncomment the relevant lines in the Makefile.

Builds with gcc or clang. Optimized SIMD code on arm, aarch64, and x86-64.

Major goals for development were simplicity, few dependencies, and easy
integration with shell scripts and other command line tools.


---------------------------------------------------------------------------
Note: Console-jpeg will probably NOT work on your nVidia or AMD discrete
GPU. It was written and tested on ARM SBCs with unified memory integrated
graphics like the Raspberry Pi.
---------------------------------------------------------------------------


Usage:
    ./your_script | console-jpeg [options] [commands]


Options:

-l, --list
    List all available outputs. Pass the output number to --out=N.

-v, --verbose
    Print details about image dimensions and performance timing.

--dev=/dev/dri/card1
    Specify device (rarely needed!)

    Normally, console-jpeg looks at every device, filtering out the render-
    only nodes, and enumerating the connectors on all mode-setting / frame
    buffer nodes. This is important because the card numbers are dynamically
    assigned at boot and NOT consistent from boot-to-boot. Usually specifying
    the output using only --out=N is the best way to get the same monitor
    every time.

--out=N
    Use output connector N. See: --list.



Commands:

    Commands passed as command line arguments are run first. After that,
    commands are read from stdin.

bgcolor:ffffff
    Set the background color to hex RGB. This affects the color of borders
    around jpegs and the color of the clear command. This command does not
    change what is currently on the screen.

clear
    Fill screen with bgcolor.

black
white
    Fill screen with black or white.

jpeg:filename.jpg
filename.jpg
    Display a jpeg. The image is roughly scaled to fit the screen, using
    libjpegturbo's scaling code. Libjpegturbo supports scale factors from
    1/8 - 2x, in multiples of 1/8. Console-jpeg picks the largest scale factor
    that gives an image <= the screen size. Any remaining border around the
    image is filled with bgcolor. The "jpeg:" prefix is optional.

heif:pic.heic
pic.heic

png:pic.png
pic.png
    HEIF and PNG files are supported, too.

flip
    Flip the double buffers without drawing anything. This lets you quickly
    go back and forth between the last two images, without decoding the files
    again. Good for A/B image comparisons.

wait:1.5
    Pause this many seconds.

halt
    Pause forever. (Ctrl-C to quit)

exit
    Quit program. Use this as the final command line argument if you don't
    want console-jpeg to read commands from stdin.

sleep
    Put the display to sleep (power down). Wake it up with clear, black,
    white, or a jpeg.



Large Images
============
Console-jpeg can use a lot of memory for large images. A 10 megapixel
progressive jpeg may require 100 MB of RAM to decode, resize, and display.

On the other hand, very large non-progressive jpegs can be decoded and resized
without ever constructing the full resolution raw image. For example, a 505 MP
31,800 x 15,900 jpeg can be decoded at 1/8 scale to 3,975 x 1,988, then
resized to 1920 x 960 for display. For a non-progressive jpeg, this takes less
than 100 MB of RAM and executes in 9 seconds on a Raspberry Pi 2 W.

If you give console-jpeg a very large jpeg, it may try to allocate more memory
than is available (esp on a 512MB RPI Zero). If the allocation fails,
console-jpeg will report the error. But the allocation may not fail, and
Raspberry OS might decide to start swapping to a microSD card. This is very
bad for system performance (and not great for the sd card). You may need to
power-cycle your Pi to recover control.

The solution is to use prlimit to restrict console-jpeg's resource usage:

$ prlimit -d=100000000 ./console-jpeg test.jpg
This command limits console-jpeg to 100 MB of RAM, which is enough to decode
most jpegs. Tune the value to suit your images and hardware.

$ prlimit -d=350000000 ./console-jpeg iphone.heic
350 MB is just enough to decode 45 MP photos from the latest iPhone 15.


Recipes & Examples
==================

Show a jpeg:
    $ console-jpeg filename.jpg

    Type exit or ctrl+D or ctrl+C to exit program.


Slideshow. Show every jpeg in a directory for 5 seconds:
    printf '%s\nwait:5\n' *.jpg | console-jpeg


Same slideshow, but the script uses sleep for pacing:
    (for x in *.jpg; do echo "$x"; sleep 5; done) | console-jpeg


Press enter to show the next image:
    (for x in *.jpg; do echo "$x"; read; done) | ./console-jpeg


Zoneminder camera snapshot every ~5 secs:
    ZM_URL="http://192.168.1.1/cgi-bin/nph-zms?mode=single&monitor=1"
    ZM_PIC="/tmp/zm-pic.jpg"
    (while curl -sSo "$ZM_PIC" "$ZM_URL"; do echo "$ZM_PIC"; sleep 5; done) \
        | console-jpeg


Put the display to sleep for 10 seconds:
    console-jpeg sleep wait:10 exit


Display PDFs 2-up and anti-aliased using pdfjam and ghostscript
---------------------------------------------------------------

Requires:
    ghostscript
    texlive-extra-utils

sudo apt install ghostscript texlive-extra-utils

# Select pages 17 and 18. Set papersize to display res/10 mm (254 dpi)
# e.g. 1920x1200 -> '{192mm,120mm}'
pdfjam ltc3309a.pdf '17,18' --nup 2x1 --papersize '{192mm,120mm}' \
    --outfile out.pdf

# Render at 2x dpi, so that console-jpeg will do a 2:1 shrink, which looks
# slightly better than ghostscript's alphaBits=4 output, imo.
gs -dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -r508 -dTextAlphaBits=4 \
        -dGraphicsAlphaBits=4 -sOutputFile=out.png out.pdf

console-jpeg out.png



License
=======

MIT License. See file LICENSE in this directory.



Author
======

Ryan Salsbury
[email protected]

About

Display images on a screen without X. Use a Raspberry Pi to show a slideshow on your TV, controlled by a shell script.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published