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

  1. Export data
  2. Glitch data
  3. 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

deck

By Ramiro Polla

deck

  • 119