1 /* 2 Copyright (c) 2014 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 // dimage is actually stripped out part of dlib - just to support reading PNG and JPEG 30 module dimage.idct; //dlib.image.io.idct 31 32 import std.math; 33 34 /* 35 * Inverse discrete cosine transform (DCT) for 64x64 blocks 36 */ 37 38 enum blockSize = 64; // A DCT block is 8x8. 39 40 enum w1 = 2841; // 2048*sqrt(2)*cos(1*pi/16) 41 enum w2 = 2676; // 2048*sqrt(2)*cos(2*pi/16) 42 enum w3 = 2408; // 2048*sqrt(2)*cos(3*pi/16) 43 enum w5 = 1609; // 2048*sqrt(2)*cos(5*pi/16) 44 enum w6 = 1108; // 2048*sqrt(2)*cos(6*pi/16) 45 enum w7 = 565; // 2048*sqrt(2)*cos(7*pi/16) 46 47 enum w1pw7 = w1 + w7; 48 enum w1mw7 = w1 - w7; 49 enum w2pw6 = w2 + w6; 50 enum w2mw6 = w2 - w6; 51 enum w3pw5 = w3 + w5; 52 enum w3mw5 = w3 - w5; 53 54 enum r2 = 181; // 256/sqrt(2) 55 56 // idct performs a 2-D Inverse Discrete Cosine Transformation. 57 // 58 // The input coefficients should already have been multiplied by the 59 // appropriate quantization table. We use fixed-point computation, with the 60 // number of bits for the fractional component varying over the intermediate 61 // stages. 62 // 63 // For more on the actual algorithm, see Z. Wang, "Fast algorithms for the 64 // discrete W transform and for the discrete Fourier transform", IEEE Trans. on 65 // ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984. 66 void idct64(int* src) 67 { 68 // Horizontal 1-D IDCT. 69 for (uint y = 0; y < 8; y++) 70 { 71 int y8 = y * 8; 72 // If all the AC components are zero, then the IDCT is trivial. 73 if (src[y8+1] == 0 && src[y8+2] == 0 && src[y8+3] == 0 && 74 src[y8+4] == 0 && src[y8+5] == 0 && src[y8+6] == 0 && src[y8+7] == 0) 75 { 76 int dc = src[y8+0] << 3; 77 src[y8+0] = dc; 78 src[y8+1] = dc; 79 src[y8+2] = dc; 80 src[y8+3] = dc; 81 src[y8+4] = dc; 82 src[y8+5] = dc; 83 src[y8+6] = dc; 84 src[y8+7] = dc; 85 continue; 86 } 87 88 // Prescale. 89 int x0 = (src[y8+0] << 11) + 128; 90 int x1 = src[y8+4] << 11; 91 int x2 = src[y8+6]; 92 int x3 = src[y8+2]; 93 int x4 = src[y8+1]; 94 int x5 = src[y8+7]; 95 int x6 = src[y8+5]; 96 int x7 = src[y8+3]; 97 98 // Stage 1. 99 int x8 = w7 * (x4 + x5); 100 x4 = x8 + w1mw7*x4; 101 x5 = x8 - w1pw7*x5; 102 x8 = w3 * (x6 + x7); 103 x6 = x8 - w3mw5*x6; 104 x7 = x8 - w3pw5*x7; 105 106 // Stage 2. 107 x8 = x0 + x1; 108 x0 -= x1; 109 x1 = w6 * (x3 + x2); 110 x2 = x1 - w2pw6*x2; 111 x3 = x1 + w2mw6*x3; 112 x1 = x4 + x6; 113 x4 -= x6; 114 x6 = x5 + x7; 115 x5 -= x7; 116 117 // Stage 3. 118 x7 = x8 + x3; 119 x8 -= x3; 120 x3 = x0 + x2; 121 x0 -= x2; 122 x2 = (r2*(x4+x5) + 128) >> 8; 123 x4 = (r2*(x4-x5) + 128) >> 8; 124 125 // Stage 4. 126 src[y8+0] = (x7 + x1) >> 8; 127 src[y8+1] = (x3 + x2) >> 8; 128 src[y8+2] = (x0 + x4) >> 8; 129 src[y8+3] = (x8 + x6) >> 8; 130 src[y8+4] = (x8 - x6) >> 8; 131 src[y8+5] = (x0 - x4) >> 8; 132 src[y8+6] = (x3 - x2) >> 8; 133 src[y8+7] = (x7 - x1) >> 8; 134 } 135 136 // Vertical 1-D IDCT. 137 for (uint x = 0; x < 8; x++) 138 { 139 // Similar to the horizontal 1-D IDCT case, if all the AC components are zero, then the IDCT is trivial. 140 // However, after performing the horizontal 1-D IDCT, there are typically non-zero AC components, so 141 // we do not bother to check for the all-zero case. 142 143 // Prescale. 144 int y0 = (src[8*0+x] << 8) + 8192; 145 int y1 = src[8*4+x] << 8; 146 int y2 = src[8*6+x]; 147 int y3 = src[8*2+x]; 148 int y4 = src[8*1+x]; 149 int y5 = src[8*7+x]; 150 int y6 = src[8*5+x]; 151 int y7 = src[8*3+x]; 152 153 // Stage 1. 154 int y8 = w7*(y4+y5) + 4; 155 y4 = (y8 + w1mw7*y4) >> 3; 156 y5 = (y8 - w1pw7*y5) >> 3; 157 y8 = w3*(y6+y7) + 4; 158 y6 = (y8 - w3mw5*y6) >> 3; 159 y7 = (y8 - w3pw5*y7) >> 3; 160 161 // Stage 2. 162 y8 = y0 + y1; 163 y0 -= y1; 164 y1 = w6*(y3+y2) + 4; 165 y2 = (y1 - w2pw6*y2) >> 3; 166 y3 = (y1 + w2mw6*y3) >> 3; 167 y1 = y4 + y6; 168 y4 -= y6; 169 y6 = y5 + y7; 170 y5 -= y7; 171 172 // Stage 3. 173 y7 = y8 + y3; 174 y8 -= y3; 175 y3 = y0 + y2; 176 y0 -= y2; 177 y2 = (r2*(y4+y5) + 128) >> 8; 178 y4 = (r2*(y4-y5) + 128) >> 8; 179 180 // Stage 4. 181 src[8*0+x] = (y7 + y1) >> 14; 182 src[8*1+x] = (y3 + y2) >> 14; 183 src[8*2+x] = (y0 + y4) >> 14; 184 src[8*3+x] = (y8 + y6) >> 14; 185 src[8*4+x] = (y8 - y6) >> 14; 186 src[8*5+x] = (y0 - y4) >> 14; 187 src[8*6+x] = (y3 - y2) >> 14; 188 src[8*7+x] = (y7 - y1) >> 14; 189 } 190 } 191 192 /* 193 void idct(float* inMat, float* outMat) 194 { 195 uint i, j, u, v; 196 float s; 197 198 for (i = 0; i < 8; i++) 199 for (j = 0; j < 8; j++) 200 { 201 s = 0; 202 203 for (u = 0; u < 8; u++) 204 for (v = 0; v < 8; v++) 205 { 206 s += inMat[u * 8 + v] 207 * cos((2 * i + 1) * u * PI / 16.0f) 208 * cos((2 * j + 1) * v * PI / 16.0f) 209 * ((u == 0) ? 1 / sqrt(2.0f) : 1.0f) 210 * ((v == 0) ? 1 / sqrt(2.0f) : 1.0f); 211 } 212 213 outMat[i * 8 + j] = s / 4.0f; 214 } 215 } 216 */ 217