FFglitch
/’fu:bar/ 2018
Ramiro Polla
Who?
- Ramiro Polla (from Brazil)
- I like hacking things
- Not bad with technical stuff, shitty as an artist
- FFmpeg dev for 5 years
- I live in Liège [BE], work as a software developer
- One million side projects
- FFglitch
What?
- Command line program (no GUI)
- Hacked FFmpeg
- Multimedia bitstream editor
- Hex editor (bytes vs bits)
- Radioactive axe
- FFglitch (bitstream)
- Genetic engineering
- True Glitch or not True Glitch?
When?
- Kaspar's post on Facebook 2 years ago
- Edit motion vectors from a video file
- I have an idea...
- It might actually be useful to someone
- Proof of concept in a couple of weeks
sink and rise
sink and rise
sink and rise
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
Codec Crash Course

Codec Crash Course



Y
U
V
Codec Crash Course

Codec Crash Course

Codec Crash Course

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,
};
Codec Crash Course
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
->
Codec Crash Course
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
->
Codec Crash Course
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,
}


Codec Crash Course
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...
Codec Crash Course
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
Codec Crash Course (recap)




Codec Crash Course (recap)



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
Codec Crash Course (recap)
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
Radioactive axe
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
Radioactive axe
10001111010011111011000101111011 10000111010110000110110111110111 10010010110011101010110001100100 1110010000001000110000001110101
Bitstream
10001111010011111011000101111011
10000111010110000110110111110111
00100010110011101010110001100100
1110010000001000110000001110101
glitched bitstream
10001111010011111011000101111011 10000111010110000110110111110111 00010010110011101010110001100100 1110010000001000110000001110101
glitched bitstream
Radioactive axe
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,
};
Radioactive axe
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
Radioactive axe
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
Enter FFglitch
- Export data
- Glitch data
- Apply glitched data
1. Export data
$ 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)
1. Export data
{
"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
2. Glitch data
3. Apply glitched data
$ 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 ],
JPEG DC glitch

Python scripting
./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
DCT AC sorting

choo choo
choo choo
# 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
choo ooɥɔ
one ant
many ants
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]
More on
Motion Vectors
- Used in P frames (predictive, inter)
- Not used in I frames (intra)
- I frames are like normal JPEG images
More on
Motion Vectors
Similar to a pixels from last frame?
I macroblock
Did it move?
Motion Vector
Differential
choo choo
choo choo crap
Preparing files
- Hacked FFmpeg
- Works with MPEG codecs
- Works with libxvid too
- Forces writing motion vectors
(even when they're zero) - Prevents I macroblocks in P frames
- -mpv_flags +nopimb+forcemv
choo choo choo
Motion Vector
Transplant
Motion Vector
Transplant
Motion Vector
Transplant
Empty JPEG
$ 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
Empty JPEG

Empty JPEG
What's next?
- More codecs (png, h264)
currently JPEG, MPEG[2-4] - More formats (mov, mkv)
currently raw and AVI - More features
currently DCT, quantization,
huffman tables, motion vectors - More examples
- Graphical User Interface
- Feedback!
Contact
- http://ffglitch.org
- https://github.com/ramiropolla
https://fb.com/ramiro.polla- ramiro.polla@gmail.com
deck
By Ramiro Polla
deck
- 119