bootsplash: Add ImageMagick voodoo

The JPEG decoder, that was added many years ago to display a boot-
splash in coreboot, has a few quirks. People used to do some voodoo
with GIMP to convert images to the right format, but we can also
achieve the same with ImageMagick's `convert`. The currently known
constraints are:
* The framebuffer's color format is ignored,
* only YCC 4:2:0 color sampling is supported, and
* width and height have to be a multiple of 16 pixels.

Beside that, we can only display the bootsplash if it completely
fits into the framebuffer. As the latter's size is often decided
at runtime, we can't do much more than offering an option to set
a specific size.

Change-Id: I564e0d89fb46503ff4c11e095726616700009968
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/76564
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
This commit is contained in:
Nico Huber 2023-07-16 19:24:13 +02:00 committed by Martin L Roth
parent 3bcb7619b4
commit 799e79d166
2 changed files with 100 additions and 1 deletions

View File

@ -356,6 +356,41 @@ cbfs-files-processor-struct= \
rm -f $(2).tmp) \
$(eval DEPENDENCIES += $(2).d)
#######################################################################
# Convert image to YCC 4:2:0 JPEG
#
# In two steps:
# 1. Convert to RGB colors, optionally resize and store as BMP.
# 2. Round final size to multiples of 16, optionally swap colors,
# convert (back) to sRGB and store as JPEG.
# The split is necessary because we don't know the exact, scaled
# size due to aspect-ratio. Note: IM v7 would allow us to do the
# calculations in one command using %[fx:...] syntax.
#
# arg1: image input file
# arg2: output jpg
cbfs-files-processor-jpg420= \
$(eval $(2): $(1) $(KCONFIG_AUTOCONFIG); \
printf " CONVERT $$<\n"; \
res=$(CONFIG_BOOTSPLASH_CONVERT_RESOLUTION); \
res=$$$$(convert $$< \
-colorspace RGB \
$$(BOOTSPLASH_RESIZE-y) \
-format '%wx%h' -write info: \
bmp:$$@); \
convert $$@ \
$$(BOOTSPLASH_ROUND16) \
$$(BOOTSPLASH_COLORSWAP-y) \
-colorspace sRGB \
-quality $$(CONFIG_BOOTSPLASH_CONVERT_QUALITY)% \
-interlace none -colorspace YCC -sampling-factor 4:2:0 \
jpg:$$@)
BOOTSPLASH_FLOOR = $$(($${res%%x*} & ~15))x$$(($${res\#\#*x} & ~15))
BOOTSPLASH_RESIZE-$(CONFIG_BOOTSPLASH_CONVERT_RESIZE) = -resize $(BOOTSPLASH_FLOOR)
BOOTSPLASH_CEIL = $$((($${res%%x*} + 15) & ~15))x$$((($${res\#\#*x} + 15) & ~15))
BOOTSPLASH_ROUND16 = -background black -gravity center -extent $(BOOTSPLASH_CEIL)
BOOTSPLASH_COLORSWAP-$(CONFIG_BOOTSPLASH_CONVERT_COLORSWAP) := -channel-fx 'red<=>blue'
#######################################################################
# Add handler for arbitrary files in CBFS
$(call add-special-class,cbfs-files)
@ -1281,10 +1316,19 @@ cbfs-files-y += build_info
build_info-file := $(obj)/build_info
build_info-type := raw
ifeq ($(CONFIG_BOOTSPLASH_CONVERT),y)
ifeq ($(shell command -v convert),)
$(error CONFIG_BOOTSPLASH_CONVERT requires the convert program (part of ImageMagick))
endif
cbfs-files-$(CONFIG_BOOTSPLASH_IMAGE) += bootsplash.jpg
bootsplash.jpg-file := $(call strip_quotes,$(CONFIG_BOOTSPLASH_FILE)):jpg420
bootsplash.jpg-type := bootsplash
else
BOOTSPLASH_SUFFIX=$(suffix $(call strip_quotes,$(CONFIG_BOOTSPLASH_FILE)))
cbfs-files-$(CONFIG_BOOTSPLASH_IMAGE) += bootsplash$(BOOTSPLASH_SUFFIX)
bootsplash$(BOOTSPLASH_SUFFIX)-file := $(call strip_quotes,$(CONFIG_BOOTSPLASH_FILE))
bootsplash$(BOOTSPLASH_SUFFIX)-type := bootsplash
endif
# Ensure that no payload segment overlaps with memory regions used by ramstage
# (not for x86 since it can relocate itself in that case)

View File

@ -447,7 +447,54 @@ config BOOTSPLASH_FILE
# Default value set at the end of the file
help
The path and filename of the file to use as graphical bootsplash
screen. The file format has to be jpg.
screen. The file format has to be JPEG with YCC 4:2:0 color sampling
unless converted with "Pre-process bootsplash file with ImageMagick".
The image can only be displayed by coreboot if it's smaller or has
the same size as the framebuffer resolution. Width and height have
to be a multiple of 16 pixels.
Setting these constraints allows a leaner implementation in coreboot.
The minimum necessary ImageMagick command line seems to be:
$ convert input.img -colorspace YCC -sampling-factor 4:2:0 bootsplash.jpg
config BOOTSPLASH_CONVERT
bool "Pre-process bootsplash file with ImageMagick"
depends on BOOTSPLASH_IMAGE
help
Use ImageMagick (`convert` program) to convert a bootsplash image
to the supported JPEG format.
config BOOTSPLASH_CONVERT_QUALITY
int "Bootsplash JPEG target quality (%)"
depends on BOOTSPLASH_CONVERT
range 1 100
# Default value set at the end of the file
config BOOTSPLASH_CONVERT_RESIZE
bool "Resize bootsplash image"
depends on BOOTSPLASH_CONVERT
help
Resize the image to the given resolution. Aspect ratio will be kept,
adding black bars as necessary.
config BOOTSPLASH_CONVERT_RESOLUTION
string "Bootsplash image target size"
depends on BOOTSPLASH_CONVERT_RESIZE
# Default value set at the end of the file
help
Target image resolution given as <width>x<height>, e.g. 1024x768.
Values not divisible by 16 will be rounded down.
When using coreboot to display the bootsplash image (CONFIG_BOOTSPLASH),
set this lower or equal to the minimum resolution you expect.
config BOOTSPLASH_CONVERT_COLORSWAP
bool "Swap red and blue color channels"
depends on BOOTSPLASH_CONVERT
help
The JPEG decoder currently ignores the framebuffer color order.
If your colors seem all wrong, try this option.
config FW_CONFIG
bool "Firmware Configuration Probing"
@ -1444,6 +1491,14 @@ config BOOTSPLASH_FILE
depends on BOOTSPLASH_IMAGE
default "bootsplash.jpg"
config BOOTSPLASH_CONVERT_QUALITY
depends on BOOTSPLASH_CONVERT
default 80
config BOOTSPLASH_CONVERT_RESOLUTION
depends on BOOTSPLASH_CONVERT_RESIZE
default "1024x768"
config CBFS_SIZE
default ROM_SIZE