feat: kitty images patch applied
This commit is contained in:
875
icat-mini.sh
Executable file
875
icat-mini.sh
Executable file
@@ -0,0 +1,875 @@
|
||||
#!/bin/sh
|
||||
|
||||
# vim: shiftwidth=4
|
||||
|
||||
script_name="$(basename "$0")"
|
||||
|
||||
short_help="Usage: $script_name [OPTIONS] <image_file>
|
||||
|
||||
This is a script to display images in the terminal using the kitty graphics
|
||||
protocol with Unicode placeholders. It is very basic, please use something else
|
||||
if you have alternatives.
|
||||
|
||||
Options:
|
||||
-h Show this help.
|
||||
-s SCALE The scale of the image, may be floating point.
|
||||
-c N, --cols N The number of columns.
|
||||
-r N, --rows N The number of rows.
|
||||
--max-cols N The maximum number of columns.
|
||||
--max-rows N The maximum number of rows.
|
||||
--cell-size WxH The cell size in pixels.
|
||||
-m METHOD The uploading method, may be 'file', 'direct' or 'auto'.
|
||||
--speed SPEED The multiplier for the animation speed (float).
|
||||
"
|
||||
|
||||
# Exit the script on keyboard interrupt
|
||||
trap "echo 'icat-mini was interrupted' >&2; exit 1" INT
|
||||
|
||||
cols=""
|
||||
rows=""
|
||||
file=""
|
||||
command_tty=""
|
||||
response_tty=""
|
||||
uploading_method="auto"
|
||||
cell_size=""
|
||||
scale=1
|
||||
max_cols=""
|
||||
max_rows=""
|
||||
speed=""
|
||||
|
||||
# Parse the command line.
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-c|--columns|--cols)
|
||||
cols="$2"
|
||||
shift 2
|
||||
;;
|
||||
-r|--rows|-l|--lines)
|
||||
rows="$2"
|
||||
shift 2
|
||||
;;
|
||||
-s|--scale)
|
||||
scale="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
echo "$short_help"
|
||||
exit 0
|
||||
;;
|
||||
-m|--upload-method|--uploading-method)
|
||||
uploading_method="$2"
|
||||
shift 2
|
||||
;;
|
||||
--cell-size)
|
||||
cell_size="$2"
|
||||
shift 2
|
||||
;;
|
||||
--max-cols)
|
||||
max_cols="$2"
|
||||
shift 2
|
||||
;;
|
||||
--max-rows)
|
||||
max_rows="$2"
|
||||
shift 2
|
||||
;;
|
||||
--speed)
|
||||
speed="$2"
|
||||
shift 2
|
||||
;;
|
||||
--)
|
||||
file="$2"
|
||||
shift 2
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
if [ -n "$file" ]; then
|
||||
echo "Multiple image files are not supported: $file and $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
file="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
file="$(realpath "$file")"
|
||||
|
||||
#####################################################################
|
||||
# Detect imagemagick
|
||||
#####################################################################
|
||||
|
||||
# If there is the 'magick' command, use it instead of separate 'convert' and
|
||||
# 'identify' commands.
|
||||
if command -v magick > /dev/null; then
|
||||
identify="magick identify"
|
||||
convert="magick"
|
||||
else
|
||||
identify="identify"
|
||||
convert="convert"
|
||||
fi
|
||||
|
||||
#####################################################################
|
||||
# Detect tmux
|
||||
#####################################################################
|
||||
|
||||
# Check if we are inside tmux.
|
||||
inside_tmux=""
|
||||
if [ -n "$TMUX" ]; then
|
||||
inside_tmux=1
|
||||
fi
|
||||
|
||||
if [ -z "$command_tty" ] && [ -n "$inside_tmux" ]; then
|
||||
# Get the pty of the current tmux pane.
|
||||
command_tty="$(tmux display-message -t "$TMUX_PANE" -p "#{pane_tty}")"
|
||||
if [ ! -e "$command_tty" ]; then
|
||||
command_tty=""
|
||||
fi
|
||||
fi
|
||||
|
||||
#####################################################################
|
||||
# Adjust the terminal state
|
||||
#####################################################################
|
||||
|
||||
if [ -z "$command_tty" ]; then
|
||||
command_tty="/dev/tty"
|
||||
fi
|
||||
if [ -z "$response_tty" ]; then
|
||||
response_tty="/dev/tty"
|
||||
fi
|
||||
|
||||
stty_orig="$(stty -g < "$response_tty")"
|
||||
stty -echo < "$response_tty"
|
||||
# Disable ctrl-z. Pressing ctrl-z during image uploading may cause some
|
||||
# horrible issues otherwise.
|
||||
stty susp undef < "$response_tty"
|
||||
stty -icanon < "$response_tty"
|
||||
|
||||
restore_echo() {
|
||||
[ -n "$stty_orig" ] || return
|
||||
stty $stty_orig < "$response_tty"
|
||||
}
|
||||
|
||||
trap restore_echo EXIT TERM
|
||||
|
||||
#####################################################################
|
||||
# Compute the number of rows and columns
|
||||
#####################################################################
|
||||
|
||||
is_pos_int() {
|
||||
if [ -z "$1" ]; then
|
||||
return 1 # false
|
||||
fi
|
||||
if [ -z "$(printf '%s' "$1" | tr -d '[:digit:]')" ]; then
|
||||
if [ "$1" -gt 0 ]; then
|
||||
return 0 # true
|
||||
fi
|
||||
fi
|
||||
return 1 # false
|
||||
}
|
||||
|
||||
if [ -n "$cols" ] || [ -n "$rows" ]; then
|
||||
if [ -n "$max_cols" ] || [ -n "$max_rows" ]; then
|
||||
echo "You can't specify both max-cols/rows and cols/rows" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get the max number of cols and rows.
|
||||
[ -n "$max_cols" ] || max_cols="$(tput cols)"
|
||||
[ -n "$max_rows" ] || max_rows="$(tput lines)"
|
||||
if [ "$max_rows" -gt 255 ]; then
|
||||
max_rows=255
|
||||
fi
|
||||
|
||||
python_ioctl_command="import array, fcntl, termios
|
||||
buf = array.array('H', [0, 0, 0, 0])
|
||||
fcntl.ioctl(0, termios.TIOCGWINSZ, buf)
|
||||
print(int(buf[2]/buf[1]), int(buf[3]/buf[0]))"
|
||||
|
||||
# Get the cell size in pixels if either cols or rows are not specified.
|
||||
if [ -z "$cols" ] || [ -z "$rows" ]; then
|
||||
cell_width=""
|
||||
cell_height=""
|
||||
# If the cell size is specified, use it.
|
||||
if [ -n "$cell_size" ]; then
|
||||
cell_width="${cell_size%x*}"
|
||||
cell_height="${cell_size#*x}"
|
||||
if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then
|
||||
echo "Invalid cell size: $cell_size" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
# Otherwise try to use TIOCGWINSZ ioctl via python.
|
||||
if [ -z "$cell_width" ] || [ -z "$cell_height" ]; then
|
||||
cell_size_ioctl="$(python3 -c "$python_ioctl_command" < "$command_tty" 2> /dev/null)"
|
||||
cell_width="${cell_size_ioctl% *}"
|
||||
cell_height="${cell_size_ioctl#* }"
|
||||
if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then
|
||||
cell_width=""
|
||||
cell_height=""
|
||||
fi
|
||||
fi
|
||||
# If it didn't work, try to use csi XTWINOPS.
|
||||
if [ -z "$cell_width" ] || [ -z "$cell_height" ]; then
|
||||
if [ -n "$inside_tmux" ]; then
|
||||
printf '\ePtmux;\e\e[16t\e\\' >> "$command_tty"
|
||||
else
|
||||
printf '\e[16t' >> "$command_tty"
|
||||
fi
|
||||
# The expected response will look like ^[[6;<height>;<width>t
|
||||
term_response=""
|
||||
while true; do
|
||||
char=$(dd bs=1 count=1 <"$response_tty" 2>/dev/null)
|
||||
if [ "$char" = "t" ]; then
|
||||
break
|
||||
fi
|
||||
term_response="$term_response$char"
|
||||
done
|
||||
cell_height="$(printf '%s' "$term_response" | cut -d ';' -f 2)"
|
||||
cell_width="$(printf '%s' "$term_response" | cut -d ';' -f 3)"
|
||||
if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then
|
||||
cell_width=8
|
||||
cell_height=16
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Compute a formula with bc and round to the nearest integer.
|
||||
bc_round() {
|
||||
LC_NUMERIC=C printf '%.0f' "$(printf '%s\n' "scale=2;($1) + 0.5" | bc)"
|
||||
}
|
||||
|
||||
# Compute the number of rows and columns of the image.
|
||||
if [ -z "$cols" ] || [ -z "$rows" ]; then
|
||||
# Get the size of the image and its resolution. If it's an animation, use
|
||||
# the first frame.
|
||||
format_output="$($identify -format '%w %h\n' "$file" | head -1)"
|
||||
img_width="$(printf '%s' "$format_output" | cut -d ' ' -f 1)"
|
||||
img_height="$(printf '%s' "$format_output" | cut -d ' ' -f 2)"
|
||||
if ! is_pos_int "$img_width" || ! is_pos_int "$img_height"; then
|
||||
echo "Couldn't get image size from identify: $format_output" >&2
|
||||
echo >&2
|
||||
exit 1
|
||||
fi
|
||||
opt_cols_expr="(${scale}*${img_width}/${cell_width})"
|
||||
opt_rows_expr="(${scale}*${img_height}/${cell_height})"
|
||||
if [ -z "$cols" ] && [ -z "$rows" ]; then
|
||||
# If columns and rows are not specified, compute the optimal values
|
||||
# using the information about rows and columns per inch.
|
||||
cols="$(bc_round "$opt_cols_expr")"
|
||||
rows="$(bc_round "$opt_rows_expr")"
|
||||
# Make sure that automatically computed rows and columns are within some
|
||||
# sane limits
|
||||
if [ "$cols" -gt "$max_cols" ]; then
|
||||
rows="$(bc_round "$rows * $max_cols / $cols")"
|
||||
cols="$max_cols"
|
||||
fi
|
||||
if [ "$rows" -gt "$max_rows" ]; then
|
||||
cols="$(bc_round "$cols * $max_rows / $rows")"
|
||||
rows="$max_rows"
|
||||
fi
|
||||
elif [ -z "$cols" ]; then
|
||||
# If only one dimension is specified, compute the other one to match the
|
||||
# aspect ratio as close as possible.
|
||||
cols="$(bc_round "${opt_cols_expr}*${rows}/${opt_rows_expr}")"
|
||||
elif [ -z "$rows" ]; then
|
||||
rows="$(bc_round "${opt_rows_expr}*${cols}/${opt_cols_expr}")"
|
||||
fi
|
||||
|
||||
if [ "$cols" -lt 1 ]; then
|
||||
cols=1
|
||||
fi
|
||||
if [ "$rows" -lt 1 ]; then
|
||||
rows=1
|
||||
fi
|
||||
fi
|
||||
|
||||
#####################################################################
|
||||
# Generate an image id
|
||||
#####################################################################
|
||||
|
||||
image_id=""
|
||||
while [ -z "$image_id" ]; do
|
||||
image_id="$(shuf -i 16777217-4294967295 -n 1)"
|
||||
# Check that the id requires 24-bit fg colors.
|
||||
if [ "$(expr \( "$image_id" / 256 \) % 65536)" -eq 0 ]; then
|
||||
image_id=""
|
||||
fi
|
||||
done
|
||||
|
||||
#####################################################################
|
||||
# Uploading the image
|
||||
#####################################################################
|
||||
|
||||
# Choose the uploading method
|
||||
if [ "$uploading_method" = "auto" ]; then
|
||||
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ] || [ -n "$SSH_CONNECTION" ]; then
|
||||
uploading_method="direct"
|
||||
else
|
||||
uploading_method="file"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Functions to emit the start and the end of a graphics command.
|
||||
if [ -n "$inside_tmux" ]; then
|
||||
# If we are in tmux we have to wrap the command in Ptmux.
|
||||
graphics_command_start='\ePtmux;\e\e_G'
|
||||
graphics_command_end='\e\e\\\e\\'
|
||||
else
|
||||
graphics_command_start='\e_G'
|
||||
graphics_command_end='\e\\'
|
||||
fi
|
||||
|
||||
# Send a graphics command with the correct start and end
|
||||
gr_command() {
|
||||
printf "${graphics_command_start}%s${graphics_command_end}" "$1" >> "$command_tty"
|
||||
}
|
||||
|
||||
# Compute the size of a data chunk for direct transmission.
|
||||
if [ "$uploading_method" = "direct" ]; then
|
||||
# Get the value of PIPE_BUF.
|
||||
pipe_buf="$(getconf PIPE_BUF "$command_tty" 2> /dev/null)"
|
||||
if is_pos_int "$pipe_buf"; then
|
||||
# Make sure it's between 512 and 4096.
|
||||
if [ "$(expr "$pipe_buf" \< 512)" -eq 1 ]; then
|
||||
pipe_buf=512
|
||||
elif [ "$(expr "$pipe_buf" \> 4096)" -eq 1 ]; then
|
||||
pipe_buf=4096
|
||||
fi
|
||||
else
|
||||
pipe_buf=512
|
||||
fi
|
||||
|
||||
# The size of each graphics command shouldn't be more than PIPE_BUF, so we
|
||||
# set the size of an encoded chunk to be PIPE_BUF - 128 to leave some space
|
||||
# for the command.
|
||||
chunk_size="$(expr "$pipe_buf" - 128)"
|
||||
fi
|
||||
|
||||
# Check if the image format is supported.
|
||||
is_format_supported() {
|
||||
arg_format="$1"
|
||||
if [ "$arg_format" = "PNG" ]; then
|
||||
return 0
|
||||
elif [ "$arg_format" = "JPEG" ]; then
|
||||
if [ -z "$inside_tmux" ]; then
|
||||
actual_term="$TERM"
|
||||
else
|
||||
# Get the actual current terminal name from tmux.
|
||||
actual_term="$(tmux display-message -p "#{client_termname}")"
|
||||
fi
|
||||
# st is known to support JPEG.
|
||||
case "$actual_term" in
|
||||
st | *-st | st-* | *-st-*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Send an uploading command. Usage: gr_upload <action> <command> <file>
|
||||
# Where <action> is a part of command that specifies the action, it will be
|
||||
# repeated for every chunk (if the method is direct), and <command> is the rest
|
||||
# of the command that specifies the image parameters. <action> and <command>
|
||||
# must not include the transmission method or ';'.
|
||||
# Example:
|
||||
# gr_upload "a=T,q=2" "U=1,i=${image_id},f=100,c=${cols},r=${rows}" "$file"
|
||||
gr_upload() {
|
||||
arg_action="$1"
|
||||
arg_command="$2"
|
||||
arg_file="$3"
|
||||
if [ "$uploading_method" = "file" ]; then
|
||||
# base64-encode the filename
|
||||
encoded_filename=$(printf '%s' "$arg_file" | base64 -w0)
|
||||
# If the file name contains 'tty-graphics-protocol', assume it's
|
||||
# temporary and use t=t.
|
||||
medium="t=f"
|
||||
case "$arg_file" in
|
||||
*tty-graphics-protocol*)
|
||||
medium="t=t"
|
||||
;;
|
||||
*)
|
||||
medium="t=f"
|
||||
;;
|
||||
esac
|
||||
gr_command "${arg_action},${arg_command},${medium};${encoded_filename}"
|
||||
fi
|
||||
if [ "$uploading_method" = "direct" ]; then
|
||||
# Create a temporary directory to store the chunked image.
|
||||
chunkdir="$(mktemp -d)"
|
||||
if [ ! "$chunkdir" ] || [ ! -d "$chunkdir" ]; then
|
||||
echo "Can't create a temp dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
# base64-encode the file and split it into chunks. The size of each
|
||||
# graphics command shouldn't be more than 4096, so we set the size of an
|
||||
# encoded chunk to be 3968, slightly less than that.
|
||||
chunk_size=3968
|
||||
cat "$arg_file" | base64 -w0 | split -b "$chunk_size" - "$chunkdir/chunk_"
|
||||
|
||||
# Issue a command indicating that we want to start data transmission for
|
||||
# a new image.
|
||||
gr_command "${arg_action},${arg_command},t=d,m=1"
|
||||
|
||||
# Transmit chunks.
|
||||
for chunk in "$chunkdir/chunk_"*; do
|
||||
gr_command "${arg_action},i=${image_id},m=1;$(cat "$chunk")"
|
||||
rm "$chunk"
|
||||
done
|
||||
|
||||
# Tell the terminal that we are done.
|
||||
gr_command "${arg_action},i=$image_id,m=0"
|
||||
|
||||
# Remove the temporary directory.
|
||||
rmdir "$chunkdir"
|
||||
fi
|
||||
}
|
||||
|
||||
delayed_frame_dir_cleanup() {
|
||||
arg_frame_dir="$1"
|
||||
sleep 2
|
||||
if [ -n "$arg_frame_dir" ]; then
|
||||
for frame in "$arg_frame_dir"/frame_*.png; do
|
||||
rm "$frame"
|
||||
done
|
||||
rmdir "$arg_frame_dir"
|
||||
fi
|
||||
}
|
||||
|
||||
upload_image_and_print_placeholder() {
|
||||
# Check if the file is an animation.
|
||||
format_output=$($identify -format '%n %m\n' "$file" | head -n 1)
|
||||
frame_count="$(printf '%s' "$format_output" | cut -d ' ' -f 1)"
|
||||
image_format="$(printf '%s' "$format_output" | cut -d ' ' -f 2)"
|
||||
|
||||
if [ "$frame_count" -gt 1 ]; then
|
||||
# The file is an animation, decompose into frames and upload each frame.
|
||||
frame_dir="$(mktemp -d)"
|
||||
frame_dir="$HOME/temp/frames${frame_dir}"
|
||||
mkdir -p "$frame_dir"
|
||||
if [ ! "$frame_dir" ] || [ ! -d "$frame_dir" ]; then
|
||||
echo "Can't create a temp dir for frames" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Decompose the animation into separate frames.
|
||||
$convert "$file" -coalesce "$frame_dir/frame_%06d.png"
|
||||
|
||||
# Get all frame delays at once, in centiseconds, as a space-separated
|
||||
# string.
|
||||
delays=$($identify -format "%T " "$file")
|
||||
|
||||
frame_number=1
|
||||
for frame in "$frame_dir"/frame_*.png; do
|
||||
# Read the delay for the current frame and convert it from
|
||||
# centiseconds to milliseconds.
|
||||
delay=$(printf '%s' "$delays" | cut -d ' ' -f "$frame_number")
|
||||
delay=$((delay * 10))
|
||||
# If the delay is 0, set it to 100ms.
|
||||
if [ "$delay" -eq 0 ]; then
|
||||
delay=100
|
||||
fi
|
||||
|
||||
if [ -n "$speed" ]; then
|
||||
delay=$(bc_round "$delay / $speed")
|
||||
fi
|
||||
|
||||
if [ "$frame_number" -eq 1 ]; then
|
||||
# Abort the previous transmission, just in case.
|
||||
gr_command "q=2,a=t,i=${image_id},m=0"
|
||||
# Upload the first frame with a=T
|
||||
gr_upload "q=2,a=T" "f=100,U=1,i=${image_id},c=${cols},r=${rows}" "$frame"
|
||||
# Set the delay for the first frame and also play the animation
|
||||
# in loading mode (s=2).
|
||||
gr_command "a=a,v=1,s=2,r=${frame_number},z=${delay},i=${image_id}"
|
||||
# Print the placeholder after the first frame to reduce the wait
|
||||
# time.
|
||||
print_placeholder
|
||||
else
|
||||
# Upload subsequent frames with a=f
|
||||
gr_upload "q=2,a=f" "f=100,i=${image_id},z=${delay}" "$frame"
|
||||
fi
|
||||
|
||||
frame_number=$((frame_number + 1))
|
||||
done
|
||||
|
||||
# Play the animation in loop mode (s=3).
|
||||
gr_command "a=a,v=1,s=3,i=${image_id}"
|
||||
|
||||
# Remove the temporary directory, but do it in the background with a
|
||||
# delay to avoid removing files before they are loaded by the terminal.
|
||||
delayed_frame_dir_cleanup "$frame_dir" 2> /dev/null &
|
||||
elif is_format_supported "$image_format"; then
|
||||
# The file is not an animation and has a supported format, upload it
|
||||
# directly.
|
||||
gr_upload "q=2,a=T" "U=1,i=${image_id},f=100,c=${cols},r=${rows}" "$file"
|
||||
# Print the placeholder
|
||||
print_placeholder
|
||||
else
|
||||
# The format is not supported, try to convert it to png.
|
||||
temp_file="$(mktemp --tmpdir "icat-mini-tty-graphics-protocol-XXXXX.png")"
|
||||
if ! $convert "$file" "$temp_file"; then
|
||||
echo "Failed to convert the image to PNG" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Upload the converted image.
|
||||
gr_upload "q=2,a=T" "U=1,i=${image_id},f=100,c=${cols},r=${rows}" "$temp_file"
|
||||
# Print the placeholder
|
||||
print_placeholder
|
||||
fi
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Printing the image placeholder
|
||||
#####################################################################
|
||||
|
||||
print_placeholder() {
|
||||
# Each line starts with the escape sequence to set the foreground color to
|
||||
# the image id.
|
||||
blue="$(expr "$image_id" % 256 )"
|
||||
green="$(expr \( "$image_id" / 256 \) % 256 )"
|
||||
red="$(expr \( "$image_id" / 65536 \) % 256 )"
|
||||
line_start="$(printf "\e[38;2;%d;%d;%dm" "$red" "$green" "$blue")"
|
||||
line_end="$(printf "\e[39;m")"
|
||||
|
||||
id4th="$(expr \( "$image_id" / 16777216 \) % 256 )"
|
||||
eval "id_diacritic=\$d${id4th}"
|
||||
|
||||
# Reset the brush state, mostly to reset the underline color.
|
||||
printf "\e[0m"
|
||||
|
||||
# Fill the output with characters representing the image
|
||||
for y in $(seq 0 "$(expr "$rows" - 1)"); do
|
||||
eval "row_diacritic=\$d${y}"
|
||||
line="$line_start"
|
||||
for x in $(seq 0 "$(expr "$cols" - 1)"); do
|
||||
eval "col_diacritic=\$d${x}"
|
||||
# Note that when $x is out of bounds, the column diacritic will
|
||||
# be empty, meaning that the column should be guessed by the
|
||||
# terminal.
|
||||
if [ "$x" -ge "$num_diacritics" ]; then
|
||||
line="${line}${placeholder}${row_diacritic}"
|
||||
else
|
||||
line="${line}${placeholder}${row_diacritic}${col_diacritic}${id_diacritic}"
|
||||
fi
|
||||
done
|
||||
line="${line}${line_end}"
|
||||
printf "%s\n" "$line"
|
||||
done
|
||||
|
||||
printf "\e[0m"
|
||||
}
|
||||
|
||||
d0="Ì…"
|
||||
d1="Ì"
|
||||
d2="ÌŽ"
|
||||
d3="Ì"
|
||||
d4="Ì’"
|
||||
d5="̽"
|
||||
d6="̾"
|
||||
d7="Ì¿"
|
||||
d8="͆"
|
||||
d9="ÍŠ"
|
||||
d10="Í‹"
|
||||
d11="͌"
|
||||
d12="Í"
|
||||
d13="Í‘"
|
||||
d14="Í’"
|
||||
d15="Í—"
|
||||
d16="Í›"
|
||||
d17="Í£"
|
||||
d18="ͤ"
|
||||
d19="Í¥"
|
||||
d20="ͦ"
|
||||
d21="ͧ"
|
||||
d22="ͨ"
|
||||
d23="Í©"
|
||||
d24="ͪ"
|
||||
d25="Í«"
|
||||
d26="ͬ"
|
||||
d27="Í"
|
||||
d28="Í®"
|
||||
d29="ͯ"
|
||||
d30="Òƒ"
|
||||
d31="Ò„"
|
||||
d32="Ò…"
|
||||
d33="Ò†"
|
||||
d34="Ò‡"
|
||||
d35="Ö’"
|
||||
d36="Ö“"
|
||||
d37="Ö”"
|
||||
d38="Ö•"
|
||||
d39="Ö—"
|
||||
d40="Ö˜"
|
||||
d41="Ö™"
|
||||
d42="֜"
|
||||
d43="Ö"
|
||||
d44="Öž"
|
||||
d45="ÖŸ"
|
||||
d46="Ö "
|
||||
d47="Ö¡"
|
||||
d48="Ö¨"
|
||||
d49="Ö©"
|
||||
d50="Ö«"
|
||||
d51="Ö¬"
|
||||
d52="Ö¯"
|
||||
d53="ׄ"
|
||||
d54="Ø"
|
||||
d55="Ø‘"
|
||||
d56="Ø’"
|
||||
d57="Ø“"
|
||||
d58="Ø”"
|
||||
d59="Ø•"
|
||||
d60="Ø–"
|
||||
d61="Ø—"
|
||||
d62="Ù—"
|
||||
d63="Ù˜"
|
||||
d64="Ù™"
|
||||
d65="Ùš"
|
||||
d66="Ù›"
|
||||
d67="Ù"
|
||||
d68="Ùž"
|
||||
d69="Û–"
|
||||
d70="Û—"
|
||||
d71="Û˜"
|
||||
d72="Û™"
|
||||
d73="Ûš"
|
||||
d74="Û›"
|
||||
d75="ۜ"
|
||||
d76="ÛŸ"
|
||||
d77="Û "
|
||||
d78="Û¡"
|
||||
d79="Û¢"
|
||||
d80="Û¤"
|
||||
d81="Û§"
|
||||
d82="Û¨"
|
||||
d83="Û«"
|
||||
d84="Û¬"
|
||||
d85="ܰ"
|
||||
d86="ܲ"
|
||||
d87="ܳ"
|
||||
d88="ܵ"
|
||||
d89="ܶ"
|
||||
d90="ܺ"
|
||||
d91="ܽ"
|
||||
d92="Ü¿"
|
||||
d93="Ý€"
|
||||
d94="Ý"
|
||||
d95="݃"
|
||||
d96="Ý…"
|
||||
d97="݇"
|
||||
d98="݉"
|
||||
d99="ÝŠ"
|
||||
d100="ß«"
|
||||
d101="߬"
|
||||
d102="ß"
|
||||
d103="ß®"
|
||||
d104="߯"
|
||||
d105="ß°"
|
||||
d106="ß±"
|
||||
d107="ß³"
|
||||
d108="à –"
|
||||
d109="à —"
|
||||
d110="à ˜"
|
||||
d111="à ™"
|
||||
d112="à ›"
|
||||
d113="à œ"
|
||||
d114="à "
|
||||
d115="à ž"
|
||||
d116="à Ÿ"
|
||||
d117="à "
|
||||
d118="à ¡"
|
||||
d119="à ¢"
|
||||
d120="à £"
|
||||
d121="à ¥"
|
||||
d122="à ¦"
|
||||
d123="à §"
|
||||
d124="à ©"
|
||||
d125="à ª"
|
||||
d126="à «"
|
||||
d127="à ¬"
|
||||
d128="à "
|
||||
d129="॑"
|
||||
d130="॓"
|
||||
d131="॔"
|
||||
d132="ྂ"
|
||||
d133="ྃ"
|
||||
d134="྆"
|
||||
d135="྇"
|
||||
d136="á"
|
||||
d137="áž"
|
||||
d138="áŸ"
|
||||
d139="áŸ"
|
||||
d140="᤺"
|
||||
d141="ᨗ"
|
||||
d142="᩵"
|
||||
d143="á©¶"
|
||||
d144="á©·"
|
||||
d145="᩸"
|
||||
d146="᩹"
|
||||
d147="᩺"
|
||||
d148="á©»"
|
||||
d149="᩼"
|
||||
d150="á«"
|
||||
d151="á"
|
||||
d152="á®"
|
||||
d153="á¯"
|
||||
d154="á°"
|
||||
d155="á±"
|
||||
d156="á²"
|
||||
d157="á³"
|
||||
d158="á³"
|
||||
d159="᳑"
|
||||
d160="á³’"
|
||||
d161="᳚"
|
||||
d162="á³›"
|
||||
d163="á³ "
|
||||
d164="á·€"
|
||||
d165="á·"
|
||||
d166="á·ƒ"
|
||||
d167="á·„"
|
||||
d168="á·…"
|
||||
d169="á·†"
|
||||
d170="á·‡"
|
||||
d171="á·ˆ"
|
||||
d172="á·‰"
|
||||
d173="á·‹"
|
||||
d174="᷌"
|
||||
d175="á·‘"
|
||||
d176="á·’"
|
||||
d177="á·“"
|
||||
d178="á·”"
|
||||
d179="á·•"
|
||||
d180="á·–"
|
||||
d181="á·—"
|
||||
d182="á·˜"
|
||||
d183="á·™"
|
||||
d184="á·š"
|
||||
d185="á·›"
|
||||
d186="ᷜ"
|
||||
d187="á·"
|
||||
d188="á·ž"
|
||||
d189="á·Ÿ"
|
||||
d190="á· "
|
||||
d191="á·¡"
|
||||
d192="á·¢"
|
||||
d193="á·£"
|
||||
d194="á·¤"
|
||||
d195="á·¥"
|
||||
d196="á·¦"
|
||||
d197="á·¾"
|
||||
d198="âƒ"
|
||||
d199="⃑"
|
||||
d200="⃔"
|
||||
d201="⃕"
|
||||
d202="⃖"
|
||||
d203="⃗"
|
||||
d204="⃛"
|
||||
d205="⃜"
|
||||
d206="⃡"
|
||||
d207="⃧"
|
||||
d208="⃩"
|
||||
d209="⃰"
|
||||
d210="⳯"
|
||||
d211="â³°"
|
||||
d212="â³±"
|
||||
d213="â· "
|
||||
d214="â·¡"
|
||||
d215="â·¢"
|
||||
d216="â·£"
|
||||
d217="â·¤"
|
||||
d218="â·¥"
|
||||
d219="â·¦"
|
||||
d220="â·§"
|
||||
d221="â·¨"
|
||||
d222="â·©"
|
||||
d223="â·ª"
|
||||
d224="â·«"
|
||||
d225="â·¬"
|
||||
d226="â·"
|
||||
d227="â·®"
|
||||
d228="â·¯"
|
||||
d229="â·°"
|
||||
d230="â·±"
|
||||
d231="â·²"
|
||||
d232="â·³"
|
||||
d233="â·´"
|
||||
d234="â·µ"
|
||||
d235="â·¶"
|
||||
d236="â··"
|
||||
d237="â·¸"
|
||||
d238="â·¹"
|
||||
d239="â·º"
|
||||
d240="â·»"
|
||||
d241="â·¼"
|
||||
d242="â·½"
|
||||
d243="â·¾"
|
||||
d244="â·¿"
|
||||
d245="꙯"
|
||||
d246="꙼"
|
||||
d247="꙽"
|
||||
d248="ê›°"
|
||||
d249="ê›±"
|
||||
d250="ê£ "
|
||||
d251="꣡"
|
||||
d252="꣢"
|
||||
d253="꣣"
|
||||
d254="꣤"
|
||||
d255="꣥"
|
||||
d256="꣦"
|
||||
d257="꣧"
|
||||
d258="꣨"
|
||||
d259="꣩"
|
||||
d260="꣪"
|
||||
d261="꣫"
|
||||
d262="꣬"
|
||||
d263="ê£"
|
||||
d264="꣮"
|
||||
d265="꣯"
|
||||
d266="꣰"
|
||||
d267="꣱"
|
||||
d268="ꪰ"
|
||||
d269="ꪲ"
|
||||
d270="ꪳ"
|
||||
d271="ꪷ"
|
||||
d272="ꪸ"
|
||||
d273="ꪾ"
|
||||
d274="꪿"
|
||||
d275="ê«"
|
||||
d276="ï¸ "
|
||||
d277="︡"
|
||||
d278="︢"
|
||||
d279="︣"
|
||||
d280="︤"
|
||||
d281="︥"
|
||||
d282="︦"
|
||||
d283="ð¨"
|
||||
d284="ð¨¸"
|
||||
d285="ð†…"
|
||||
d286="ð††"
|
||||
d287="ð†‡"
|
||||
d288="ð†ˆ"
|
||||
d289="ð†‰"
|
||||
d290="ð†ª"
|
||||
d291="ð†«"
|
||||
d292="ð†¬"
|
||||
d293="ð†"
|
||||
d294="ð‰‚"
|
||||
d295="ð‰ƒ"
|
||||
d296="ð‰„"
|
||||
|
||||
num_diacritics="297"
|
||||
|
||||
placeholder="ôŽ»®"
|
||||
|
||||
#####################################################################
|
||||
# Upload the image and print the placeholder
|
||||
#####################################################################
|
||||
|
||||
upload_image_and_print_placeholder
|
||||
Reference in New Issue
Block a user