From 0c9e832ea1fe321737b1980588407f283ec92ef2 Mon Sep 17 00:00:00 2001
From: Nico Huber <nico.h@gmx.de>
Date: Sun, 16 Jul 2023 19:24:13 +0200
Subject: [PATCH] bootsplash: Add ImageMagick voodoo

Ta-da!

(commit message tbd)

Change-Id: I564e0d89fb46503ff4c11e095726616700009968
Signed-off-by: Nico Huber <nico.h@gmx.de>
---

diff --git a/Makefile.inc b/Makefile.inc
index 0d38ea3..5e1dcee 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -357,6 +357,24 @@
 	$(eval DEPENDENCIES += $(2).d)
 
 #######################################################################
+# Convert image to YCC 4:2:0 JPEG
+# arg1: image input file
+# arg2: output jpg
+cbfs-files-processor-jpg420= \
+	$(eval $(2): $(1) $(KCONFIG_AUTOCONFIG); \
+		printf "    CONVERT    $$<\n";  \
+		convert $$< $(BOOTSPLASH_RESIZE-y) $(BOOTSPLASH_COLORSWAP-y) \
+			-quality $(CONFIG_BOOTSPLASH_CONVERT_QUALITY)%  \
+			-interlace none -colorspace YCC -sampling-factor 4:2:0 \
+			jpg:$$@)
+BOOTSPLASH_RESOLUTION = $(shell res=$(CONFIG_BOOTSPLASH_CONVERT_RESOLUTION); \
+				echo $$(($${res%%x*}/16*16))x$$(($${res##*x}/16*16)) 2>/dev/null)
+BOOTSPLASH_RESIZE-$(CONFIG_BOOTSPLASH_CONVERT_RESIZE) =    \
+	-resize $(BOOTSPLASH_RESOLUTION) -background black \
+	-gravity center -extent $(BOOTSPLASH_RESOLUTION)
+BOOTSPLASH_COLORSWAP-$(CONFIG_BOOTSPLASH_CONVERT_COLORSWAP) := -channel-fx 'red<=>blue'
+
+#######################################################################
 # Add handler for arbitrary files in CBFS
 $(call add-special-class,cbfs-files)
 cbfs-files-handler= \
@@ -1281,10 +1299,16 @@
 build_info-file := $(obj)/build_info
 build_info-type := raw
 
+ifeq ($(CONFIG_BOOTSPLASH_CONVERT),y)
+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)
diff --git a/src/Kconfig b/src/Kconfig
index f5ba4fc..e906130 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -447,7 +447,52 @@
 	# 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
+	# Default value set at the end of the file
+	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.
+
+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 +1489,18 @@
 	depends on BOOTSPLASH_IMAGE
 	default "bootsplash.jpg"
 
+config BOOTSPLASH_CONVERT
+	depends on BOOTSPLASH_IMAGE
+	default y
+
+config BOOTSPLASH_CONVERT_QUALITY
+	depends on BOOTSPLASH_CONVERT
+	default 70
+
+config BOOTSPLASH_CONVERT_RESOLUTION
+	depends on BOOTSPLASH_CONVERT_RESIZE
+	default "1024x768"
+
 config CBFS_SIZE
 	default ROM_SIZE
 
