Blame view

mjpeg/dct.py 1.36 KB
1d19f0e7   Chunk   staged.
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
## $Id$
## -*- coding: utf-8 -*-

# jpeg.dct
# ========

from numpy import dot, linalg
import numpy


def auxcos(x, u):
    return numpy.cos((numpy.pi / 8) * (x + 0.5) * u)


def cosmat(M=8, N=8):
    C = numpy.array([[auxcos(x, u) for u in range(N)]
                     for x in range(M)]) / 2
    C[:, 0] = C[:, 0] / numpy.sqrt(2)
    # C[0,:] = C[0,:] / numpy.sqrt(2)
    return C


auxM = cosmat(8, 8)
invM = linalg.inv(auxM)
auxT = numpy.transpose(auxM)
invT = numpy.transpose(invM)


def dct2(g):
    """
      Perform a 2D DCT transform on g, assuming that g is 8x8.
    """
    assert (8, 8) == numpy.shape(g)
    return dot(auxT, dot(g, auxM))


def idct2(g):
    """
      Perform a 2D inverse DCT transform on g, assuming that g is 8x8.
    """
    assert (8, 8) == numpy.shape(g)
    # return dot( invM, dot( g, invT ) )
    return dot(invT, dot(g, invM))


def bdct(C, f=dct2):
    """
      Make a blockwise (8x8 blocks) 2D DCT transform on the matrix C.
      The optional second parameter f specifies the DCT transform function.
      The height and width of C have to be divisible by 8.
    """
    (M, N) = numpy.shape(C)
    assert M % 8 == 0
    assert N % 8 == 0
    S = numpy.ndarray((M, N))
    for i in range(0, M, 8):
        for j in range(0, N, 8):
            S[i:(i + 8), j:(j + 8)] = f(C[i:(i + 8), j:(j + 8)])
    return S


def ibdct(C): return bdct(C, f=idct2)