/// <summary>
/// Compute the Inverse DCT
/// </summary>
/// <param name="dctBuffer">F(u, v); DCT coefficients</param>
/// <param name="fBasis">DCT basis functions</param>
/// <param name="imgBuffer">f(x, y); destination image</param>
public PixelArray InverseDCT(PixelArray dctBuffer)
{
//int N = fBlockSize;
// extract the dimensions of the DCT buffer
int width = dctBuffer.Width;
int height = dctBuffer.Height;
PixelArray imgBuffer = new PixelArray(width, height, PixelType.BGRb, PixmapOrientation.TopToBottom, 1);
// intermediate result (an NxN block)
PixelArray dctBlock = new PixelArray(fBlockSize, fBlockSize, PixelType.RGBd, PixmapOrientation.TopToBottom, 1);
//
// for every NxN block of the coefficients
//
for (int y = 0; y < height; y += fBlockSize)
{
for (int x = 0; x < width; x += fBlockSize)
{
//
// do the first matrix multiplication
// ([fBasis][dctBuffer])
// and store the results in dctBlock
//
for (int col = 0; col < fBlockSize; ++col)
{
for (int row = 0; row < fBlockSize; ++row)
{
RGBd result = new RGBd(0.0, 0.0, 0.0);
for (int index = 0; index < fBlockSize; ++index)
{
RGBd coeff = new RGBd();
coeff.SetBytes(dctBuffer.GetPixelBytes(x + index, y + row));
double cosVal = fBasis[col, index];
result.red += cosVal * coeff.Red;
result.green += cosVal * coeff.Green;
result.blue += cosVal * coeff.Blue;
}
dctBlock.SetPixel(col, row, result);
}
}
//
// do the second matrix multiplication
// ([dctBlock][fBasis]')
// and store the results in imgBuffer
//
for (int col2 = 0; col2 < fBlockSize; ++col2)
{
for (int row2 = 0; row2 < fBlockSize; ++row2)
{
RGBd result = new RGBd(0.0, 0.0, 0.0);
for (int index = 0; index < fBlockSize; ++index)
{
RGBd coeff = new RGBd();
coeff.SetBytes(dctBlock.GetPixelBytes(col2, index));
double cosVal_transpose = fBasis[row2, index];
result.red += coeff.Red * cosVal_transpose;
result.green += coeff.Green * cosVal_transpose;
result.blue += coeff.Blue * cosVal_transpose;
}
//
// assign the computed value back to the image
//
byte red = (byte)Math.Floor(result.Red + 0.5);
byte green = (byte)Math.Floor(result.Green + 0.5);
byte blue = (byte)Math.Floor(result.Blue + 0.5);
BGRb new_pixel = new BGRb(red, green, blue);
imgBuffer.SetPixel(x + col2, y + row2, new_pixel);
}
}
}
}
return imgBuffer;
}