forward DCT computation "in one dimension" (fast AAN algorithm by Arai, Agui and Nakajima: "A fast DCT-SQ scheme for images")
| 204 | |
| 205 | // forward DCT computation "in one dimension" (fast AAN algorithm by Arai, Agui and Nakajima: "A fast DCT-SQ scheme for images") |
| 206 | void DCT(float block[8*8], uint8_t stride) // stride must be 1 (=horizontal) or 8 (=vertical) |
| 207 | { |
| 208 | const auto SqrtHalfSqrt = 1.306562965f; // sqrt((2 + sqrt(2)) / 2) = cos(pi * 1 / 8) * sqrt(2) |
| 209 | const auto InvSqrt = 0.707106781f; // 1 / sqrt(2) = cos(pi * 2 / 8) |
| 210 | const auto HalfSqrtSqrt = 0.382683432f; // sqrt(2 - sqrt(2)) / 2 = cos(pi * 3 / 8) |
| 211 | const auto InvSqrtSqrt = 0.541196100f; // 1 / sqrt(2 - sqrt(2)) = cos(pi * 3 / 8) * sqrt(2) |
| 212 | |
| 213 | // modify in-place |
| 214 | auto& block0 = block[0 ]; |
| 215 | auto& block1 = block[1 * stride]; |
| 216 | auto& block2 = block[2 * stride]; |
| 217 | auto& block3 = block[3 * stride]; |
| 218 | auto& block4 = block[4 * stride]; |
| 219 | auto& block5 = block[5 * stride]; |
| 220 | auto& block6 = block[6 * stride]; |
| 221 | auto& block7 = block[7 * stride]; |
| 222 | |
| 223 | // based on https://dev.w3.org/Amaya/libjpeg/jfdctflt.c , the original variable names can be found in my comments |
| 224 | auto add07 = block0 + block7; auto sub07 = block0 - block7; // tmp0, tmp7 |
| 225 | auto add16 = block1 + block6; auto sub16 = block1 - block6; // tmp1, tmp6 |
| 226 | auto add25 = block2 + block5; auto sub25 = block2 - block5; // tmp2, tmp5 |
| 227 | auto add34 = block3 + block4; auto sub34 = block3 - block4; // tmp3, tmp4 |
| 228 | |
| 229 | auto add0347 = add07 + add34; auto sub07_34 = add07 - add34; // tmp10, tmp13 ("even part" / "phase 2") |
| 230 | auto add1256 = add16 + add25; auto sub16_25 = add16 - add25; // tmp11, tmp12 |
| 231 | |
| 232 | block0 = add0347 + add1256; block4 = add0347 - add1256; // "phase 3" |
| 233 | |
| 234 | auto z1 = (sub16_25 + sub07_34) * InvSqrt; // all temporary z-variables kept their original names |
| 235 | block2 = sub07_34 + z1; block6 = sub07_34 - z1; // "phase 5" |
| 236 | |
| 237 | auto sub23_45 = sub25 + sub34; // tmp10 ("odd part" / "phase 2") |
| 238 | auto sub12_56 = sub16 + sub25; // tmp11 |
| 239 | auto sub01_67 = sub16 + sub07; // tmp12 |
| 240 | |
| 241 | auto z5 = (sub23_45 - sub01_67) * HalfSqrtSqrt; |
| 242 | auto z2 = sub23_45 * InvSqrtSqrt + z5; |
| 243 | auto z3 = sub12_56 * InvSqrt; |
| 244 | auto z4 = sub01_67 * SqrtHalfSqrt + z5; |
| 245 | auto z6 = sub07 + z3; // z11 ("phase 5") |
| 246 | auto z7 = sub07 - z3; // z13 |
| 247 | block1 = z6 + z4; block7 = z6 - z4; // "phase 6" |
| 248 | block5 = z7 + z2; block3 = z7 - z2; |
| 249 | } |
| 250 | |
| 251 | // run DCT, quantize and write Huffman bit codes |
| 252 | int16_t encodeBlock(BitWriter& writer, float block[8][8], const float scaled[8*8], int16_t lastDC, |