I have a c program, that should print an image to a terminal, using the Kitty graphics protocol and utilizing ImageMagick 7.
I created this minimal example from the code i have. Note that error checks and memory freeing is missing for simplicity:
#include <stdint.h>
#include <stdio.h>
#include <MagickCore/MagickCore.h>
int main()
{
ExceptionInfo* exceptionInfo = AcquireExceptionInfo();
ImageInfo* imageInfoIn = AcquireImageInfo();
CopyMagickString(imageInfoIn->filename, "./image.jpg", 12);
Image* image = ReadImage(imageInfoIn, exceptionInfo);
ImageInfo* imageInfoOut = AcquireImageInfo();
CopyMagickString(imageInfoOut->magick, "RGBA", 5);
size_t length;
void* blob = ImageToBlob(imageInfoOut, image, &length, exceptionInfo);
blob = Base64Encode(blob, length, &length);
printf("\033_Ga=T,f=32,s=%u,v=%u;", image->columns, image->rows);
fwrite(blob, sizeof(char), length, stdout);
puts("\033\\");
return 0;
}
This code works perfectly fine in Konsole, WezTerm and Wayst (displays the image), but in kitty itself it just prints the base64 encoding of the RGBA data as text.
kitty kitten icat path/to/some/image.png
works fine, so terminal support is working.
What am i missing to make it work in kitty too?
CodePudding user response:
The problem was, that kitty allows only 4096 bytes of image data to be sent at once. So you need to split it up in multiple escape codes to use it.
The program above modified to work in kitty too looks like this:
#include <stdint.h>
#include <stdio.h>
#include <MagickCore/MagickCore.h>
static void printChunc(void** blob, size_t* length, uint32_t chunkSize)
{
size_t toWrite = chunkSize < *length ? chunkSize : *length;
printf("\033_Gm=%i;", toWrite == chunkSize ? 1 : 0);
fwrite(*blob, sizeof(char), toWrite, stdout);
fputs("\033\\", stdout);
*blob = ((char*) *blob) toWrite;
*length -= toWrite;
}
int main()
{
ExceptionInfo* exceptionInfo = AcquireExceptionInfo();
ImageInfo* imageInfoIn = AcquireImageInfo();
CopyMagickString(imageInfoIn->filename, "./image.jpg", 12);
Image* image = ReadImage(imageInfoIn, exceptionInfo);
ImageInfo* imageInfoOut = AcquireImageInfo();
CopyMagickString(imageInfoOut->magick, "RGBA", 5);
size_t length;
void* blob = ImageToBlob(imageInfoOut, image, &length, exceptionInfo);
blob = Base64Encode(blob, length, &length);
printf("\033_Ga=T,f=32,s=%u,v=%u,m=1;\033\\", image->columns, image->rows);
while(length > 0)
printChunc(&blob, &length, 4096);
putchar('\n');
return 0;
}
Note the m= key, telling kitty if there is more data to come or not.
Thanks to u/aumerlex on Reddit for helping figure that out.