1 // jpgd.h - C++ class for JPEG decompression. 2 // Rich Geldreich <richgel99@gmail.com> 3 // Alex Evans: Linear memory allocator (taken from jpge.h). 4 // v1.04, May. 19, 2012: Code tweaks to fix VS2008 static code analysis warnings (all looked harmless) 5 // D translation by Ketmar // Invisible Vector 6 // 7 // This is free and unencumbered software released into the public domain. 8 // 9 // Anyone is free to copy, modify, publish, use, compile, sell, or 10 // distribute this software, either in source code form or as a compiled 11 // binary, for any purpose, commercial or non-commercial, and by any 12 // means. 13 // 14 // In jurisdictions that recognize copyright laws, the author or authors 15 // of this software dedicate any and all copyright interest in the 16 // software to the public domain. We make this dedication for the benefit 17 // of the public at large and to the detriment of our heirs and 18 // successors. We intend this dedication to be an overt act of 19 // relinquishment in perpetuity of all present and future rights to this 20 // software under copyright law. 21 // 22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 26 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 // OTHER DEALINGS IN THE SOFTWARE. 29 // 30 // For more information, please refer to <http://unlicense.org/> 31 // 32 // Supports progressive and baseline sequential JPEG image files, and the most common chroma subsampling factors: Y, H1V1, H2V1, H1V2, and H2V2. 33 // 34 // Chroma upsampling quality: H2V2 is upsampled in the frequency domain, H2V1 and H1V2 are upsampled using point sampling. 35 // Chroma upsampling reference: "Fast Scheme for Image Size Change in the Compressed Domain" 36 // http://vision.ai.uiuc.edu/~dugad/research/dct/index.html 37 /** 38 * Loads a JPEG image from a memory buffer or a file. 39 * req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA). 40 * On return, width/height will be set to the image's dimensions, and actual_comps will be set to the either 1 (grayscale) or 3 (RGB). 41 * Requesting a 8 or 32bpp image is currently a little faster than 24bpp because the jpeg_decoder class itself currently always unpacks to either 8 or 32bpp. 42 */ 43 module arsd.jpeg; 44 45 // Set to 1 to enable freq. domain chroma upsampling on images using H2V2 subsampling (0=faster nearest neighbor sampling). 46 // This is slower, but results in higher quality on images with highly saturated colors. 47 version = JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING; 48 49 /// Input stream interface. 50 /// This delegate is called when the internal input buffer is empty. 51 /// Parameters: 52 /// pBuf - input buffer 53 /// max_bytes_to_read - maximum bytes that can be written to pBuf 54 /// pEOF_flag - set this to true if at end of stream (no more bytes remaining) 55 /// Returns -1 on error, otherwise return the number of bytes actually written to the buffer (which may be 0). 56 /// Notes: This delegate will be called in a loop until you set *pEOF_flag to true or the internal buffer is full. 57 alias JpegStreamReadFunc = int delegate (void* pBuf, int max_bytes_to_read, bool* pEOF_flag); 58 59 60 // ////////////////////////////////////////////////////////////////////////// // 61 private: 62 void *jpgd_malloc (size_t nSize) { import core.stdc.stdlib : malloc; return malloc(nSize); } 63 void jpgd_free (void *p) { import core.stdc.stdlib : free; if (p !is null) free(p); } 64 65 // Success/failure error codes. 66 alias jpgd_status = int; 67 enum /*jpgd_status*/ { 68 JPGD_SUCCESS = 0, JPGD_FAILED = -1, JPGD_DONE = 1, 69 JPGD_BAD_DHT_COUNTS = -256, JPGD_BAD_DHT_INDEX, JPGD_BAD_DHT_MARKER, JPGD_BAD_DQT_MARKER, JPGD_BAD_DQT_TABLE, 70 JPGD_BAD_PRECISION, JPGD_BAD_HEIGHT, JPGD_BAD_WIDTH, JPGD_TOO_MANY_COMPONENTS, 71 JPGD_BAD_SOF_LENGTH, JPGD_BAD_VARIABLE_MARKER, JPGD_BAD_DRI_LENGTH, JPGD_BAD_SOS_LENGTH, 72 JPGD_BAD_SOS_COMP_ID, JPGD_W_EXTRA_BYTES_BEFORE_MARKER, JPGD_NO_ARITHMITIC_SUPPORT, JPGD_UNEXPECTED_MARKER, 73 JPGD_NOT_JPEG, JPGD_UNSUPPORTED_MARKER, JPGD_BAD_DQT_LENGTH, JPGD_TOO_MANY_BLOCKS, 74 JPGD_UNDEFINED_QUANT_TABLE, JPGD_UNDEFINED_HUFF_TABLE, JPGD_NOT_SINGLE_SCAN, JPGD_UNSUPPORTED_COLORSPACE, 75 JPGD_UNSUPPORTED_SAMP_FACTORS, JPGD_DECODE_ERROR, JPGD_BAD_RESTART_MARKER, JPGD_ASSERTION_ERROR, 76 JPGD_BAD_SOS_SPECTRAL, JPGD_BAD_SOS_SUCCESSIVE, JPGD_STREAM_READ, JPGD_NOTENOUGHMEM, 77 } 78 79 enum { 80 JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4, 81 JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384, 82 } 83 84 // DCT coefficients are stored in this sequence. 85 static immutable int[64] g_ZAG = [ 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 ]; 86 87 alias JPEG_MARKER = int; 88 enum /*JPEG_MARKER*/ { 89 M_SOF0 = 0xC0, M_SOF1 = 0xC1, M_SOF2 = 0xC2, M_SOF3 = 0xC3, M_SOF5 = 0xC5, M_SOF6 = 0xC6, M_SOF7 = 0xC7, M_JPG = 0xC8, 90 M_SOF9 = 0xC9, M_SOF10 = 0xCA, M_SOF11 = 0xCB, M_SOF13 = 0xCD, M_SOF14 = 0xCE, M_SOF15 = 0xCF, M_DHT = 0xC4, M_DAC = 0xCC, 91 M_RST0 = 0xD0, M_RST1 = 0xD1, M_RST2 = 0xD2, M_RST3 = 0xD3, M_RST4 = 0xD4, M_RST5 = 0xD5, M_RST6 = 0xD6, M_RST7 = 0xD7, 92 M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_DNL = 0xDC, M_DRI = 0xDD, M_DHP = 0xDE, M_EXP = 0xDF, 93 M_APP0 = 0xE0, M_APP15 = 0xEF, M_JPG0 = 0xF0, M_JPG13 = 0xFD, M_COM = 0xFE, M_TEM = 0x01, M_ERROR = 0x100, RST0 = 0xD0, 94 } 95 96 alias JPEG_SUBSAMPLING = int; 97 enum /*JPEG_SUBSAMPLING*/ { JPGD_GRAYSCALE = 0, JPGD_YH1V1, JPGD_YH2V1, JPGD_YH1V2, JPGD_YH2V2 }; 98 99 enum CONST_BITS = 13; 100 enum PASS1_BITS = 2; 101 enum SCALEDONE = cast(int)1; 102 103 enum FIX_0_298631336 = cast(int)2446; /* FIX(0.298631336) */ 104 enum FIX_0_390180644 = cast(int)3196; /* FIX(0.390180644) */ 105 enum FIX_0_541196100 = cast(int)4433; /* FIX(0.541196100) */ 106 enum FIX_0_765366865 = cast(int)6270; /* FIX(0.765366865) */ 107 enum FIX_0_899976223 = cast(int)7373; /* FIX(0.899976223) */ 108 enum FIX_1_175875602 = cast(int)9633; /* FIX(1.175875602) */ 109 enum FIX_1_501321110 = cast(int)12299; /* FIX(1.501321110) */ 110 enum FIX_1_847759065 = cast(int)15137; /* FIX(1.847759065) */ 111 enum FIX_1_961570560 = cast(int)16069; /* FIX(1.961570560) */ 112 enum FIX_2_053119869 = cast(int)16819; /* FIX(2.053119869) */ 113 enum FIX_2_562915447 = cast(int)20995; /* FIX(2.562915447) */ 114 enum FIX_3_072711026 = cast(int)25172; /* FIX(3.072711026) */ 115 116 int DESCALE() (int x, int n) { pragma(inline, true); return (((x) + (SCALEDONE << ((n)-1))) >> (n)); } 117 int DESCALE_ZEROSHIFT() (int x, int n) { pragma(inline, true); return (((x) + (128 << (n)) + (SCALEDONE << ((n)-1))) >> (n)); } 118 ubyte CLAMP() (int i) { pragma(inline, true); return cast(ubyte)(cast(uint)i > 255 ? (((~i) >> 31) & 0xFF) : i); } 119 120 121 // Compiler creates a fast path 1D IDCT for X non-zero columns 122 struct Row(int NONZERO_COLS) { 123 pure nothrow @trusted @nogc: 124 static void idct(int* pTemp, const(jpeg_decoder.jpgd_block_t)* pSrc) { 125 static if (NONZERO_COLS == 0) { 126 // nothing 127 } else static if (NONZERO_COLS == 1) { 128 immutable int dcval = (pSrc[0] << PASS1_BITS); 129 pTemp[0] = dcval; 130 pTemp[1] = dcval; 131 pTemp[2] = dcval; 132 pTemp[3] = dcval; 133 pTemp[4] = dcval; 134 pTemp[5] = dcval; 135 pTemp[6] = dcval; 136 pTemp[7] = dcval; 137 } else { 138 // ACCESS_COL() will be optimized at compile time to either an array access, or 0. 139 //#define ACCESS_COL(x) (((x) < NONZERO_COLS) ? (int)pSrc[x] : 0) 140 template ACCESS_COL(int x) { 141 static if (x < NONZERO_COLS) enum ACCESS_COL = "cast(int)pSrc["~x.stringof~"]"; else enum ACCESS_COL = "0"; 142 } 143 144 immutable int z2 = mixin(ACCESS_COL!2), z3 = mixin(ACCESS_COL!6); 145 146 immutable int z1 = (z2 + z3)*FIX_0_541196100; 147 immutable int tmp2 = z1 + z3*(-FIX_1_847759065); 148 immutable int tmp3 = z1 + z2*FIX_0_765366865; 149 150 immutable int tmp0 = (mixin(ACCESS_COL!0) + mixin(ACCESS_COL!4)) << CONST_BITS; 151 immutable int tmp1 = (mixin(ACCESS_COL!0) - mixin(ACCESS_COL!4)) << CONST_BITS; 152 153 immutable int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2; 154 155 immutable int atmp0 = mixin(ACCESS_COL!7), atmp1 = mixin(ACCESS_COL!5), atmp2 = mixin(ACCESS_COL!3), atmp3 = mixin(ACCESS_COL!1); 156 157 immutable int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3; 158 immutable int bz5 = (bz3 + bz4)*FIX_1_175875602; 159 160 immutable int az1 = bz1*(-FIX_0_899976223); 161 immutable int az2 = bz2*(-FIX_2_562915447); 162 immutable int az3 = bz3*(-FIX_1_961570560) + bz5; 163 immutable int az4 = bz4*(-FIX_0_390180644) + bz5; 164 165 immutable int btmp0 = atmp0*FIX_0_298631336 + az1 + az3; 166 immutable int btmp1 = atmp1*FIX_2_053119869 + az2 + az4; 167 immutable int btmp2 = atmp2*FIX_3_072711026 + az2 + az3; 168 immutable int btmp3 = atmp3*FIX_1_501321110 + az1 + az4; 169 170 pTemp[0] = DESCALE(tmp10 + btmp3, CONST_BITS-PASS1_BITS); 171 pTemp[7] = DESCALE(tmp10 - btmp3, CONST_BITS-PASS1_BITS); 172 pTemp[1] = DESCALE(tmp11 + btmp2, CONST_BITS-PASS1_BITS); 173 pTemp[6] = DESCALE(tmp11 - btmp2, CONST_BITS-PASS1_BITS); 174 pTemp[2] = DESCALE(tmp12 + btmp1, CONST_BITS-PASS1_BITS); 175 pTemp[5] = DESCALE(tmp12 - btmp1, CONST_BITS-PASS1_BITS); 176 pTemp[3] = DESCALE(tmp13 + btmp0, CONST_BITS-PASS1_BITS); 177 pTemp[4] = DESCALE(tmp13 - btmp0, CONST_BITS-PASS1_BITS); 178 } 179 } 180 } 181 182 183 // Compiler creates a fast path 1D IDCT for X non-zero rows 184 struct Col (int NONZERO_ROWS) { 185 pure nothrow @trusted @nogc: 186 static void idct(ubyte* pDst_ptr, const(int)* pTemp) { 187 static assert(NONZERO_ROWS > 0); 188 static if (NONZERO_ROWS == 1) { 189 int dcval = DESCALE_ZEROSHIFT(pTemp[0], PASS1_BITS+3); 190 immutable ubyte dcval_clamped = cast(ubyte)CLAMP(dcval); 191 pDst_ptr[0*8] = dcval_clamped; 192 pDst_ptr[1*8] = dcval_clamped; 193 pDst_ptr[2*8] = dcval_clamped; 194 pDst_ptr[3*8] = dcval_clamped; 195 pDst_ptr[4*8] = dcval_clamped; 196 pDst_ptr[5*8] = dcval_clamped; 197 pDst_ptr[6*8] = dcval_clamped; 198 pDst_ptr[7*8] = dcval_clamped; 199 } else { 200 // ACCESS_ROW() will be optimized at compile time to either an array access, or 0. 201 //#define ACCESS_ROW(x) (((x) < NONZERO_ROWS) ? pTemp[x * 8] : 0) 202 template ACCESS_ROW(int x) { 203 static if (x < NONZERO_ROWS) enum ACCESS_ROW = "pTemp["~(x*8).stringof~"]"; else enum ACCESS_ROW = "0"; 204 } 205 206 immutable int z2 = mixin(ACCESS_ROW!2); 207 immutable int z3 = mixin(ACCESS_ROW!6); 208 209 immutable int z1 = (z2 + z3)*FIX_0_541196100; 210 immutable int tmp2 = z1 + z3*(-FIX_1_847759065); 211 immutable int tmp3 = z1 + z2*FIX_0_765366865; 212 213 immutable int tmp0 = (mixin(ACCESS_ROW!0) + mixin(ACCESS_ROW!4)) << CONST_BITS; 214 immutable int tmp1 = (mixin(ACCESS_ROW!0) - mixin(ACCESS_ROW!4)) << CONST_BITS; 215 216 immutable int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2; 217 218 immutable int atmp0 = mixin(ACCESS_ROW!7), atmp1 = mixin(ACCESS_ROW!5), atmp2 = mixin(ACCESS_ROW!3), atmp3 = mixin(ACCESS_ROW!1); 219 220 immutable int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3; 221 immutable int bz5 = (bz3 + bz4)*FIX_1_175875602; 222 223 immutable int az1 = bz1*(-FIX_0_899976223); 224 immutable int az2 = bz2*(-FIX_2_562915447); 225 immutable int az3 = bz3*(-FIX_1_961570560) + bz5; 226 immutable int az4 = bz4*(-FIX_0_390180644) + bz5; 227 228 immutable int btmp0 = atmp0*FIX_0_298631336 + az1 + az3; 229 immutable int btmp1 = atmp1*FIX_2_053119869 + az2 + az4; 230 immutable int btmp2 = atmp2*FIX_3_072711026 + az2 + az3; 231 immutable int btmp3 = atmp3*FIX_1_501321110 + az1 + az4; 232 233 int i = DESCALE_ZEROSHIFT(tmp10 + btmp3, CONST_BITS+PASS1_BITS+3); 234 pDst_ptr[8*0] = cast(ubyte)CLAMP(i); 235 236 i = DESCALE_ZEROSHIFT(tmp10 - btmp3, CONST_BITS+PASS1_BITS+3); 237 pDst_ptr[8*7] = cast(ubyte)CLAMP(i); 238 239 i = DESCALE_ZEROSHIFT(tmp11 + btmp2, CONST_BITS+PASS1_BITS+3); 240 pDst_ptr[8*1] = cast(ubyte)CLAMP(i); 241 242 i = DESCALE_ZEROSHIFT(tmp11 - btmp2, CONST_BITS+PASS1_BITS+3); 243 pDst_ptr[8*6] = cast(ubyte)CLAMP(i); 244 245 i = DESCALE_ZEROSHIFT(tmp12 + btmp1, CONST_BITS+PASS1_BITS+3); 246 pDst_ptr[8*2] = cast(ubyte)CLAMP(i); 247 248 i = DESCALE_ZEROSHIFT(tmp12 - btmp1, CONST_BITS+PASS1_BITS+3); 249 pDst_ptr[8*5] = cast(ubyte)CLAMP(i); 250 251 i = DESCALE_ZEROSHIFT(tmp13 + btmp0, CONST_BITS+PASS1_BITS+3); 252 pDst_ptr[8*3] = cast(ubyte)CLAMP(i); 253 254 i = DESCALE_ZEROSHIFT(tmp13 - btmp0, CONST_BITS+PASS1_BITS+3); 255 pDst_ptr[8*4] = cast(ubyte)CLAMP(i); 256 } 257 } 258 } 259 260 261 static immutable ubyte[512] s_idct_row_table = [ 262 1,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0, 2,1,0,0,0,0,0,0, 2,1,1,0,0,0,0,0, 2,2,1,0,0,0,0,0, 3,2,1,0,0,0,0,0, 4,2,1,0,0,0,0,0, 4,3,1,0,0,0,0,0, 263 4,3,2,0,0,0,0,0, 4,3,2,1,0,0,0,0, 4,3,2,1,1,0,0,0, 4,3,2,2,1,0,0,0, 4,3,3,2,1,0,0,0, 4,4,3,2,1,0,0,0, 5,4,3,2,1,0,0,0, 6,4,3,2,1,0,0,0, 264 6,5,3,2,1,0,0,0, 6,5,4,2,1,0,0,0, 6,5,4,3,1,0,0,0, 6,5,4,3,2,0,0,0, 6,5,4,3,2,1,0,0, 6,5,4,3,2,1,1,0, 6,5,4,3,2,2,1,0, 6,5,4,3,3,2,1,0, 265 6,5,4,4,3,2,1,0, 6,5,5,4,3,2,1,0, 6,6,5,4,3,2,1,0, 7,6,5,4,3,2,1,0, 8,6,5,4,3,2,1,0, 8,7,5,4,3,2,1,0, 8,7,6,4,3,2,1,0, 8,7,6,5,3,2,1,0, 266 8,7,6,5,4,2,1,0, 8,7,6,5,4,3,1,0, 8,7,6,5,4,3,2,0, 8,7,6,5,4,3,2,1, 8,7,6,5,4,3,2,2, 8,7,6,5,4,3,3,2, 8,7,6,5,4,4,3,2, 8,7,6,5,5,4,3,2, 267 8,7,6,6,5,4,3,2, 8,7,7,6,5,4,3,2, 8,8,7,6,5,4,3,2, 8,8,8,6,5,4,3,2, 8,8,8,7,5,4,3,2, 8,8,8,7,6,4,3,2, 8,8,8,7,6,5,3,2, 8,8,8,7,6,5,4,2, 268 8,8,8,7,6,5,4,3, 8,8,8,7,6,5,4,4, 8,8,8,7,6,5,5,4, 8,8,8,7,6,6,5,4, 8,8,8,7,7,6,5,4, 8,8,8,8,7,6,5,4, 8,8,8,8,8,6,5,4, 8,8,8,8,8,7,5,4, 269 8,8,8,8,8,7,6,4, 8,8,8,8,8,7,6,5, 8,8,8,8,8,7,6,6, 8,8,8,8,8,7,7,6, 8,8,8,8,8,8,7,6, 8,8,8,8,8,8,8,6, 8,8,8,8,8,8,8,7, 8,8,8,8,8,8,8,8, 270 ]; 271 272 static immutable ubyte[64] s_idct_col_table = [ 1, 1, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ]; 273 274 void idct() (const(jpeg_decoder.jpgd_block_t)* pSrc_ptr, ubyte* pDst_ptr, int block_max_zag) { 275 assert(block_max_zag >= 1); 276 assert(block_max_zag <= 64); 277 278 if (block_max_zag <= 1) 279 { 280 int k = ((pSrc_ptr[0] + 4) >> 3) + 128; 281 k = CLAMP(k); 282 k = k | (k<<8); 283 k = k | (k<<16); 284 285 for (int i = 8; i > 0; i--) 286 { 287 *cast(int*)&pDst_ptr[0] = k; 288 *cast(int*)&pDst_ptr[4] = k; 289 pDst_ptr += 8; 290 } 291 return; 292 } 293 294 int[64] temp; 295 296 const(jpeg_decoder.jpgd_block_t)* pSrc = pSrc_ptr; 297 int* pTemp = temp.ptr; 298 299 const(ubyte)* pRow_tab = &s_idct_row_table.ptr[(block_max_zag - 1) * 8]; 300 int i; 301 for (i = 8; i > 0; i--, pRow_tab++) 302 { 303 switch (*pRow_tab) 304 { 305 case 0: Row!(0).idct(pTemp, pSrc); break; 306 case 1: Row!(1).idct(pTemp, pSrc); break; 307 case 2: Row!(2).idct(pTemp, pSrc); break; 308 case 3: Row!(3).idct(pTemp, pSrc); break; 309 case 4: Row!(4).idct(pTemp, pSrc); break; 310 case 5: Row!(5).idct(pTemp, pSrc); break; 311 case 6: Row!(6).idct(pTemp, pSrc); break; 312 case 7: Row!(7).idct(pTemp, pSrc); break; 313 case 8: Row!(8).idct(pTemp, pSrc); break; 314 default: assert(0); 315 } 316 317 pSrc += 8; 318 pTemp += 8; 319 } 320 321 pTemp = temp.ptr; 322 323 immutable int nonzero_rows = s_idct_col_table.ptr[block_max_zag - 1]; 324 for (i = 8; i > 0; i--) 325 { 326 switch (nonzero_rows) 327 { 328 case 1: Col!(1).idct(pDst_ptr, pTemp); break; 329 case 2: Col!(2).idct(pDst_ptr, pTemp); break; 330 case 3: Col!(3).idct(pDst_ptr, pTemp); break; 331 case 4: Col!(4).idct(pDst_ptr, pTemp); break; 332 case 5: Col!(5).idct(pDst_ptr, pTemp); break; 333 case 6: Col!(6).idct(pDst_ptr, pTemp); break; 334 case 7: Col!(7).idct(pDst_ptr, pTemp); break; 335 case 8: Col!(8).idct(pDst_ptr, pTemp); break; 336 default: assert(0); 337 } 338 339 pTemp++; 340 pDst_ptr++; 341 } 342 } 343 344 void idct_4x4() (const(jpeg_decoder.jpgd_block_t)* pSrc_ptr, ubyte* pDst_ptr) { 345 int[64] temp; 346 int* pTemp = temp.ptr; 347 const(jpeg_decoder.jpgd_block_t)* pSrc = pSrc_ptr; 348 349 for (int i = 4; i > 0; i--) 350 { 351 Row!(4).idct(pTemp, pSrc); 352 pSrc += 8; 353 pTemp += 8; 354 } 355 356 pTemp = temp.ptr; 357 for (int i = 8; i > 0; i--) 358 { 359 Col!(4).idct(pDst_ptr, pTemp); 360 pTemp++; 361 pDst_ptr++; 362 } 363 } 364 365 366 // ////////////////////////////////////////////////////////////////////////// // 367 struct jpeg_decoder { 368 private import core.stdc.string : memcpy, memset; 369 private: 370 static auto JPGD_MIN(T) (T a, T b) pure nothrow @safe @nogc { pragma(inline, true); return (a < b ? a : b); } 371 static auto JPGD_MAX(T) (T a, T b) pure nothrow @safe @nogc { pragma(inline, true); return (a > b ? a : b); } 372 373 alias jpgd_quant_t = short; 374 alias jpgd_block_t = short; 375 alias pDecode_block_func = void function (ref jpeg_decoder, int, int, int); 376 377 static struct huff_tables { 378 bool ac_table; 379 uint[256] look_up; 380 uint[256] look_up2; 381 ubyte[256] code_size; 382 uint[512] tree; 383 } 384 385 static struct coeff_buf { 386 ubyte* pData; 387 int block_num_x, block_num_y; 388 int block_len_x, block_len_y; 389 int block_size; 390 } 391 392 static struct mem_block { 393 mem_block* m_pNext; 394 size_t m_used_count; 395 size_t m_size; 396 char[1] m_data; 397 } 398 399 mem_block* m_pMem_blocks; 400 int m_image_x_size; 401 int m_image_y_size; 402 JpegStreamReadFunc readfn; 403 int m_progressive_flag; 404 ubyte[JPGD_MAX_HUFF_TABLES] m_huff_ac; 405 ubyte*[JPGD_MAX_HUFF_TABLES] m_huff_num; // pointer to number of Huffman codes per bit size 406 ubyte*[JPGD_MAX_HUFF_TABLES] m_huff_val; // pointer to Huffman codes per bit size 407 jpgd_quant_t*[JPGD_MAX_QUANT_TABLES] m_quant; // pointer to quantization tables 408 int m_scan_type; // Gray, Yh1v1, Yh1v2, Yh2v1, Yh2v2 (CMYK111, CMYK4114 no longer supported) 409 int m_comps_in_frame; // # of components in frame 410 int[JPGD_MAX_COMPONENTS] m_comp_h_samp; // component's horizontal sampling factor 411 int[JPGD_MAX_COMPONENTS] m_comp_v_samp; // component's vertical sampling factor 412 int[JPGD_MAX_COMPONENTS] m_comp_quant; // component's quantization table selector 413 int[JPGD_MAX_COMPONENTS] m_comp_ident; // component's ID 414 int[JPGD_MAX_COMPONENTS] m_comp_h_blocks; 415 int[JPGD_MAX_COMPONENTS] m_comp_v_blocks; 416 int m_comps_in_scan; // # of components in scan 417 int[JPGD_MAX_COMPS_IN_SCAN] m_comp_list; // components in this scan 418 int[JPGD_MAX_COMPONENTS] m_comp_dc_tab; // component's DC Huffman coding table selector 419 int[JPGD_MAX_COMPONENTS] m_comp_ac_tab; // component's AC Huffman coding table selector 420 int m_spectral_start; // spectral selection start 421 int m_spectral_end; // spectral selection end 422 int m_successive_low; // successive approximation low 423 int m_successive_high; // successive approximation high 424 int m_max_mcu_x_size; // MCU's max. X size in pixels 425 int m_max_mcu_y_size; // MCU's max. Y size in pixels 426 int m_blocks_per_mcu; 427 int m_max_blocks_per_row; 428 int m_mcus_per_row, m_mcus_per_col; 429 int[JPGD_MAX_BLOCKS_PER_MCU] m_mcu_org; 430 int m_total_lines_left; // total # lines left in image 431 int m_mcu_lines_left; // total # lines left in this MCU 432 int m_real_dest_bytes_per_scan_line; 433 int m_dest_bytes_per_scan_line; // rounded up 434 int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y) 435 huff_tables*[JPGD_MAX_HUFF_TABLES] m_pHuff_tabs; 436 coeff_buf*[JPGD_MAX_COMPONENTS] m_dc_coeffs; 437 coeff_buf*[JPGD_MAX_COMPONENTS] m_ac_coeffs; 438 int m_eob_run; 439 int[JPGD_MAX_COMPONENTS] m_block_y_mcu; 440 ubyte* m_pIn_buf_ofs; 441 int m_in_buf_left; 442 int m_tem_flag; 443 bool m_eof_flag; 444 ubyte[128] m_in_buf_pad_start; 445 ubyte[JPGD_IN_BUF_SIZE+128] m_in_buf; 446 ubyte[128] m_in_buf_pad_end; 447 int m_bits_left; 448 uint m_bit_buf; 449 int m_restart_interval; 450 int m_restarts_left; 451 int m_next_restart_num; 452 int m_max_mcus_per_row; 453 int m_max_blocks_per_mcu; 454 int m_expanded_blocks_per_mcu; 455 int m_expanded_blocks_per_row; 456 int m_expanded_blocks_per_component; 457 bool m_freq_domain_chroma_upsample; 458 int m_max_mcus_per_col; 459 uint[JPGD_MAX_COMPONENTS] m_last_dc_val; 460 jpgd_block_t* m_pMCU_coefficients; 461 int[JPGD_MAX_BLOCKS_PER_MCU] m_mcu_block_max_zag; 462 ubyte* m_pSample_buf; 463 int[256] m_crr; 464 int[256] m_cbb; 465 int[256] m_crg; 466 int[256] m_cbg; 467 ubyte* m_pScan_line_0; 468 ubyte* m_pScan_line_1; 469 jpgd_status m_error_code; 470 bool m_ready_flag; 471 int m_total_bytes_read; 472 473 public: 474 // Inspect `error_code` after constructing to determine if the stream is valid or not. You may look at the `width`, `height`, etc. 475 // methods after the constructor is called. You may then either destruct the object, or begin decoding the image by calling begin_decoding(), then decode() on each scanline. 476 this (JpegStreamReadFunc rfn) { decode_init(rfn); } 477 478 ~this () { free_all_blocks(); } 479 480 @disable this (this); // no copies 481 482 // Call this method after constructing the object to begin decompression. 483 // If JPGD_SUCCESS is returned you may then call decode() on each scanline. 484 int begin_decoding () { 485 if (m_ready_flag) return JPGD_SUCCESS; 486 if (m_error_code) return JPGD_FAILED; 487 try { 488 decode_start(); 489 m_ready_flag = true; 490 return JPGD_SUCCESS; 491 } catch (Exception e) { 492 //version(jpegd_test) {{ import core.stdc.stdio; stderr.fprintf("ERROR: %.*s...\n", cast(int)e.msg.length, e.msg.ptr); }} 493 version(jpegd_test) {{ import std.stdio; stderr.writeln(e.toString); }} 494 } 495 return JPGD_FAILED; 496 } 497 498 // Returns the next scan line. 499 // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (`bytes_per_pixel` will return 1). 500 // Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and `bytes_per_pixel` will return 4). 501 // Returns JPGD_SUCCESS if a scan line has been returned. 502 // Returns JPGD_DONE if all scan lines have been returned. 503 // Returns JPGD_FAILED if an error occurred. Inspect `error_code` for a more info. 504 int decode (/*const void** */void** pScan_line, uint* pScan_line_len) { 505 if (m_error_code || !m_ready_flag) return JPGD_FAILED; 506 if (m_total_lines_left == 0) return JPGD_DONE; 507 try { 508 if (m_mcu_lines_left == 0) { 509 if (m_progressive_flag) load_next_row(); else decode_next_row(); 510 // Find the EOI marker if that was the last row. 511 if (m_total_lines_left <= m_max_mcu_y_size) find_eoi(); 512 m_mcu_lines_left = m_max_mcu_y_size; 513 } 514 if (m_freq_domain_chroma_upsample) { 515 expanded_convert(); 516 *pScan_line = m_pScan_line_0; 517 } else { 518 switch (m_scan_type) { 519 case JPGD_YH2V2: 520 if ((m_mcu_lines_left & 1) == 0) { 521 H2V2Convert(); 522 *pScan_line = m_pScan_line_0; 523 } else { 524 *pScan_line = m_pScan_line_1; 525 } 526 break; 527 case JPGD_YH2V1: 528 H2V1Convert(); 529 *pScan_line = m_pScan_line_0; 530 break; 531 case JPGD_YH1V2: 532 if ((m_mcu_lines_left & 1) == 0) { 533 H1V2Convert(); 534 *pScan_line = m_pScan_line_0; 535 } else { 536 *pScan_line = m_pScan_line_1; 537 } 538 break; 539 case JPGD_YH1V1: 540 H1V1Convert(); 541 *pScan_line = m_pScan_line_0; 542 break; 543 case JPGD_GRAYSCALE: 544 gray_convert(); 545 *pScan_line = m_pScan_line_0; 546 break; 547 default: 548 } 549 } 550 *pScan_line_len = m_real_dest_bytes_per_scan_line; 551 --m_mcu_lines_left; 552 --m_total_lines_left; 553 return JPGD_SUCCESS; 554 } catch (Exception) {} 555 return JPGD_FAILED; 556 } 557 558 @property const pure nothrow @safe @nogc { 559 jpgd_status error_code () { pragma(inline, true); return m_error_code; } 560 561 int width () { pragma(inline, true); return m_image_x_size; } 562 int height () { pragma(inline, true); return m_image_y_size; } 563 564 int num_components () { pragma(inline, true); return m_comps_in_frame; } 565 566 int bytes_per_pixel () { pragma(inline, true); return m_dest_bytes_per_pixel; } 567 int bytes_per_scan_line () { pragma(inline, true); return m_image_x_size * bytes_per_pixel(); } 568 569 // Returns the total number of bytes actually consumed by the decoder (which should equal the actual size of the JPEG file). 570 int total_bytes_read () { pragma(inline, true); return m_total_bytes_read; } 571 } 572 573 private: 574 // Retrieve one character from the input stream. 575 uint get_char () { 576 // Any bytes remaining in buffer? 577 if (!m_in_buf_left) { 578 // Try to get more bytes. 579 prep_in_buffer(); 580 // Still nothing to get? 581 if (!m_in_buf_left) { 582 // Pad the end of the stream with 0xFF 0xD9 (EOI marker) 583 int t = m_tem_flag; 584 m_tem_flag ^= 1; 585 return (t ? 0xD9 : 0xFF); 586 } 587 } 588 uint c = *m_pIn_buf_ofs++; 589 --m_in_buf_left; 590 return c; 591 } 592 593 // Same as previous method, except can indicate if the character is a pad character or not. 594 uint get_char (bool* pPadding_flag) { 595 if (!m_in_buf_left) { 596 prep_in_buffer(); 597 if (!m_in_buf_left) { 598 *pPadding_flag = true; 599 int t = m_tem_flag; 600 m_tem_flag ^= 1; 601 return (t ? 0xD9 : 0xFF); 602 } 603 } 604 *pPadding_flag = false; 605 uint c = *m_pIn_buf_ofs++; 606 --m_in_buf_left; 607 return c; 608 } 609 610 // Inserts a previously retrieved character back into the input buffer. 611 void stuff_char (ubyte q) { 612 *(--m_pIn_buf_ofs) = q; 613 m_in_buf_left++; 614 } 615 616 // Retrieves one character from the input stream, but does not read past markers. Will continue to return 0xFF when a marker is encountered. 617 ubyte get_octet () { 618 bool padding_flag; 619 int c = get_char(&padding_flag); 620 if (c == 0xFF) { 621 if (padding_flag) return 0xFF; 622 c = get_char(&padding_flag); 623 if (padding_flag) { stuff_char(0xFF); return 0xFF; } 624 if (c == 0x00) return 0xFF; 625 stuff_char(cast(ubyte)(c)); 626 stuff_char(0xFF); 627 return 0xFF; 628 } 629 return cast(ubyte)(c); 630 } 631 632 // Retrieves a variable number of bits from the input stream. Does not recognize markers. 633 uint get_bits (int num_bits) { 634 if (!num_bits) return 0; 635 uint i = m_bit_buf >> (32 - num_bits); 636 if ((m_bits_left -= num_bits) <= 0) { 637 m_bit_buf <<= (num_bits += m_bits_left); 638 uint c1 = get_char(); 639 uint c2 = get_char(); 640 m_bit_buf = (m_bit_buf & 0xFFFF0000) | (c1 << 8) | c2; 641 m_bit_buf <<= -m_bits_left; 642 m_bits_left += 16; 643 assert(m_bits_left >= 0); 644 } else { 645 m_bit_buf <<= num_bits; 646 } 647 return i; 648 } 649 650 // Retrieves a variable number of bits from the input stream. Markers will not be read into the input bit buffer. Instead, an infinite number of all 1's will be returned when a marker is encountered. 651 uint get_bits_no_markers (int num_bits) { 652 if (!num_bits) return 0; 653 uint i = m_bit_buf >> (32 - num_bits); 654 if ((m_bits_left -= num_bits) <= 0) { 655 m_bit_buf <<= (num_bits += m_bits_left); 656 if (m_in_buf_left < 2 || m_pIn_buf_ofs[0] == 0xFF || m_pIn_buf_ofs[1] == 0xFF) { 657 uint c1 = get_octet(); 658 uint c2 = get_octet(); 659 m_bit_buf |= (c1 << 8) | c2; 660 } else { 661 m_bit_buf |= (cast(uint)m_pIn_buf_ofs[0] << 8) | m_pIn_buf_ofs[1]; 662 m_in_buf_left -= 2; 663 m_pIn_buf_ofs += 2; 664 } 665 m_bit_buf <<= -m_bits_left; 666 m_bits_left += 16; 667 assert(m_bits_left >= 0); 668 } else { 669 m_bit_buf <<= num_bits; 670 } 671 return i; 672 } 673 674 // Decodes a Huffman encoded symbol. 675 int huff_decode (huff_tables *pH) { 676 int symbol; 677 // Check first 8-bits: do we have a complete symbol? 678 if ((symbol = pH.look_up.ptr[m_bit_buf >> 24]) < 0) { 679 // Decode more bits, use a tree traversal to find symbol. 680 int ofs = 23; 681 do { 682 symbol = pH.tree.ptr[-cast(int)(symbol + ((m_bit_buf >> ofs) & 1))]; 683 --ofs; 684 } while (symbol < 0); 685 get_bits_no_markers(8 + (23 - ofs)); 686 } else { 687 get_bits_no_markers(pH.code_size.ptr[symbol]); 688 } 689 return symbol; 690 } 691 692 // Decodes a Huffman encoded symbol. 693 int huff_decode (huff_tables *pH, ref int extra_bits) { 694 int symbol; 695 // Check first 8-bits: do we have a complete symbol? 696 if ((symbol = pH.look_up2.ptr[m_bit_buf >> 24]) < 0) { 697 // Use a tree traversal to find symbol. 698 int ofs = 23; 699 do { 700 symbol = pH.tree.ptr[-cast(int)(symbol + ((m_bit_buf >> ofs) & 1))]; 701 --ofs; 702 } while (symbol < 0); 703 get_bits_no_markers(8 + (23 - ofs)); 704 extra_bits = get_bits_no_markers(symbol & 0xF); 705 } else { 706 assert(((symbol >> 8) & 31) == pH.code_size.ptr[symbol & 255] + ((symbol & 0x8000) ? (symbol & 15) : 0)); 707 if (symbol & 0x8000) { 708 get_bits_no_markers((symbol >> 8) & 31); 709 extra_bits = symbol >> 16; 710 } else { 711 int code_size = (symbol >> 8) & 31; 712 int num_extra_bits = symbol & 0xF; 713 int bits = code_size + num_extra_bits; 714 if (bits <= (m_bits_left + 16)) { 715 extra_bits = get_bits_no_markers(bits) & ((1 << num_extra_bits) - 1); 716 } else { 717 get_bits_no_markers(code_size); 718 extra_bits = get_bits_no_markers(num_extra_bits); 719 } 720 } 721 symbol &= 0xFF; 722 } 723 return symbol; 724 } 725 726 // Tables and macro used to fully decode the DPCM differences. 727 static immutable int[16] s_extend_test = [ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 ]; 728 static immutable int[16] s_extend_offset = [ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 ]; 729 static immutable int[18] s_extend_mask = [ 0, (1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7), (1<<8), (1<<9), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15), (1<<16) ]; 730 // The logical AND's in this macro are to shut up static code analysis (aren't really necessary - couldn't find another way to do this) 731 //#define JPGD_HUFF_EXTEND(x, s) (((x) < s_extend_test[s & 15]) ? ((x) + s_extend_offset[s & 15]) : (x)) 732 static JPGD_HUFF_EXTEND (int x, int s) nothrow @trusted @nogc { pragma(inline, true); return (((x) < s_extend_test.ptr[s & 15]) ? ((x) + s_extend_offset.ptr[s & 15]) : (x)); } 733 734 // Clamps a value between 0-255. 735 //static ubyte clamp (int i) { if (cast(uint)(i) > 255) i = (((~i) >> 31) & 0xFF); return cast(ubyte)(i); } 736 alias clamp = CLAMP; 737 738 static struct DCT_Upsample { 739 static: 740 static struct Matrix44 { 741 pure nothrow @trusted @nogc: 742 alias Element_Type = int; 743 enum { NUM_ROWS = 4, NUM_COLS = 4 } 744 745 Element_Type[NUM_COLS][NUM_ROWS] v; 746 747 this() (in auto ref Matrix44 m) { 748 foreach (immutable r; 0..NUM_ROWS) v[r][] = m.v[r][]; 749 } 750 751 //@property int rows () const { pragma(inline, true); return NUM_ROWS; } 752 //@property int cols () const { pragma(inline, true); return NUM_COLS; } 753 754 ref inout(Element_Type) at (int r, int c) inout { pragma(inline, true); return v.ptr[r].ptr[c]; } 755 756 ref Matrix44 opOpAssign(string op:"+") (in auto ref Matrix44 a) { 757 foreach (int r; 0..NUM_ROWS) { 758 at(r, 0) += a.at(r, 0); 759 at(r, 1) += a.at(r, 1); 760 at(r, 2) += a.at(r, 2); 761 at(r, 3) += a.at(r, 3); 762 } 763 return this; 764 } 765 766 ref Matrix44 opOpAssign(string op:"-") (in auto ref Matrix44 a) { 767 foreach (int r; 0..NUM_ROWS) { 768 at(r, 0) -= a.at(r, 0); 769 at(r, 1) -= a.at(r, 1); 770 at(r, 2) -= a.at(r, 2); 771 at(r, 3) -= a.at(r, 3); 772 } 773 return this; 774 } 775 776 Matrix44 opBinary(string op:"+") (in auto ref Matrix44 b) const { 777 alias a = this; 778 Matrix44 ret; 779 foreach (int r; 0..NUM_ROWS) { 780 ret.at(r, 0) = a.at(r, 0) + b.at(r, 0); 781 ret.at(r, 1) = a.at(r, 1) + b.at(r, 1); 782 ret.at(r, 2) = a.at(r, 2) + b.at(r, 2); 783 ret.at(r, 3) = a.at(r, 3) + b.at(r, 3); 784 } 785 return ret; 786 } 787 788 Matrix44 opBinary(string op:"-") (in auto ref Matrix44 b) const { 789 alias a = this; 790 Matrix44 ret; 791 foreach (int r; 0..NUM_ROWS) { 792 ret.at(r, 0) = a.at(r, 0) - b.at(r, 0); 793 ret.at(r, 1) = a.at(r, 1) - b.at(r, 1); 794 ret.at(r, 2) = a.at(r, 2) - b.at(r, 2); 795 ret.at(r, 3) = a.at(r, 3) - b.at(r, 3); 796 } 797 return ret; 798 } 799 800 static void add_and_store() (jpgd_block_t* pDst, in auto ref Matrix44 a, in auto ref Matrix44 b) { 801 foreach (int r; 0..4) { 802 pDst[0*8 + r] = cast(jpgd_block_t)(a.at(r, 0) + b.at(r, 0)); 803 pDst[1*8 + r] = cast(jpgd_block_t)(a.at(r, 1) + b.at(r, 1)); 804 pDst[2*8 + r] = cast(jpgd_block_t)(a.at(r, 2) + b.at(r, 2)); 805 pDst[3*8 + r] = cast(jpgd_block_t)(a.at(r, 3) + b.at(r, 3)); 806 } 807 } 808 809 static void sub_and_store() (jpgd_block_t* pDst, in auto ref Matrix44 a, in auto ref Matrix44 b) { 810 foreach (int r; 0..4) { 811 pDst[0*8 + r] = cast(jpgd_block_t)(a.at(r, 0) - b.at(r, 0)); 812 pDst[1*8 + r] = cast(jpgd_block_t)(a.at(r, 1) - b.at(r, 1)); 813 pDst[2*8 + r] = cast(jpgd_block_t)(a.at(r, 2) - b.at(r, 2)); 814 pDst[3*8 + r] = cast(jpgd_block_t)(a.at(r, 3) - b.at(r, 3)); 815 } 816 } 817 } 818 819 enum FRACT_BITS = 10; 820 enum SCALE = 1 << FRACT_BITS; 821 822 alias Temp_Type = int; 823 //TODO: convert defines to mixins 824 //#define D(i) (((i) + (SCALE >> 1)) >> FRACT_BITS) 825 //#define F(i) ((int)((i) * SCALE + .5f)) 826 // Any decent C++ compiler will optimize this at compile time to a 0, or an array access. 827 //#define AT(c, r) ((((c)>=NUM_COLS)||((r)>=NUM_ROWS)) ? 0 : pSrc[(c)+(r)*8]) 828 829 static int D(T) (T i) { pragma(inline, true); return (((i) + (SCALE >> 1)) >> FRACT_BITS); } 830 enum F(float i) = (cast(int)((i) * SCALE + 0.5f)); 831 832 // NUM_ROWS/NUM_COLS = # of non-zero rows/cols in input matrix 833 static struct P_Q(int NUM_ROWS, int NUM_COLS) { 834 static void calc (ref Matrix44 P, ref Matrix44 Q, const(jpgd_block_t)* pSrc) { 835 //auto AT (int c, int r) nothrow @trusted @nogc { return (c >= NUM_COLS || r >= NUM_ROWS ? 0 : pSrc[c+r*8]); } 836 template AT(int c, int r) { 837 static if (c >= NUM_COLS || r >= NUM_ROWS) enum AT = "0"; else enum AT = "pSrc["~c.stringof~"+"~r.stringof~"*8]"; 838 } 839 // 4x8 = 4x8 times 8x8, matrix 0 is constant 840 immutable Temp_Type X000 = mixin(AT!(0, 0)); 841 immutable Temp_Type X001 = mixin(AT!(0, 1)); 842 immutable Temp_Type X002 = mixin(AT!(0, 2)); 843 immutable Temp_Type X003 = mixin(AT!(0, 3)); 844 immutable Temp_Type X004 = mixin(AT!(0, 4)); 845 immutable Temp_Type X005 = mixin(AT!(0, 5)); 846 immutable Temp_Type X006 = mixin(AT!(0, 6)); 847 immutable Temp_Type X007 = mixin(AT!(0, 7)); 848 immutable Temp_Type X010 = D(F!(0.415735f) * mixin(AT!(1, 0)) + F!(0.791065f) * mixin(AT!(3, 0)) + F!(-0.352443f) * mixin(AT!(5, 0)) + F!(0.277785f) * mixin(AT!(7, 0))); 849 immutable Temp_Type X011 = D(F!(0.415735f) * mixin(AT!(1, 1)) + F!(0.791065f) * mixin(AT!(3, 1)) + F!(-0.352443f) * mixin(AT!(5, 1)) + F!(0.277785f) * mixin(AT!(7, 1))); 850 immutable Temp_Type X012 = D(F!(0.415735f) * mixin(AT!(1, 2)) + F!(0.791065f) * mixin(AT!(3, 2)) + F!(-0.352443f) * mixin(AT!(5, 2)) + F!(0.277785f) * mixin(AT!(7, 2))); 851 immutable Temp_Type X013 = D(F!(0.415735f) * mixin(AT!(1, 3)) + F!(0.791065f) * mixin(AT!(3, 3)) + F!(-0.352443f) * mixin(AT!(5, 3)) + F!(0.277785f) * mixin(AT!(7, 3))); 852 immutable Temp_Type X014 = D(F!(0.415735f) * mixin(AT!(1, 4)) + F!(0.791065f) * mixin(AT!(3, 4)) + F!(-0.352443f) * mixin(AT!(5, 4)) + F!(0.277785f) * mixin(AT!(7, 4))); 853 immutable Temp_Type X015 = D(F!(0.415735f) * mixin(AT!(1, 5)) + F!(0.791065f) * mixin(AT!(3, 5)) + F!(-0.352443f) * mixin(AT!(5, 5)) + F!(0.277785f) * mixin(AT!(7, 5))); 854 immutable Temp_Type X016 = D(F!(0.415735f) * mixin(AT!(1, 6)) + F!(0.791065f) * mixin(AT!(3, 6)) + F!(-0.352443f) * mixin(AT!(5, 6)) + F!(0.277785f) * mixin(AT!(7, 6))); 855 immutable Temp_Type X017 = D(F!(0.415735f) * mixin(AT!(1, 7)) + F!(0.791065f) * mixin(AT!(3, 7)) + F!(-0.352443f) * mixin(AT!(5, 7)) + F!(0.277785f) * mixin(AT!(7, 7))); 856 immutable Temp_Type X020 = mixin(AT!(4, 0)); 857 immutable Temp_Type X021 = mixin(AT!(4, 1)); 858 immutable Temp_Type X022 = mixin(AT!(4, 2)); 859 immutable Temp_Type X023 = mixin(AT!(4, 3)); 860 immutable Temp_Type X024 = mixin(AT!(4, 4)); 861 immutable Temp_Type X025 = mixin(AT!(4, 5)); 862 immutable Temp_Type X026 = mixin(AT!(4, 6)); 863 immutable Temp_Type X027 = mixin(AT!(4, 7)); 864 immutable Temp_Type X030 = D(F!(0.022887f) * mixin(AT!(1, 0)) + F!(-0.097545f) * mixin(AT!(3, 0)) + F!(0.490393f) * mixin(AT!(5, 0)) + F!(0.865723f) * mixin(AT!(7, 0))); 865 immutable Temp_Type X031 = D(F!(0.022887f) * mixin(AT!(1, 1)) + F!(-0.097545f) * mixin(AT!(3, 1)) + F!(0.490393f) * mixin(AT!(5, 1)) + F!(0.865723f) * mixin(AT!(7, 1))); 866 immutable Temp_Type X032 = D(F!(0.022887f) * mixin(AT!(1, 2)) + F!(-0.097545f) * mixin(AT!(3, 2)) + F!(0.490393f) * mixin(AT!(5, 2)) + F!(0.865723f) * mixin(AT!(7, 2))); 867 immutable Temp_Type X033 = D(F!(0.022887f) * mixin(AT!(1, 3)) + F!(-0.097545f) * mixin(AT!(3, 3)) + F!(0.490393f) * mixin(AT!(5, 3)) + F!(0.865723f) * mixin(AT!(7, 3))); 868 immutable Temp_Type X034 = D(F!(0.022887f) * mixin(AT!(1, 4)) + F!(-0.097545f) * mixin(AT!(3, 4)) + F!(0.490393f) * mixin(AT!(5, 4)) + F!(0.865723f) * mixin(AT!(7, 4))); 869 immutable Temp_Type X035 = D(F!(0.022887f) * mixin(AT!(1, 5)) + F!(-0.097545f) * mixin(AT!(3, 5)) + F!(0.490393f) * mixin(AT!(5, 5)) + F!(0.865723f) * mixin(AT!(7, 5))); 870 immutable Temp_Type X036 = D(F!(0.022887f) * mixin(AT!(1, 6)) + F!(-0.097545f) * mixin(AT!(3, 6)) + F!(0.490393f) * mixin(AT!(5, 6)) + F!(0.865723f) * mixin(AT!(7, 6))); 871 immutable Temp_Type X037 = D(F!(0.022887f) * mixin(AT!(1, 7)) + F!(-0.097545f) * mixin(AT!(3, 7)) + F!(0.490393f) * mixin(AT!(5, 7)) + F!(0.865723f) * mixin(AT!(7, 7))); 872 873 // 4x4 = 4x8 times 8x4, matrix 1 is constant 874 P.at(0, 0) = X000; 875 P.at(0, 1) = D(X001 * F!(0.415735f) + X003 * F!(0.791065f) + X005 * F!(-0.352443f) + X007 * F!(0.277785f)); 876 P.at(0, 2) = X004; 877 P.at(0, 3) = D(X001 * F!(0.022887f) + X003 * F!(-0.097545f) + X005 * F!(0.490393f) + X007 * F!(0.865723f)); 878 P.at(1, 0) = X010; 879 P.at(1, 1) = D(X011 * F!(0.415735f) + X013 * F!(0.791065f) + X015 * F!(-0.352443f) + X017 * F!(0.277785f)); 880 P.at(1, 2) = X014; 881 P.at(1, 3) = D(X011 * F!(0.022887f) + X013 * F!(-0.097545f) + X015 * F!(0.490393f) + X017 * F!(0.865723f)); 882 P.at(2, 0) = X020; 883 P.at(2, 1) = D(X021 * F!(0.415735f) + X023 * F!(0.791065f) + X025 * F!(-0.352443f) + X027 * F!(0.277785f)); 884 P.at(2, 2) = X024; 885 P.at(2, 3) = D(X021 * F!(0.022887f) + X023 * F!(-0.097545f) + X025 * F!(0.490393f) + X027 * F!(0.865723f)); 886 P.at(3, 0) = X030; 887 P.at(3, 1) = D(X031 * F!(0.415735f) + X033 * F!(0.791065f) + X035 * F!(-0.352443f) + X037 * F!(0.277785f)); 888 P.at(3, 2) = X034; 889 P.at(3, 3) = D(X031 * F!(0.022887f) + X033 * F!(-0.097545f) + X035 * F!(0.490393f) + X037 * F!(0.865723f)); 890 // 40 muls 24 adds 891 892 // 4x4 = 4x8 times 8x4, matrix 1 is constant 893 Q.at(0, 0) = D(X001 * F!(0.906127f) + X003 * F!(-0.318190f) + X005 * F!(0.212608f) + X007 * F!(-0.180240f)); 894 Q.at(0, 1) = X002; 895 Q.at(0, 2) = D(X001 * F!(-0.074658f) + X003 * F!(0.513280f) + X005 * F!(0.768178f) + X007 * F!(-0.375330f)); 896 Q.at(0, 3) = X006; 897 Q.at(1, 0) = D(X011 * F!(0.906127f) + X013 * F!(-0.318190f) + X015 * F!(0.212608f) + X017 * F!(-0.180240f)); 898 Q.at(1, 1) = X012; 899 Q.at(1, 2) = D(X011 * F!(-0.074658f) + X013 * F!(0.513280f) + X015 * F!(0.768178f) + X017 * F!(-0.375330f)); 900 Q.at(1, 3) = X016; 901 Q.at(2, 0) = D(X021 * F!(0.906127f) + X023 * F!(-0.318190f) + X025 * F!(0.212608f) + X027 * F!(-0.180240f)); 902 Q.at(2, 1) = X022; 903 Q.at(2, 2) = D(X021 * F!(-0.074658f) + X023 * F!(0.513280f) + X025 * F!(0.768178f) + X027 * F!(-0.375330f)); 904 Q.at(2, 3) = X026; 905 Q.at(3, 0) = D(X031 * F!(0.906127f) + X033 * F!(-0.318190f) + X035 * F!(0.212608f) + X037 * F!(-0.180240f)); 906 Q.at(3, 1) = X032; 907 Q.at(3, 2) = D(X031 * F!(-0.074658f) + X033 * F!(0.513280f) + X035 * F!(0.768178f) + X037 * F!(-0.375330f)); 908 Q.at(3, 3) = X036; 909 // 40 muls 24 adds 910 } 911 } 912 913 static struct R_S(int NUM_ROWS, int NUM_COLS) { 914 static void calc(ref Matrix44 R, ref Matrix44 S, const(jpgd_block_t)* pSrc) { 915 //auto AT (int c, int r) nothrow @trusted @nogc { return (c >= NUM_COLS || r >= NUM_ROWS ? 0 : pSrc[c+r*8]); } 916 template AT(int c, int r) { 917 static if (c >= NUM_COLS || r >= NUM_ROWS) enum AT = "0"; else enum AT = "pSrc["~c.stringof~"+"~r.stringof~"*8]"; 918 } 919 // 4x8 = 4x8 times 8x8, matrix 0 is constant 920 immutable Temp_Type X100 = D(F!(0.906127f) * mixin(AT!(1, 0)) + F!(-0.318190f) * mixin(AT!(3, 0)) + F!(0.212608f) * mixin(AT!(5, 0)) + F!(-0.180240f) * mixin(AT!(7, 0))); 921 immutable Temp_Type X101 = D(F!(0.906127f) * mixin(AT!(1, 1)) + F!(-0.318190f) * mixin(AT!(3, 1)) + F!(0.212608f) * mixin(AT!(5, 1)) + F!(-0.180240f) * mixin(AT!(7, 1))); 922 immutable Temp_Type X102 = D(F!(0.906127f) * mixin(AT!(1, 2)) + F!(-0.318190f) * mixin(AT!(3, 2)) + F!(0.212608f) * mixin(AT!(5, 2)) + F!(-0.180240f) * mixin(AT!(7, 2))); 923 immutable Temp_Type X103 = D(F!(0.906127f) * mixin(AT!(1, 3)) + F!(-0.318190f) * mixin(AT!(3, 3)) + F!(0.212608f) * mixin(AT!(5, 3)) + F!(-0.180240f) * mixin(AT!(7, 3))); 924 immutable Temp_Type X104 = D(F!(0.906127f) * mixin(AT!(1, 4)) + F!(-0.318190f) * mixin(AT!(3, 4)) + F!(0.212608f) * mixin(AT!(5, 4)) + F!(-0.180240f) * mixin(AT!(7, 4))); 925 immutable Temp_Type X105 = D(F!(0.906127f) * mixin(AT!(1, 5)) + F!(-0.318190f) * mixin(AT!(3, 5)) + F!(0.212608f) * mixin(AT!(5, 5)) + F!(-0.180240f) * mixin(AT!(7, 5))); 926 immutable Temp_Type X106 = D(F!(0.906127f) * mixin(AT!(1, 6)) + F!(-0.318190f) * mixin(AT!(3, 6)) + F!(0.212608f) * mixin(AT!(5, 6)) + F!(-0.180240f) * mixin(AT!(7, 6))); 927 immutable Temp_Type X107 = D(F!(0.906127f) * mixin(AT!(1, 7)) + F!(-0.318190f) * mixin(AT!(3, 7)) + F!(0.212608f) * mixin(AT!(5, 7)) + F!(-0.180240f) * mixin(AT!(7, 7))); 928 immutable Temp_Type X110 = mixin(AT!(2, 0)); 929 immutable Temp_Type X111 = mixin(AT!(2, 1)); 930 immutable Temp_Type X112 = mixin(AT!(2, 2)); 931 immutable Temp_Type X113 = mixin(AT!(2, 3)); 932 immutable Temp_Type X114 = mixin(AT!(2, 4)); 933 immutable Temp_Type X115 = mixin(AT!(2, 5)); 934 immutable Temp_Type X116 = mixin(AT!(2, 6)); 935 immutable Temp_Type X117 = mixin(AT!(2, 7)); 936 immutable Temp_Type X120 = D(F!(-0.074658f) * mixin(AT!(1, 0)) + F!(0.513280f) * mixin(AT!(3, 0)) + F!(0.768178f) * mixin(AT!(5, 0)) + F!(-0.375330f) * mixin(AT!(7, 0))); 937 immutable Temp_Type X121 = D(F!(-0.074658f) * mixin(AT!(1, 1)) + F!(0.513280f) * mixin(AT!(3, 1)) + F!(0.768178f) * mixin(AT!(5, 1)) + F!(-0.375330f) * mixin(AT!(7, 1))); 938 immutable Temp_Type X122 = D(F!(-0.074658f) * mixin(AT!(1, 2)) + F!(0.513280f) * mixin(AT!(3, 2)) + F!(0.768178f) * mixin(AT!(5, 2)) + F!(-0.375330f) * mixin(AT!(7, 2))); 939 immutable Temp_Type X123 = D(F!(-0.074658f) * mixin(AT!(1, 3)) + F!(0.513280f) * mixin(AT!(3, 3)) + F!(0.768178f) * mixin(AT!(5, 3)) + F!(-0.375330f) * mixin(AT!(7, 3))); 940 immutable Temp_Type X124 = D(F!(-0.074658f) * mixin(AT!(1, 4)) + F!(0.513280f) * mixin(AT!(3, 4)) + F!(0.768178f) * mixin(AT!(5, 4)) + F!(-0.375330f) * mixin(AT!(7, 4))); 941 immutable Temp_Type X125 = D(F!(-0.074658f) * mixin(AT!(1, 5)) + F!(0.513280f) * mixin(AT!(3, 5)) + F!(0.768178f) * mixin(AT!(5, 5)) + F!(-0.375330f) * mixin(AT!(7, 5))); 942 immutable Temp_Type X126 = D(F!(-0.074658f) * mixin(AT!(1, 6)) + F!(0.513280f) * mixin(AT!(3, 6)) + F!(0.768178f) * mixin(AT!(5, 6)) + F!(-0.375330f) * mixin(AT!(7, 6))); 943 immutable Temp_Type X127 = D(F!(-0.074658f) * mixin(AT!(1, 7)) + F!(0.513280f) * mixin(AT!(3, 7)) + F!(0.768178f) * mixin(AT!(5, 7)) + F!(-0.375330f) * mixin(AT!(7, 7))); 944 immutable Temp_Type X130 = mixin(AT!(6, 0)); 945 immutable Temp_Type X131 = mixin(AT!(6, 1)); 946 immutable Temp_Type X132 = mixin(AT!(6, 2)); 947 immutable Temp_Type X133 = mixin(AT!(6, 3)); 948 immutable Temp_Type X134 = mixin(AT!(6, 4)); 949 immutable Temp_Type X135 = mixin(AT!(6, 5)); 950 immutable Temp_Type X136 = mixin(AT!(6, 6)); 951 immutable Temp_Type X137 = mixin(AT!(6, 7)); 952 // 80 muls 48 adds 953 954 // 4x4 = 4x8 times 8x4, matrix 1 is constant 955 R.at(0, 0) = X100; 956 R.at(0, 1) = D(X101 * F!(0.415735f) + X103 * F!(0.791065f) + X105 * F!(-0.352443f) + X107 * F!(0.277785f)); 957 R.at(0, 2) = X104; 958 R.at(0, 3) = D(X101 * F!(0.022887f) + X103 * F!(-0.097545f) + X105 * F!(0.490393f) + X107 * F!(0.865723f)); 959 R.at(1, 0) = X110; 960 R.at(1, 1) = D(X111 * F!(0.415735f) + X113 * F!(0.791065f) + X115 * F!(-0.352443f) + X117 * F!(0.277785f)); 961 R.at(1, 2) = X114; 962 R.at(1, 3) = D(X111 * F!(0.022887f) + X113 * F!(-0.097545f) + X115 * F!(0.490393f) + X117 * F!(0.865723f)); 963 R.at(2, 0) = X120; 964 R.at(2, 1) = D(X121 * F!(0.415735f) + X123 * F!(0.791065f) + X125 * F!(-0.352443f) + X127 * F!(0.277785f)); 965 R.at(2, 2) = X124; 966 R.at(2, 3) = D(X121 * F!(0.022887f) + X123 * F!(-0.097545f) + X125 * F!(0.490393f) + X127 * F!(0.865723f)); 967 R.at(3, 0) = X130; 968 R.at(3, 1) = D(X131 * F!(0.415735f) + X133 * F!(0.791065f) + X135 * F!(-0.352443f) + X137 * F!(0.277785f)); 969 R.at(3, 2) = X134; 970 R.at(3, 3) = D(X131 * F!(0.022887f) + X133 * F!(-0.097545f) + X135 * F!(0.490393f) + X137 * F!(0.865723f)); 971 // 40 muls 24 adds 972 // 4x4 = 4x8 times 8x4, matrix 1 is constant 973 S.at(0, 0) = D(X101 * F!(0.906127f) + X103 * F!(-0.318190f) + X105 * F!(0.212608f) + X107 * F!(-0.180240f)); 974 S.at(0, 1) = X102; 975 S.at(0, 2) = D(X101 * F!(-0.074658f) + X103 * F!(0.513280f) + X105 * F!(0.768178f) + X107 * F!(-0.375330f)); 976 S.at(0, 3) = X106; 977 S.at(1, 0) = D(X111 * F!(0.906127f) + X113 * F!(-0.318190f) + X115 * F!(0.212608f) + X117 * F!(-0.180240f)); 978 S.at(1, 1) = X112; 979 S.at(1, 2) = D(X111 * F!(-0.074658f) + X113 * F!(0.513280f) + X115 * F!(0.768178f) + X117 * F!(-0.375330f)); 980 S.at(1, 3) = X116; 981 S.at(2, 0) = D(X121 * F!(0.906127f) + X123 * F!(-0.318190f) + X125 * F!(0.212608f) + X127 * F!(-0.180240f)); 982 S.at(2, 1) = X122; 983 S.at(2, 2) = D(X121 * F!(-0.074658f) + X123 * F!(0.513280f) + X125 * F!(0.768178f) + X127 * F!(-0.375330f)); 984 S.at(2, 3) = X126; 985 S.at(3, 0) = D(X131 * F!(0.906127f) + X133 * F!(-0.318190f) + X135 * F!(0.212608f) + X137 * F!(-0.180240f)); 986 S.at(3, 1) = X132; 987 S.at(3, 2) = D(X131 * F!(-0.074658f) + X133 * F!(0.513280f) + X135 * F!(0.768178f) + X137 * F!(-0.375330f)); 988 S.at(3, 3) = X136; 989 // 40 muls 24 adds 990 } 991 } 992 } // end namespace DCT_Upsample 993 994 // Unconditionally frees all allocated m_blocks. 995 void free_all_blocks () { 996 //m_pStream = null; 997 readfn = null; 998 for (mem_block *b = m_pMem_blocks; b; ) { 999 mem_block* n = b.m_pNext; 1000 jpgd_free(b); 1001 b = n; 1002 } 1003 m_pMem_blocks = null; 1004 } 1005 1006 // This method handles all errors. It will never return. 1007 // It could easily be changed to use C++ exceptions. 1008 /*JPGD_NORETURN*/ void stop_decoding (jpgd_status status, size_t line=__LINE__) { 1009 m_error_code = status; 1010 free_all_blocks(); 1011 //longjmp(m_jmp_state, status); 1012 throw new Exception("jpeg decoding error", __FILE__, line); 1013 } 1014 1015 void* alloc (size_t nSize, bool zero=false) { 1016 nSize = (JPGD_MAX(nSize, 1) + 3) & ~3; 1017 char *rv = null; 1018 for (mem_block *b = m_pMem_blocks; b; b = b.m_pNext) 1019 { 1020 if ((b.m_used_count + nSize) <= b.m_size) 1021 { 1022 rv = b.m_data.ptr + b.m_used_count; 1023 b.m_used_count += nSize; 1024 break; 1025 } 1026 } 1027 if (!rv) 1028 { 1029 size_t capacity = JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047); 1030 mem_block *b = cast(mem_block*)jpgd_malloc(mem_block.sizeof + capacity); 1031 if (!b) { stop_decoding(JPGD_NOTENOUGHMEM); } 1032 b.m_pNext = m_pMem_blocks; m_pMem_blocks = b; 1033 b.m_used_count = nSize; 1034 b.m_size = capacity; 1035 rv = b.m_data.ptr; 1036 } 1037 if (zero) memset(rv, 0, nSize); 1038 return rv; 1039 } 1040 1041 void word_clear (void *p, ushort c, uint n) { 1042 ubyte *pD = cast(ubyte*)p; 1043 immutable ubyte l = c & 0xFF, h = (c >> 8) & 0xFF; 1044 while (n) 1045 { 1046 pD[0] = l; pD[1] = h; pD += 2; 1047 n--; 1048 } 1049 } 1050 1051 // Refill the input buffer. 1052 // This method will sit in a loop until (A) the buffer is full or (B) 1053 // the stream's read() method reports and end of file condition. 1054 void prep_in_buffer () { 1055 m_in_buf_left = 0; 1056 m_pIn_buf_ofs = m_in_buf.ptr; 1057 1058 if (m_eof_flag) 1059 return; 1060 1061 do 1062 { 1063 int bytes_read = readfn(m_in_buf.ptr + m_in_buf_left, JPGD_IN_BUF_SIZE - m_in_buf_left, &m_eof_flag); 1064 if (bytes_read == -1) 1065 stop_decoding(JPGD_STREAM_READ); 1066 1067 m_in_buf_left += bytes_read; 1068 } while ((m_in_buf_left < JPGD_IN_BUF_SIZE) && (!m_eof_flag)); 1069 1070 m_total_bytes_read += m_in_buf_left; 1071 1072 // Pad the end of the block with M_EOI (prevents the decompressor from going off the rails if the stream is invalid). 1073 // (This dates way back to when this decompressor was written in C/asm, and the all-asm Huffman decoder did some fancy things to increase perf.) 1074 word_clear(m_pIn_buf_ofs + m_in_buf_left, 0xD9FF, 64); 1075 } 1076 1077 // Read a Huffman code table. 1078 void read_dht_marker () { 1079 int i, index, count; 1080 ubyte[17] huff_num; 1081 ubyte[256] huff_val; 1082 1083 uint num_left = get_bits(16); 1084 1085 if (num_left < 2) 1086 stop_decoding(JPGD_BAD_DHT_MARKER); 1087 1088 num_left -= 2; 1089 1090 while (num_left) 1091 { 1092 index = get_bits(8); 1093 1094 huff_num.ptr[0] = 0; 1095 1096 count = 0; 1097 1098 for (i = 1; i <= 16; i++) 1099 { 1100 huff_num.ptr[i] = cast(ubyte)(get_bits(8)); 1101 count += huff_num.ptr[i]; 1102 } 1103 1104 if (count > 255) 1105 stop_decoding(JPGD_BAD_DHT_COUNTS); 1106 1107 for (i = 0; i < count; i++) 1108 huff_val.ptr[i] = cast(ubyte)(get_bits(8)); 1109 1110 i = 1 + 16 + count; 1111 1112 if (num_left < cast(uint)i) 1113 stop_decoding(JPGD_BAD_DHT_MARKER); 1114 1115 num_left -= i; 1116 1117 if ((index & 0x10) > 0x10) 1118 stop_decoding(JPGD_BAD_DHT_INDEX); 1119 1120 index = (index & 0x0F) + ((index & 0x10) >> 4) * (JPGD_MAX_HUFF_TABLES >> 1); 1121 1122 if (index >= JPGD_MAX_HUFF_TABLES) 1123 stop_decoding(JPGD_BAD_DHT_INDEX); 1124 1125 if (!m_huff_num.ptr[index]) 1126 m_huff_num.ptr[index] = cast(ubyte*)alloc(17); 1127 1128 if (!m_huff_val.ptr[index]) 1129 m_huff_val.ptr[index] = cast(ubyte*)alloc(256); 1130 1131 m_huff_ac.ptr[index] = (index & 0x10) != 0; 1132 memcpy(m_huff_num.ptr[index], huff_num.ptr, 17); 1133 memcpy(m_huff_val.ptr[index], huff_val.ptr, 256); 1134 } 1135 } 1136 1137 // Read a quantization table. 1138 void read_dqt_marker () { 1139 int n, i, prec; 1140 uint num_left; 1141 uint temp; 1142 1143 num_left = get_bits(16); 1144 1145 if (num_left < 2) 1146 stop_decoding(JPGD_BAD_DQT_MARKER); 1147 1148 num_left -= 2; 1149 1150 while (num_left) 1151 { 1152 n = get_bits(8); 1153 prec = n >> 4; 1154 n &= 0x0F; 1155 1156 if (n >= JPGD_MAX_QUANT_TABLES) 1157 stop_decoding(JPGD_BAD_DQT_TABLE); 1158 1159 if (!m_quant.ptr[n]) 1160 m_quant.ptr[n] = cast(jpgd_quant_t*)alloc(64 * jpgd_quant_t.sizeof); 1161 1162 // read quantization entries, in zag order 1163 for (i = 0; i < 64; i++) 1164 { 1165 temp = get_bits(8); 1166 1167 if (prec) 1168 temp = (temp << 8) + get_bits(8); 1169 1170 m_quant.ptr[n][i] = cast(jpgd_quant_t)(temp); 1171 } 1172 1173 i = 64 + 1; 1174 1175 if (prec) 1176 i += 64; 1177 1178 if (num_left < cast(uint)i) 1179 stop_decoding(JPGD_BAD_DQT_LENGTH); 1180 1181 num_left -= i; 1182 } 1183 } 1184 1185 // Read the start of frame (SOF) marker. 1186 void read_sof_marker () { 1187 int i; 1188 uint num_left; 1189 1190 num_left = get_bits(16); 1191 1192 if (get_bits(8) != 8) /* precision: sorry, only 8-bit precision is supported right now */ 1193 stop_decoding(JPGD_BAD_PRECISION); 1194 1195 m_image_y_size = get_bits(16); 1196 1197 if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT)) 1198 stop_decoding(JPGD_BAD_HEIGHT); 1199 1200 m_image_x_size = get_bits(16); 1201 1202 if ((m_image_x_size < 1) || (m_image_x_size > JPGD_MAX_WIDTH)) 1203 stop_decoding(JPGD_BAD_WIDTH); 1204 1205 m_comps_in_frame = get_bits(8); 1206 1207 if (m_comps_in_frame > JPGD_MAX_COMPONENTS) 1208 stop_decoding(JPGD_TOO_MANY_COMPONENTS); 1209 1210 if (num_left != cast(uint)(m_comps_in_frame * 3 + 8)) 1211 stop_decoding(JPGD_BAD_SOF_LENGTH); 1212 1213 for (i = 0; i < m_comps_in_frame; i++) 1214 { 1215 m_comp_ident.ptr[i] = get_bits(8); 1216 m_comp_h_samp.ptr[i] = get_bits(4); 1217 m_comp_v_samp.ptr[i] = get_bits(4); 1218 m_comp_quant.ptr[i] = get_bits(8); 1219 } 1220 } 1221 1222 // Used to skip unrecognized markers. 1223 void skip_variable_marker () { 1224 uint num_left; 1225 1226 num_left = get_bits(16); 1227 1228 if (num_left < 2) 1229 stop_decoding(JPGD_BAD_VARIABLE_MARKER); 1230 1231 num_left -= 2; 1232 1233 while (num_left) 1234 { 1235 get_bits(8); 1236 num_left--; 1237 } 1238 } 1239 1240 // Read a define restart interval (DRI) marker. 1241 void read_dri_marker () { 1242 if (get_bits(16) != 4) 1243 stop_decoding(JPGD_BAD_DRI_LENGTH); 1244 1245 m_restart_interval = get_bits(16); 1246 } 1247 1248 // Read a start of scan (SOS) marker. 1249 void read_sos_marker () { 1250 uint num_left; 1251 int i, ci, n, c, cc; 1252 1253 num_left = get_bits(16); 1254 1255 n = get_bits(8); 1256 1257 m_comps_in_scan = n; 1258 1259 num_left -= 3; 1260 1261 if ( (num_left != cast(uint)(n * 2 + 3)) || (n < 1) || (n > JPGD_MAX_COMPS_IN_SCAN) ) 1262 stop_decoding(JPGD_BAD_SOS_LENGTH); 1263 1264 for (i = 0; i < n; i++) 1265 { 1266 cc = get_bits(8); 1267 c = get_bits(8); 1268 num_left -= 2; 1269 1270 for (ci = 0; ci < m_comps_in_frame; ci++) 1271 if (cc == m_comp_ident.ptr[ci]) 1272 break; 1273 1274 if (ci >= m_comps_in_frame) 1275 stop_decoding(JPGD_BAD_SOS_COMP_ID); 1276 1277 m_comp_list.ptr[i] = ci; 1278 m_comp_dc_tab.ptr[ci] = (c >> 4) & 15; 1279 m_comp_ac_tab.ptr[ci] = (c & 15) + (JPGD_MAX_HUFF_TABLES >> 1); 1280 } 1281 1282 m_spectral_start = get_bits(8); 1283 m_spectral_end = get_bits(8); 1284 m_successive_high = get_bits(4); 1285 m_successive_low = get_bits(4); 1286 1287 if (!m_progressive_flag) 1288 { 1289 m_spectral_start = 0; 1290 m_spectral_end = 63; 1291 } 1292 1293 num_left -= 3; 1294 1295 /* read past whatever is num_left */ 1296 while (num_left) 1297 { 1298 get_bits(8); 1299 num_left--; 1300 } 1301 } 1302 1303 // Finds the next marker. 1304 int next_marker () { 1305 uint c, bytes; 1306 1307 bytes = 0; 1308 1309 do 1310 { 1311 do 1312 { 1313 bytes++; 1314 c = get_bits(8); 1315 } while (c != 0xFF); 1316 1317 do 1318 { 1319 c = get_bits(8); 1320 } while (c == 0xFF); 1321 1322 } while (c == 0); 1323 1324 // If bytes > 0 here, there where extra bytes before the marker (not good). 1325 1326 return c; 1327 } 1328 1329 // Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is 1330 // encountered. 1331 int process_markers () { 1332 int c; 1333 1334 for ( ; ; ) { 1335 c = next_marker(); 1336 1337 switch (c) 1338 { 1339 case M_SOF0: 1340 case M_SOF1: 1341 case M_SOF2: 1342 case M_SOF3: 1343 case M_SOF5: 1344 case M_SOF6: 1345 case M_SOF7: 1346 //case M_JPG: 1347 case M_SOF9: 1348 case M_SOF10: 1349 case M_SOF11: 1350 case M_SOF13: 1351 case M_SOF14: 1352 case M_SOF15: 1353 case M_SOI: 1354 case M_EOI: 1355 case M_SOS: 1356 return c; 1357 case M_DHT: 1358 read_dht_marker(); 1359 break; 1360 // No arithmitic support - dumb patents! 1361 case M_DAC: 1362 stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT); 1363 break; 1364 case M_DQT: 1365 read_dqt_marker(); 1366 break; 1367 case M_DRI: 1368 read_dri_marker(); 1369 break; 1370 //case M_APP0: /* no need to read the JFIF marker */ 1371 1372 case M_JPG: 1373 case M_RST0: /* no parameters */ 1374 case M_RST1: 1375 case M_RST2: 1376 case M_RST3: 1377 case M_RST4: 1378 case M_RST5: 1379 case M_RST6: 1380 case M_RST7: 1381 case M_TEM: 1382 stop_decoding(JPGD_UNEXPECTED_MARKER); 1383 break; 1384 default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */ 1385 skip_variable_marker(); 1386 break; 1387 } 1388 } 1389 } 1390 1391 // Finds the start of image (SOI) marker. 1392 // This code is rather defensive: it only checks the first 512 bytes to avoid 1393 // false positives. 1394 void locate_soi_marker () { 1395 uint lastchar, thischar; 1396 uint bytesleft; 1397 1398 lastchar = get_bits(8); 1399 1400 thischar = get_bits(8); 1401 1402 /* ok if it's a normal JPEG file without a special header */ 1403 1404 if ((lastchar == 0xFF) && (thischar == M_SOI)) 1405 return; 1406 1407 bytesleft = 4096; //512; 1408 1409 for ( ; ; ) 1410 { 1411 if (--bytesleft == 0) 1412 stop_decoding(JPGD_NOT_JPEG); 1413 1414 lastchar = thischar; 1415 1416 thischar = get_bits(8); 1417 1418 if (lastchar == 0xFF) 1419 { 1420 if (thischar == M_SOI) 1421 break; 1422 else if (thischar == M_EOI) // get_bits will keep returning M_EOI if we read past the end 1423 stop_decoding(JPGD_NOT_JPEG); 1424 } 1425 } 1426 1427 // Check the next character after marker: if it's not 0xFF, it can't be the start of the next marker, so the file is bad. 1428 thischar = (m_bit_buf >> 24) & 0xFF; 1429 1430 if (thischar != 0xFF) 1431 stop_decoding(JPGD_NOT_JPEG); 1432 } 1433 1434 // Find a start of frame (SOF) marker. 1435 void locate_sof_marker () { 1436 locate_soi_marker(); 1437 1438 int c = process_markers(); 1439 1440 switch (c) 1441 { 1442 case M_SOF2: 1443 m_progressive_flag = true; 1444 goto case; 1445 case M_SOF0: /* baseline DCT */ 1446 case M_SOF1: /* extended sequential DCT */ 1447 read_sof_marker(); 1448 break; 1449 case M_SOF9: /* Arithmitic coding */ 1450 stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT); 1451 break; 1452 default: 1453 stop_decoding(JPGD_UNSUPPORTED_MARKER); 1454 break; 1455 } 1456 } 1457 1458 // Find a start of scan (SOS) marker. 1459 int locate_sos_marker () { 1460 int c; 1461 1462 c = process_markers(); 1463 1464 if (c == M_EOI) 1465 return false; 1466 else if (c != M_SOS) 1467 stop_decoding(JPGD_UNEXPECTED_MARKER); 1468 1469 read_sos_marker(); 1470 1471 return true; 1472 } 1473 1474 // Reset everything to default/uninitialized state. 1475 void initit (JpegStreamReadFunc rfn) { 1476 m_pMem_blocks = null; 1477 m_error_code = JPGD_SUCCESS; 1478 m_ready_flag = false; 1479 m_image_x_size = m_image_y_size = 0; 1480 readfn = rfn; 1481 m_progressive_flag = false; 1482 1483 memset(m_huff_ac.ptr, 0, m_huff_ac.sizeof); 1484 memset(m_huff_num.ptr, 0, m_huff_num.sizeof); 1485 memset(m_huff_val.ptr, 0, m_huff_val.sizeof); 1486 memset(m_quant.ptr, 0, m_quant.sizeof); 1487 1488 m_scan_type = 0; 1489 m_comps_in_frame = 0; 1490 1491 memset(m_comp_h_samp.ptr, 0, m_comp_h_samp.sizeof); 1492 memset(m_comp_v_samp.ptr, 0, m_comp_v_samp.sizeof); 1493 memset(m_comp_quant.ptr, 0, m_comp_quant.sizeof); 1494 memset(m_comp_ident.ptr, 0, m_comp_ident.sizeof); 1495 memset(m_comp_h_blocks.ptr, 0, m_comp_h_blocks.sizeof); 1496 memset(m_comp_v_blocks.ptr, 0, m_comp_v_blocks.sizeof); 1497 1498 m_comps_in_scan = 0; 1499 memset(m_comp_list.ptr, 0, m_comp_list.sizeof); 1500 memset(m_comp_dc_tab.ptr, 0, m_comp_dc_tab.sizeof); 1501 memset(m_comp_ac_tab.ptr, 0, m_comp_ac_tab.sizeof); 1502 1503 m_spectral_start = 0; 1504 m_spectral_end = 0; 1505 m_successive_low = 0; 1506 m_successive_high = 0; 1507 m_max_mcu_x_size = 0; 1508 m_max_mcu_y_size = 0; 1509 m_blocks_per_mcu = 0; 1510 m_max_blocks_per_row = 0; 1511 m_mcus_per_row = 0; 1512 m_mcus_per_col = 0; 1513 m_expanded_blocks_per_component = 0; 1514 m_expanded_blocks_per_mcu = 0; 1515 m_expanded_blocks_per_row = 0; 1516 m_freq_domain_chroma_upsample = false; 1517 1518 memset(m_mcu_org.ptr, 0, m_mcu_org.sizeof); 1519 1520 m_total_lines_left = 0; 1521 m_mcu_lines_left = 0; 1522 m_real_dest_bytes_per_scan_line = 0; 1523 m_dest_bytes_per_scan_line = 0; 1524 m_dest_bytes_per_pixel = 0; 1525 1526 memset(m_pHuff_tabs.ptr, 0, m_pHuff_tabs.sizeof); 1527 1528 memset(m_dc_coeffs.ptr, 0, m_dc_coeffs.sizeof); 1529 memset(m_ac_coeffs.ptr, 0, m_ac_coeffs.sizeof); 1530 memset(m_block_y_mcu.ptr, 0, m_block_y_mcu.sizeof); 1531 1532 m_eob_run = 0; 1533 1534 memset(m_block_y_mcu.ptr, 0, m_block_y_mcu.sizeof); 1535 1536 m_pIn_buf_ofs = m_in_buf.ptr; 1537 m_in_buf_left = 0; 1538 m_eof_flag = false; 1539 m_tem_flag = 0; 1540 1541 memset(m_in_buf_pad_start.ptr, 0, m_in_buf_pad_start.sizeof); 1542 memset(m_in_buf.ptr, 0, m_in_buf.sizeof); 1543 memset(m_in_buf_pad_end.ptr, 0, m_in_buf_pad_end.sizeof); 1544 1545 m_restart_interval = 0; 1546 m_restarts_left = 0; 1547 m_next_restart_num = 0; 1548 1549 m_max_mcus_per_row = 0; 1550 m_max_blocks_per_mcu = 0; 1551 m_max_mcus_per_col = 0; 1552 1553 memset(m_last_dc_val.ptr, 0, m_last_dc_val.sizeof); 1554 m_pMCU_coefficients = null; 1555 m_pSample_buf = null; 1556 1557 m_total_bytes_read = 0; 1558 1559 m_pScan_line_0 = null; 1560 m_pScan_line_1 = null; 1561 1562 // Ready the input buffer. 1563 prep_in_buffer(); 1564 1565 // Prime the bit buffer. 1566 m_bits_left = 16; 1567 m_bit_buf = 0; 1568 1569 get_bits(16); 1570 get_bits(16); 1571 1572 for (int i = 0; i < JPGD_MAX_BLOCKS_PER_MCU; i++) 1573 m_mcu_block_max_zag.ptr[i] = 64; 1574 } 1575 1576 enum SCALEBITS = 16; 1577 enum ONE_HALF = (cast(int) 1 << (SCALEBITS-1)); 1578 enum FIX(float x) = (cast(int)((x) * (1L<<SCALEBITS) + 0.5f)); 1579 1580 // Create a few tables that allow us to quickly convert YCbCr to RGB. 1581 void create_look_ups () { 1582 for (int i = 0; i <= 255; i++) 1583 { 1584 int k = i - 128; 1585 m_crr.ptr[i] = ( FIX!(1.40200f) * k + ONE_HALF) >> SCALEBITS; 1586 m_cbb.ptr[i] = ( FIX!(1.77200f) * k + ONE_HALF) >> SCALEBITS; 1587 m_crg.ptr[i] = (-FIX!(0.71414f)) * k; 1588 m_cbg.ptr[i] = (-FIX!(0.34414f)) * k + ONE_HALF; 1589 } 1590 } 1591 1592 // This method throws back into the stream any bytes that where read 1593 // into the bit buffer during initial marker scanning. 1594 void fix_in_buffer () { 1595 // In case any 0xFF's where pulled into the buffer during marker scanning. 1596 assert((m_bits_left & 7) == 0); 1597 1598 if (m_bits_left == 16) 1599 stuff_char(cast(ubyte)(m_bit_buf & 0xFF)); 1600 1601 if (m_bits_left >= 8) 1602 stuff_char(cast(ubyte)((m_bit_buf >> 8) & 0xFF)); 1603 1604 stuff_char(cast(ubyte)((m_bit_buf >> 16) & 0xFF)); 1605 stuff_char(cast(ubyte)((m_bit_buf >> 24) & 0xFF)); 1606 1607 m_bits_left = 16; 1608 get_bits_no_markers(16); 1609 get_bits_no_markers(16); 1610 } 1611 1612 void transform_mcu (int mcu_row) { 1613 jpgd_block_t* pSrc_ptr = m_pMCU_coefficients; 1614 ubyte* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64; 1615 1616 for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++) 1617 { 1618 idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag.ptr[mcu_block]); 1619 pSrc_ptr += 64; 1620 pDst_ptr += 64; 1621 } 1622 } 1623 1624 static immutable ubyte[64] s_max_rc = [ 1625 17, 18, 34, 50, 50, 51, 52, 52, 52, 68, 84, 84, 84, 84, 85, 86, 86, 86, 86, 86, 1626 102, 118, 118, 118, 118, 118, 118, 119, 120, 120, 120, 120, 120, 120, 120, 136, 1627 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 1628 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136 1629 ]; 1630 1631 void transform_mcu_expand (int mcu_row) { 1632 jpgd_block_t* pSrc_ptr = m_pMCU_coefficients; 1633 ubyte* pDst_ptr = m_pSample_buf + mcu_row * m_expanded_blocks_per_mcu * 64; 1634 1635 // Y IDCT 1636 int mcu_block; 1637 for (mcu_block = 0; mcu_block < m_expanded_blocks_per_component; mcu_block++) 1638 { 1639 idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag.ptr[mcu_block]); 1640 pSrc_ptr += 64; 1641 pDst_ptr += 64; 1642 } 1643 1644 // Chroma IDCT, with upsampling 1645 jpgd_block_t[64] temp_block; 1646 1647 for (int i = 0; i < 2; i++) 1648 { 1649 DCT_Upsample.Matrix44 P, Q, R, S; 1650 1651 assert(m_mcu_block_max_zag.ptr[mcu_block] >= 1); 1652 assert(m_mcu_block_max_zag.ptr[mcu_block] <= 64); 1653 1654 int max_zag = m_mcu_block_max_zag.ptr[mcu_block++] - 1; 1655 if (max_zag <= 0) max_zag = 0; // should never happen, only here to shut up static analysis 1656 switch (s_max_rc.ptr[max_zag]) 1657 { 1658 case 1*16+1: 1659 DCT_Upsample.P_Q!(1, 1).calc(P, Q, pSrc_ptr); 1660 DCT_Upsample.R_S!(1, 1).calc(R, S, pSrc_ptr); 1661 break; 1662 case 1*16+2: 1663 DCT_Upsample.P_Q!(1, 2).calc(P, Q, pSrc_ptr); 1664 DCT_Upsample.R_S!(1, 2).calc(R, S, pSrc_ptr); 1665 break; 1666 case 2*16+2: 1667 DCT_Upsample.P_Q!(2, 2).calc(P, Q, pSrc_ptr); 1668 DCT_Upsample.R_S!(2, 2).calc(R, S, pSrc_ptr); 1669 break; 1670 case 3*16+2: 1671 DCT_Upsample.P_Q!(3, 2).calc(P, Q, pSrc_ptr); 1672 DCT_Upsample.R_S!(3, 2).calc(R, S, pSrc_ptr); 1673 break; 1674 case 3*16+3: 1675 DCT_Upsample.P_Q!(3, 3).calc(P, Q, pSrc_ptr); 1676 DCT_Upsample.R_S!(3, 3).calc(R, S, pSrc_ptr); 1677 break; 1678 case 3*16+4: 1679 DCT_Upsample.P_Q!(3, 4).calc(P, Q, pSrc_ptr); 1680 DCT_Upsample.R_S!(3, 4).calc(R, S, pSrc_ptr); 1681 break; 1682 case 4*16+4: 1683 DCT_Upsample.P_Q!(4, 4).calc(P, Q, pSrc_ptr); 1684 DCT_Upsample.R_S!(4, 4).calc(R, S, pSrc_ptr); 1685 break; 1686 case 5*16+4: 1687 DCT_Upsample.P_Q!(5, 4).calc(P, Q, pSrc_ptr); 1688 DCT_Upsample.R_S!(5, 4).calc(R, S, pSrc_ptr); 1689 break; 1690 case 5*16+5: 1691 DCT_Upsample.P_Q!(5, 5).calc(P, Q, pSrc_ptr); 1692 DCT_Upsample.R_S!(5, 5).calc(R, S, pSrc_ptr); 1693 break; 1694 case 5*16+6: 1695 DCT_Upsample.P_Q!(5, 6).calc(P, Q, pSrc_ptr); 1696 DCT_Upsample.R_S!(5, 6).calc(R, S, pSrc_ptr); 1697 break; 1698 case 6*16+6: 1699 DCT_Upsample.P_Q!(6, 6).calc(P, Q, pSrc_ptr); 1700 DCT_Upsample.R_S!(6, 6).calc(R, S, pSrc_ptr); 1701 break; 1702 case 7*16+6: 1703 DCT_Upsample.P_Q!(7, 6).calc(P, Q, pSrc_ptr); 1704 DCT_Upsample.R_S!(7, 6).calc(R, S, pSrc_ptr); 1705 break; 1706 case 7*16+7: 1707 DCT_Upsample.P_Q!(7, 7).calc(P, Q, pSrc_ptr); 1708 DCT_Upsample.R_S!(7, 7).calc(R, S, pSrc_ptr); 1709 break; 1710 case 7*16+8: 1711 DCT_Upsample.P_Q!(7, 8).calc(P, Q, pSrc_ptr); 1712 DCT_Upsample.R_S!(7, 8).calc(R, S, pSrc_ptr); 1713 break; 1714 case 8*16+8: 1715 DCT_Upsample.P_Q!(8, 8).calc(P, Q, pSrc_ptr); 1716 DCT_Upsample.R_S!(8, 8).calc(R, S, pSrc_ptr); 1717 break; 1718 default: 1719 assert(false); 1720 } 1721 1722 auto a = DCT_Upsample.Matrix44(P + Q); 1723 P -= Q; 1724 DCT_Upsample.Matrix44* b = &P; 1725 auto c = DCT_Upsample.Matrix44(R + S); 1726 R -= S; 1727 DCT_Upsample.Matrix44* d = &R; 1728 1729 DCT_Upsample.Matrix44.add_and_store(temp_block.ptr, a, c); 1730 idct_4x4(temp_block.ptr, pDst_ptr); 1731 pDst_ptr += 64; 1732 1733 DCT_Upsample.Matrix44.sub_and_store(temp_block.ptr, a, c); 1734 idct_4x4(temp_block.ptr, pDst_ptr); 1735 pDst_ptr += 64; 1736 1737 DCT_Upsample.Matrix44.add_and_store(temp_block.ptr, *b, *d); 1738 idct_4x4(temp_block.ptr, pDst_ptr); 1739 pDst_ptr += 64; 1740 1741 DCT_Upsample.Matrix44.sub_and_store(temp_block.ptr, *b, *d); 1742 idct_4x4(temp_block.ptr, pDst_ptr); 1743 pDst_ptr += 64; 1744 1745 pSrc_ptr += 64; 1746 } 1747 } 1748 1749 // Loads and dequantizes the next row of (already decoded) coefficients. 1750 // Progressive images only. 1751 void load_next_row () { 1752 int i; 1753 jpgd_block_t *p; 1754 jpgd_quant_t *q; 1755 int mcu_row, mcu_block, row_block = 0; 1756 int component_num, component_id; 1757 int[JPGD_MAX_COMPONENTS] block_x_mcu; 1758 1759 memset(block_x_mcu.ptr, 0, JPGD_MAX_COMPONENTS * int.sizeof); 1760 1761 for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++) 1762 { 1763 int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0; 1764 1765 for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++) 1766 { 1767 component_id = m_mcu_org.ptr[mcu_block]; 1768 q = m_quant.ptr[m_comp_quant.ptr[component_id]]; 1769 1770 p = m_pMCU_coefficients + 64 * mcu_block; 1771 1772 jpgd_block_t* pAC = coeff_buf_getp(m_ac_coeffs.ptr[component_id], block_x_mcu.ptr[component_id] + block_x_mcu_ofs, m_block_y_mcu.ptr[component_id] + block_y_mcu_ofs); 1773 jpgd_block_t* pDC = coeff_buf_getp(m_dc_coeffs.ptr[component_id], block_x_mcu.ptr[component_id] + block_x_mcu_ofs, m_block_y_mcu.ptr[component_id] + block_y_mcu_ofs); 1774 p[0] = pDC[0]; 1775 memcpy(&p[1], &pAC[1], 63 * jpgd_block_t.sizeof); 1776 1777 for (i = 63; i > 0; i--) 1778 if (p[g_ZAG[i]]) 1779 break; 1780 1781 m_mcu_block_max_zag.ptr[mcu_block] = i + 1; 1782 1783 for ( ; i >= 0; i--) 1784 if (p[g_ZAG[i]]) 1785 p[g_ZAG[i]] = cast(jpgd_block_t)(p[g_ZAG[i]] * q[i]); 1786 1787 row_block++; 1788 1789 if (m_comps_in_scan == 1) 1790 block_x_mcu.ptr[component_id]++; 1791 else 1792 { 1793 if (++block_x_mcu_ofs == m_comp_h_samp.ptr[component_id]) 1794 { 1795 block_x_mcu_ofs = 0; 1796 1797 if (++block_y_mcu_ofs == m_comp_v_samp.ptr[component_id]) 1798 { 1799 block_y_mcu_ofs = 0; 1800 1801 block_x_mcu.ptr[component_id] += m_comp_h_samp.ptr[component_id]; 1802 } 1803 } 1804 } 1805 } 1806 1807 if (m_freq_domain_chroma_upsample) 1808 transform_mcu_expand(mcu_row); 1809 else 1810 transform_mcu(mcu_row); 1811 } 1812 1813 if (m_comps_in_scan == 1) 1814 m_block_y_mcu.ptr[m_comp_list.ptr[0]]++; 1815 else 1816 { 1817 for (component_num = 0; component_num < m_comps_in_scan; component_num++) 1818 { 1819 component_id = m_comp_list.ptr[component_num]; 1820 1821 m_block_y_mcu.ptr[component_id] += m_comp_v_samp.ptr[component_id]; 1822 } 1823 } 1824 } 1825 1826 // Restart interval processing. 1827 void process_restart () { 1828 int i; 1829 int c = 0; 1830 1831 // Align to a byte boundry 1832 // FIXME: Is this really necessary? get_bits_no_markers() never reads in markers! 1833 //get_bits_no_markers(m_bits_left & 7); 1834 1835 // Let's scan a little bit to find the marker, but not _too_ far. 1836 // 1536 is a "fudge factor" that determines how much to scan. 1837 for (i = 1536; i > 0; i--) 1838 if (get_char() == 0xFF) 1839 break; 1840 1841 if (i == 0) 1842 stop_decoding(JPGD_BAD_RESTART_MARKER); 1843 1844 for ( ; i > 0; i--) 1845 if ((c = get_char()) != 0xFF) 1846 break; 1847 1848 if (i == 0) 1849 stop_decoding(JPGD_BAD_RESTART_MARKER); 1850 1851 // Is it the expected marker? If not, something bad happened. 1852 if (c != (m_next_restart_num + M_RST0)) 1853 stop_decoding(JPGD_BAD_RESTART_MARKER); 1854 1855 // Reset each component's DC prediction values. 1856 memset(&m_last_dc_val, 0, m_comps_in_frame * uint.sizeof); 1857 1858 m_eob_run = 0; 1859 1860 m_restarts_left = m_restart_interval; 1861 1862 m_next_restart_num = (m_next_restart_num + 1) & 7; 1863 1864 // Get the bit buffer going again... 1865 1866 m_bits_left = 16; 1867 get_bits_no_markers(16); 1868 get_bits_no_markers(16); 1869 } 1870 1871 static int dequantize_ac (int c, int q) { pragma(inline, true); c *= q; return c; } 1872 1873 // Decodes and dequantizes the next row of coefficients. 1874 void decode_next_row () { 1875 int row_block = 0; 1876 1877 for (int mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++) 1878 { 1879 if ((m_restart_interval) && (m_restarts_left == 0)) 1880 process_restart(); 1881 1882 jpgd_block_t* p = m_pMCU_coefficients; 1883 for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++, p += 64) 1884 { 1885 int component_id = m_mcu_org.ptr[mcu_block]; 1886 jpgd_quant_t* q = m_quant.ptr[m_comp_quant.ptr[component_id]]; 1887 1888 int r, s; 1889 s = huff_decode(m_pHuff_tabs.ptr[m_comp_dc_tab.ptr[component_id]], r); 1890 s = JPGD_HUFF_EXTEND(r, s); 1891 1892 m_last_dc_val.ptr[component_id] = (s += m_last_dc_val.ptr[component_id]); 1893 1894 p[0] = cast(jpgd_block_t)(s * q[0]); 1895 1896 int prev_num_set = m_mcu_block_max_zag.ptr[mcu_block]; 1897 1898 huff_tables *pH = m_pHuff_tabs.ptr[m_comp_ac_tab.ptr[component_id]]; 1899 1900 int k; 1901 for (k = 1; k < 64; k++) 1902 { 1903 int extra_bits; 1904 s = huff_decode(pH, extra_bits); 1905 1906 r = s >> 4; 1907 s &= 15; 1908 1909 if (s) 1910 { 1911 if (r) 1912 { 1913 if ((k + r) > 63) 1914 stop_decoding(JPGD_DECODE_ERROR); 1915 1916 if (k < prev_num_set) 1917 { 1918 int n = JPGD_MIN(r, prev_num_set - k); 1919 int kt = k; 1920 while (n--) 1921 p[g_ZAG[kt++]] = 0; 1922 } 1923 1924 k += r; 1925 } 1926 1927 s = JPGD_HUFF_EXTEND(extra_bits, s); 1928 1929 assert(k < 64); 1930 1931 p[g_ZAG[k]] = cast(jpgd_block_t)(dequantize_ac(s, q[k])); //s * q[k]; 1932 } 1933 else 1934 { 1935 if (r == 15) 1936 { 1937 if ((k + 16) > 64) 1938 stop_decoding(JPGD_DECODE_ERROR); 1939 1940 if (k < prev_num_set) 1941 { 1942 int n = JPGD_MIN(16, prev_num_set - k); 1943 int kt = k; 1944 while (n--) 1945 { 1946 assert(kt <= 63); 1947 p[g_ZAG[kt++]] = 0; 1948 } 1949 } 1950 1951 k += 16 - 1; // - 1 because the loop counter is k 1952 assert(p[g_ZAG[k]] == 0); 1953 } 1954 else 1955 break; 1956 } 1957 } 1958 1959 if (k < prev_num_set) 1960 { 1961 int kt = k; 1962 while (kt < prev_num_set) 1963 p[g_ZAG[kt++]] = 0; 1964 } 1965 1966 m_mcu_block_max_zag.ptr[mcu_block] = k; 1967 1968 row_block++; 1969 } 1970 1971 if (m_freq_domain_chroma_upsample) 1972 transform_mcu_expand(mcu_row); 1973 else 1974 transform_mcu(mcu_row); 1975 1976 m_restarts_left--; 1977 } 1978 } 1979 1980 // YCbCr H1V1 (1x1:1:1, 3 m_blocks per MCU) to RGB 1981 void H1V1Convert () { 1982 int row = m_max_mcu_y_size - m_mcu_lines_left; 1983 ubyte *d = m_pScan_line_0; 1984 ubyte *s = m_pSample_buf + row * 8; 1985 1986 for (int i = m_max_mcus_per_row; i > 0; i--) 1987 { 1988 for (int j = 0; j < 8; j++) 1989 { 1990 int y = s[j]; 1991 int cb = s[64+j]; 1992 int cr = s[128+j]; 1993 1994 d[0] = clamp(y + m_crr.ptr[cr]); 1995 d[1] = clamp(y + ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16)); 1996 d[2] = clamp(y + m_cbb.ptr[cb]); 1997 d[3] = 255; 1998 1999 d += 4; 2000 } 2001 2002 s += 64*3; 2003 } 2004 } 2005 2006 // YCbCr H2V1 (2x1:1:1, 4 m_blocks per MCU) to RGB 2007 void H2V1Convert () { 2008 int row = m_max_mcu_y_size - m_mcu_lines_left; 2009 ubyte *d0 = m_pScan_line_0; 2010 ubyte *y = m_pSample_buf + row * 8; 2011 ubyte *c = m_pSample_buf + 2*64 + row * 8; 2012 2013 for (int i = m_max_mcus_per_row; i > 0; i--) 2014 { 2015 for (int l = 0; l < 2; l++) 2016 { 2017 for (int j = 0; j < 4; j++) 2018 { 2019 int cb = c[0]; 2020 int cr = c[64]; 2021 2022 int rc = m_crr.ptr[cr]; 2023 int gc = ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16); 2024 int bc = m_cbb.ptr[cb]; 2025 2026 int yy = y[j<<1]; 2027 d0[0] = clamp(yy+rc); 2028 d0[1] = clamp(yy+gc); 2029 d0[2] = clamp(yy+bc); 2030 d0[3] = 255; 2031 2032 yy = y[(j<<1)+1]; 2033 d0[4] = clamp(yy+rc); 2034 d0[5] = clamp(yy+gc); 2035 d0[6] = clamp(yy+bc); 2036 d0[7] = 255; 2037 2038 d0 += 8; 2039 2040 c++; 2041 } 2042 y += 64; 2043 } 2044 2045 y += 64*4 - 64*2; 2046 c += 64*4 - 8; 2047 } 2048 } 2049 2050 // YCbCr H2V1 (1x2:1:1, 4 m_blocks per MCU) to RGB 2051 void H1V2Convert () { 2052 int row = m_max_mcu_y_size - m_mcu_lines_left; 2053 ubyte *d0 = m_pScan_line_0; 2054 ubyte *d1 = m_pScan_line_1; 2055 ubyte *y; 2056 ubyte *c; 2057 2058 if (row < 8) 2059 y = m_pSample_buf + row * 8; 2060 else 2061 y = m_pSample_buf + 64*1 + (row & 7) * 8; 2062 2063 c = m_pSample_buf + 64*2 + (row >> 1) * 8; 2064 2065 for (int i = m_max_mcus_per_row; i > 0; i--) 2066 { 2067 for (int j = 0; j < 8; j++) 2068 { 2069 int cb = c[0+j]; 2070 int cr = c[64+j]; 2071 2072 int rc = m_crr.ptr[cr]; 2073 int gc = ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16); 2074 int bc = m_cbb.ptr[cb]; 2075 2076 int yy = y[j]; 2077 d0[0] = clamp(yy+rc); 2078 d0[1] = clamp(yy+gc); 2079 d0[2] = clamp(yy+bc); 2080 d0[3] = 255; 2081 2082 yy = y[8+j]; 2083 d1[0] = clamp(yy+rc); 2084 d1[1] = clamp(yy+gc); 2085 d1[2] = clamp(yy+bc); 2086 d1[3] = 255; 2087 2088 d0 += 4; 2089 d1 += 4; 2090 } 2091 2092 y += 64*4; 2093 c += 64*4; 2094 } 2095 } 2096 2097 // YCbCr H2V2 (2x2:1:1, 6 m_blocks per MCU) to RGB 2098 void H2V2Convert () { 2099 int row = m_max_mcu_y_size - m_mcu_lines_left; 2100 ubyte *d0 = m_pScan_line_0; 2101 ubyte *d1 = m_pScan_line_1; 2102 ubyte *y; 2103 ubyte *c; 2104 2105 if (row < 8) 2106 y = m_pSample_buf + row * 8; 2107 else 2108 y = m_pSample_buf + 64*2 + (row & 7) * 8; 2109 2110 c = m_pSample_buf + 64*4 + (row >> 1) * 8; 2111 2112 for (int i = m_max_mcus_per_row; i > 0; i--) 2113 { 2114 for (int l = 0; l < 2; l++) 2115 { 2116 for (int j = 0; j < 8; j += 2) 2117 { 2118 int cb = c[0]; 2119 int cr = c[64]; 2120 2121 int rc = m_crr.ptr[cr]; 2122 int gc = ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16); 2123 int bc = m_cbb.ptr[cb]; 2124 2125 int yy = y[j]; 2126 d0[0] = clamp(yy+rc); 2127 d0[1] = clamp(yy+gc); 2128 d0[2] = clamp(yy+bc); 2129 d0[3] = 255; 2130 2131 yy = y[j+1]; 2132 d0[4] = clamp(yy+rc); 2133 d0[5] = clamp(yy+gc); 2134 d0[6] = clamp(yy+bc); 2135 d0[7] = 255; 2136 2137 yy = y[j+8]; 2138 d1[0] = clamp(yy+rc); 2139 d1[1] = clamp(yy+gc); 2140 d1[2] = clamp(yy+bc); 2141 d1[3] = 255; 2142 2143 yy = y[j+8+1]; 2144 d1[4] = clamp(yy+rc); 2145 d1[5] = clamp(yy+gc); 2146 d1[6] = clamp(yy+bc); 2147 d1[7] = 255; 2148 2149 d0 += 8; 2150 d1 += 8; 2151 2152 c++; 2153 } 2154 y += 64; 2155 } 2156 2157 y += 64*6 - 64*2; 2158 c += 64*6 - 8; 2159 } 2160 } 2161 2162 // Y (1 block per MCU) to 8-bit grayscale 2163 void gray_convert () { 2164 int row = m_max_mcu_y_size - m_mcu_lines_left; 2165 ubyte *d = m_pScan_line_0; 2166 ubyte *s = m_pSample_buf + row * 8; 2167 2168 for (int i = m_max_mcus_per_row; i > 0; i--) 2169 { 2170 *cast(uint*)d = *cast(uint*)s; 2171 *cast(uint*)(&d[4]) = *cast(uint*)(&s[4]); 2172 2173 s += 64; 2174 d += 8; 2175 } 2176 } 2177 2178 void expanded_convert () { 2179 int row = m_max_mcu_y_size - m_mcu_lines_left; 2180 2181 ubyte* Py = m_pSample_buf + (row / 8) * 64 * m_comp_h_samp.ptr[0] + (row & 7) * 8; 2182 2183 ubyte* d = m_pScan_line_0; 2184 2185 for (int i = m_max_mcus_per_row; i > 0; i--) 2186 { 2187 for (int k = 0; k < m_max_mcu_x_size; k += 8) 2188 { 2189 immutable int Y_ofs = k * 8; 2190 immutable int Cb_ofs = Y_ofs + 64 * m_expanded_blocks_per_component; 2191 immutable int Cr_ofs = Y_ofs + 64 * m_expanded_blocks_per_component * 2; 2192 for (int j = 0; j < 8; j++) 2193 { 2194 int y = Py[Y_ofs + j]; 2195 int cb = Py[Cb_ofs + j]; 2196 int cr = Py[Cr_ofs + j]; 2197 2198 d[0] = clamp(y + m_crr.ptr[cr]); 2199 d[1] = clamp(y + ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16)); 2200 d[2] = clamp(y + m_cbb.ptr[cb]); 2201 d[3] = 255; 2202 2203 d += 4; 2204 } 2205 } 2206 2207 Py += 64 * m_expanded_blocks_per_mcu; 2208 } 2209 } 2210 2211 // Find end of image (EOI) marker, so we can return to the user the exact size of the input stream. 2212 void find_eoi () { 2213 if (!m_progressive_flag) 2214 { 2215 // Attempt to read the EOI marker. 2216 //get_bits_no_markers(m_bits_left & 7); 2217 2218 // Prime the bit buffer 2219 m_bits_left = 16; 2220 get_bits(16); 2221 get_bits(16); 2222 2223 // The next marker _should_ be EOI 2224 process_markers(); 2225 } 2226 2227 m_total_bytes_read -= m_in_buf_left; 2228 } 2229 2230 // Creates the tables needed for efficient Huffman decoding. 2231 void make_huff_table (int index, huff_tables *pH) { 2232 int p, i, l, si; 2233 ubyte[257] huffsize; 2234 uint[257] huffcode; 2235 uint code; 2236 uint subtree; 2237 int code_size; 2238 int lastp; 2239 int nextfreeentry; 2240 int currententry; 2241 2242 pH.ac_table = m_huff_ac.ptr[index] != 0; 2243 2244 p = 0; 2245 2246 for (l = 1; l <= 16; l++) 2247 { 2248 for (i = 1; i <= m_huff_num.ptr[index][l]; i++) 2249 huffsize.ptr[p++] = cast(ubyte)(l); 2250 } 2251 2252 huffsize.ptr[p] = 0; 2253 2254 lastp = p; 2255 2256 code = 0; 2257 si = huffsize.ptr[0]; 2258 p = 0; 2259 2260 while (huffsize.ptr[p]) 2261 { 2262 while (huffsize.ptr[p] == si) 2263 { 2264 huffcode.ptr[p++] = code; 2265 code++; 2266 } 2267 2268 code <<= 1; 2269 si++; 2270 } 2271 2272 memset(pH.look_up.ptr, 0, pH.look_up.sizeof); 2273 memset(pH.look_up2.ptr, 0, pH.look_up2.sizeof); 2274 memset(pH.tree.ptr, 0, pH.tree.sizeof); 2275 memset(pH.code_size.ptr, 0, pH.code_size.sizeof); 2276 2277 nextfreeentry = -1; 2278 2279 p = 0; 2280 2281 while (p < lastp) 2282 { 2283 i = m_huff_val.ptr[index][p]; 2284 code = huffcode.ptr[p]; 2285 code_size = huffsize.ptr[p]; 2286 2287 pH.code_size.ptr[i] = cast(ubyte)(code_size); 2288 2289 if (code_size <= 8) 2290 { 2291 code <<= (8 - code_size); 2292 2293 for (l = 1 << (8 - code_size); l > 0; l--) 2294 { 2295 assert(i < 256); 2296 2297 pH.look_up.ptr[code] = i; 2298 2299 bool has_extrabits = false; 2300 int extra_bits = 0; 2301 int num_extra_bits = i & 15; 2302 2303 int bits_to_fetch = code_size; 2304 if (num_extra_bits) 2305 { 2306 int total_codesize = code_size + num_extra_bits; 2307 if (total_codesize <= 8) 2308 { 2309 has_extrabits = true; 2310 extra_bits = ((1 << num_extra_bits) - 1) & (code >> (8 - total_codesize)); 2311 assert(extra_bits <= 0x7FFF); 2312 bits_to_fetch += num_extra_bits; 2313 } 2314 } 2315 2316 if (!has_extrabits) 2317 pH.look_up2.ptr[code] = i | (bits_to_fetch << 8); 2318 else 2319 pH.look_up2.ptr[code] = i | 0x8000 | (extra_bits << 16) | (bits_to_fetch << 8); 2320 2321 code++; 2322 } 2323 } 2324 else 2325 { 2326 subtree = (code >> (code_size - 8)) & 0xFF; 2327 2328 currententry = pH.look_up.ptr[subtree]; 2329 2330 if (currententry == 0) 2331 { 2332 pH.look_up.ptr[subtree] = currententry = nextfreeentry; 2333 pH.look_up2.ptr[subtree] = currententry = nextfreeentry; 2334 2335 nextfreeentry -= 2; 2336 } 2337 2338 code <<= (16 - (code_size - 8)); 2339 2340 for (l = code_size; l > 9; l--) 2341 { 2342 if ((code & 0x8000) == 0) 2343 currententry--; 2344 2345 if (pH.tree.ptr[-currententry - 1] == 0) 2346 { 2347 pH.tree.ptr[-currententry - 1] = nextfreeentry; 2348 2349 currententry = nextfreeentry; 2350 2351 nextfreeentry -= 2; 2352 } 2353 else 2354 currententry = pH.tree.ptr[-currententry - 1]; 2355 2356 code <<= 1; 2357 } 2358 2359 if ((code & 0x8000) == 0) 2360 currententry--; 2361 2362 pH.tree.ptr[-currententry - 1] = i; 2363 } 2364 2365 p++; 2366 } 2367 } 2368 2369 // Verifies the quantization tables needed for this scan are available. 2370 void check_quant_tables () { 2371 for (int i = 0; i < m_comps_in_scan; i++) 2372 if (m_quant.ptr[m_comp_quant.ptr[m_comp_list.ptr[i]]] == null) 2373 stop_decoding(JPGD_UNDEFINED_QUANT_TABLE); 2374 } 2375 2376 // Verifies that all the Huffman tables needed for this scan are available. 2377 void check_huff_tables () { 2378 for (int i = 0; i < m_comps_in_scan; i++) 2379 { 2380 if ((m_spectral_start == 0) && (m_huff_num.ptr[m_comp_dc_tab.ptr[m_comp_list.ptr[i]]] == null)) 2381 stop_decoding(JPGD_UNDEFINED_HUFF_TABLE); 2382 2383 if ((m_spectral_end > 0) && (m_huff_num.ptr[m_comp_ac_tab.ptr[m_comp_list.ptr[i]]] == null)) 2384 stop_decoding(JPGD_UNDEFINED_HUFF_TABLE); 2385 } 2386 2387 for (int i = 0; i < JPGD_MAX_HUFF_TABLES; i++) 2388 if (m_huff_num.ptr[i]) 2389 { 2390 if (!m_pHuff_tabs.ptr[i]) 2391 m_pHuff_tabs.ptr[i] = cast(huff_tables*)alloc(huff_tables.sizeof); 2392 2393 make_huff_table(i, m_pHuff_tabs.ptr[i]); 2394 } 2395 } 2396 2397 // Determines the component order inside each MCU. 2398 // Also calcs how many MCU's are on each row, etc. 2399 void calc_mcu_block_order () { 2400 int component_num, component_id; 2401 int max_h_samp = 0, max_v_samp = 0; 2402 2403 for (component_id = 0; component_id < m_comps_in_frame; component_id++) 2404 { 2405 if (m_comp_h_samp.ptr[component_id] > max_h_samp) 2406 max_h_samp = m_comp_h_samp.ptr[component_id]; 2407 2408 if (m_comp_v_samp.ptr[component_id] > max_v_samp) 2409 max_v_samp = m_comp_v_samp.ptr[component_id]; 2410 } 2411 2412 for (component_id = 0; component_id < m_comps_in_frame; component_id++) 2413 { 2414 m_comp_h_blocks.ptr[component_id] = ((((m_image_x_size * m_comp_h_samp.ptr[component_id]) + (max_h_samp - 1)) / max_h_samp) + 7) / 8; 2415 m_comp_v_blocks.ptr[component_id] = ((((m_image_y_size * m_comp_v_samp.ptr[component_id]) + (max_v_samp - 1)) / max_v_samp) + 7) / 8; 2416 } 2417 2418 if (m_comps_in_scan == 1) 2419 { 2420 m_mcus_per_row = m_comp_h_blocks.ptr[m_comp_list.ptr[0]]; 2421 m_mcus_per_col = m_comp_v_blocks.ptr[m_comp_list.ptr[0]]; 2422 } 2423 else 2424 { 2425 m_mcus_per_row = (((m_image_x_size + 7) / 8) + (max_h_samp - 1)) / max_h_samp; 2426 m_mcus_per_col = (((m_image_y_size + 7) / 8) + (max_v_samp - 1)) / max_v_samp; 2427 } 2428 2429 if (m_comps_in_scan == 1) 2430 { 2431 m_mcu_org.ptr[0] = m_comp_list.ptr[0]; 2432 2433 m_blocks_per_mcu = 1; 2434 } 2435 else 2436 { 2437 m_blocks_per_mcu = 0; 2438 2439 for (component_num = 0; component_num < m_comps_in_scan; component_num++) 2440 { 2441 int num_blocks; 2442 2443 component_id = m_comp_list.ptr[component_num]; 2444 2445 num_blocks = m_comp_h_samp.ptr[component_id] * m_comp_v_samp.ptr[component_id]; 2446 2447 while (num_blocks--) 2448 m_mcu_org.ptr[m_blocks_per_mcu++] = component_id; 2449 } 2450 } 2451 } 2452 2453 // Starts a new scan. 2454 int init_scan () { 2455 if (!locate_sos_marker()) 2456 return false; 2457 2458 calc_mcu_block_order(); 2459 2460 check_huff_tables(); 2461 2462 check_quant_tables(); 2463 2464 memset(m_last_dc_val.ptr, 0, m_comps_in_frame * uint.sizeof); 2465 2466 m_eob_run = 0; 2467 2468 if (m_restart_interval) 2469 { 2470 m_restarts_left = m_restart_interval; 2471 m_next_restart_num = 0; 2472 } 2473 2474 fix_in_buffer(); 2475 2476 return true; 2477 } 2478 2479 // Starts a frame. Determines if the number of components or sampling factors 2480 // are supported. 2481 void init_frame () { 2482 int i; 2483 2484 if (m_comps_in_frame == 1) 2485 { 2486 version(jpegd_test) {{ import std.stdio; stderr.writeln("m_comp_h_samp=", m_comp_h_samp.ptr[0], "; m_comp_v_samp=", m_comp_v_samp.ptr[0]); }} 2487 2488 //if ((m_comp_h_samp.ptr[0] != 1) || (m_comp_v_samp.ptr[0] != 1)) 2489 // stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); 2490 2491 if ((m_comp_h_samp.ptr[0] == 1) && (m_comp_v_samp.ptr[0] == 1)) 2492 { 2493 m_scan_type = JPGD_GRAYSCALE; 2494 m_max_blocks_per_mcu = 1; 2495 m_max_mcu_x_size = 8; 2496 m_max_mcu_y_size = 8; 2497 } 2498 else if ((m_comp_h_samp.ptr[0] == 2) && (m_comp_v_samp.ptr[0] == 2)) 2499 { 2500 //k8: i added this, and i absolutely don't know what it means; but it decoded two sample images i found 2501 m_scan_type = JPGD_GRAYSCALE; 2502 m_max_blocks_per_mcu = 4; 2503 m_max_mcu_x_size = 8; 2504 m_max_mcu_y_size = 8; 2505 } 2506 else 2507 stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); 2508 } 2509 else if (m_comps_in_frame == 3) 2510 { 2511 if ( ((m_comp_h_samp.ptr[1] != 1) || (m_comp_v_samp.ptr[1] != 1)) || 2512 ((m_comp_h_samp.ptr[2] != 1) || (m_comp_v_samp.ptr[2] != 1)) ) 2513 stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); 2514 2515 if ((m_comp_h_samp.ptr[0] == 1) && (m_comp_v_samp.ptr[0] == 1)) 2516 { 2517 m_scan_type = JPGD_YH1V1; 2518 2519 m_max_blocks_per_mcu = 3; 2520 m_max_mcu_x_size = 8; 2521 m_max_mcu_y_size = 8; 2522 } 2523 else if ((m_comp_h_samp.ptr[0] == 2) && (m_comp_v_samp.ptr[0] == 1)) 2524 { 2525 m_scan_type = JPGD_YH2V1; 2526 m_max_blocks_per_mcu = 4; 2527 m_max_mcu_x_size = 16; 2528 m_max_mcu_y_size = 8; 2529 } 2530 else if ((m_comp_h_samp.ptr[0] == 1) && (m_comp_v_samp.ptr[0] == 2)) 2531 { 2532 m_scan_type = JPGD_YH1V2; 2533 m_max_blocks_per_mcu = 4; 2534 m_max_mcu_x_size = 8; 2535 m_max_mcu_y_size = 16; 2536 } 2537 else if ((m_comp_h_samp.ptr[0] == 2) && (m_comp_v_samp.ptr[0] == 2)) 2538 { 2539 m_scan_type = JPGD_YH2V2; 2540 m_max_blocks_per_mcu = 6; 2541 m_max_mcu_x_size = 16; 2542 m_max_mcu_y_size = 16; 2543 } 2544 else 2545 stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); 2546 } 2547 else 2548 stop_decoding(JPGD_UNSUPPORTED_COLORSPACE); 2549 2550 m_max_mcus_per_row = (m_image_x_size + (m_max_mcu_x_size - 1)) / m_max_mcu_x_size; 2551 m_max_mcus_per_col = (m_image_y_size + (m_max_mcu_y_size - 1)) / m_max_mcu_y_size; 2552 2553 // These values are for the *destination* pixels: after conversion. 2554 if (m_scan_type == JPGD_GRAYSCALE) 2555 m_dest_bytes_per_pixel = 1; 2556 else 2557 m_dest_bytes_per_pixel = 4; 2558 2559 m_dest_bytes_per_scan_line = ((m_image_x_size + 15) & 0xFFF0) * m_dest_bytes_per_pixel; 2560 2561 m_real_dest_bytes_per_scan_line = (m_image_x_size * m_dest_bytes_per_pixel); 2562 2563 // Initialize two scan line buffers. 2564 m_pScan_line_0 = cast(ubyte*)alloc(m_dest_bytes_per_scan_line, true); 2565 if ((m_scan_type == JPGD_YH1V2) || (m_scan_type == JPGD_YH2V2)) 2566 m_pScan_line_1 = cast(ubyte*)alloc(m_dest_bytes_per_scan_line, true); 2567 2568 m_max_blocks_per_row = m_max_mcus_per_row * m_max_blocks_per_mcu; 2569 2570 // Should never happen 2571 if (m_max_blocks_per_row > JPGD_MAX_BLOCKS_PER_ROW) 2572 stop_decoding(JPGD_ASSERTION_ERROR); 2573 2574 // Allocate the coefficient buffer, enough for one MCU 2575 m_pMCU_coefficients = cast(jpgd_block_t*)alloc(m_max_blocks_per_mcu * 64 * jpgd_block_t.sizeof); 2576 2577 for (i = 0; i < m_max_blocks_per_mcu; i++) 2578 m_mcu_block_max_zag.ptr[i] = 64; 2579 2580 m_expanded_blocks_per_component = m_comp_h_samp.ptr[0] * m_comp_v_samp.ptr[0]; 2581 m_expanded_blocks_per_mcu = m_expanded_blocks_per_component * m_comps_in_frame; 2582 m_expanded_blocks_per_row = m_max_mcus_per_row * m_expanded_blocks_per_mcu; 2583 // Freq. domain chroma upsampling is only supported for H2V2 subsampling factor (the most common one I've seen). 2584 m_freq_domain_chroma_upsample = false; 2585 version(JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING) { 2586 m_freq_domain_chroma_upsample = (m_expanded_blocks_per_mcu == 4*3); 2587 } 2588 2589 if (m_freq_domain_chroma_upsample) 2590 m_pSample_buf = cast(ubyte*)alloc(m_expanded_blocks_per_row * 64); 2591 else 2592 m_pSample_buf = cast(ubyte*)alloc(m_max_blocks_per_row * 64); 2593 2594 m_total_lines_left = m_image_y_size; 2595 2596 m_mcu_lines_left = 0; 2597 2598 create_look_ups(); 2599 } 2600 2601 // The coeff_buf series of methods originally stored the coefficients 2602 // into a "virtual" file which was located in EMS, XMS, or a disk file. A cache 2603 // was used to make this process more efficient. Now, we can store the entire 2604 // thing in RAM. 2605 coeff_buf* coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y) { 2606 coeff_buf* cb = cast(coeff_buf*)alloc(coeff_buf.sizeof); 2607 2608 cb.block_num_x = block_num_x; 2609 cb.block_num_y = block_num_y; 2610 cb.block_len_x = block_len_x; 2611 cb.block_len_y = block_len_y; 2612 cb.block_size = cast(int)((block_len_x * block_len_y) * jpgd_block_t.sizeof); 2613 cb.pData = cast(ubyte*)alloc(cb.block_size * block_num_x * block_num_y, true); 2614 return cb; 2615 } 2616 2617 jpgd_block_t* coeff_buf_getp (coeff_buf *cb, int block_x, int block_y) { 2618 assert((block_x < cb.block_num_x) && (block_y < cb.block_num_y)); 2619 return cast(jpgd_block_t*)(cb.pData + block_x * cb.block_size + block_y * (cb.block_size * cb.block_num_x)); 2620 } 2621 2622 // The following methods decode the various types of m_blocks encountered 2623 // in progressively encoded images. 2624 static void decode_block_dc_first (ref jpeg_decoder pD, int component_id, int block_x, int block_y) { 2625 int s, r; 2626 jpgd_block_t *p = pD.coeff_buf_getp(pD.m_dc_coeffs.ptr[component_id], block_x, block_y); 2627 2628 if ((s = pD.huff_decode(pD.m_pHuff_tabs.ptr[pD.m_comp_dc_tab.ptr[component_id]])) != 0) 2629 { 2630 r = pD.get_bits_no_markers(s); 2631 s = JPGD_HUFF_EXTEND(r, s); 2632 } 2633 2634 pD.m_last_dc_val.ptr[component_id] = (s += pD.m_last_dc_val.ptr[component_id]); 2635 2636 p[0] = cast(jpgd_block_t)(s << pD.m_successive_low); 2637 } 2638 2639 static void decode_block_dc_refine (ref jpeg_decoder pD, int component_id, int block_x, int block_y) { 2640 if (pD.get_bits_no_markers(1)) 2641 { 2642 jpgd_block_t *p = pD.coeff_buf_getp(pD.m_dc_coeffs.ptr[component_id], block_x, block_y); 2643 2644 p[0] |= (1 << pD.m_successive_low); 2645 } 2646 } 2647 2648 static void decode_block_ac_first (ref jpeg_decoder pD, int component_id, int block_x, int block_y) { 2649 int k, s, r; 2650 2651 if (pD.m_eob_run) 2652 { 2653 pD.m_eob_run--; 2654 return; 2655 } 2656 2657 jpgd_block_t *p = pD.coeff_buf_getp(pD.m_ac_coeffs.ptr[component_id], block_x, block_y); 2658 2659 for (k = pD.m_spectral_start; k <= pD.m_spectral_end; k++) 2660 { 2661 s = pD.huff_decode(pD.m_pHuff_tabs.ptr[pD.m_comp_ac_tab.ptr[component_id]]); 2662 2663 r = s >> 4; 2664 s &= 15; 2665 2666 if (s) 2667 { 2668 if ((k += r) > 63) 2669 pD.stop_decoding(JPGD_DECODE_ERROR); 2670 2671 r = pD.get_bits_no_markers(s); 2672 s = JPGD_HUFF_EXTEND(r, s); 2673 2674 p[g_ZAG[k]] = cast(jpgd_block_t)(s << pD.m_successive_low); 2675 } 2676 else 2677 { 2678 if (r == 15) 2679 { 2680 if ((k += 15) > 63) 2681 pD.stop_decoding(JPGD_DECODE_ERROR); 2682 } 2683 else 2684 { 2685 pD.m_eob_run = 1 << r; 2686 2687 if (r) 2688 pD.m_eob_run += pD.get_bits_no_markers(r); 2689 2690 pD.m_eob_run--; 2691 2692 break; 2693 } 2694 } 2695 } 2696 } 2697 2698 static void decode_block_ac_refine (ref jpeg_decoder pD, int component_id, int block_x, int block_y) { 2699 int s, k, r; 2700 int p1 = 1 << pD.m_successive_low; 2701 int m1 = (-1) << pD.m_successive_low; 2702 jpgd_block_t *p = pD.coeff_buf_getp(pD.m_ac_coeffs.ptr[component_id], block_x, block_y); 2703 2704 assert(pD.m_spectral_end <= 63); 2705 2706 k = pD.m_spectral_start; 2707 2708 if (pD.m_eob_run == 0) 2709 { 2710 for ( ; k <= pD.m_spectral_end; k++) 2711 { 2712 s = pD.huff_decode(pD.m_pHuff_tabs.ptr[pD.m_comp_ac_tab.ptr[component_id]]); 2713 2714 r = s >> 4; 2715 s &= 15; 2716 2717 if (s) 2718 { 2719 if (s != 1) 2720 pD.stop_decoding(JPGD_DECODE_ERROR); 2721 2722 if (pD.get_bits_no_markers(1)) 2723 s = p1; 2724 else 2725 s = m1; 2726 } 2727 else 2728 { 2729 if (r != 15) 2730 { 2731 pD.m_eob_run = 1 << r; 2732 2733 if (r) 2734 pD.m_eob_run += pD.get_bits_no_markers(r); 2735 2736 break; 2737 } 2738 } 2739 2740 do 2741 { 2742 jpgd_block_t *this_coef = p + g_ZAG[k & 63]; 2743 2744 if (*this_coef != 0) 2745 { 2746 if (pD.get_bits_no_markers(1)) 2747 { 2748 if ((*this_coef & p1) == 0) 2749 { 2750 if (*this_coef >= 0) 2751 *this_coef = cast(jpgd_block_t)(*this_coef + p1); 2752 else 2753 *this_coef = cast(jpgd_block_t)(*this_coef + m1); 2754 } 2755 } 2756 } 2757 else 2758 { 2759 if (--r < 0) 2760 break; 2761 } 2762 2763 k++; 2764 2765 } while (k <= pD.m_spectral_end); 2766 2767 if ((s) && (k < 64)) 2768 { 2769 p[g_ZAG[k]] = cast(jpgd_block_t)(s); 2770 } 2771 } 2772 } 2773 2774 if (pD.m_eob_run > 0) 2775 { 2776 for ( ; k <= pD.m_spectral_end; k++) 2777 { 2778 jpgd_block_t *this_coef = p + g_ZAG[k & 63]; // logical AND to shut up static code analysis 2779 2780 if (*this_coef != 0) 2781 { 2782 if (pD.get_bits_no_markers(1)) 2783 { 2784 if ((*this_coef & p1) == 0) 2785 { 2786 if (*this_coef >= 0) 2787 *this_coef = cast(jpgd_block_t)(*this_coef + p1); 2788 else 2789 *this_coef = cast(jpgd_block_t)(*this_coef + m1); 2790 } 2791 } 2792 } 2793 } 2794 2795 pD.m_eob_run--; 2796 } 2797 } 2798 2799 // Decode a scan in a progressively encoded image. 2800 void decode_scan (pDecode_block_func decode_block_func) { 2801 int mcu_row, mcu_col, mcu_block; 2802 int[JPGD_MAX_COMPONENTS] block_x_mcu; 2803 int[JPGD_MAX_COMPONENTS] m_block_y_mcu; 2804 2805 memset(m_block_y_mcu.ptr, 0, m_block_y_mcu.sizeof); 2806 2807 for (mcu_col = 0; mcu_col < m_mcus_per_col; mcu_col++) 2808 { 2809 int component_num, component_id; 2810 2811 memset(block_x_mcu.ptr, 0, block_x_mcu.sizeof); 2812 2813 for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++) 2814 { 2815 int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0; 2816 2817 if ((m_restart_interval) && (m_restarts_left == 0)) 2818 process_restart(); 2819 2820 for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++) 2821 { 2822 component_id = m_mcu_org.ptr[mcu_block]; 2823 2824 decode_block_func(this, component_id, block_x_mcu.ptr[component_id] + block_x_mcu_ofs, m_block_y_mcu.ptr[component_id] + block_y_mcu_ofs); 2825 2826 if (m_comps_in_scan == 1) 2827 block_x_mcu.ptr[component_id]++; 2828 else 2829 { 2830 if (++block_x_mcu_ofs == m_comp_h_samp.ptr[component_id]) 2831 { 2832 block_x_mcu_ofs = 0; 2833 2834 if (++block_y_mcu_ofs == m_comp_v_samp.ptr[component_id]) 2835 { 2836 block_y_mcu_ofs = 0; 2837 block_x_mcu.ptr[component_id] += m_comp_h_samp.ptr[component_id]; 2838 } 2839 } 2840 } 2841 } 2842 2843 m_restarts_left--; 2844 } 2845 2846 if (m_comps_in_scan == 1) 2847 m_block_y_mcu.ptr[m_comp_list.ptr[0]]++; 2848 else 2849 { 2850 for (component_num = 0; component_num < m_comps_in_scan; component_num++) 2851 { 2852 component_id = m_comp_list.ptr[component_num]; 2853 m_block_y_mcu.ptr[component_id] += m_comp_v_samp.ptr[component_id]; 2854 } 2855 } 2856 } 2857 } 2858 2859 // Decode a progressively encoded image. 2860 void init_progressive () { 2861 int i; 2862 2863 if (m_comps_in_frame == 4) 2864 stop_decoding(JPGD_UNSUPPORTED_COLORSPACE); 2865 2866 // Allocate the coefficient buffers. 2867 for (i = 0; i < m_comps_in_frame; i++) 2868 { 2869 m_dc_coeffs.ptr[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp.ptr[i], m_max_mcus_per_col * m_comp_v_samp.ptr[i], 1, 1); 2870 m_ac_coeffs.ptr[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp.ptr[i], m_max_mcus_per_col * m_comp_v_samp.ptr[i], 8, 8); 2871 } 2872 2873 for ( ; ; ) 2874 { 2875 int dc_only_scan, refinement_scan; 2876 pDecode_block_func decode_block_func; 2877 2878 if (!init_scan()) 2879 break; 2880 2881 dc_only_scan = (m_spectral_start == 0); 2882 refinement_scan = (m_successive_high != 0); 2883 2884 if ((m_spectral_start > m_spectral_end) || (m_spectral_end > 63)) 2885 stop_decoding(JPGD_BAD_SOS_SPECTRAL); 2886 2887 if (dc_only_scan) 2888 { 2889 if (m_spectral_end) 2890 stop_decoding(JPGD_BAD_SOS_SPECTRAL); 2891 } 2892 else if (m_comps_in_scan != 1) /* AC scans can only contain one component */ 2893 stop_decoding(JPGD_BAD_SOS_SPECTRAL); 2894 2895 if ((refinement_scan) && (m_successive_low != m_successive_high - 1)) 2896 stop_decoding(JPGD_BAD_SOS_SUCCESSIVE); 2897 2898 if (dc_only_scan) 2899 { 2900 if (refinement_scan) 2901 decode_block_func = &decode_block_dc_refine; 2902 else 2903 decode_block_func = &decode_block_dc_first; 2904 } 2905 else 2906 { 2907 if (refinement_scan) 2908 decode_block_func = &decode_block_ac_refine; 2909 else 2910 decode_block_func = &decode_block_ac_first; 2911 } 2912 2913 decode_scan(decode_block_func); 2914 2915 m_bits_left = 16; 2916 get_bits(16); 2917 get_bits(16); 2918 } 2919 2920 m_comps_in_scan = m_comps_in_frame; 2921 2922 for (i = 0; i < m_comps_in_frame; i++) 2923 m_comp_list.ptr[i] = i; 2924 2925 calc_mcu_block_order(); 2926 } 2927 2928 void init_sequential () { 2929 if (!init_scan()) 2930 stop_decoding(JPGD_UNEXPECTED_MARKER); 2931 } 2932 2933 void decode_start () { 2934 init_frame(); 2935 2936 if (m_progressive_flag) 2937 init_progressive(); 2938 else 2939 init_sequential(); 2940 } 2941 2942 void decode_init (JpegStreamReadFunc rfn) { 2943 initit(rfn); 2944 locate_sof_marker(); 2945 } 2946 } 2947 2948 2949 // ////////////////////////////////////////////////////////////////////////// // 2950 /// read JPEG image header, determine dimensions and number of components. 2951 /// return `false` if image is not JPEG (i hope). 2952 public bool detect_jpeg_image_from_stream (scope JpegStreamReadFunc rfn, out int width, out int height, out int actual_comps) { 2953 if (rfn is null) return false; 2954 auto decoder = jpeg_decoder(rfn); 2955 version(jpegd_test) { import core.stdc.stdio : printf; printf("%u bytes read.\n", cast(uint)decoder.total_bytes_read); } 2956 if (decoder.error_code != JPGD_SUCCESS) return false; 2957 width = decoder.width; 2958 height = decoder.height; 2959 actual_comps = decoder.num_components; 2960 return true; 2961 } 2962 2963 2964 // ////////////////////////////////////////////////////////////////////////// // 2965 /// read JPEG image header, determine dimensions and number of components. 2966 /// return `false` if image is not JPEG (i hope). 2967 public bool detect_jpeg_image_from_file (const(char)[] filename, out int width, out int height, out int actual_comps) { 2968 import core.stdc.stdio; 2969 2970 FILE* m_pFile; 2971 bool m_eof_flag, m_error_flag; 2972 2973 if (filename.length == 0) throw new Exception("cannot open unnamed file"); 2974 if (filename.length < 512) { 2975 char[513] buffer; 2976 //import core.stdc.stdlib : alloca; 2977 auto tfn = buffer[0 .. filename.length + 1]; // (cast(char*)alloca(filename.length+1))[0..filename.length+1]; 2978 tfn[0..filename.length] = filename[]; 2979 tfn[filename.length] = 0; 2980 m_pFile = fopen(tfn.ptr, "rb"); 2981 } else { 2982 import core.stdc.stdlib : malloc, free; 2983 auto tfn = (cast(char*)malloc(filename.length+1))[0..filename.length+1]; 2984 if (tfn !is null) { 2985 scope(exit) free(tfn.ptr); 2986 m_pFile = fopen(tfn.ptr, "rb"); 2987 } 2988 } 2989 if (m_pFile is null) throw new Exception("cannot open file '"~filename.idup~"'"); 2990 scope(exit) if (m_pFile) fclose(m_pFile); 2991 2992 return detect_jpeg_image_from_stream( 2993 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 2994 if (m_pFile is null) return -1; 2995 if (m_eof_flag) { 2996 *pEOF_flag = true; 2997 return 0; 2998 } 2999 if (m_error_flag) return -1; 3000 int bytes_read = cast(int)(fread(pBuf, 1, max_bytes_to_read, m_pFile)); 3001 if (bytes_read < max_bytes_to_read) { 3002 if (ferror(m_pFile)) { 3003 m_error_flag = true; 3004 return -1; 3005 } 3006 m_eof_flag = true; 3007 *pEOF_flag = true; 3008 } 3009 return bytes_read; 3010 }, 3011 width, height, actual_comps); 3012 } 3013 3014 3015 // ////////////////////////////////////////////////////////////////////////// // 3016 /// read JPEG image header, determine dimensions and number of components. 3017 /// return `false` if image is not JPEG (i hope). 3018 public bool detect_jpeg_image_from_memory (const(void)[] buf, out int width, out int height, out int actual_comps) { 3019 size_t bufpos; 3020 return detect_jpeg_image_from_stream( 3021 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3022 import core.stdc.string : memcpy; 3023 if (bufpos >= buf.length) { 3024 *pEOF_flag = true; 3025 return 0; 3026 } 3027 if (buf.length-bufpos < max_bytes_to_read) max_bytes_to_read = cast(int)(buf.length-bufpos); 3028 memcpy(pBuf, (cast(const(ubyte)*)buf.ptr)+bufpos, max_bytes_to_read); 3029 bufpos += max_bytes_to_read; 3030 return max_bytes_to_read; 3031 }, 3032 width, height, actual_comps); 3033 } 3034 3035 3036 // ////////////////////////////////////////////////////////////////////////// // 3037 /// decompress JPEG image, what else? 3038 /// you can specify required color components in `req_comps` (3 for RGB or 4 for RGBA), or leave it as is to use image value. 3039 public ubyte[] decompress_jpeg_image_from_stream(bool useMalloc=false) (scope JpegStreamReadFunc rfn, out int width, out int height, out int actual_comps, int req_comps=-1) { 3040 import core.stdc.string : memcpy; 3041 3042 //actual_comps = 0; 3043 if (rfn is null) return null; 3044 if (req_comps != -1 && req_comps != 1 && req_comps != 3 && req_comps != 4) return null; 3045 3046 auto decoder = jpeg_decoder(rfn); 3047 if (decoder.error_code != JPGD_SUCCESS) return null; 3048 version(jpegd_test) scope(exit) { import core.stdc.stdio : printf; printf("%u bytes read.\n", cast(uint)decoder.total_bytes_read); } 3049 3050 immutable int image_width = decoder.width; 3051 immutable int image_height = decoder.height; 3052 width = image_width; 3053 height = image_height; 3054 actual_comps = decoder.num_components; 3055 if (req_comps < 0) req_comps = decoder.num_components; 3056 3057 if (decoder.begin_decoding() != JPGD_SUCCESS) return null; 3058 3059 immutable int dst_bpl = image_width*req_comps; 3060 3061 static if (useMalloc) { 3062 ubyte* pImage_data = cast(ubyte*)jpgd_malloc(dst_bpl*image_height); 3063 if (pImage_data is null) return null; 3064 auto idata = pImage_data[0..dst_bpl*image_height]; 3065 } else { 3066 auto idata = new ubyte[](dst_bpl*image_height); 3067 auto pImage_data = idata.ptr; 3068 } 3069 3070 scope(failure) { 3071 static if (useMalloc) { 3072 jpgd_free(pImage_data); 3073 } else { 3074 import core.memory : GC; 3075 GC.free(idata.ptr); 3076 idata = null; 3077 } 3078 } 3079 3080 for (int y = 0; y < image_height; ++y) { 3081 const(ubyte)* pScan_line; 3082 uint scan_line_len; 3083 if (decoder.decode(/*(const void**)*/cast(void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS) { 3084 static if (useMalloc) { 3085 jpgd_free(pImage_data); 3086 } else { 3087 import core.memory : GC; 3088 GC.free(idata.ptr); 3089 idata = null; 3090 } 3091 return null; 3092 } 3093 3094 ubyte* pDst = pImage_data+y*dst_bpl; 3095 3096 if ((req_comps == 1 && decoder.num_components == 1) || (req_comps == 4 && decoder.num_components == 3)) { 3097 memcpy(pDst, pScan_line, dst_bpl); 3098 } else if (decoder.num_components == 1) { 3099 if (req_comps == 3) { 3100 for (int x = 0; x < image_width; ++x) { 3101 ubyte luma = pScan_line[x]; 3102 pDst[0] = luma; 3103 pDst[1] = luma; 3104 pDst[2] = luma; 3105 pDst += 3; 3106 } 3107 } else { 3108 for (int x = 0; x < image_width; ++x) { 3109 ubyte luma = pScan_line[x]; 3110 pDst[0] = luma; 3111 pDst[1] = luma; 3112 pDst[2] = luma; 3113 pDst[3] = 255; 3114 pDst += 4; 3115 } 3116 } 3117 } else if (decoder.num_components == 3) { 3118 if (req_comps == 1) { 3119 immutable int YR = 19595, YG = 38470, YB = 7471; 3120 for (int x = 0; x < image_width; ++x) { 3121 int r = pScan_line[x*4+0]; 3122 int g = pScan_line[x*4+1]; 3123 int b = pScan_line[x*4+2]; 3124 *pDst++ = cast(ubyte)((r * YR + g * YG + b * YB + 32768) >> 16); 3125 } 3126 } else { 3127 for (int x = 0; x < image_width; ++x) { 3128 pDst[0] = pScan_line[x*4+0]; 3129 pDst[1] = pScan_line[x*4+1]; 3130 pDst[2] = pScan_line[x*4+2]; 3131 pDst += 3; 3132 } 3133 } 3134 } 3135 } 3136 3137 return idata; 3138 } 3139 3140 3141 // ////////////////////////////////////////////////////////////////////////// // 3142 /// decompress JPEG image from disk file. 3143 /// you can specify required color components in `req_comps` (3 for RGB or 4 for RGBA), or leave it as is to use image value. 3144 public ubyte[] decompress_jpeg_image_from_file(bool useMalloc=false) (const(char)[] filename, out int width, out int height, out int actual_comps, int req_comps=-1) { 3145 import core.stdc.stdio; 3146 3147 FILE* m_pFile; 3148 bool m_eof_flag, m_error_flag; 3149 3150 if (filename.length == 0) throw new Exception("cannot open unnamed file"); 3151 if (filename.length < 512) { 3152 char[513] buffer; 3153 //import core.stdc.stdlib : alloca; 3154 auto tfn = buffer[0 .. filename.length + 1]; // (cast(char*)alloca(filename.length+1))[0..filename.length+1]; 3155 tfn[0..filename.length] = filename[]; 3156 tfn[filename.length] = 0; 3157 m_pFile = fopen(tfn.ptr, "rb"); 3158 } else { 3159 import core.stdc.stdlib : malloc, free; 3160 auto tfn = (cast(char*)malloc(filename.length+1))[0..filename.length+1]; 3161 if (tfn !is null) { 3162 scope(exit) free(tfn.ptr); 3163 m_pFile = fopen(tfn.ptr, "rb"); 3164 } 3165 } 3166 if (m_pFile is null) throw new Exception("cannot open file '"~filename.idup~"'"); 3167 scope(exit) if (m_pFile) fclose(m_pFile); 3168 3169 return decompress_jpeg_image_from_stream!useMalloc( 3170 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3171 if (m_pFile is null) return -1; 3172 if (m_eof_flag) { 3173 *pEOF_flag = true; 3174 return 0; 3175 } 3176 if (m_error_flag) return -1; 3177 int bytes_read = cast(int)(fread(pBuf, 1, max_bytes_to_read, m_pFile)); 3178 if (bytes_read < max_bytes_to_read) { 3179 if (ferror(m_pFile)) { 3180 m_error_flag = true; 3181 return -1; 3182 } 3183 m_eof_flag = true; 3184 *pEOF_flag = true; 3185 } 3186 return bytes_read; 3187 }, 3188 width, height, actual_comps, req_comps); 3189 } 3190 3191 3192 // ////////////////////////////////////////////////////////////////////////// // 3193 /// decompress JPEG image from memory buffer. 3194 /// you can specify required color components in `req_comps` (3 for RGB or 4 for RGBA), or leave it as is to use image value. 3195 public ubyte[] decompress_jpeg_image_from_memory(bool useMalloc=false) (const(void)[] buf, out int width, out int height, out int actual_comps, int req_comps=-1) { 3196 size_t bufpos; 3197 return decompress_jpeg_image_from_stream!useMalloc( 3198 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3199 import core.stdc.string : memcpy; 3200 if (bufpos >= buf.length) { 3201 *pEOF_flag = true; 3202 return 0; 3203 } 3204 if (buf.length-bufpos < max_bytes_to_read) max_bytes_to_read = cast(int)(buf.length-bufpos); 3205 memcpy(pBuf, (cast(const(ubyte)*)buf.ptr)+bufpos, max_bytes_to_read); 3206 bufpos += max_bytes_to_read; 3207 return max_bytes_to_read; 3208 }, 3209 width, height, actual_comps, req_comps); 3210 } 3211 3212 3213 // ////////////////////////////////////////////////////////////////////////// // 3214 // if we have access "iv.vfs", add some handy API 3215 static if (__traits(compiles, { import iv.vfs; })) enum JpegHasIVVFS = true; else enum JpegHasIVVFS = false; 3216 3217 static if (JpegHasIVVFS) { 3218 import iv.vfs; 3219 3220 // ////////////////////////////////////////////////////////////////////////// // 3221 /// decompress JPEG image from disk file. 3222 /// you can specify required color components in `req_comps` (3 for RGB or 4 for RGBA), or leave it as is to use image value. 3223 public ubyte[] decompress_jpeg_image_from_file(bool useMalloc=false) (VFile fl, out int width, out int height, out int actual_comps, int req_comps=-1) { 3224 return decompress_jpeg_image_from_stream!useMalloc( 3225 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3226 if (!fl.isOpen) return -1; 3227 if (fl.eof) { 3228 *pEOF_flag = true; 3229 return 0; 3230 } 3231 auto rd = fl.rawRead(pBuf[0..max_bytes_to_read]); 3232 if (fl.eof) *pEOF_flag = true; 3233 return cast(int)rd.length; 3234 }, 3235 width, height, actual_comps, req_comps); 3236 } 3237 // vfs API 3238 } 3239 3240 3241 // ////////////////////////////////////////////////////////////////////////// // 3242 // if we have access "arsd.color", add some handy API 3243 static if (__traits(compiles, { import arsd.color; })) enum JpegHasArsd = true; else enum JpegHasArsd = false; 3244 3245 static if (JpegHasArsd) { 3246 import arsd.color; 3247 3248 // ////////////////////////////////////////////////////////////////////////// // 3249 /// decompress JPEG image, what else? 3250 public MemoryImage readJpegFromStream (scope JpegStreamReadFunc rfn) { 3251 import core.stdc.string : memcpy; 3252 enum req_comps = 4; 3253 3254 if (rfn is null) return null; 3255 3256 auto decoder = jpeg_decoder(rfn); 3257 if (decoder.error_code != JPGD_SUCCESS) return null; 3258 version(jpegd_test) scope(exit) { import core.stdc.stdio : printf; printf("%u bytes read.\n", cast(uint)decoder.total_bytes_read); } 3259 3260 immutable int image_width = decoder.width; 3261 immutable int image_height = decoder.height; 3262 //width = image_width; 3263 //height = image_height; 3264 //actual_comps = decoder.num_components; 3265 3266 version(jpegd_test) {{ import core.stdc.stdio; stderr.fprintf("starting (%dx%d)...\n", image_width, image_height); }} 3267 3268 if (decoder.begin_decoding() != JPGD_SUCCESS || image_width < 1 || image_height < 1) return null; 3269 3270 immutable int dst_bpl = image_width*req_comps; 3271 auto img = new TrueColorImage(image_width, image_height); 3272 scope(failure) { img.clearInternal(); img = null; } 3273 ubyte* pImage_data = img.imageData.bytes.ptr; 3274 3275 for (int y = 0; y < image_height; ++y) { 3276 //version(jpegd_test) {{ import core.stdc.stdio; stderr.fprintf("loading line %d...\n", y); }} 3277 3278 const(ubyte)* pScan_line; 3279 uint scan_line_len; 3280 if (decoder.decode(/*(const void**)*/cast(void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS) { 3281 img.clearInternal(); 3282 img = null; 3283 //jpgd_free(pImage_data); 3284 return null; 3285 } 3286 3287 ubyte* pDst = pImage_data+y*dst_bpl; 3288 3289 if ((req_comps == 1 && decoder.num_components == 1) || (req_comps == 4 && decoder.num_components == 3)) { 3290 memcpy(pDst, pScan_line, dst_bpl); 3291 } else if (decoder.num_components == 1) { 3292 if (req_comps == 3) { 3293 for (int x = 0; x < image_width; ++x) { 3294 ubyte luma = pScan_line[x]; 3295 pDst[0] = luma; 3296 pDst[1] = luma; 3297 pDst[2] = luma; 3298 pDst += 3; 3299 } 3300 } else { 3301 for (int x = 0; x < image_width; ++x) { 3302 ubyte luma = pScan_line[x]; 3303 pDst[0] = luma; 3304 pDst[1] = luma; 3305 pDst[2] = luma; 3306 pDst[3] = 255; 3307 pDst += 4; 3308 } 3309 } 3310 } else if (decoder.num_components == 3) { 3311 if (req_comps == 1) { 3312 immutable int YR = 19595, YG = 38470, YB = 7471; 3313 for (int x = 0; x < image_width; ++x) { 3314 int r = pScan_line[x*4+0]; 3315 int g = pScan_line[x*4+1]; 3316 int b = pScan_line[x*4+2]; 3317 *pDst++ = cast(ubyte)((r * YR + g * YG + b * YB + 32768) >> 16); 3318 } 3319 } else { 3320 for (int x = 0; x < image_width; ++x) { 3321 pDst[0] = pScan_line[x*4+0]; 3322 pDst[1] = pScan_line[x*4+1]; 3323 pDst[2] = pScan_line[x*4+2]; 3324 pDst += 3; 3325 } 3326 } 3327 } 3328 } 3329 3330 return img; 3331 } 3332 3333 3334 // ////////////////////////////////////////////////////////////////////////// // 3335 /// decompress JPEG image from disk file. 3336 public MemoryImage readJpeg (const(char)[] filename) { 3337 import core.stdc.stdio; 3338 3339 FILE* m_pFile; 3340 bool m_eof_flag, m_error_flag; 3341 3342 if (filename.length == 0) throw new Exception("cannot open unnamed file"); 3343 if (filename.length < 512) { 3344 char[513] buffer; 3345 //import core.stdc.stdlib : alloca; 3346 auto tfn = buffer[0 .. filename.length + 1]; // (cast(char*)alloca(filename.length+1))[0..filename.length+1]; 3347 tfn[0..filename.length] = filename[]; 3348 tfn[filename.length] = 0; 3349 m_pFile = fopen(tfn.ptr, "rb"); 3350 } else { 3351 import core.stdc.stdlib : malloc, free; 3352 auto tfn = (cast(char*)malloc(filename.length+1))[0..filename.length+1]; 3353 if (tfn !is null) { 3354 scope(exit) free(tfn.ptr); 3355 m_pFile = fopen(tfn.ptr, "rb"); 3356 } 3357 } 3358 if (m_pFile is null) throw new Exception("cannot open file '"~filename.idup~"'"); 3359 scope(exit) if (m_pFile) fclose(m_pFile); 3360 3361 return readJpegFromStream( 3362 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3363 if (m_pFile is null) return -1; 3364 if (m_eof_flag) { 3365 *pEOF_flag = true; 3366 return 0; 3367 } 3368 if (m_error_flag) return -1; 3369 int bytes_read = cast(int)(fread(pBuf, 1, max_bytes_to_read, m_pFile)); 3370 if (bytes_read < max_bytes_to_read) { 3371 if (ferror(m_pFile)) { 3372 m_error_flag = true; 3373 return -1; 3374 } 3375 m_eof_flag = true; 3376 *pEOF_flag = true; 3377 } 3378 return bytes_read; 3379 } 3380 ); 3381 } 3382 3383 3384 // ////////////////////////////////////////////////////////////////////////// // 3385 /// decompress JPEG image from memory buffer. 3386 public MemoryImage readJpegFromMemory (const(void)[] buf) { 3387 size_t bufpos; 3388 return readJpegFromStream( 3389 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3390 import core.stdc.string : memcpy; 3391 if (bufpos >= buf.length) { 3392 *pEOF_flag = true; 3393 return 0; 3394 } 3395 if (buf.length-bufpos < max_bytes_to_read) max_bytes_to_read = cast(int)(buf.length-bufpos); 3396 memcpy(pBuf, (cast(const(ubyte)*)buf.ptr)+bufpos, max_bytes_to_read); 3397 bufpos += max_bytes_to_read; 3398 return max_bytes_to_read; 3399 } 3400 ); 3401 } 3402 // done with arsd API 3403 } 3404 3405 3406 static if (JpegHasIVVFS) { 3407 public MemoryImage readJpeg (VFile fl) { 3408 return readJpegFromStream( 3409 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3410 if (!fl.isOpen) return -1; 3411 if (fl.eof) { 3412 *pEOF_flag = true; 3413 return 0; 3414 } 3415 auto rd = fl.rawRead(pBuf[0..max_bytes_to_read]); 3416 if (fl.eof) *pEOF_flag = true; 3417 return cast(int)rd.length; 3418 } 3419 ); 3420 } 3421 3422 public bool detectJpeg (VFile fl, out int width, out int height, out int actual_comps) { 3423 return detect_jpeg_image_from_stream( 3424 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3425 if (!fl.isOpen) return -1; 3426 if (fl.eof) { 3427 *pEOF_flag = true; 3428 return 0; 3429 } 3430 auto rd = fl.rawRead(pBuf[0..max_bytes_to_read]); 3431 if (fl.eof) *pEOF_flag = true; 3432 return cast(int)rd.length; 3433 }, 3434 width, height, actual_comps); 3435 } 3436 // vfs API 3437 } 3438 3439 3440 // ////////////////////////////////////////////////////////////////////////// // 3441 version(jpegd_test) { 3442 import arsd.color; 3443 import arsd.png; 3444 3445 void main (string[] args) { 3446 import std.stdio; 3447 int width, height, comps; 3448 { 3449 assert(detect_jpeg_image_from_file((args.length > 1 ? args[1] : "image.jpg"), width, height, comps)); 3450 writeln(width, "x", height, "x", comps); 3451 auto img = readJpeg((args.length > 1 ? args[1] : "image.jpg")); 3452 writeln(img.width, "x", img.height); 3453 writePng("z00.png", img); 3454 } 3455 { 3456 ubyte[] file; 3457 { 3458 auto fl = File(args.length > 1 ? args[1] : "image.jpg"); 3459 file.length = cast(int)fl.size; 3460 fl.rawRead(file[]); 3461 } 3462 assert(detect_jpeg_image_from_memory(file[], width, height, comps)); 3463 writeln(width, "x", height, "x", comps); 3464 auto img = readJpegFromMemory(file[]); 3465 writeln(img.width, "x", img.height); 3466 writePng("z01.png", img); 3467 } 3468 } 3469 }