/’fu:bar/ 2018
Ramiro Polla
def glitch_frame(frame):
try:
fwd_mv = frame["forward"]
except KeyError:
# No forward motion vector found. Probably an I or B frame.
return
# for each row
for row in fwd_mv:
# for each column
for mv in row:
# clear element 0 (horizontal) of motion vector
mv[0] = 0
Y
U
V
uint8_t block[64] =
{
39, 35, 40, 87, 87, 65, 86, 121,
37, 35, 38, 55, 90, 65, 50, 72,
47, 40, 42, 68, 112, 77, 56, 66,
72, 66, 66, 90, 108, 74, 53, 87,
84, 84, 91, 83, 72, 57, 66, 126,
86, 90, 80, 76, 55, 65, 113, 173,
54, 60, 57, 64, 77, 107, 160, 198,
63, 65, 75, 88, 127, 158, 188, 202,
};
uint8_t block[64] =
{
39, 35, 40, 87, 87, 65, 86, 121,
37, 35, 38, 55, 90, 65, 50, 72,
47, 40, 42, 68, 112, 77, 56, 66,
72, 66, 66, 90, 108, 74, 53, 87,
84, 84, 91, 83, 72, 57, 66, 126,
86, 90, 80, 76, 55, 65, 113, 173,
54, 60, 57, 64, 77, 107, 160, 198,
63, 65, 75, 88, 127, 158, 188, 202,
};
int16_t dct_coeffs[64] =
{
5270, -1303, 294, -240, 462, -217, -16, 30,
-1151, 648, -664, 205, 262, -93, -26, 23,
308, -892, 84, 116, -107, 107, -78, 7,
-29, 131, 484, -465, 44, 100, -23, -101,
340, 41, -140, -35, 72, 24, 28, -24,
27, -191, 13, 14, 57, 44, -71, -35,
169, 1, 4, -4, 25, 40, -38, -8,
-54, -80, -5, -13, -14, 12, 8, 26,
};
magic
->
uint8_t block[64] =
{
39, 35, 40, 87, 87, 65, 86, 121,
37, 35, 38, 55, 90, 65, 50, 72,
47, 40, 42, 68, 112, 77, 56, 66,
72, 66, 66, 90, 108, 74, 53, 87,
84, 84, 91, 83, 72, 57, 66, 126,
86, 90, 80, 76, 55, 65, 113, 173,
54, 60, 57, 64, 77, 107, 160, 198,
63, 65, 75, 88, 127, 158, 188, 202,
};
int16_t dct_coeffs[64] =
{
5270, -1303, 294, -240, 462, -217, -16, 30,
-1151, 648, -664, 205, 262, -93, -26, 23,
308, -892, 84, 116, -107, 107, -78, 7,
-29, 131, 484, -465, 44, 100, -23, -101,
340, 41, -140, -35, 72, 24, 28, -24,
27, -191, 13, 14, 57, 44, -71, -35,
169, 1, 4, -4, 25, 40, -38, -8,
-54, -80, -5, -13, -14, 12, 8, 26,
};
reverse magic
->
int16_t dct_coeffs[64] =
{
5270, -1303, 294, -240, 462, -217, -16, 30,
-1151, 648, -664, 205, 262, -93, -26, 23,
308, -892, 84, 116, -107, 107, -78, 7,
-29, 131, 484, -465, 44, 100, -23, -101,
340, 41, -140, -35, 72, 24, 28, -24,
27, -191, 13, 14, 57, 44, -71, -35,
169, 1, 4, -4, 25, 40, -38, -8,
-54, -80, -5, -13, -14, 12, 8, 26,
};
int16_t quantized_coeffs[64] =
{
82, -16, 3, -2, 3, -2, 0, 0,
-14, 8, -6, 2, 2, -1, 0, 0,
3, -8, 1, 1, -1, 1, 0, 0,
0, 1, 4, -4, 0, 0, 0, 0,
3, 0, -1, 0, 0, 0, 0, 0,
0, -1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
quantization
->
int16_t dequantized_coeffs[64] =
{
5248, -1280, 264, -208, 384, -256, 0, 0,
-1120, 640, -624, 240, 256, -144, 0, 0,
264, -832, 128, 128, -144, 168, 0, 0,
0, 104, 512, -512, 0, 0, 0, 0,
312, 0, -128, 0, 0, 0, 0, 0,
0, -128, 0, 0, 0, 0, 0, 0,
128, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
int16_t quantized_coeffs[64] =
{
82, -16, 3, -2, 3, -2, 0, 0,
-14, 8, -6, 2, 2, -1, 0, 0,
3, -8, 1, 1, -1, 1, 0, 0,
0, 1, 4, -4, 0, 0, 0, 0,
3, 0, -1, 0, 0, 0, 0, 0,
0, -1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
dequantize
->
reverse
magic
->
int16_t dequantized_coeffs[64] =
{
5248, -1280, 264, -208, 384, -256, 0, 0,
-1120, 640, -624, 240, 256, -144, 0, 0,
264, -832, 128, 128, -144, 168, 0, 0,
0, 104, 512, -512, 0, 0, 0, 0,
312, 0, -128, 0, 0, 0, 0, 0,
0, -128, 0, 0, 0, 0, 0, 0,
128, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
uint8_t decoded_block[64] =
{
38, 40, 48, 70, 84, 72, 81, 119,
40, 34, 32, 61, 87, 68, 52, 74,
51, 44, 39, 74, 110, 82, 48, 61,
63, 67, 63, 86, 110, 78, 54, 83,
80, 93, 88, 84, 80, 58, 71, 128,
77, 89, 85, 69, 59, 64, 111, 176,
57, 63, 66, 66, 74, 106, 155, 192,
62, 60, 71, 90, 117, 160, 190, 191,
}
int16_t quantized_coeffs[64] =
{
82, -16, 3, -2, 3, -2, 0, 0,
-14, 8, -6, 2, 2, -1, 0, 0,
3, -8, 1, 1, -1, 1, 0, 0,
0, 1, 4, -4, 0, 0, 0, 0,
3, 0, -1, 0, 0, 0, 0, 0,
0, -1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
int16_t quantized_coeffs[64] =
{
82, -16, 3, -2, 3, -2, two zeros
-14, 8, -6, 2, 2, -1, two zeros
3, -8, 1, 1, -1, 1, three zeros
1, 4, -4, four zeros
3, 0, -1, six zeros
-1, six zeros
1, seven zeros
eight zeros
};
82, -16, -14, 3, 8, 3, -2, -6, -8
one zero
3, 1, 1, 2, 3, -2, 2, 1, 4
two zeros
1, -1, -1, -4, -1, -1
three zeros
1
the rest is just zeros...
82, -16, -14, 3, 8, 3, -2, -6, -8
one zero
3, 1, 1, 2, 3, -2, 2, 1, 4
two zeros
1, -1, -1, -4, -1, -1
three zeros
1
the rest is just zeros...
-> variable-length codes (VLC)
-4 100011
-16 1101001111
-14 10110001
3 0111
8 10111000
3 0111
-2 0101
-6 100001
-8 10110111
3 1101111
1 001
1 001
2 0110
3 0111
-2 0101
2 0110
1 001
4 100100
1 111001
-1 000
-1 000
-4 100011
-1 000
-1 000
1 1110101
macroblock ->
block
|
</
uint8_t block[64] =
{
39, 35, 40, 87, 87, 65, 86, 121,
37, 35, 38, 55, 90, 65, 50, 72,
47, 40, 42, 68, 112, 77, 56, 66,
72, 66, 66, 90, 108, 74, 53, 87,
84, 84, 91, 83, 72, 57, 66, 126,
86, 90, 80, 76, 55, 65, 113, 173,
54, 60, 57, 64, 77, 107, 160, 198,
63, 65, 75, 88, 127, 158, 188, 202,
};
<- values
uint8_t block[64] =
{
39, 35, 40, 87, 87, 65, 86, 121,
37, 35, 38, 55, 90, 65, 50, 72,
47, 40, 42, 68, 112, 77, 56, 66,
72, 66, 66, 90, 108, 74, 53, 87,
84, 84, 91, 83, 72, 57, 66, 126,
86, 90, 80, 76, 55, 65, 113, 173,
54, 60, 57, 64, 77, 107, 160, 198,
63, 65, 75, 88, 127, 158, 188, 202,
};
int16_t dct_coeffs[64] =
{
5270, -1303, 294, -240, 462, -217, -16, 30,
-1151, 648, -664, 205, 262, -93, -26, 23,
308, -892, 84, 116, -107, 107, -78, 7,
-29, 131, 484, -465, 44, 100, -23, -101,
340, 41, -140, -35, 72, 24, 28, -24,
27, -191, 13, 14, 57, 44, -71, -35,
169, 1, 4, -4, 25, 40, -38, -8,
-54, -80, -5, -13, -14, 12, 8, 26,
};
magic
->
-------\
|
quantization|
(lossy) |
<---------------/
int16_t quantized_coeffs[64] =
{
82, -16, 3, -2, 3, -2, 0, 0,
-14, 8, -6, 2, 2, -1, 0, 0,
3, -8, 1, 1, -1, 1, 0, 0,
0, 1, 4, -4, 0, 0, 0, 0,
3, 0, -1, 0, 0, 0, 0, 0,
0, -1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
82, -16, -14, 3, 8, 3, -2, -6, -8
one zero
3, 1, 1, 2, 3, -2, 2, 1, 4
two zeros
1, -1, -1, -4, -1, -1
three zeros
1
the rest is just zeros...
<- zig-zag
|
|
\- variable-length codes ->
10001111010011111011000101111011 10000111010110000110110111110111 10010010110011101010110001100100 1110010000001000110000001110101
10001111 01001111 10110001 01111011 10000111 01011000 01101101 11110111 10010010 11001110 10101100 01100100 11100100 00001000 11000000 11101010
10001111010011111011000101111011 10000111010110000110110111110111 10010010110011101010110001100100 1110010000001000110000001110101
Bitstream
split in 8 bits
8f 4f b1 7b 87 58 6d f7 92 ce ac 64 e4 08 c0 ea
hexdump
8f 4f b1 7b 87 58 6d f7
42 ce ac 64 e4 08 c0 ea
glitched bytes
10001111010011111011000101111011
10000111010110000110110111110111
00100010110011101010110001100100
1110010000001000110000001110101
glitched bitstream
10001111010011111011000101111011 10000111010110000110110111110111 10010010110011101010110001100100 1110010000001000110000001110101
Bitstream
10001111010011111011000101111011
10000111010110000110110111110111
00100010110011101010110001100100
1110010000001000110000001110101
glitched bitstream
10001111010011111011000101111011 10000111010110000110110111110111 00010010110011101010110001100100 1110010000001000110000001110101
glitched bitstream
10001111010011111011000101111011 10000111010110000110110111110111 10010010110011101010110001100100 1110010000001000110000001110101
Bitstream
glitched bitstream
int16_t quantized_coeffs[64] =
{
82, -16, 3, -2, 3, -2, 0, 0,
-14, 8, -6, 2, 2, -1, 0, 0,
3, -8, 1, 1, -1, 1, 0, 0,
0, 1, 4, -4, 0, 0, 0, 0,
3, 0, -1, 0, 0, 0, 0, 0,
0, -1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
10001111010011111011000101111011 10000111010110000110110111110111 00010010110011101010110001100100 1110010000001000110000001110101
int16_t glitched_coeffs[64] =
{
82, -16, 3, -2, -2, 2, 0, 0,
-14, 8, -6, 3, 1, 0, 1, 0,
3, -8, 2, 4, -1, 0, 0, 0,
0, -6, 0, -1, 0, 0, 0, 0,
2, 0, -4, 0, 0, 0, 0, 0,
1, -1, 0, 0, 0, 0, 0, 0,
-1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
10001111 01001111 10110001 01111011 10000111 01011000 01101101 11110111 10010010 11001110 10101100 01100100 11100100 00001000 11000000 11101010
10001111010011111011000101111011 10000111010110000110110111110111 10010010110011101010110001100100 1110010000001000110000001110101
Bitstream
split in 8 bits
8f 4f b1 7b 87 58 6d f7 92 ce ac 64 e4 08 c0 ea
hexdump
8f 4f b1 7b 87 58 6d f7 92 ce ac 64 e4 08 c0 7f
glitched bytes
[mjpeg @ 0x2cc4ec0] error count: 66
10001111 01001111 10110001 01111011 10000111 01011000 01101101 11110111 10010010 11001110 10101100 01100100 11100100 00001000 11000000 11101011 01011110 11101011 00100101 10111100 01101111 00010110 11000111 11000011 00001101 10111011 01111001 11111010 01010
longer
bitstream
10001111 01001111 10110001 01111011 10000111 01011000 01101101 11110111 10010010 11001110 10101100 01100100 11100100 00001000 11000000 01111111 01011110 11101011 00100101 10111100 01101111 00010110 11000111 11000011 00001101 10111011 01111001 11111010 01010
longer
glitched
bitstream
too many coefficients!
[mjpeg @ 0x2cc4ec0] error count: 66
$ ffedit lena.jpg -f q_dct -e q_dct.json
^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^
| | | \-> export to file
| | \-> feature we want to edit
| \-> input file name
\-> program name (used to be called ffglitch)
{
"ffedit_version":"ffglitch-0.6.001",
"filename":"lena420.jpg",
"features":[
"q_dct"
],
"streams":[
{
"frames":[
{
"pts":0,
"dts":0,
"q_dct":{
"data":[
[
[
[.......]
[ -4, -16, -14, 3, 8, 3, -2, -6, -8, 0, 3, 1, 1, 2, 3, -1, 2, 1, 4, 0, 0, 1, -1, -1, -4, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 117, 4, -8, -4, 3, -5, 0, -3, 3, 0, -1, 2, -1, 0, -2, 0, -2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[.......]
]
]
]
}
}
]
}
]
}
Edit these values
$ ffedit lena.jpg -f q_dct -a q_dct.json glitched.jpg ^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^
| | | | \-> output file
| | | \-> apply from file
| | \-> feature we want to edit
| \-> input file name
\-> program name (used to be called ffglitch)
[ -4, -16, -14, 3, 8, 3, -2, -6, -8, 0, 3, 1, 1, 2, 3, -1, 2, 1, 4, 0, 0, 1, -1, -1, -4, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 117, 4, -8, -4, 3, -5, 0, -3, 3, 0, -1, 2, -1, 0, -2, 0, -2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ -4, -16, -14, 3, 8, 3, -2, -6, -8, 0, 3, 1, 1, 2, 3, -1, 2, 1, 4, 0, 0, 1, -1, -1, -4, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 42, 4, -8, -4, 3, -5, 0, -3, 3, 0, -1, 2, -1, 0, -2, 0, -2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
./ffglitch.py -i in.mpg -f mv -s script.py -o out.mpg
def glitch_frame(frame):
dct_data = frame["data"]
# for all 3 planes (y, cb, cr)
for plane in dct_data:
# for each row
for y in plane:
for i,x in enumerate(y):
y_ac = sorted(y[i][1:])
y[i] = [ y[i][0] ] + y_ac
# reorder entire macroblocks
frame_counter = 0
def glitch_frame(frame):
global frame_counter
# for every 20 frames...
if (frame_counter / 20) % 2 == 1:
# ... reorder all macroblocks in reverse
frame["data"] = frame["data"][::-1]
# increment frame counter
frame_counter = frame_counter + 1
frame_counter = 0
old_ants = []
def glitch_frame(frame):
# skip the first few frames because they suck
global frame_counter
frame_counter = frame_counter + 1
if frame_counter < 4:
return
# get frame width provided by FFglitch
global json_stream
mbs_per_row = json_stream["width"] / 16
# track the ant in this frame (longest macroblock)
mb_data = frame["data"]
lengths = []
for i,mb in enumerate(mb_data):
lengths.append((i, len(mb)))
lengths.sort(key=lambda mb: mb[1], reverse=True)
ant_mb = lengths[0][0]
# save macroblocks for this ant
global old_ants
ant = []
for i in xrange(-1,2):
for j in xrange(-1,2):
mb_idx = ant_mb+(i*mbs_per_row)+j
if mb_idx < 0 or mb_idx >= len(mb_data):
continue
ant.append((mb_idx, mb_data[mb_idx]))
old_ants.append(ant)
# copy ants 30 frames apart
for old_ant in old_ants[::-1][0::30]:
for mb in old_ant:
frame["data"][mb[0]] = mb[1]
Similar to a pixels from last frame?
I macroblock
Did it move?
Motion Vector
Differential
$ ffmpeg -s 16x16 -pix_fmt monow -f rawvideo -i /dev/zero \ -huffman default -pix_fmt yuvj420p -vframes 1 \ -y empty.jpeg
(not to scale)
{
"filename":"empty.jpeg",
"features":[
"q_dct"
],
"streams":[
{
"frames":[
{
"q_dct":{
"data":[
[
[
[ 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
],
[
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
]
],
[
[
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
]
],
[
[
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
]
]
]
}
}
],
"width":16,
"height":16
}
]
}
def glitch_frame(frame):
dct_data = frame["data"]
# for all 3 planes (y, cb, cr)
for plane in dct_data:
# for each row
for y in plane:
for i,x in enumerate(y):
for j,c in enumerate("/'fu:bar/ 2018"):
y[i][j+1] = ord(c)
$ ./ffglitch.py -i empty.jpeg -f q_dct \ -s text_inject.py -o fubar.jpg