Kitty graphics protocol support

This commit is contained in:
Linus Dierheimer
2022-04-14 11:36:57 +02:00
parent 703ec597fa
commit 31bdd25a26
4 changed files with 113 additions and 33 deletions
+10 -1
View File
@@ -4,17 +4,26 @@
#include <magick/MagickCore.h>
static FF_LIBRARY_SYMBOL(ResizeImage);
static FF_LIBRARY_SYMBOL(WriteImage);
static void* logoResize(const void* image, size_t width, size_t height, void* exceptionInfo)
{
return ffResizeImage(image, width, height, UndefinedFilter, 1.0, exceptionInfo);
}
static bool logoWrite(void* imageInfo, void* image, void* exceptionInfo)
{
FF_UNUSED(exceptionInfo);
return ffWriteImage(imageInfo, image) == MagickTrue;
}
FFLogoImageResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoType type)
{
FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_IMAGE_RESULT_INIT_ERROR, "libMagickCore-6.Q16HDRI.so", 8, "libMagickCore-6.Q16.so", 8)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, type);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffWriteImage, WriteImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, logoWrite, type);
}
#endif
+9 -1
View File
@@ -4,17 +4,25 @@
#include <MagickCore/MagickCore.h>
static FF_LIBRARY_SYMBOL(ResizeImage);
static FF_LIBRARY_SYMBOL(WriteImage);
static void* logoResize(const void* image, size_t width, size_t height, void* exceptionInfo)
{
return ffResizeImage(image, width, height, UndefinedFilter, exceptionInfo);
}
static bool logoWrite(void* imageInfo, void* image, void* exceptionInfo)
{
return ffWriteImage(imageInfo, image, exceptionInfo) == MagickTrue;
}
FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoType type)
{
FF_LIBRARY_LOAD(imageMagick, instance->config.libImageMagick, FF_LOGO_IMAGE_RESULT_INIT_ERROR, "libMagickCore-7.Q16HDRI.so", 11, "libMagickCore-7.Q16.so", 11)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, type);
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, ffWriteImage, WriteImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
return ffLogoPrintImageImpl(instance, imageMagick, logoResize, logoWrite, type);
}
#endif
+92 -30
View File
@@ -2,6 +2,8 @@
#if defined(FF_HAVE_IMAGEMAGICK7) || defined(FF_HAVE_IMAGEMAGICK6)
#define FF_KITTY_MAX_CHUNK_SIZE 4096
//We use only the defines from here, that are exactly the same in both versions
#ifdef FF_HAVE_IMAGEMAGICK7
#include <MagickCore/MagickCore.h>
@@ -9,7 +11,81 @@
#include <magick/MagickCore.h>
#endif
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick, FFLogoIMResizeFunc resizeFunc, FFLogoType type)
typedef struct ImageMagickFunctions
{
FF_LIBRARY_SYMBOL(CopyMagickString)
FF_LIBRARY_SYMBOL(ImageToBlob)
FF_LIBRARY_SYMBOL(Base64Encode)
FFLogoIMWriteFunc writeFunc;
} ImageMagickFunctions;
static inline bool checkAllocationResult(void* data, size_t length)
{
if(data == NULL)
return false;
if(length == 0)
{
free(data);
return false;
}
return true;
}
static void printImageKittyChunc(char** blob, size_t* length, uint32_t chunkSize)
{
size_t toWrite = chunkSize < *length ? chunkSize : *length;
fputs("\033_Gm=1;", stdout);
fwrite(*blob, sizeof(**blob), toWrite, stdout);
fputs("\033\\", stdout);
*blob = *blob + toWrite;
*length -= toWrite;
}
static bool printImageKitty(ImageInfo* imageInfo, Image* image, ExceptionInfo* ExceptionInfo, uint32_t paddingLeft, ImageMagickFunctions* functions)
{
functions->ffCopyMagickString(imageInfo->magick, "RGBA", 5);
size_t length;
void* blob = functions->ffImageToBlob(imageInfo, image, &length, ExceptionInfo);
if(!checkAllocationResult(blob, length))
return false;
void* encoded = functions->ffBase64Encode(blob, length, &length);
free(blob);
if(!checkAllocationResult(encoded, length))
return false;
ffPrintCharTimes(' ', paddingLeft);
char* currentPos = (char*) encoded;
printf("\033_Ga=T,f=32,s=%u,v=%u,m=1;\033\\", (uint32_t) image->columns, (uint32_t) image->rows);
while (length > 0)
printImageKittyChunc(&currentPos, &length, FF_KITTY_MAX_CHUNK_SIZE);
fputs("\033_Gm=0;\033\\", stdout);
free(encoded);
return true;
}
static bool printImageSixel(ImageInfo* imageInfo, Image* image, ExceptionInfo* exceptionInfo, uint32_t paddingLeft, ImageMagickFunctions* functions)
{
ffPrintCharTimes(' ', paddingLeft);
functions->ffCopyMagickString(imageInfo->magick, "SIXEL", 6);
imageInfo->file = stdout;
bool writeResult = functions->writeFunc(imageInfo, image, exceptionInfo);
if(!writeResult)
printf("\033[%uD", paddingLeft);
return writeResult;
}
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick, FFLogoIMResizeFunc resizeFunc, FFLogoIMWriteFunc writeFunc, FFLogoType type)
{
struct winsize winsize;
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != 0)
@@ -19,11 +95,15 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick,
FF_LIBRARY_LOAD_SYMBOL(imageMagick, DestroyExceptionInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
FF_LIBRARY_LOAD_SYMBOL(imageMagick, AcquireImageInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
FF_LIBRARY_LOAD_SYMBOL(imageMagick, DestroyImageInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
FF_LIBRARY_LOAD_SYMBOL(imageMagick, CopyMagickString, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
FF_LIBRARY_LOAD_SYMBOL(imageMagick, ReadImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
FF_LIBRARY_LOAD_SYMBOL(imageMagick, DestroyImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
FF_LIBRARY_LOAD_SYMBOL(imageMagick, ImageToBlob, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
FF_LIBRARY_LOAD_SYMBOL(imageMagick, Base64Encode, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
ImageMagickFunctions functions;
functions.writeFunc = writeFunc;
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, functions.ffCopyMagickString, CopyMagickString, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, functions.ffImageToBlob, ImageToBlob, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
FF_LIBRARY_LOAD_SYMBOL_ADRESS(imageMagick, functions.ffBase64Encode, Base64Encode, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
ExceptionInfo* exceptionInfo = ffAcquireExceptionInfo();
if(exceptionInfo == NULL)
@@ -41,7 +121,7 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick,
}
//+1, because we need to copy the null byte too
ffCopyMagickString(imageInfoIn->filename, instance->config.logoName.chars, instance->config.logoName.length + 1);
functions.ffCopyMagickString(imageInfoIn->filename, instance->config.logoName.chars, instance->config.logoName.length + 1);
Image* originalImage = ffReadImage(imageInfoIn, exceptionInfo);
ffDestroyImageInfo(imageInfoIn);
@@ -85,37 +165,19 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* imageMagick,
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
if(type == FF_LOGO_TYPE_SIXEL)
ffCopyMagickString(imageInfoOut->magick, "SIXEL", 6);
else //Kitty
ffCopyMagickString(imageInfoOut->magick, "RGBA", 5);
size_t length;
void* data = ffImageToBlob(imageInfoOut, resizedImage, &length, exceptionInfo);
bool printSuccessful;
if(type == FF_LOGO_TYPE_KITTY)
printSuccessful = printImageKitty(imageInfoOut, resizedImage, exceptionInfo, instance->config.logoPaddingLeft, &functions);
else
printSuccessful = printImageSixel(imageInfoOut, resizedImage, exceptionInfo, instance->config.logoPaddingLeft, &functions);
ffDestroyImageInfo(imageInfoOut);
ffDestroyImage(resizedImage);
ffDestroyExceptionInfo(exceptionInfo);
dlclose(imageMagick);
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);
if(!printSuccessful)
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
instance->state.logoHeight = (uint32_t) (imagePixelHeight / characterPixelHeight);
instance->state.logoWidth = instance->config.logoWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
+2 -1
View File
@@ -21,8 +21,9 @@ typedef enum FFLogoImageResult
} FFLogoImageResult;
typedef void*(*FFLogoIMResizeFunc)(const void* image, size_t width, size_t height, void* exceptionInfo);
typedef bool(*FFLogoIMWriteFunc)(void* imageInfo, void* image, void* exceptionInfo);
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* library, FFLogoIMResizeFunc resizeFunc, FFLogoType type);
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, void* library, FFLogoIMResizeFunc resizeFunc, FFLogoIMWriteFunc writeFunc, FFLogoType type);
#endif