-
Notifications
You must be signed in to change notification settings - Fork 6
/
raster.sh
executable file
·227 lines (199 loc) · 6.44 KB
/
raster.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#!/usr/bin/env bash
set -e
font="${font:-Ubuntu}"
pt=${pt:-9}
tmpname="${tmpname:-ai.pgm}"
outname="${outname:-$(dirname "$0")/dates.txt}"
weeks=53
maxcolors=4
numcolors=${numcolors:-${maxcolors}}
usage="Usage: $0 [OPTIONS]\n
Render the text 'ABOLISH ICE' with a given font to ${outname} for use with $(dirname "$0")/paint.sh\n
\n
\t -n\t\t\t disable prompts\n
\t -f, --font <font>\t select a font (name or filepath) for rendering [default '${font}']\n
\t -s, --size <fontsize>\t select a font size for rendering [default '${pt}']\n
\t -c, --colors <colors>\t set the number of foreground colors to be used [maximum '${maxcolors}']\n
\t -p, --palette\t\t use the final palette when rasterizing, instead of greyscale\n
\t\t\t\t\tNote: seems to result in fewer colors being used, maybe worse lettering\n
\t -i, --invert\t\t Dark Mode. light text on a dark background\n
\t -b, --background\t uniform background color (uses one foreground color)\n
\t\t\t\t\tNote: if inverted this affects the text color\n
\t -w\t\t\t week-day background only\n
\t -l, --no-partial\t dont render pixels to the current partial week\n
\t -t, --temp\t\t use a temporary file for image, rather than overwriting ${tmpname}\n
\t -d, --debug\t\t debugging output\n
\t -h, --help\t\t see this message and exit"
while (( "$#" )); do
case $1 in
-n)
noprompt=1
;;
-f|--font)
font="$2"
shift
;;
-l|--no-partial)
((--weeks))
;;
-s|--size)
pt=$2
shift
;;
-c|--colors)
numcolors=$2
shift
;;
-p|--palette)
usepalette=1
;;
-i|--invert)
invert=1
;;
-b|--background)
((--numcolors))
background=1
;;
-w)
((--numcolors))
background=1
weekend=1
;;
-t|--temp)
tmpname="/tmp/${tmpname}"
;;
-d|--debug)
debug=1
;;
-h|--help)
echo -e "${usage}"
exit
;;
esac
shift
done
# validation
if [ "${numcolors}" -gt "${maxcolors}" ]; then
numcolors="${maxcolors}"
fi
# decide if we have the tools to generate $tmpname, or if not, if we have a valid file to use
if [ -z "$(which convert 2> /dev/null)" ]; then
if [ ! -f "${tmpname}" ]; then
echo "This script requires imagemagick to be installed or an uncompressed .ngm image to be supplied."
exit 10
elif [ "$(head -n1 "${tmpname}")" != "P2" ]; then
echo "only uncompressed .ngm image files are supported"
exit 11
elif [ "$(head -2 "${tmpname}"|tail -1)" != "${weeks} 7" ]; then
echo "image must be ${weeks}x7"
exit 12
fi
else
# generate palette file if missing
palettename=palette.png
if [ ! -f ${palettename} ]; then
convert -size 12x12 xc:#ebedf0 xc:#9be9a8 xc:#40c463 xc:#30a14e xc:#216e39 +append png:palette.png
fi
colorcmd=""
if [ -n "${invert}" ]; then
colorcmd+="-fill white -background black "
fi
# palette must be specified before number of colors
if [[ -f ${palettename} && -n ${usepalette} ]]; then
# FIXME: palettename cannot be properly quoted and will probably break if there is a space
colorcmd+="-remap ${palettename} "
fi
colorcmd+="-colors $((numcolors+2))"
# render the image to a greyscale, acsii format for easy parsing
convert -pointsize "${pt}" -font "${font}" -size "${weeks}x7" ${colorcmd} -gravity center label:'ABOLISH ICE' -depth 8 -compress none "pgm:${tmpname}"
# give a full color preview if we are using a palette and have viu
if [[ -n "${usepalette}" && -n "$(which viu 2> /dev/null)" ]]; then
convert -pointsize "${pt}" -font "${font}" -size "${weeks}x7" ${colorcmd} -gravity center label:'ABOLISH ICE' "png:${tmpname}.png";viu "${tmpname}.png";rm "${tmpname}.png"
fi
err=$?
if [ ! $err ]; then
echo "Imagemagick failed, maybe it was built without truetype or fontconfig support?"
exit $err
fi
fi
# you don't need root to run cargo, so why not offer to get viu, if possible
if [[ -z "$noprompt" && -z "$(which viu 2> /dev/null)" && -n "$(which cargo 2> /dev/null)" ]]; then
read -r -t 5 -n 1 -p " Would you like to 'cargo install viu' for image previews [y/N]? " answer
echo
case ${answer} in
y|Y )
cargo install viu
;;
n|N )
echo " Cool, you can invoke $0 with the -n option to disable this prompt."
;;
esac
fi
# give the user a greyscale preview of what we'll put on the commit graph
if [ -n "$(which viu 2> /dev/null)" ]; then
viu "${tmpname}"
fi
# the greyscale colors are 8-bit colors, but we only have 5 colors to work with, 2 of which will be used for background blocks, depending on whether a given day has prior commits or not
# we want to reduce this to no more than 4 colors
I="${maxcolors}"
colormap=()
while read -r line
do
if [ "${I}" -gt "$((maxcolors - numcolors))" ]; then
# bash arrays are sparse wo we can just write to the proper index
colormap[${I}]="${line}"
if [ -n "${debug}" ]; then
echo "${line} ${I}"
fi
else
if [ -n "${debug}" ]; then
echo " discarding ${line} ${I}"
fi
fi
# lol. this gets treated like an error when $I goes to 0, so then script dies with 'set -e'
((--I)) || true
# makes a list of unique colors in the image:
# remove 3 lines of metadata, turn 2D array of pixels into 1D, sort,
# remove duplicates and remove empty lines
done <<< "$(tail +4 "${tmpname}"|tr ' ' '\n'|sort -n|uniq|grep -v "^$" )"
if [ -n "${debug}" ]; then
echo "${!colormap[@]}" "${colormap[@]}"
fi
# function for looking up a color in the colormap, so that we don't need an associative array
lookup_color() {
target=$1
# ! iterates indices
for i in "${!colormap[@]}"
do
if [ "${colormap[$i]}" -eq "${target}" ]; then
echo "$i"
return
fi
done
}
# inspired by dates.sh, turns image's pixels, by position and color, into dates.txt
# shellcheck source=lib-date.sh
source "$(dirname "$0")/lib-date.sh"
start="$(one_year_ago)"
echo "Starting on $start ..." >&2
# image is not in calendar order, we iterate all the sundays first, then mondays, etc.
# so the output is sorted before being written
days=0
while read -r line
do
weeks=0
for i in $line
do
color="$(lookup_color "${i}")"
if [ -n "${color}" ]; then
echo "$(add_weeks "${start}" "${weeks}")-${color}"
elif [[ -n "${background}" ]]; then
if [[ -z "${weekend}" || $days -ne 0 && $days -ne 1 && $days -ne 5 && $days -ne 6 ]]; then
echo "$(add_weeks "${start}" "${weeks}")-1"
fi
fi
((++weeks))
done
((++days))
start="$(add_days "${start}" 1)"
done <<< "$(tail +4 "${tmpname}")" | sort -n > ${outname}