Skip to content

Commit 31bdd25

Browse files
Kitty graphics protocol support
1 parent 703ec59 commit 31bdd25

File tree

4 files changed

+113
-33
lines changed

4 files changed

+113
-33
lines changed

src/logo/image/im6.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,26 @@
44
#include <magick/MagickCore.h>
55

66
static FF_LIBRARY_SYMBOL(ResizeImage);
7+
static FF_LIBRARY_SYMBOL(WriteImage);
78

89
static void* logoResize(const void* image, size_t width, size_t height, void* exceptionInfo)
910
{
1011
return ffResizeImage(image, width, height, UndefinedFilter, 1.0, exceptionInfo);
1112
}
1213

14+
static bool logoWrite(void* imageInfo, void* image, void* exceptionInfo)
15+
{
16+
FF_UNUSED(exceptionInfo);
17+
return ffWriteImage(imageInfo, image) == MagickTrue;
18+
}
19+
1320
FFLogoImageResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoType type)
1421
{
1522
FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_IMAGE_RESULT_INIT_ERROR, "libMagickCore-6.Q16HDRI.so", 8, "libMagickCore-6.Q16.so", 8)
1623
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
17-
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, type);
24+
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffWriteImage, WriteImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
25+
26+
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, logoWrite, type);
1827
}
1928

2029
#endif

src/logo/image/im7.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,25 @@
44
#include <MagickCore/MagickCore.h>
55

66
static FF_LIBRARY_SYMBOL(ResizeImage);
7+
static FF_LIBRARY_SYMBOL(WriteImage);
78

89
static void* logoResize(const void* image, size_t width, size_t height, void* exceptionInfo)
910
{
1011
return ffResizeImage(image, width, height, UndefinedFilter, exceptionInfo);
1112
}
1213

14+
static bool logoWrite(void* imageInfo, void* image, void* exceptionInfo)
15+
{
16+
return ffWriteImage(imageInfo, image, exceptionInfo) == MagickTrue;
17+
}
18+
1319
FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoType type)
1420
{
1521
FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_IMAGE_RESULT_INIT_ERROR, "libMagickCore-7.Q16HDRI.so", 11, "libMagickCore-7.Q16.so", 11)
1622
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
17-
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, type);
23+
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffWriteImage, WriteImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
24+
25+
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, logoWrite, type);
1826
}
1927

2028
#endif

src/logo/image/image.c

Lines changed: 92 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,90 @@
22

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

5+
#define FF_KITTY_MAX_CHUNK_SIZE 4096
6+
57
//We use only the defines from here, that are exactly the same in both versions
68
#ifdef FF_HAVE_IMAGEMAGICK7
79
#include <MagickCore/MagickCore.h>
810
#else
911
#include <magick/MagickCore.h>
1012
#endif
1113

12-
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick, FFLogoIMResizeFunc resizeFunc, FFLogoType type)
14+
typedef struct ImageMagickFunctions
15+
{
16+
FF_LIBRARY_SYMBOL(CopyMagickString)
17+
FF_LIBRARY_SYMBOL(ImageToBlob)
18+
FF_LIBRARY_SYMBOL(Base64Encode)
19+
20+
FFLogoIMWriteFunc writeFunc;
21+
} ImageMagickFunctions;
22+
23+
static inline bool checkAllocationResult(void* data, size_t length)
24+
{
25+
if(data == NULL)
26+
return false;
27+
28+
if(length == 0)
29+
{
30+
free(data);
31+
return false;
32+
}
33+
34+
return true;
35+
}
36+
37+
static void printImageKittyChunc(char** blob, size_t* length, uint32_t chunkSize)
38+
{
39+
size_t toWrite = chunkSize < *length ? chunkSize : *length;
40+
fputs("\033_Gm=1;", stdout);
41+
fwrite(*blob, sizeof(**blob), toWrite, stdout);
42+
fputs("\033\\", stdout);
43+
*blob = *blob + toWrite;
44+
*length -= toWrite;
45+
}
46+
47+
static bool printImageKitty(ImageInfo* imageInfo, Image* image, ExceptionInfo* ExceptionInfo, uint32_t paddingLeft, ImageMagickFunctions* functions)
48+
{
49+
functions->ffCopyMagickString(imageInfo->magick, "RGBA", 5);
50+
51+
size_t length;
52+
void* blob = functions->ffImageToBlob(imageInfo, image, &length, ExceptionInfo);
53+
if(!checkAllocationResult(blob, length))
54+
return false;
55+
56+
void* encoded = functions->ffBase64Encode(blob, length, &length);
57+
free(blob);
58+
if(!checkAllocationResult(encoded, length))
59+
return false;
60+
61+
ffPrintCharTimes(' ', paddingLeft);
62+
63+
char* currentPos = (char*) encoded;
64+
65+
printf("\033_Ga=T,f=32,s=%u,v=%u,m=1;\033\\", (uint32_t) image->columns, (uint32_t) image->rows);
66+
while (length > 0)
67+
printImageKittyChunc(&currentPos, &length, FF_KITTY_MAX_CHUNK_SIZE);
68+
fputs("\033_Gm=0;\033\\", stdout);
69+
70+
free(encoded);
71+
return true;
72+
}
73+
74+
static bool printImageSixel(ImageInfo* imageInfo, Image* image, ExceptionInfo* exceptionInfo, uint32_t paddingLeft, ImageMagickFunctions* functions)
75+
{
76+
ffPrintCharTimes(' ', paddingLeft);
77+
78+
functions->ffCopyMagickString(imageInfo->magick, "SIXEL", 6);
79+
imageInfo->file = stdout;
80+
bool writeResult = functions->writeFunc(imageInfo, image, exceptionInfo);
81+
82+
if(!writeResult)
83+
printf("\033[%uD", paddingLeft);
84+
85+
return writeResult;
86+
}
87+
88+
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick, FFLogoIMResizeFunc resizeFunc, FFLogoIMWriteFunc writeFunc, FFLogoType type)
1389
{
1490
struct winsize winsize;
1591
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != 0)
@@ -19,11 +95,15 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick,
1995
FF_LIBRARY_LOAD_SYMBOL(imageMagick, DestroyExceptionInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
2096
FF_LIBRARY_LOAD_SYMBOL(imageMagick, AcquireImageInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
2197
FF_LIBRARY_LOAD_SYMBOL(imageMagick, DestroyImageInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
22-
FF_LIBRARY_LOAD_SYMBOL(imageMagick, CopyMagickString, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
2398
FF_LIBRARY_LOAD_SYMBOL(imageMagick, ReadImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
2499
FF_LIBRARY_LOAD_SYMBOL(imageMagick, DestroyImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
25-
FF_LIBRARY_LOAD_SYMBOL(imageMagick, ImageToBlob, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
26-
FF_LIBRARY_LOAD_SYMBOL(imageMagick, Base64Encode, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
100+
101+
ImageMagickFunctions functions;
102+
functions.writeFunc = writeFunc;
103+
104+
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, functions.ffCopyMagickString, CopyMagickString, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
105+
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, functions.ffImageToBlob, ImageToBlob, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
106+
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, functions.ffBase64Encode, Base64Encode, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
27107

28108
ExceptionInfo* exceptionInfo = ffAcquireExceptionInfo();
29109
if(exceptionInfo == NULL)
@@ -41,7 +121,7 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick,
41121
}
42122

43123
//+1, because we need to copy the null byte too
44-
ffCopyMagickString(imageInfoIn->filename, instance->config.logoName.chars, instance->config.logoName.length + 1);
124+
functions.ffCopyMagickString(imageInfoIn->filename, instance->config.logoName.chars, instance->config.logoName.length + 1);
45125

46126
Image* originalImage = ffReadImage(imageInfoIn, exceptionInfo);
47127
ffDestroyImageInfo(imageInfoIn);
@@ -85,37 +165,19 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick,
85165
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
86166
}
87167

88-
if(type == FF_LOGO_TYPE_SIXEL)
89-
ffCopyMagickString(imageInfoOut->magick, "SIXEL", 6);
90-
else //Kitty
91-
ffCopyMagickString(imageInfoOut->magick, "RGBA", 5);
92-
93-
size_t length;
94-
void* data = ffImageToBlob(imageInfoOut, resizedImage, &length, exceptionInfo);
168+
bool printSuccessful;
169+
if(type == FF_LOGO_TYPE_KITTY)
170+
printSuccessful = printImageKitty(imageInfoOut, resizedImage, exceptionInfo, instance->config.logoPaddingLeft, &functions);
171+
else
172+
printSuccessful = printImageSixel(imageInfoOut, resizedImage, exceptionInfo, instance->config.logoPaddingLeft, &functions);
95173

96174
ffDestroyImageInfo(imageInfoOut);
97175
ffDestroyImage(resizedImage);
98176
ffDestroyExceptionInfo(exceptionInfo);
99177
dlclose(imageMagick);
100178

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);
179+
if(!printSuccessful)
180+
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
119181

120182
instance->state.logoHeight = (uint32_t) (imagePixelHeight / characterPixelHeight);
121183
instance->state.logoWidth = instance->config.logoWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;

src/logo/image/image.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ typedef enum FFLogoImageResult
2121
} FFLogoImageResult;
2222

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

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

2728
#endif
2829

0 commit comments

Comments
 (0)