From 3b1314102f8bca587008c5919f48633d01e9ab47 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Wed, 13 Apr 2022 23:04:42 +0200 Subject: [PATCH] Kitty graphics initial support --- CMakeLists.txt | 8 +++-- README.md | 2 +- src/data/config.txt | 2 +- src/data/help.txt | 3 +- src/fastfetch.c | 7 ++++ src/fastfetch.h | 1 + src/logo/image/im6.c | 20 +++++++++++ src/logo/image/im7.c | 20 +++++++++++ src/logo/{sixel/sixel.c => image/image.c} | 44 ++++++++++++++++------- src/logo/{sixel/sixel.h => image/image.h} | 11 +++--- src/logo/logo.c | 8 ++--- src/logo/logo.h | 4 +-- src/logo/sixel/im6.c | 31 ---------------- src/logo/sixel/im7.c | 30 ---------------- 14 files changed, 100 insertions(+), 91 deletions(-) create mode 100644 src/logo/image/im6.c create mode 100644 src/logo/image/im7.c rename src/logo/{sixel/sixel.c => image/image.c} (76%) rename src/logo/{sixel/sixel.h => image/image.h} (65%) delete mode 100644 src/logo/sixel/im6.c delete mode 100644 src/logo/sixel/im7.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 85bce946d..8ee5be415 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,9 +113,9 @@ add_library(libfastfetch STATIC src/common/networking.c src/logo/logo.c src/logo/builtin.c - src/logo/sixel/sixel.c - src/logo/sixel/im7.c - src/logo/sixel/im6.c + src/logo/image/image.c + src/logo/image/im7.c + src/logo/image/im6.c src/detection/os.c src/detection/plasma.c src/detection/gtk.c @@ -418,6 +418,8 @@ set(CPACK_DEBIAN_PACKAGE_RECOMMENDS " libglib2.0-0 libdbus-1-3 libxfconf-0-3 + libmagickcore-6.q16hdri-6 + libmagickcore-6.q16-6 ") set(CPACK_RPM_PACKAGE_LICENSE "MIT") diff --git a/README.md b/README.md index 05d3ba2f2..2c74fbf70 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ The following libraries are used if present at runtime: * [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor. * [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings. * [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings. -* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel +* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol. * [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song. * [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font. * [`librpm`](http://rpm.org/): Needed for rpm package count. diff --git a/src/data/config.txt b/src/data/config.txt index 30fa02224..bb6ab565b 100644 --- a/src/data/config.txt +++ b/src/data/config.txt @@ -61,7 +61,7 @@ # Logo type option: # Sets the logo type to use. -# Must be auto, builtin, file, raw or sixel. +# Must be auto, builtin, file, raw, sixel or kitty. # Default is auto. #--logo-type auto diff --git a/src/data/help.txt b/src/data/help.txt index a06bde090..f91bceb56 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -21,7 +21,7 @@ General options: Logo options: -l,--logo : set the logo to use. The type is specified by --logo-type. If default: the name of a builtin logo or a path to a file - --logo-type : set the type of the logo given. Must be auto, builtin, file, raw or sixel + --logo-type : set the type of the logo given. Must be auto, builtin, file, raw, sixel or kitty. --logo-width : set the width of the logo (in characters), if it is an image --logo-color-[1-9] : overwrite a color in the logo --logo-padding : set the padding on the left and the right of the logo @@ -29,6 +29,7 @@ Logo options: --logo-padding-right : set the padding on the right of the logo --logo-print-remaining : weather to print the remaining logo, if it has more lines than modules to display --sixel : short for --logo-type sixel --logo + --kitty : short for --logo-type kitty --logo Display options: -s,--structure : sets the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available. diff --git a/src/fastfetch.c b/src/fastfetch.c index 1f5e45f14..3389d5676 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -733,6 +733,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.logoType = FF_LOGO_TYPE_RAW; else if(strcasecmp(value, "sixel") == 0) instance->config.logoType = FF_LOGO_TYPE_SIXEL; + else if(strcasecmp(value, "kitty") == 0) + instance->config.logoType = FF_LOGO_TYPE_KITTY; else { fprintf(stderr, "Error: unknown logo type: %s\n", value); @@ -772,6 +774,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseString(key, value, &instance->config.logoName); instance->config.logoType = FF_LOGO_TYPE_SIXEL; } + else if(strcasecmp(key, "--kitty") == 0) + { + optionParseString(key, value, &instance->config.logoName); + instance->config.logoType = FF_LOGO_TYPE_KITTY; + } /////////////////// //Display options// diff --git a/src/fastfetch.h b/src/fastfetch.h index 7b80a14e4..ddad19804 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -38,6 +38,7 @@ typedef enum FFLogoType FF_LOGO_TYPE_FILE, //Raw text file, printed as is. FF_LOGO_TYPE_RAW, //Raw text file, printed with color codes replacement. FF_LOGO_TYPE_SIXEL, //Image file, printed as sixel codes. + FF_LOGO_TYPE_KITTY //Image file, printed as kitty graphics protocol } FFLogoType; typedef struct FFconfig diff --git a/src/logo/image/im6.c b/src/logo/image/im6.c new file mode 100644 index 000000000..dcad96bc9 --- /dev/null +++ b/src/logo/image/im6.c @@ -0,0 +1,20 @@ +#ifdef FF_HAVE_IMAGEMAGICK6 + +#include "image.h" +#include + +static FF_LIBRARY_SYMBOL(ResizeImage); + +static void* logoResize(const void* image, size_t width, size_t height, void* exceptionInfo) +{ + return ffResizeImage(image, width, height, UndefinedFilter, 1.0, exceptionInfo); +} + +FFLogoImageResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoType type) +{ + FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_SIXEL_RESULT_INIT_ERROR, "libMagickCore-6.Q16HDRI.so", 8, "libMagickCore-6.Q16.so", 8) + FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR); + return ffLogoPrintImageImpl(instance, imageMagick, logoResize, type); +} + +#endif diff --git a/src/logo/image/im7.c b/src/logo/image/im7.c new file mode 100644 index 000000000..6f82d1c25 --- /dev/null +++ b/src/logo/image/im7.c @@ -0,0 +1,20 @@ +#ifdef FF_HAVE_IMAGEMAGICK7 + +#include "image.h" +#include + +static FF_LIBRARY_SYMBOL(ResizeImage); + +static void* logoResize(const void* image, size_t width, size_t height, void* exceptionInfo) +{ + return ffResizeImage(image, width, height, UndefinedFilter, exceptionInfo); +} + +FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoType type) +{ + FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_SIXEL_RESULT_INIT_ERROR, "libMagickCore-7.Q16HDRI.so", 11, "libMagickCore-7.Q16.so", 11) + FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR); + return ffLogoPrintImageImpl(instance, imageMagick, logoResize, type); +} + +#endif diff --git a/src/logo/sixel/sixel.c b/src/logo/image/image.c similarity index 76% rename from src/logo/sixel/sixel.c rename to src/logo/image/image.c index e3f7f3890..212cef841 100644 --- a/src/logo/sixel/sixel.c +++ b/src/logo/image/image.c @@ -1,4 +1,4 @@ -#include "sixel.h" +#include "image.h" #if defined(FF_HAVE_IMAGEMAGICK7) || defined(FF_HAVE_IMAGEMAGICK6) @@ -9,7 +9,7 @@ #include #endif -FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* imageMagick, FFLogoIMResizeFunc resizeFunc, FFLogoIMWriteFunc writeFunc) +FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick, FFLogoIMResizeFunc resizeFunc, FFLogoType type) { struct winsize winsize; if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != 0) @@ -22,6 +22,8 @@ FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* imageMagick, FF_LIBRARY_LOAD_SYMBOL(imageMagick, CopyMagickString, FF_LOGO_SIXEL_RESULT_INIT_ERROR) FF_LIBRARY_LOAD_SYMBOL(imageMagick, ReadImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR) FF_LIBRARY_LOAD_SYMBOL(imageMagick, DestroyImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR) + FF_LIBRARY_LOAD_SYMBOL(imageMagick, ImageToBlob, FF_LOGO_SIXEL_RESULT_INIT_ERROR) + FF_LIBRARY_LOAD_SYMBOL(imageMagick, Base64Encode, FF_LOGO_SIXEL_RESULT_INIT_ERROR) ExceptionInfo* exceptionInfo = ffAcquireExceptionInfo(); if(exceptionInfo == NULL) @@ -83,20 +85,37 @@ FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* imageMagick, return FF_LOGO_SIXEL_RESULT_RUN_ERROR; } - ffPrintCharTimes(' ', instance->config.logoPaddingLeft); + if(type == FF_LOGO_TYPE_SIXEL) + ffCopyMagickString(imageInfoOut->magick, "SIXEL", 6); + else //Kitty + ffCopyMagickString(imageInfoOut->magick, "RGBA", 5); - imageInfoOut->file = stdout; - ffCopyMagickString(imageInfoOut->magick, "SIXEL", 6); - - MagickBooleanType writeResult = writeFunc(resizedImage, imageInfoOut, exceptionInfo) ? MagickTrue : MagickFalse; + size_t length; + void* data = ffImageToBlob(imageInfoOut, resizedImage, &length, exceptionInfo); ffDestroyImageInfo(imageInfoOut); ffDestroyImage(resizedImage); ffDestroyExceptionInfo(exceptionInfo); dlclose(imageMagick); - if(writeResult == MagickFalse) - return FF_LOGO_SIXEL_RESULT_RUN_ERROR; + if(data == NULL || length == 0) + return false; + + ffPrintCharTimes(' ', instance->config.logoPaddingLeft); + + if(type == FF_LOGO_TYPE_KITTY) + { + void* encoded = ffBase64Encode(data, length, &length); + free(data); + data = encoded; + printf("\033_Ga=T,f=32,s=%u,v=%u;", (uint32_t) imagePixelWidth, (uint32_t) imagePixelHeight); + } + + fwrite(data, sizeof(char), length, stdout); + free(data); + + if(type == FF_LOGO_TYPE_KITTY) + fputs("\033\\", stdout); instance->state.logoHeight = (uint32_t) (imagePixelHeight / characterPixelHeight); instance->state.logoWidth = instance->config.logoWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight; @@ -106,16 +125,17 @@ FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* imageMagick, return FF_LOGO_SIXEL_RESULT_SUCCESS; } + #endif -bool ffLogoPrintSixelIfExists(FFinstance* instance) +bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type) { #if !defined(FF_HAVE_IMAGEMAGICK7) && !defined(FF_HAVE_IMAGEMAGICK6) FF_UNUSED(instance); #endif #ifdef FF_HAVE_IMAGEMAGICK7 - FFLogoSixelResult result = ffLogoPrintSixelIM7(instance); + FFLogoImageResult result = ffLogoPrintImageIM7(instance, type); if(result == FF_LOGO_SIXEL_RESULT_SUCCESS) return true; else if(result == FF_LOGO_SIXEL_RESULT_RUN_ERROR) @@ -123,7 +143,7 @@ bool ffLogoPrintSixelIfExists(FFinstance* instance) #endif #ifdef FF_HAVE_IMAGEMAGICK6 - return ffLogoPrintSixelIM6(instance) == FF_LOGO_SIXEL_RESULT_SUCCESS; + return ffLogoPrintImageIM6(instance, type) == FF_LOGO_SIXEL_RESULT_SUCCESS; #endif return false; diff --git a/src/logo/sixel/sixel.h b/src/logo/image/image.h similarity index 65% rename from src/logo/sixel/sixel.h rename to src/logo/image/image.h index e2c238a85..bf4605072 100644 --- a/src/logo/sixel/sixel.h +++ b/src/logo/image/image.h @@ -13,27 +13,26 @@ #define MAGICKCORE_HDRI_ENABLE 1 #define MAGICKCORE_QUANTUM_DEPTH 16 -typedef enum FFLogoSixelResult +typedef enum FFLogoImageResult { FF_LOGO_SIXEL_RESULT_SUCCESS, //Logo printed FF_LOGO_SIXEL_RESULT_INIT_ERROR, //Failed to load library, try again with next IM version FF_LOGO_SIXEL_RESULT_RUN_ERROR //Failed to load / convert image, cancle whole sixel code -} FFLogoSixelResult; +} FFLogoImageResult; typedef void*(*FFLogoIMResizeFunc)(const void* image, size_t width, size_t height, void* exceptionInfo); -typedef bool(*FFLogoIMWriteFunc)(void* image, const void* imageInfo, void* exceptionInfo); -FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* library, FFLogoIMResizeFunc resizeFunc, FFLogoIMWriteFunc writeFunc); +FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* library, FFLogoIMResizeFunc resizeFunc, FFLogoType type); #endif #ifdef FF_HAVE_IMAGEMAGICK7 -FFLogoSixelResult ffLogoPrintSixelIM7(FFinstance* instance); +FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoType type); #endif #ifdef FF_HAVE_IMAGEMAGICK6 #include -FFLogoSixelResult ffLogoPrintSixelIM6(FFinstance* instance); +FFLogoSixelResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoType type); #endif diff --git a/src/logo/logo.c b/src/logo/logo.c index 22f504219..7fe826b69 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -162,7 +162,7 @@ static void logoPrintDetected(FFinstance* instance) { if( !ffLogoPrintBuiltinIfExists(instance) && - !ffLogoPrintSixelIfExists(instance) + !ffLogoPrintImageIfExists(instance, FF_LOGO_TYPE_KITTY) ) logoPrintFile(instance, true); return; } @@ -188,10 +188,10 @@ void ffPrintLogo(FFinstance* instance) logoPrintFile(instance, true); else if(instance->config.logoType == FF_LOGO_TYPE_RAW) logoPrintFile(instance, false); - else if(instance->config.logoType == FF_LOGO_TYPE_SIXEL) + else if(instance->config.logoType == FF_LOGO_TYPE_SIXEL || instance->config.logoType == FF_LOGO_TYPE_KITTY) { - if(!ffLogoPrintSixelIfExists(instance)) - ffLogoPrintUnknown(instance); + if(!ffLogoPrintImageIfExists(instance, instance->config.logoType)) + ffLogoPrintBuiltinDetected(instance); } else logoPrintDetected(instance); diff --git a/src/logo/logo.h b/src/logo/logo.h index 3ff2c39bd..02d4ba363 100644 --- a/src/logo/logo.h +++ b/src/logo/logo.h @@ -16,7 +16,7 @@ void ffLogoPrintBuiltin(FFinstance* instance); bool ffLogoPrintBuiltinIfExists(FFinstance* instance); void ffLogoPrintBuiltinDetected(FFinstance* instance); -//sixel/sixel.c -bool ffLogoPrintSixelIfExists(FFinstance* instance); +//sixel/image.c +bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type); #endif diff --git a/src/logo/sixel/im6.c b/src/logo/sixel/im6.c deleted file mode 100644 index d21a19753..000000000 --- a/src/logo/sixel/im6.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "sixel.h" - -#ifdef FF_HAVE_IMAGEMAGICK6 - -#include - -static FF_LIBRARY_SYMBOL(ResizeImage); -static FF_LIBRARY_SYMBOL(WriteImage); - -static void* logoResizeIM6(const void* image, size_t width, size_t height, void* exceptionInfo) -{ - return ffResizeImage(image, width, height, UndefinedFilter, 1.0, exceptionInfo); -} - -static bool logoWriteIM6(void* image, const void* imageInfo, void* exceptionInfo) -{ - FF_UNUSED(exceptionInfo); - return ffWriteImage(imageInfo, image) == MagickTrue; -} - -FFLogoSixelResult ffLogoPrintSixelIM6(FFinstance* instance) -{ - FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_SIXEL_RESULT_INIT_ERROR, "libMagickCore-6.Q16HDRI.so", 8, "libMagickCore-6.Q16.so", 8) - - FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR); - FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffWriteImage, WriteImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR); - - return ffLogoPrintSixelImpl(instance, imageMagick, logoResizeIM6, logoWriteIM6); -} - -#endif diff --git a/src/logo/sixel/im7.c b/src/logo/sixel/im7.c deleted file mode 100644 index ddaa2eeb3..000000000 --- a/src/logo/sixel/im7.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "sixel.h" - -#ifdef FF_HAVE_IMAGEMAGICK7 - -#include - -static FF_LIBRARY_SYMBOL(ResizeImage); -static FF_LIBRARY_SYMBOL(WriteImage); - -static void* logoResizeIM7(const void* image, size_t width, size_t height, void* exceptionInfo) -{ - return ffResizeImage(image, width, height, UndefinedFilter, exceptionInfo); -} - -static bool logoWriteIM7(void* image, const void* imageInfo, void* exceptionInfo) -{ - return ffWriteImage(imageInfo, image, exceptionInfo) == MagickTrue; -} - -FFLogoSixelResult ffLogoPrintSixelIM7(FFinstance* instance) -{ - FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_SIXEL_RESULT_INIT_ERROR, "libMagickCore-7.Q16HDRI.so", 11, "libMagickCore-7.Q16.so", 11) - - FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR); - FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffWriteImage, WriteImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR); - - return ffLogoPrintSixelImpl(instance, imageMagick, logoResizeIM7, logoWriteIM7); -} - -#endif