Image: add dirty support of iTerm image protocol

iTerm image protocol supports most commonly used image formats so we don't need image magick to convert image format.
However, since we don't know anything about the image, `--logo-width` `--logo-height` must be specified to make sure that logo will not be covered by texts.
This commit is contained in:
李通洲
2022-12-22 21:37:16 +08:00
parent c45ef08926
commit 89347b7bee
5 changed files with 88 additions and 22 deletions
+1
View File
@@ -137,6 +137,7 @@ static void defaultConfig(FFinstance* instance)
instance->config.logo.paddingLeft = 0;
instance->config.logo.paddingRight = 4;
instance->config.logo.printRemaining = true;
instance->config.logo.preserveAspectRadio = false;
instance->config.logo.chafaFgOnly = false;
ffStrbufInitS(&instance->config.logo.chafaSymbols, "block+border+space-wide-inverted"); // Chafa default
+23 -21
View File
@@ -22,27 +22,29 @@ General options:
--pipe <?value>: Disable logo and all escape sequences
Logo options:
-l,--logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
--logo-type <type>: Set the type of the logo given; must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty or chafa
--logo-width <width>: Set the width of the logo (in characters), if it is an image
--logo-height <height>: Set the height of the logo (in characters), if it is an image
--logo-color-[1-9] <color>: Overwrite a color in the logo
--logo-padding <padding>: Set the padding on the left and the right of the logo
--logo-padding-left <padding>: Set the padding on the left of the logo
--logo-padding-right <padding>: Set the padding on the right of the logo
--logo-print-remaining <?value>: Whether to print the remaining logo, if it has more lines than modules to display
--file <file>: Short for --logo-type file --logo <file>
--file-raw <file>: Short for --logo-type file-raw --logo <file>
--data <data>: Short for --logo-type data --logo <data>
--data-raw <data>: Short for --logo-type data-raw --logo <data>
--sixel <file>: Short for --logo-type sixel --logo <file>
--kitty <file>: Short for --logo-type kitty --logo <file>
--chafa <file>: Short for --logo-type chafa --logo <file>
--chafa-fg-only <?value>: Produce character-cell output using foreground colors only. See chafa document for detail
--chafa-symbols <str>: Specify character symbols to employ in final output. See chafa document for detail
--chafa-canvas-mode <value>: Determine how colors are used in the output. This value maps the int value of enum ChafaCanvasMode. See chafa document for detail
--chafa-color-space <value>: Set color space used for quantization. 0 for RGB; 1 for DIN99d. See chafa document for detail
--chafa-dither-mode <value>: Set output dither mode (No effect with 24-bit color). This value maps the int value of enum ChafaDitherMode. See chafa document for detail
-l,--logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
--logo-type <type>: Set the type of the logo given; must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty, iterm or chafa
--logo-width <width>: Set the width of the logo (in characters), if it is an image. Required for iTerm image protocol
--logo-height <height>: Set the height of the logo (in characters), if it is an image. Required for iTerm image protocol
--logo-preserve-aspect-radio <?value>: Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol
--logo-color-[1-9] <color>: Overwrite a color in the logo
--logo-padding <padding>: Set the padding on the left and the right of the logo
--logo-padding-left <padding>: Set the padding on the left of the logo
--logo-padding-right <padding>: Set the padding on the right of the logo
--logo-print-remaining <?value>: Whether to print the remaining logo, if it has more lines than modules to display
--file <file>: Short for --logo-type file --logo <file>
--file-raw <file>: Short for --logo-type file-raw --logo <file>
--data <data>: Short for --logo-type data --logo <data>
--data-raw <data>: Short for --logo-type data-raw --logo <data>
--sixel <file>: Short for --logo-type sixel --logo <file>
--kitty <file>: Short for --logo-type kitty --logo <file>
--iterm <file>: Short for --logo-type iterm --logo <file>
--chafa <file>: Short for --logo-type chafa --logo <file>
--chafa-fg-only <?value>: Produce character-cell output using foreground colors only. See chafa document for detail
--chafa-symbols <str>: Specify character symbols to employ in final output. See chafa document for detail
--chafa-canvas-mode <value>: Determine how colors are used in the output. This value maps the int value of enum ChafaCanvasMode. See chafa document for detail
--chafa-color-space <value>: Set color space used for quantization. 0 for RGB; 1 for DIN99d. See chafa document for detail
--chafa-dither-mode <value>: Set output dither mode (No effect with 24-bit color). This value maps the int value of enum ChafaDitherMode. See chafa document for detail
Display options:
-s,--structure <structure>: Set the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.
+7
View File
@@ -979,6 +979,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
instance->config.logo.paddingRight = optionParseUInt32(key, value);
else if(strcasecmp(subkey, "-print-remaining") == 0)
instance->config.logo.printRemaining = optionParseBoolean(value);
else if(strcasecmp(subkey, "-preserve-aspect-radio") == 0)
instance->config.logo.preserveAspectRadio = optionParseBoolean(value);
else
goto error;
}
@@ -1017,6 +1019,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.logo.source);
instance->config.logo.type = FF_LOGO_TYPE_IMAGE_CHAFA;
}
else if(strcasecmp(key, "--iterm") == 0)
{
optionParseString(key, value, &instance->config.logo.source);
instance->config.logo.type = FF_LOGO_TYPE_IMAGE_ITERM;
}
else if(strcasecmp(key, "--chafa-fg-only") == 0)
instance->config.logo.chafaFgOnly = optionParseBoolean(value);
else if(strcasecmp(key, "--chafa-symbols") == 0)
+2
View File
@@ -38,6 +38,7 @@ typedef enum FFLogoType
FF_LOGO_TYPE_DATA_RAW, //text data, printed as is
FF_LOGO_TYPE_IMAGE_SIXEL, //image file, printed as sixel codes.
FF_LOGO_TYPE_IMAGE_KITTY, //image file, printed as kitty graphics protocol
FF_LOGO_TYPE_IMAGE_ITERM, //image file, printed as iterm graphics protocol
FF_LOGO_TYPE_IMAGE_CHAFA, //image file, printed as ascii art using libchafa
} FFLogoType;
@@ -75,6 +76,7 @@ typedef struct FFconfig
uint32_t paddingLeft;
uint32_t paddingRight;
bool printRemaining;
bool preserveAspectRadio;
bool chafaFgOnly;
FFstrbuf chafaSymbols;
+55 -1
View File
@@ -2,6 +2,56 @@
#include "common/io.h"
#include "common/printing.h"
static FFstrbuf base64Encode(FFstrbuf* in)
{
const char* base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
FFstrbuf out;
ffStrbufInitA(&out, 8 * (1 + in->length / 6));
unsigned val = 0;
int valb = -6;
for (uint32_t i = 0; i < in->length; ++i)
{
unsigned char c = (unsigned char) in->chars[i];
val = (val << 8) + c;
valb += 8;
while (valb >= 0)
{
ffStrbufAppendC(&out, base64Chars[(val>>valb)&0x3F]);
valb -= 6;
}
}
if (valb > -6) ffStrbufAppendC(&out, base64Chars[((val<<8)>>(valb+8))&0x3F]);
while (out.length % 4) ffStrbufAppendC(&out, '=');
return out;
}
static bool printImageIterm(FFinstance* instance)
{
if(instance->config.logo.width == 0 || instance->config.logo.height == 0)
return false;
FFstrbuf buf;
ffStrbufInit(&buf);
if(!ffAppendFileBuffer(instance->config.logo.source.chars, &buf))
return false;
ffPrintCharTimes(' ', instance->config.logo.paddingLeft);
FFstrbuf base64 = base64Encode(&buf);
printf("\033]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\033[9999999D\n\033[%uA",
instance->config.logo.width,
instance->config.logo.height,
(unsigned) instance->config.logo.preserveAspectRadio,
base64.chars,
instance->config.logo.height
);
instance->state.logoWidth = instance->config.logo.width + instance->config.logo.paddingLeft + instance->config.logo.paddingRight;
instance->state.logoHeight = instance->config.logo.height;
return true;
}
#if defined(FF_HAVE_IMAGEMAGICK7) || defined(FF_HAVE_IMAGEMAGICK6)
#define FF_KITTY_MAX_CHUNK_SIZE 4096
@@ -589,6 +639,9 @@ static bool getCharacterPixelDimensions(FFLogoRequestData* requestData)
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
{
if(type == FF_LOGO_TYPE_IMAGE_ITERM)
return printImageIterm(instance);
//Performance optimisation
#ifndef FF_HAVE_CHAFA
if(type == FF_LOGO_TYPE_IMAGE_CHAFA)
@@ -664,7 +717,8 @@ bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
#else //FF_HAVE_IMAGEMAGICK{6, 7}
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
{
FF_UNUSED(instance, type);
if(type == FF_LOGO_TYPE_IMAGE_ITERM)
return printImageIterm(instance);
return false;
}
#endif //FF_HAVE_IMAGEMAGICK{6, 7}