View Raw SPL
/*****************************************************************************
*                                                                            *
*   IDCT.SPL     Copyright (C) 1998-2012 DSP Development Corporation         *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:      Randy Race                                                  *
*                                                                            *
*   Synopsis:    Calculates the Inverse Discrete Cosine Transform            *
*                                                                            *
*   Revisions:   16 Mar 1998  RRR  Creation                                  *
*                25 Apr 2012  RRR  scaling                                   *
*                                                                            *
*****************************************************************************/


#if @HELP_IDCT

    IDCT

    Purpose: Calculates the Inverse Discrete Cosine Transform

    Syntax:  IDCT(s, n)

              s - input series or array

              n - optional integer, transform length (defaults to length
                  of input)

    Returns: A series or array.

    Example:
             idct(dct(gcos(100, 1/100, 20)))

             returns a 20 Hz cosine wave.

    Remarks:
             The transform is applied to each column if the input is an
             array. The IDCT is often used in conjunction with DCT
             to perform image compression.

    See Also:
             Dct
             Dct2
             Fft
             Idct2
             Ifft

    References:

    [1] Jae S. Lim, "Two-dimensional Signal and Image Processing",
        pp. 148-162.  Implements an even-symmetrical DCT.

    [2] Jain, "Fundamentals of Digital Image Processing", pp. 150-153.

    [3] Wallace, "The JPEG Still Picture Compression Standard",
        Communications of the ACM, April 1991.

#endif


/* compute the inverse discrete cosine transform */
ITERATE idct(b, n)
{
        local bb, y, yy, ww, a;

        if (argc < 2)
        {
                n  = length(b);
                bb = refseries(b);
        }
        else
        {
                bb = extract(b, 1, n);
        }
        
        /* weights */
        ww     = exp(i * (0..n - 1) * pi / (2 * n)) * sqrt(2 * n);
        ww[1] *= sqrt(2);

        if ((n % 2) == 1)
        {
                /*
                 *  odd case
                 */

                /* even symmetric series */
                yy = {ww * bb, 0, -i * ww[2..n] * reverse(bb[2..n])};

                /* X units */
                sethunits(yy, gethunits(bb));

                y = ifft(yy);

                /* extract inverse DCT */
                a = extract(y, 1, n);
        }

        else
        {
                /*
                 *  even case
                 */
                 
                /* compute precorrection factor */
                ww[1] /= 2;

                /* weights */                
                yy = ww * bb;

                /* units */
                sethunits(yy, gethunits(bb));

                /* compute x tilde using equation (5.93) in Jain */
                y = ifft(yy);

                /*
                 *  reorder elements of each column according to equations (5.93)
                 *  and (5.94) in Jain
                 */
                 
                a = merge(extract(y, 1, int(n / 2)), rev(extract(y, int(n / 2 + 1), n / 2)));
        }

        if (isreal(b))
        {
                a = real(a);
        }

        /* set correct deltax */
        setdeltax(a, 1 / (2 * n * deltax(b)));

        return(a);
}