forked from bboymega/File2PNG
-
Notifications
You must be signed in to change notification settings - Fork 0
/
file2png
executable file
·314 lines (256 loc) · 8.32 KB
/
file2png
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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
#!/bin/sh
## File2PNG script. Store any file as PNG image.
## Copyright (C) 2018 BrainFucker <[email protected]>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
VERSION='0.7'
_NAME_="$(basename "$0")"
USAGE="USAGE
$_NAME_ -store input_file output_file.png
Store input_file as output_file.png
$_NAME_ -restore input_file.png output_file
Restore file from input_file.png
Will save original file name saved to same directory as input file
if no output file supplied.
$_NAME_ -info input_file.png
Print file info.
OPTIONS
-comment 'comment string'
Add comment.
-bitdepth
Force image bit depth. Using 16 by default. Supported values: 8 or 16.
-force
Force output even if decode failed.
-help
Print this help.
COPYRIGHT
File2PNG $VERSION Copyright (C) 2018 BrainFucker
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions."
## print messages to stderr
errlog () {
echo "$@" 1>&2
}
## Args parser
## Supported arg formats:
## -arg --arg (both are identical)
## -arg value
## -arg=value
parse_args() {
local ARG _PREV_ARG _ARG _VAR _VAL _ARGN SKIP
__ARGS=''
for ARG in "$@"; do
case "$ARG" in
--) _PREV_ARG=''
SKIP=1 ;;
-[-a-zA-Z0-9]*) if [ -z "$SKIP" ]; then
_ARG="$(echo -n "$ARG" | sed 's/^-\+//' | sed 's/-/_/g' | tr -d '\r' | tr '\t\v\n' ' ')"
case "$_ARG" in
*=*) _PREV_ARG=''
_VAR="$(echo -n "$_ARG" | sed 's/=.*//')"
_VAL="$(echo -n "$_ARG" | sed 's/.\+=//')"
if [ -z "$_VAL" ]; then
_VAL=0
fi
__ARGS="$__ARGS\n__arg_${_VAR}__ $_VAL"
eval "_arg_$_VAR=\$_VAL" ;;
*) _PREV_ARG="_arg_$_ARG"
__ARGS="$__ARGS\n__arg_${_ARG}__ 1"
eval "_arg_$_ARG=1" ;;
esac
fi ;;
*) if [ -n "$_PREV_ARG" ]; then
__ARGS="$__ARGS\n_${_PREV_ARG}__ $ARG"
eval "$_PREV_ARG=\$ARG"
_PREV_ARG=''
else
_ARGN=$((_ARGN+1))
__ARGS="$__ARGS\n__arg_${_ARGN}__ $_ARG"
eval "_arg$_ARGN=\$ARG"
fi ;;
esac
done
} # parse_args()
## get arg value
## $1 arg name
fn_get_arg() {
echo -n "$__ARGS" | grep "__arg_$1__" | tail -n 1 | sed "s/__arg_$1__ //"
}
## check for installed required utils
UTILS="convert sha256sum dd bc awk grep mktemp sed"
for anutil in $UTILS; do
if [ _"$(which "$anutil")" = _ ]; then
errlog "Error: util $anutil not found."
exit 1
fi
done
parse_args "$@"
## Exit if no args supplied
if [ _"$1" = _ ] || [ _"$2" = _ ]; then
errlog "$USAGE"
exit 0
fi
fn_check_file() {
local FILE
local DEV
if [ _"$2" != _"out" ] && [ _"$2" != _"in" ]; then
DEV='/dev/stdin'
else
DEV="/dev/std$2"
fi
if [ _"$1" = _- ]; then
## Read from stdin if supplied filename is -
FILE="$DEV"
else
FILE="$1"
## Exit if file not exists
if [ ! -f "$FILE" ]; then
errlog "File $FILE not exists."
exit 1
fi
fi
echo "$FILE"
}
## Show supplied file info
showinfo () {
convert PNG:"$1" RGB:- | sed -En 's/^###(NAME|SIZE|SHA256|VERSION|COMMENT)(.+) .+###/\1\2/p'
} # showinfo
## restore file
## $1 input file
## $2 output file
restorefile () {
local IN OUT
_RAW="$(mktemp)"
IN="$(fn_check_file "$1" in)"
#OUT="$(fn_check_file "$2" out)"
convert PNG:"$IN" RGB:"$_RAW"
INFO="$( grep -a '###' "$_RAW" )"
_SIZE="$( echo -n "$INFO" | grep -a '###SIZE:' | awk '{print $2}')"
_SHA="$( echo -n "$INFO" | grep -a '###SHA256:' | awk '{print $2}')"
_VERSION="$( echo -n "$INFO" | grep -a '###VERSION:' | awk '{print $2}')"
_NAME="$( echo -n "$INFO" | grep -a '###NAME:' | sed 's/###NAME: //' | sed 's/ :ENAM###//')"
if [ -z "$2" ]; then
DIR="$(dirname "$IN")"
OUTPUT="$DIR/$_NAME"
else
OUTPUT="$2"
fi
if [ _"$_SIZE" = _ ] || [ _"$_NAME" = _ ] || [ _"$_SHA" = _ ]; then
errlog "No data found inside. Restoring failed."
_SIZE=''
if [ -z "$_arg_force" ]; then
rm "$_RAW"
exit 1
fi
fi
if [ _"$_VERSION" != _"$VERSION" ]; then
errlog "Warning: file was created by different version of $_NAME_."
fi
if [ -n "$_SIZE" ]; then
_SIZE="bs=$_SIZE"
fi
if [ _"$OUTPUT" = _'-' ]; then
OUTPUT='/dev/stdout'
dd if="$_RAW" $_SIZE count=1
else
dd if="$_RAW" of="$OUTPUT" $_SIZE count=1
fi
rm "$_RAW"
if [ _"$OUTPUT" != _'/dev/stdout' ]; then
echo "$OUTPUT"
_NEWSHA="$(sha256sum "$OUTPUT" | awk '{print $1}')"
if [ _"$_NEWSHA" != _"$_SHA" ]; then
errlog "Sha sums not equal, something weng wrong.
Original: $_SHA
Output: $_NEWSHA"
exit 1
fi
fi
} # restorefile
## store file
## $1 input file
## $2 output file
storefile () {
## force 8 bit depth by setting this env variable
## some image hosters don't like 16bit.
## using 16 bit by default
if [ -z "$_arg_bitdepth" ]; then
_arg_bitdepth=16
fi
IN="$(fn_check_file "$1" in)"
#OUT="$(fn_check_file "$2" out)"
OUT="$2"
## bytes per 3 color pixel
PIXBYTE=$(( $_arg_bitdepth * 3 / 8 ))
if [ _"$IN" = _'/dev/stdin' ] || [ _"$OUT" = _'/dev/stdout' ]; then
errlog "Stdin and stdout not supported for this type of operation."
exit 1
fi
NAME="$(basename "$IN")"
if [ -z "$OUT" ]; then
OUTPUT="$(mktemp 'XXXXXXXXXX.png')"
else
OUTPUT="$OUT"
fi
SHA="$(sha256sum "$IN" | awk '{print $1}')"
SIZE="$(stat -c '%s' "$IN")"
TMP="$(mktemp)"
cp "$IN" "$TMP"
## Store metadata
echo '' >> "$TMP"
echo "###SIZE: $SIZE :EZIS###" >> "$TMP"
echo "###NAME: $NAME :ENAM###" >> "$TMP"
echo "###SHA256: $SHA :652AHS###" >> "$TMP"
echo "###VERSION: $VERSION :NOISREV###" >> "$TMP"
if [ -n "$_arg_comment" ]; then
echo "$_arg_comment" | while read L; do
echo "###COMMENT: $L :TNEMMOC###" >> "$TMP"
done
fi
echo "###UTIL: Decode: https://github.com/rekcuFniarB/file2png#readme :LITU###" >> "$TMP"
SIZE="$(stat -c '%s' "$TMP")"
_PIXELS=$(( $SIZE / $PIXBYTE ))
errlog "TMP pixels: $_PIXELS"
RESOL="$(echo "sqrt($_PIXELS) +1" | bc)"
errlog "Target resolution: ${RESOL}x${RESOL}"
PIXELS=$(( $RESOL * $RESOL ))
## calculating target size
CONTAINERSIZE=$(( $PIXELS * $PIXBYTE ))
errlog "Container size: $CONTAINERSIZE"
BYTESDIFF=$(( $CONTAINERSIZE - $SIZE ))
if [ $BYTESDIFF -gt 0 ]; then
## adding missing bytes
dd if=/dev/zero bs=$BYTESDIFF count=1 >> "$TMP"
elif [ $BYTESDIFF -lt 0 ]; then
errlog "Error: unexpected container size."
exit 1
fi
convert -size ${RESOL}x${RESOL} -depth $_arg_bitdepth RGB:"$TMP" PNG00:"$OUTPUT"
echo "$OUTPUT"
rm "$TMP"
} # storefile()
if [ -n "$_arg_help" ] || [ -n "$_arg_h" ]; then
errlog "$USAGE"
exit 0
elif [ -n "$_arg_info" ]; then
showinfo "$_arg_info"
exit 0
elif [ -n "$_arg_restore" ]; then
restorefile "$_arg_restore" "$_arg1"
exit 0
elif [ -n "$_arg_store" ]; then
storefile "$_arg_store" "$_arg1"
exit 0
else
errlog "$USAGE"
exit 1
fi