Skip to content

Commit 3b13141

Browse files
Kitty graphics initial support
1 parent d349b7f commit 3b13141

File tree

14 files changed

+100
-91
lines changed

14 files changed

+100
-91
lines changed

CMakeLists.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ add_library(libfastfetch STATIC
113113
src/common/networking.c
114114
src/logo/logo.c
115115
src/logo/builtin.c
116-
src/logo/sixel/sixel.c
117-
src/logo/sixel/im7.c
118-
src/logo/sixel/im6.c
116+
src/logo/image/image.c
117+
src/logo/image/im7.c
118+
src/logo/image/im6.c
119119
src/detection/os.c
120120
src/detection/plasma.c
121121
src/detection/gtk.c
@@ -418,6 +418,8 @@ set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "
418418
libglib2.0-0
419419
libdbus-1-3
420420
libxfconf-0-3
421+
libmagickcore-6.q16hdri-6
422+
libmagickcore-6.q16-6
421423
")
422424

423425
set(CPACK_RPM_PACKAGE_LICENSE "MIT")

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ The following libraries are used if present at runtime:
2828
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor.
2929
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
3030
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
31-
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel
31+
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
3232
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
3333
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
3434
* [`librpm`](http://rpm.org/): Needed for rpm package count.

src/data/config.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161

6262
# Logo type option:
6363
# Sets the logo type to use.
64-
# Must be auto, builtin, file, raw or sixel.
64+
# Must be auto, builtin, file, raw, sixel or kitty.
6565
# Default is auto.
6666
#--logo-type auto
6767

src/data/help.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@ General options:
2121

2222
Logo options:
2323
-l,--logo <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
24-
--logo-type <type>: set the type of the logo given. Must be auto, builtin, file, raw or sixel
24+
--logo-type <type>: set the type of the logo given. Must be auto, builtin, file, raw, sixel or kitty.
2525
--logo-width <width>: set the width of the logo (in characters), if it is an image
2626
--logo-color-[1-9] <color>: overwrite a color in the logo
2727
--logo-padding <padding>: set the padding on the left and the right of the logo
2828
--logo-padding-left <padding>: set the padding on the left of the logo
2929
--logo-padding-right <padding>: set the padding on the right of the logo
3030
--logo-print-remaining <?value>: weather to print the remaining logo, if it has more lines than modules to display
3131
--sixel <file>: short for --logo-type sixel --logo <file>
32+
--kitty <file>: short for --logo-type kitty --logo <file>
3233

3334
Display options:
3435
-s,--structure <structure>: sets the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.

src/fastfetch.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
733733
instance->config.logoType = FF_LOGO_TYPE_RAW;
734734
else if(strcasecmp(value, "sixel") == 0)
735735
instance->config.logoType = FF_LOGO_TYPE_SIXEL;
736+
else if(strcasecmp(value, "kitty") == 0)
737+
instance->config.logoType = FF_LOGO_TYPE_KITTY;
736738
else
737739
{
738740
fprintf(stderr, "Error: unknown logo type: %s\n", value);
@@ -772,6 +774,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
772774
optionParseString(key, value, &instance->config.logoName);
773775
instance->config.logoType = FF_LOGO_TYPE_SIXEL;
774776
}
777+
else if(strcasecmp(key, "--kitty") == 0)
778+
{
779+
optionParseString(key, value, &instance->config.logoName);
780+
instance->config.logoType = FF_LOGO_TYPE_KITTY;
781+
}
775782

776783
///////////////////
777784
//Display options//

src/fastfetch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ typedef enum FFLogoType
3838
FF_LOGO_TYPE_FILE, //Raw text file, printed as is.
3939
FF_LOGO_TYPE_RAW, //Raw text file, printed with color codes replacement.
4040
FF_LOGO_TYPE_SIXEL, //Image file, printed as sixel codes.
41+
FF_LOGO_TYPE_KITTY //Image file, printed as kitty graphics protocol
4142
} FFLogoType;
4243

4344
typedef struct FFconfig

src/logo/image/im6.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifdef FF_HAVE_IMAGEMAGICK6
2+
3+
#include "image.h"
4+
#include <magick/MagickCore.h>
5+
6+
static FF_LIBRARY_SYMBOL(ResizeImage);
7+
8+
static void* logoResize(const void* image, size_t width, size_t height, void* exceptionInfo)
9+
{
10+
return ffResizeImage(image, width, height, UndefinedFilter, 1.0, exceptionInfo);
11+
}
12+
13+
FFLogoImageResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoType type)
14+
{
15+
FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_SIXEL_RESULT_INIT_ERROR, "libMagickCore-6.Q16HDRI.so", 8, "libMagickCore-6.Q16.so", 8)
16+
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR);
17+
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, type);
18+
}
19+
20+
#endif

src/logo/image/im7.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifdef FF_HAVE_IMAGEMAGICK7
2+
3+
#include "image.h"
4+
#include <MagickCore/MagickCore.h>
5+
6+
static FF_LIBRARY_SYMBOL(ResizeImage);
7+
8+
static void* logoResize(const void* image, size_t width, size_t height, void* exceptionInfo)
9+
{
10+
return ffResizeImage(image, width, height, UndefinedFilter, exceptionInfo);
11+
}
12+
13+
FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoType type)
14+
{
15+
FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_SIXEL_RESULT_INIT_ERROR, "libMagickCore-7.Q16HDRI.so", 11, "libMagickCore-7.Q16.so", 11)
16+
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR);
17+
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, type);
18+
}
19+
20+
#endif
Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "sixel.h"
1+
#include "image.h"
22

33
#if defined(FF_HAVE_IMAGEMAGICK7) || defined(FF_HAVE_IMAGEMAGICK6)
44

@@ -9,7 +9,7 @@
99
#include <magick/MagickCore.h>
1010
#endif
1111

12-
FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* imageMagick, FFLogoIMResizeFunc resizeFunc, FFLogoIMWriteFunc writeFunc)
12+
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick, FFLogoIMResizeFunc resizeFunc, FFLogoType type)
1313
{
1414
struct winsize winsize;
1515
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != 0)
@@ -22,6 +22,8 @@ FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* imageMagick,
2222
FF_LIBRARY_LOAD_SYMBOL(imageMagick, CopyMagickString, FF_LOGO_SIXEL_RESULT_INIT_ERROR)
2323
FF_LIBRARY_LOAD_SYMBOL(imageMagick, ReadImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR)
2424
FF_LIBRARY_LOAD_SYMBOL(imageMagick, DestroyImage, FF_LOGO_SIXEL_RESULT_INIT_ERROR)
25+
FF_LIBRARY_LOAD_SYMBOL(imageMagick, ImageToBlob, FF_LOGO_SIXEL_RESULT_INIT_ERROR)
26+
FF_LIBRARY_LOAD_SYMBOL(imageMagick, Base64Encode, FF_LOGO_SIXEL_RESULT_INIT_ERROR)
2527

2628
ExceptionInfo* exceptionInfo = ffAcquireExceptionInfo();
2729
if(exceptionInfo == NULL)
@@ -83,20 +85,37 @@ FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* imageMagick,
8385
return FF_LOGO_SIXEL_RESULT_RUN_ERROR;
8486
}
8587

86-
ffPrintCharTimes(' ', instance->config.logoPaddingLeft);
87-
88-
imageInfoOut->file = stdout;
89-
ffCopyMagickString(imageInfoOut->magick, "SIXEL", 6);
88+
if(type == FF_LOGO_TYPE_SIXEL)
89+
ffCopyMagickString(imageInfoOut->magick, "SIXEL", 6);
90+
else //Kitty
91+
ffCopyMagickString(imageInfoOut->magick, "RGBA", 5);
9092

91-
MagickBooleanType writeResult = writeFunc(resizedImage, imageInfoOut, exceptionInfo) ? MagickTrue : MagickFalse;
93+
size_t length;
94+
void* data = ffImageToBlob(imageInfoOut, resizedImage, &length, exceptionInfo);
9295

9396
ffDestroyImageInfo(imageInfoOut);
9497
ffDestroyImage(resizedImage);
9598
ffDestroyExceptionInfo(exceptionInfo);
9699
dlclose(imageMagick);
97100

98-
if(writeResult == MagickFalse)
99-
return FF_LOGO_SIXEL_RESULT_RUN_ERROR;
101+
if(data == NULL || length == 0)
102+
return false;
103+
104+
ffPrintCharTimes(' ', instance->config.logoPaddingLeft);
105+
106+
if(type == FF_LOGO_TYPE_KITTY)
107+
{
108+
void* encoded = ffBase64Encode(data, length, &length);
109+
free(data);
110+
data = encoded;
111+
printf("\033_Ga=T,f=32,s=%u,v=%u;", (uint32_t) imagePixelWidth, (uint32_t) imagePixelHeight);
112+
}
113+
114+
fwrite(data, sizeof(char), length, stdout);
115+
free(data);
116+
117+
if(type == FF_LOGO_TYPE_KITTY)
118+
fputs("\033\\", stdout);
100119

101120
instance->state.logoHeight = (uint32_t) (imagePixelHeight / characterPixelHeight);
102121
instance->state.logoWidth = instance->config.logoWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
@@ -106,24 +125,25 @@ FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* imageMagick,
106125

107126
return FF_LOGO_SIXEL_RESULT_SUCCESS;
108127
}
128+
109129
#endif
110130

111-
bool ffLogoPrintSixelIfExists(FFinstance* instance)
131+
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
112132
{
113133
#if !defined(FF_HAVE_IMAGEMAGICK7) && !defined(FF_HAVE_IMAGEMAGICK6)
114134
FF_UNUSED(instance);
115135
#endif
116136

117137
#ifdef FF_HAVE_IMAGEMAGICK7
118-
FFLogoSixelResult result = ffLogoPrintSixelIM7(instance);
138+
FFLogoImageResult result = ffLogoPrintImageIM7(instance, type);
119139
if(result == FF_LOGO_SIXEL_RESULT_SUCCESS)
120140
return true;
121141
else if(result == FF_LOGO_SIXEL_RESULT_RUN_ERROR)
122142
return false;
123143
#endif
124144

125145
#ifdef FF_HAVE_IMAGEMAGICK6
126-
return ffLogoPrintSixelIM6(instance) == FF_LOGO_SIXEL_RESULT_SUCCESS;
146+
return ffLogoPrintImageIM6(instance, type) == FF_LOGO_SIXEL_RESULT_SUCCESS;
127147
#endif
128148

129149
return false;
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,26 @@
1313
#define MAGICKCORE_HDRI_ENABLE 1
1414
#define MAGICKCORE_QUANTUM_DEPTH 16
1515

16-
typedef enum FFLogoSixelResult
16+
typedef enum FFLogoImageResult
1717
{
1818
FF_LOGO_SIXEL_RESULT_SUCCESS, //Logo printed
1919
FF_LOGO_SIXEL_RESULT_INIT_ERROR, //Failed to load library, try again with next IM version
2020
FF_LOGO_SIXEL_RESULT_RUN_ERROR //Failed to load / convert image, cancle whole sixel code
21-
} FFLogoSixelResult;
21+
} FFLogoImageResult;
2222

2323
typedef void*(*FFLogoIMResizeFunc)(const void* image, size_t width, size_t height, void* exceptionInfo);
24-
typedef bool(*FFLogoIMWriteFunc)(void* image, const void* imageInfo, void* exceptionInfo);
2524

26-
FFLogoSixelResult ffLogoPrintSixelImpl(FFinstance* instance, void* library, FFLogoIMResizeFunc resizeFunc, FFLogoIMWriteFunc writeFunc);
25+
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* library, FFLogoIMResizeFunc resizeFunc, FFLogoType type);
2726

2827
#endif
2928

3029
#ifdef FF_HAVE_IMAGEMAGICK7
31-
FFLogoSixelResult ffLogoPrintSixelIM7(FFinstance* instance);
30+
FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoType type);
3231
#endif
3332

3433
#ifdef FF_HAVE_IMAGEMAGICK6
3534
#include <math.h>
36-
FFLogoSixelResult ffLogoPrintSixelIM6(FFinstance* instance);
35+
FFLogoSixelResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoType type);
3736
#endif
3837

3938

0 commit comments

Comments
 (0)