#[inline(always)]
pub fn identity_transform(pixels: &[f32; 64], coefficients: &mut [f32; 64]) {
for y in 0..2usize {
for x in 0..2usize {
let mut block_dc = 0.0f32;
for iy in 0..4 {
for ix in 0..4 {
block_dc += pixels[(y * 4 + iy) * 8 + x * 4 + ix];
}
}
block_dc *= 1.0 / 16.0;
let ref_pixel = pixels[(y * 4 + 1) * 8 + x * 4 + 1];
for iy in 0..4usize {
for ix in 0..4usize {
if ix == 1 && iy == 1 {
continue; }
coefficients[(y + iy * 2) * 8 + x + ix * 2] =
pixels[(y * 4 + iy) * 8 + x * 4 + ix] - ref_pixel;
}
}
coefficients[(y + 2) * 8 + x + 2] = coefficients[y * 8 + x];
coefficients[y * 8 + x] = block_dc;
}
}
let block00 = coefficients[0];
let block01 = coefficients[1];
let block10 = coefficients[8];
let block11 = coefficients[9];
coefficients[0] = (block00 + block01 + block10 + block11) * 0.25;
coefficients[1] = (block00 + block01 - block10 - block11) * 0.25;
coefficients[8] = (block00 - block01 + block10 - block11) * 0.25;
coefficients[9] = (block00 - block01 - block10 + block11) * 0.25;
}
#[inline(always)]
fn dct2_top_block_first<const S: usize>(block: &[f32; 64], out: &mut [f32; 64]) {
let num_2x2 = S / 2;
let mut temp = [0.0f32; 64];
for y in 0..num_2x2 {
for x in 0..num_2x2 {
let c00 = block[y * 2 * 8 + x * 2];
let c01 = block[y * 2 * 8 + x * 2 + 1];
let c10 = block[(y * 2 + 1) * 8 + x * 2];
let c11 = block[(y * 2 + 1) * 8 + x * 2 + 1];
let r00 = (c00 + c01 + c10 + c11) * 0.25;
let r01 = (c00 + c01 - c10 - c11) * 0.25;
let r10 = (c00 - c01 + c10 - c11) * 0.25;
let r11 = (c00 - c01 - c10 + c11) * 0.25;
temp[y * 8 + x] = r00;
temp[y * 8 + num_2x2 + x] = r01;
temp[(y + num_2x2) * 8 + x] = r10;
temp[(y + num_2x2) * 8 + num_2x2 + x] = r11;
}
}
for y in 0..S {
out[y * 8..y * 8 + S].copy_from_slice(&temp[y * 8..y * 8 + S]);
}
}
#[inline(always)]
fn dct2_top_block_inplace<const S: usize>(data: &mut [f32; 64]) {
let num_2x2 = S / 2;
let mut temp = [0.0f32; 64];
for y in 0..num_2x2 {
for x in 0..num_2x2 {
let c00 = data[y * 2 * 8 + x * 2];
let c01 = data[y * 2 * 8 + x * 2 + 1];
let c10 = data[(y * 2 + 1) * 8 + x * 2];
let c11 = data[(y * 2 + 1) * 8 + x * 2 + 1];
let r00 = (c00 + c01 + c10 + c11) * 0.25;
let r01 = (c00 + c01 - c10 - c11) * 0.25;
let r10 = (c00 - c01 + c10 - c11) * 0.25;
let r11 = (c00 - c01 - c10 + c11) * 0.25;
temp[y * 8 + x] = r00;
temp[y * 8 + num_2x2 + x] = r01;
temp[(y + num_2x2) * 8 + x] = r10;
temp[(y + num_2x2) * 8 + num_2x2 + x] = r11;
}
}
for y in 0..S {
data[y * 8..y * 8 + S].copy_from_slice(&temp[y * 8..y * 8 + S]);
}
}
#[inline(always)]
pub fn dct2x2_transform(pixels: &[f32; 64], coefficients: &mut [f32; 64]) {
dct2_top_block_first::<8>(pixels, coefficients);
dct2_top_block_inplace::<4>(coefficients);
dct2_top_block_inplace::<2>(coefficients);
}
#[inline(always)]
pub fn inverse_identity_transform(coefficients: &[f32; 64], pixels: &mut [f32; 64]) {
let block00 = coefficients[0];
let block01 = coefficients[1];
let block10 = coefficients[8];
let block11 = coefficients[9];
let dcs = [
block00 + block01 + block10 + block11,
block00 + block01 - block10 - block11,
block00 - block01 + block10 - block11,
block00 - block01 - block10 + block11,
];
for y in 0..2usize {
for x in 0..2usize {
let block_dc = dcs[y * 2 + x];
let mut residual_sum = 0.0f32;
for iy in 0..4usize {
for ix in 0..4usize {
if ix == 0 && iy == 0 {
continue;
}
residual_sum += coefficients[(y + iy * 2) * 8 + x + ix * 2];
}
}
let ref_pixel = block_dc - residual_sum * (1.0 / 16.0);
pixels[(4 * y + 1) * 8 + 4 * x + 1] = ref_pixel;
for iy in 0..4usize {
for ix in 0..4usize {
if ix == 1 && iy == 1 {
continue;
}
pixels[(y * 4 + iy) * 8 + x * 4 + ix] =
coefficients[(y + iy * 2) * 8 + x + ix * 2] + ref_pixel;
}
}
pixels[y * 4 * 8 + x * 4] = coefficients[(y + 2) * 8 + x + 2] + ref_pixel;
}
}
}
#[inline(always)]
fn idct2_top_block_inplace<const S: usize>(data: &mut [f32; 64]) {
let num_2x2 = S / 2;
let mut temp = [0.0f32; 64];
for y in 0..num_2x2 {
for x in 0..num_2x2 {
let c00 = data[y * 8 + x];
let c01 = data[y * 8 + num_2x2 + x];
let c10 = data[(y + num_2x2) * 8 + x];
let c11 = data[(y + num_2x2) * 8 + num_2x2 + x];
let r00 = c00 + c01 + c10 + c11;
let r01 = c00 + c01 - c10 - c11;
let r10 = c00 - c01 + c10 - c11;
let r11 = c00 - c01 - c10 + c11;
temp[y * 2 * 8 + x * 2] = r00;
temp[y * 2 * 8 + x * 2 + 1] = r01;
temp[(y * 2 + 1) * 8 + x * 2] = r10;
temp[(y * 2 + 1) * 8 + x * 2 + 1] = r11;
}
}
for y in 0..S {
data[y * 8..y * 8 + S].copy_from_slice(&temp[y * 8..y * 8 + S]);
}
}
#[inline(always)]
pub fn inverse_dct2x2_transform(coefficients: &[f32; 64], pixels: &mut [f32; 64]) {
*pixels = *coefficients;
idct2_top_block_inplace::<2>(pixels);
idct2_top_block_inplace::<4>(pixels);
idct2_top_block_inplace::<8>(pixels);
}