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 * 40 * req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA). 41 * 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). 42 * 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. 43 */ 44 module arsd.jpeg; 45 46 // Set to 1 to enable freq. domain chroma upsampling on images using H2V2 subsampling (0=faster nearest neighbor sampling). 47 // This is slower, but results in higher quality on images with highly saturated colors. 48 version = JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING; 49 50 /// Input stream interface. 51 /// This delegate is called when the internal input buffer is empty. 52 /// Parameters: 53 /// pBuf - input buffer 54 /// max_bytes_to_read - maximum bytes that can be written to pBuf 55 /// pEOF_flag - set this to true if at end of stream (no more bytes remaining) 56 /// Returns -1 on error, otherwise return the number of bytes actually written to the buffer (which may be 0). 57 /// Notes: This delegate will be called in a loop until you set *pEOF_flag to true or the internal buffer is full. 58 alias JpegStreamReadFunc = int delegate (void* pBuf, int max_bytes_to_read, bool* pEOF_flag); 59 60 61 // ////////////////////////////////////////////////////////////////////////// // 62 private: 63 void *jpgd_malloc (size_t nSize) { import core.stdc.stdlib : malloc; return malloc(nSize); } 64 void jpgd_free (void *p) { import core.stdc.stdlib : free; if (p !is null) free(p); } 65 66 // Success/failure error codes. 67 alias jpgd_status = int; 68 enum /*jpgd_status*/ { 69 JPGD_SUCCESS = 0, JPGD_FAILED = -1, JPGD_DONE = 1, 70 JPGD_BAD_DHT_COUNTS = -256, JPGD_BAD_DHT_INDEX, JPGD_BAD_DHT_MARKER, JPGD_BAD_DQT_MARKER, JPGD_BAD_DQT_TABLE, 71 JPGD_BAD_PRECISION, JPGD_BAD_HEIGHT, JPGD_BAD_WIDTH, JPGD_TOO_MANY_COMPONENTS, 72 JPGD_BAD_SOF_LENGTH, JPGD_BAD_VARIABLE_MARKER, JPGD_BAD_DRI_LENGTH, JPGD_BAD_SOS_LENGTH, 73 JPGD_BAD_SOS_COMP_ID, JPGD_W_EXTRA_BYTES_BEFORE_MARKER, JPGD_NO_ARITHMITIC_SUPPORT, JPGD_UNEXPECTED_MARKER, 74 JPGD_NOT_JPEG, JPGD_UNSUPPORTED_MARKER, JPGD_BAD_DQT_LENGTH, JPGD_TOO_MANY_BLOCKS, 75 JPGD_UNDEFINED_QUANT_TABLE, JPGD_UNDEFINED_HUFF_TABLE, JPGD_NOT_SINGLE_SCAN, JPGD_UNSUPPORTED_COLORSPACE, 76 JPGD_UNSUPPORTED_SAMP_FACTORS, JPGD_DECODE_ERROR, JPGD_BAD_RESTART_MARKER, JPGD_ASSERTION_ERROR, 77 JPGD_BAD_SOS_SPECTRAL, JPGD_BAD_SOS_SUCCESSIVE, JPGD_STREAM_READ, JPGD_NOTENOUGHMEM, 78 } 79 80 enum { 81 JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4, 82 JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384, 83 } 84 85 // DCT coefficients are stored in this sequence. 86 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 ]; 87 88 alias JPEG_MARKER = int; 89 enum /*JPEG_MARKER*/ { 90 M_SOF0 = 0xC0, M_SOF1 = 0xC1, M_SOF2 = 0xC2, M_SOF3 = 0xC3, M_SOF5 = 0xC5, M_SOF6 = 0xC6, M_SOF7 = 0xC7, M_JPG = 0xC8, 91 M_SOF9 = 0xC9, M_SOF10 = 0xCA, M_SOF11 = 0xCB, M_SOF13 = 0xCD, M_SOF14 = 0xCE, M_SOF15 = 0xCF, M_DHT = 0xC4, M_DAC = 0xCC, 92 M_RST0 = 0xD0, M_RST1 = 0xD1, M_RST2 = 0xD2, M_RST3 = 0xD3, M_RST4 = 0xD4, M_RST5 = 0xD5, M_RST6 = 0xD6, M_RST7 = 0xD7, 93 M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_DNL = 0xDC, M_DRI = 0xDD, M_DHP = 0xDE, M_EXP = 0xDF, 94 M_APP0 = 0xE0, M_APP15 = 0xEF, M_JPG0 = 0xF0, M_JPG13 = 0xFD, M_COM = 0xFE, M_TEM = 0x01, M_ERROR = 0x100, RST0 = 0xD0, 95 } 96 97 alias JPEG_SUBSAMPLING = int; 98 enum /*JPEG_SUBSAMPLING*/ { JPGD_GRAYSCALE = 0, JPGD_YH1V1, JPGD_YH2V1, JPGD_YH1V2, JPGD_YH2V2 }; 99 100 enum CONST_BITS = 13; 101 enum PASS1_BITS = 2; 102 enum SCALEDONE = cast(int)1; 103 104 enum FIX_0_298631336 = cast(int)2446; /* FIX(0.298631336) */ 105 enum FIX_0_390180644 = cast(int)3196; /* FIX(0.390180644) */ 106 enum FIX_0_541196100 = cast(int)4433; /* FIX(0.541196100) */ 107 enum FIX_0_765366865 = cast(int)6270; /* FIX(0.765366865) */ 108 enum FIX_0_899976223 = cast(int)7373; /* FIX(0.899976223) */ 109 enum FIX_1_175875602 = cast(int)9633; /* FIX(1.175875602) */ 110 enum FIX_1_501321110 = cast(int)12299; /* FIX(1.501321110) */ 111 enum FIX_1_847759065 = cast(int)15137; /* FIX(1.847759065) */ 112 enum FIX_1_961570560 = cast(int)16069; /* FIX(1.961570560) */ 113 enum FIX_2_053119869 = cast(int)16819; /* FIX(2.053119869) */ 114 enum FIX_2_562915447 = cast(int)20995; /* FIX(2.562915447) */ 115 enum FIX_3_072711026 = cast(int)25172; /* FIX(3.072711026) */ 116 117 int DESCALE() (int x, int n) { pragma(inline, true); return (((x) + (SCALEDONE << ((n)-1))) >> (n)); } 118 int DESCALE_ZEROSHIFT() (int x, int n) { pragma(inline, true); return (((x) + (128 << (n)) + (SCALEDONE << ((n)-1))) >> (n)); } 119 ubyte CLAMP() (int i) { pragma(inline, true); return cast(ubyte)(cast(uint)i > 255 ? (((~i) >> 31) & 0xFF) : i); } 120 121 122 // Compiler creates a fast path 1D IDCT for X non-zero columns 123 struct Row(int NONZERO_COLS) { 124 pure nothrow @trusted @nogc: 125 static void idct(int* pTemp, const(jpeg_decoder.jpgd_block_t)* pSrc) { 126 static if (NONZERO_COLS == 0) { 127 // nothing 128 } else static if (NONZERO_COLS == 1) { 129 immutable int dcval = (pSrc[0] << PASS1_BITS); 130 pTemp[0] = dcval; 131 pTemp[1] = dcval; 132 pTemp[2] = dcval; 133 pTemp[3] = dcval; 134 pTemp[4] = dcval; 135 pTemp[5] = dcval; 136 pTemp[6] = dcval; 137 pTemp[7] = dcval; 138 } else { 139 // ACCESS_COL() will be optimized at compile time to either an array access, or 0. 140 //#define ACCESS_COL(x) (((x) < NONZERO_COLS) ? (int)pSrc[x] : 0) 141 template ACCESS_COL(int x) { 142 static if (x < NONZERO_COLS) enum ACCESS_COL = "cast(int)pSrc["~x.stringof~"]"; else enum ACCESS_COL = "0"; 143 } 144 145 immutable int z2 = mixin(ACCESS_COL!2), z3 = mixin(ACCESS_COL!6); 146 147 immutable int z1 = (z2 + z3)*FIX_0_541196100; 148 immutable int tmp2 = z1 + z3*(-FIX_1_847759065); 149 immutable int tmp3 = z1 + z2*FIX_0_765366865; 150 151 immutable int tmp0 = (mixin(ACCESS_COL!0) + mixin(ACCESS_COL!4)) << CONST_BITS; 152 immutable int tmp1 = (mixin(ACCESS_COL!0) - mixin(ACCESS_COL!4)) << CONST_BITS; 153 154 immutable int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2; 155 156 immutable int atmp0 = mixin(ACCESS_COL!7), atmp1 = mixin(ACCESS_COL!5), atmp2 = mixin(ACCESS_COL!3), atmp3 = mixin(ACCESS_COL!1); 157 158 immutable int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3; 159 immutable int bz5 = (bz3 + bz4)*FIX_1_175875602; 160 161 immutable int az1 = bz1*(-FIX_0_899976223); 162 immutable int az2 = bz2*(-FIX_2_562915447); 163 immutable int az3 = bz3*(-FIX_1_961570560) + bz5; 164 immutable int az4 = bz4*(-FIX_0_390180644) + bz5; 165 166 immutable int btmp0 = atmp0*FIX_0_298631336 + az1 + az3; 167 immutable int btmp1 = atmp1*FIX_2_053119869 + az2 + az4; 168 immutable int btmp2 = atmp2*FIX_3_072711026 + az2 + az3; 169 immutable int btmp3 = atmp3*FIX_1_501321110 + az1 + az4; 170 171 pTemp[0] = DESCALE(tmp10 + btmp3, CONST_BITS-PASS1_BITS); 172 pTemp[7] = DESCALE(tmp10 - btmp3, CONST_BITS-PASS1_BITS); 173 pTemp[1] = DESCALE(tmp11 + btmp2, CONST_BITS-PASS1_BITS); 174 pTemp[6] = DESCALE(tmp11 - btmp2, CONST_BITS-PASS1_BITS); 175 pTemp[2] = DESCALE(tmp12 + btmp1, CONST_BITS-PASS1_BITS); 176 pTemp[5] = DESCALE(tmp12 - btmp1, CONST_BITS-PASS1_BITS); 177 pTemp[3] = DESCALE(tmp13 + btmp0, CONST_BITS-PASS1_BITS); 178 pTemp[4] = DESCALE(tmp13 - btmp0, CONST_BITS-PASS1_BITS); 179 } 180 } 181 } 182 183 184 // Compiler creates a fast path 1D IDCT for X non-zero rows 185 struct Col (int NONZERO_ROWS) { 186 pure nothrow @trusted @nogc: 187 static void idct(ubyte* pDst_ptr, const(int)* pTemp) { 188 static assert(NONZERO_ROWS > 0); 189 static if (NONZERO_ROWS == 1) { 190 int dcval = DESCALE_ZEROSHIFT(pTemp[0], PASS1_BITS+3); 191 immutable ubyte dcval_clamped = cast(ubyte)CLAMP(dcval); 192 pDst_ptr[0*8] = dcval_clamped; 193 pDst_ptr[1*8] = dcval_clamped; 194 pDst_ptr[2*8] = dcval_clamped; 195 pDst_ptr[3*8] = dcval_clamped; 196 pDst_ptr[4*8] = dcval_clamped; 197 pDst_ptr[5*8] = dcval_clamped; 198 pDst_ptr[6*8] = dcval_clamped; 199 pDst_ptr[7*8] = dcval_clamped; 200 } else { 201 // ACCESS_ROW() will be optimized at compile time to either an array access, or 0. 202 //#define ACCESS_ROW(x) (((x) < NONZERO_ROWS) ? pTemp[x * 8] : 0) 203 template ACCESS_ROW(int x) { 204 static if (x < NONZERO_ROWS) enum ACCESS_ROW = "pTemp["~(x*8).stringof~"]"; else enum ACCESS_ROW = "0"; 205 } 206 207 immutable int z2 = mixin(ACCESS_ROW!2); 208 immutable int z3 = mixin(ACCESS_ROW!6); 209 210 immutable int z1 = (z2 + z3)*FIX_0_541196100; 211 immutable int tmp2 = z1 + z3*(-FIX_1_847759065); 212 immutable int tmp3 = z1 + z2*FIX_0_765366865; 213 214 immutable int tmp0 = (mixin(ACCESS_ROW!0) + mixin(ACCESS_ROW!4)) << CONST_BITS; 215 immutable int tmp1 = (mixin(ACCESS_ROW!0) - mixin(ACCESS_ROW!4)) << CONST_BITS; 216 217 immutable int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2; 218 219 immutable int atmp0 = mixin(ACCESS_ROW!7), atmp1 = mixin(ACCESS_ROW!5), atmp2 = mixin(ACCESS_ROW!3), atmp3 = mixin(ACCESS_ROW!1); 220 221 immutable int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3; 222 immutable int bz5 = (bz3 + bz4)*FIX_1_175875602; 223 224 immutable int az1 = bz1*(-FIX_0_899976223); 225 immutable int az2 = bz2*(-FIX_2_562915447); 226 immutable int az3 = bz3*(-FIX_1_961570560) + bz5; 227 immutable int az4 = bz4*(-FIX_0_390180644) + bz5; 228 229 immutable int btmp0 = atmp0*FIX_0_298631336 + az1 + az3; 230 immutable int btmp1 = atmp1*FIX_2_053119869 + az2 + az4; 231 immutable int btmp2 = atmp2*FIX_3_072711026 + az2 + az3; 232 immutable int btmp3 = atmp3*FIX_1_501321110 + az1 + az4; 233 234 int i = DESCALE_ZEROSHIFT(tmp10 + btmp3, CONST_BITS+PASS1_BITS+3); 235 pDst_ptr[8*0] = cast(ubyte)CLAMP(i); 236 237 i = DESCALE_ZEROSHIFT(tmp10 - btmp3, CONST_BITS+PASS1_BITS+3); 238 pDst_ptr[8*7] = cast(ubyte)CLAMP(i); 239 240 i = DESCALE_ZEROSHIFT(tmp11 + btmp2, CONST_BITS+PASS1_BITS+3); 241 pDst_ptr[8*1] = cast(ubyte)CLAMP(i); 242 243 i = DESCALE_ZEROSHIFT(tmp11 - btmp2, CONST_BITS+PASS1_BITS+3); 244 pDst_ptr[8*6] = cast(ubyte)CLAMP(i); 245 246 i = DESCALE_ZEROSHIFT(tmp12 + btmp1, CONST_BITS+PASS1_BITS+3); 247 pDst_ptr[8*2] = cast(ubyte)CLAMP(i); 248 249 i = DESCALE_ZEROSHIFT(tmp12 - btmp1, CONST_BITS+PASS1_BITS+3); 250 pDst_ptr[8*5] = cast(ubyte)CLAMP(i); 251 252 i = DESCALE_ZEROSHIFT(tmp13 + btmp0, CONST_BITS+PASS1_BITS+3); 253 pDst_ptr[8*3] = cast(ubyte)CLAMP(i); 254 255 i = DESCALE_ZEROSHIFT(tmp13 - btmp0, CONST_BITS+PASS1_BITS+3); 256 pDst_ptr[8*4] = cast(ubyte)CLAMP(i); 257 } 258 } 259 } 260 261 262 static immutable ubyte[512] s_idct_row_table = [ 263 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, 264 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, 265 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, 266 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, 267 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, 268 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, 269 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, 270 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, 271 ]; 272 273 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 ]; 274 275 void idct() (const(jpeg_decoder.jpgd_block_t)* pSrc_ptr, ubyte* pDst_ptr, int block_max_zag) { 276 assert(block_max_zag >= 1); 277 assert(block_max_zag <= 64); 278 279 if (block_max_zag <= 1) 280 { 281 int k = ((pSrc_ptr[0] + 4) >> 3) + 128; 282 k = CLAMP(k); 283 k = k | (k<<8); 284 k = k | (k<<16); 285 286 for (int i = 8; i > 0; i--) 287 { 288 *cast(int*)&pDst_ptr[0] = k; 289 *cast(int*)&pDst_ptr[4] = k; 290 pDst_ptr += 8; 291 } 292 return; 293 } 294 295 int[64] temp; 296 297 const(jpeg_decoder.jpgd_block_t)* pSrc = pSrc_ptr; 298 int* pTemp = temp.ptr; 299 300 const(ubyte)* pRow_tab = &s_idct_row_table.ptr[(block_max_zag - 1) * 8]; 301 int i; 302 for (i = 8; i > 0; i--, pRow_tab++) 303 { 304 switch (*pRow_tab) 305 { 306 case 0: Row!(0).idct(pTemp, pSrc); break; 307 case 1: Row!(1).idct(pTemp, pSrc); break; 308 case 2: Row!(2).idct(pTemp, pSrc); break; 309 case 3: Row!(3).idct(pTemp, pSrc); break; 310 case 4: Row!(4).idct(pTemp, pSrc); break; 311 case 5: Row!(5).idct(pTemp, pSrc); break; 312 case 6: Row!(6).idct(pTemp, pSrc); break; 313 case 7: Row!(7).idct(pTemp, pSrc); break; 314 case 8: Row!(8).idct(pTemp, pSrc); break; 315 default: assert(0); 316 } 317 318 pSrc += 8; 319 pTemp += 8; 320 } 321 322 pTemp = temp.ptr; 323 324 immutable int nonzero_rows = s_idct_col_table.ptr[block_max_zag - 1]; 325 for (i = 8; i > 0; i--) 326 { 327 switch (nonzero_rows) 328 { 329 case 1: Col!(1).idct(pDst_ptr, pTemp); break; 330 case 2: Col!(2).idct(pDst_ptr, pTemp); break; 331 case 3: Col!(3).idct(pDst_ptr, pTemp); break; 332 case 4: Col!(4).idct(pDst_ptr, pTemp); break; 333 case 5: Col!(5).idct(pDst_ptr, pTemp); break; 334 case 6: Col!(6).idct(pDst_ptr, pTemp); break; 335 case 7: Col!(7).idct(pDst_ptr, pTemp); break; 336 case 8: Col!(8).idct(pDst_ptr, pTemp); break; 337 default: assert(0); 338 } 339 340 pTemp++; 341 pDst_ptr++; 342 } 343 } 344 345 void idct_4x4() (const(jpeg_decoder.jpgd_block_t)* pSrc_ptr, ubyte* pDst_ptr) { 346 int[64] temp; 347 int* pTemp = temp.ptr; 348 const(jpeg_decoder.jpgd_block_t)* pSrc = pSrc_ptr; 349 350 for (int i = 4; i > 0; i--) 351 { 352 Row!(4).idct(pTemp, pSrc); 353 pSrc += 8; 354 pTemp += 8; 355 } 356 357 pTemp = temp.ptr; 358 for (int i = 8; i > 0; i--) 359 { 360 Col!(4).idct(pDst_ptr, pTemp); 361 pTemp++; 362 pDst_ptr++; 363 } 364 } 365 366 367 // ////////////////////////////////////////////////////////////////////////// // 368 struct jpeg_decoder { 369 private import core.stdc.string : memcpy, memset; 370 private: 371 static auto JPGD_MIN(T) (T a, T b) pure nothrow @safe @nogc { pragma(inline, true); return (a < b ? a : b); } 372 static auto JPGD_MAX(T) (T a, T b) pure nothrow @safe @nogc { pragma(inline, true); return (a > b ? a : b); } 373 374 alias jpgd_quant_t = short; 375 alias jpgd_block_t = short; 376 alias pDecode_block_func = void function (ref jpeg_decoder, int, int, int); 377 378 static struct huff_tables { 379 bool ac_table; 380 uint[256] look_up; 381 uint[256] look_up2; 382 ubyte[256] code_size; 383 uint[512] tree; 384 } 385 386 static struct coeff_buf { 387 ubyte* pData; 388 int block_num_x, block_num_y; 389 int block_len_x, block_len_y; 390 int block_size; 391 } 392 393 static struct mem_block { 394 mem_block* m_pNext; 395 size_t m_used_count; 396 size_t m_size; 397 char[1] m_data; 398 } 399 400 mem_block* m_pMem_blocks; 401 int m_image_x_size; 402 int m_image_y_size; 403 JpegStreamReadFunc readfn; 404 int m_progressive_flag; 405 ubyte[JPGD_MAX_HUFF_TABLES] m_huff_ac; 406 ubyte*[JPGD_MAX_HUFF_TABLES] m_huff_num; // pointer to number of Huffman codes per bit size 407 ubyte*[JPGD_MAX_HUFF_TABLES] m_huff_val; // pointer to Huffman codes per bit size 408 jpgd_quant_t*[JPGD_MAX_QUANT_TABLES] m_quant; // pointer to quantization tables 409 int m_scan_type; // Gray, Yh1v1, Yh1v2, Yh2v1, Yh2v2 (CMYK111, CMYK4114 no longer supported) 410 int m_comps_in_frame; // # of components in frame 411 int[JPGD_MAX_COMPONENTS] m_comp_h_samp; // component's horizontal sampling factor 412 int[JPGD_MAX_COMPONENTS] m_comp_v_samp; // component's vertical sampling factor 413 int[JPGD_MAX_COMPONENTS] m_comp_quant; // component's quantization table selector 414 int[JPGD_MAX_COMPONENTS] m_comp_ident; // component's ID 415 int[JPGD_MAX_COMPONENTS] m_comp_h_blocks; 416 int[JPGD_MAX_COMPONENTS] m_comp_v_blocks; 417 int m_comps_in_scan; // # of components in scan 418 int[JPGD_MAX_COMPS_IN_SCAN] m_comp_list; // components in this scan 419 int[JPGD_MAX_COMPONENTS] m_comp_dc_tab; // component's DC Huffman coding table selector 420 int[JPGD_MAX_COMPONENTS] m_comp_ac_tab; // component's AC Huffman coding table selector 421 int m_spectral_start; // spectral selection start 422 int m_spectral_end; // spectral selection end 423 int m_successive_low; // successive approximation low 424 int m_successive_high; // successive approximation high 425 int m_max_mcu_x_size; // MCU's max. X size in pixels 426 int m_max_mcu_y_size; // MCU's max. Y size in pixels 427 int m_blocks_per_mcu; 428 int m_max_blocks_per_row; 429 int m_mcus_per_row, m_mcus_per_col; 430 int[JPGD_MAX_BLOCKS_PER_MCU] m_mcu_org; 431 int m_total_lines_left; // total # lines left in image 432 int m_mcu_lines_left; // total # lines left in this MCU 433 int m_real_dest_bytes_per_scan_line; 434 int m_dest_bytes_per_scan_line; // rounded up 435 int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y) 436 huff_tables*[JPGD_MAX_HUFF_TABLES] m_pHuff_tabs; 437 coeff_buf*[JPGD_MAX_COMPONENTS] m_dc_coeffs; 438 coeff_buf*[JPGD_MAX_COMPONENTS] m_ac_coeffs; 439 int m_eob_run; 440 int[JPGD_MAX_COMPONENTS] m_block_y_mcu; 441 ubyte* m_pIn_buf_ofs; 442 int m_in_buf_left; 443 int m_tem_flag; 444 bool m_eof_flag; 445 ubyte[128] m_in_buf_pad_start; 446 ubyte[JPGD_IN_BUF_SIZE+128] m_in_buf; 447 ubyte[128] m_in_buf_pad_end; 448 int m_bits_left; 449 uint m_bit_buf; 450 int m_restart_interval; 451 int m_restarts_left; 452 int m_next_restart_num; 453 int m_max_mcus_per_row; 454 int m_max_blocks_per_mcu; 455 int m_expanded_blocks_per_mcu; 456 int m_expanded_blocks_per_row; 457 int m_expanded_blocks_per_component; 458 bool m_freq_domain_chroma_upsample; 459 int m_max_mcus_per_col; 460 uint[JPGD_MAX_COMPONENTS] m_last_dc_val; 461 jpgd_block_t* m_pMCU_coefficients; 462 int[JPGD_MAX_BLOCKS_PER_MCU] m_mcu_block_max_zag; 463 ubyte* m_pSample_buf; 464 int[256] m_crr; 465 int[256] m_cbb; 466 int[256] m_crg; 467 int[256] m_cbg; 468 ubyte* m_pScan_line_0; 469 ubyte* m_pScan_line_1; 470 jpgd_status m_error_code; 471 bool m_ready_flag; 472 int m_total_bytes_read; 473 474 public: 475 // Inspect `error_code` after constructing to determine if the stream is valid or not. You may look at the `width`, `height`, etc. 476 // 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. 477 this (JpegStreamReadFunc rfn) { decode_init(rfn); } 478 479 ~this () { free_all_blocks(); } 480 481 @disable this (this); // no copies 482 483 // Call this method after constructing the object to begin decompression. 484 // If JPGD_SUCCESS is returned you may then call decode() on each scanline. 485 int begin_decoding () { 486 if (m_ready_flag) return JPGD_SUCCESS; 487 if (m_error_code) return JPGD_FAILED; 488 try { 489 decode_start(); 490 m_ready_flag = true; 491 return JPGD_SUCCESS; 492 } catch (Exception e) { 493 //version(jpegd_test) {{ import core.stdc.stdio; stderr.fprintf("ERROR: %.*s...\n", cast(int)e.msg.length, e.msg.ptr); }} 494 version(jpegd_test) {{ import std.stdio; stderr.writeln(e.toString); }} 495 } 496 return JPGD_FAILED; 497 } 498 499 // Returns the next scan line. 500 // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (`bytes_per_pixel` will return 1). 501 // 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). 502 // Returns JPGD_SUCCESS if a scan line has been returned. 503 // Returns JPGD_DONE if all scan lines have been returned. 504 // Returns JPGD_FAILED if an error occurred. Inspect `error_code` for a more info. 505 int decode (/*const void** */void** pScan_line, uint* pScan_line_len) { 506 if (m_error_code || !m_ready_flag) return JPGD_FAILED; 507 if (m_total_lines_left == 0) return JPGD_DONE; 508 try { 509 if (m_mcu_lines_left == 0) { 510 if (m_progressive_flag) load_next_row(); else decode_next_row(); 511 // Find the EOI marker if that was the last row. 512 if (m_total_lines_left <= m_max_mcu_y_size) find_eoi(); 513 m_mcu_lines_left = m_max_mcu_y_size; 514 } 515 if (m_freq_domain_chroma_upsample) { 516 expanded_convert(); 517 *pScan_line = m_pScan_line_0; 518 } else { 519 switch (m_scan_type) { 520 case JPGD_YH2V2: 521 if ((m_mcu_lines_left & 1) == 0) { 522 H2V2Convert(); 523 *pScan_line = m_pScan_line_0; 524 } else { 525 *pScan_line = m_pScan_line_1; 526 } 527 break; 528 case JPGD_YH2V1: 529 H2V1Convert(); 530 *pScan_line = m_pScan_line_0; 531 break; 532 case JPGD_YH1V2: 533 if ((m_mcu_lines_left & 1) == 0) { 534 H1V2Convert(); 535 *pScan_line = m_pScan_line_0; 536 } else { 537 *pScan_line = m_pScan_line_1; 538 } 539 break; 540 case JPGD_YH1V1: 541 H1V1Convert(); 542 *pScan_line = m_pScan_line_0; 543 break; 544 case JPGD_GRAYSCALE: 545 gray_convert(); 546 *pScan_line = m_pScan_line_0; 547 break; 548 default: 549 } 550 } 551 *pScan_line_len = m_real_dest_bytes_per_scan_line; 552 --m_mcu_lines_left; 553 --m_total_lines_left; 554 return JPGD_SUCCESS; 555 } catch (Exception) {} 556 return JPGD_FAILED; 557 } 558 559 @property const pure nothrow @safe @nogc { 560 jpgd_status error_code () { pragma(inline, true); return m_error_code; } 561 562 int width () { pragma(inline, true); return m_image_x_size; } 563 int height () { pragma(inline, true); return m_image_y_size; } 564 565 int num_components () { pragma(inline, true); return m_comps_in_frame; } 566 567 int bytes_per_pixel () { pragma(inline, true); return m_dest_bytes_per_pixel; } 568 int bytes_per_scan_line () { pragma(inline, true); return m_image_x_size * bytes_per_pixel(); } 569 570 // Returns the total number of bytes actually consumed by the decoder (which should equal the actual size of the JPEG file). 571 int total_bytes_read () { pragma(inline, true); return m_total_bytes_read; } 572 } 573 574 private: 575 // Retrieve one character from the input stream. 576 uint get_char () { 577 // Any bytes remaining in buffer? 578 if (!m_in_buf_left) { 579 // Try to get more bytes. 580 prep_in_buffer(); 581 // Still nothing to get? 582 if (!m_in_buf_left) { 583 // Pad the end of the stream with 0xFF 0xD9 (EOI marker) 584 int t = m_tem_flag; 585 m_tem_flag ^= 1; 586 return (t ? 0xD9 : 0xFF); 587 } 588 } 589 uint c = *m_pIn_buf_ofs++; 590 --m_in_buf_left; 591 return c; 592 } 593 594 // Same as previous method, except can indicate if the character is a pad character or not. 595 uint get_char (bool* pPadding_flag) { 596 if (!m_in_buf_left) { 597 prep_in_buffer(); 598 if (!m_in_buf_left) { 599 *pPadding_flag = true; 600 int t = m_tem_flag; 601 m_tem_flag ^= 1; 602 return (t ? 0xD9 : 0xFF); 603 } 604 } 605 *pPadding_flag = false; 606 uint c = *m_pIn_buf_ofs++; 607 --m_in_buf_left; 608 return c; 609 } 610 611 // Inserts a previously retrieved character back into the input buffer. 612 void stuff_char (ubyte q) { 613 *(--m_pIn_buf_ofs) = q; 614 m_in_buf_left++; 615 } 616 617 // Retrieves one character from the input stream, but does not read past markers. Will continue to return 0xFF when a marker is encountered. 618 ubyte get_octet () { 619 bool padding_flag; 620 int c = get_char(&padding_flag); 621 if (c == 0xFF) { 622 if (padding_flag) return 0xFF; 623 c = get_char(&padding_flag); 624 if (padding_flag) { stuff_char(0xFF); return 0xFF; } 625 if (c == 0x00) return 0xFF; 626 stuff_char(cast(ubyte)(c)); 627 stuff_char(0xFF); 628 return 0xFF; 629 } 630 return cast(ubyte)(c); 631 } 632 633 // Retrieves a variable number of bits from the input stream. Does not recognize markers. 634 uint get_bits (int num_bits) { 635 if (!num_bits) return 0; 636 uint i = m_bit_buf >> (32 - num_bits); 637 if ((m_bits_left -= num_bits) <= 0) { 638 m_bit_buf <<= (num_bits += m_bits_left); 639 uint c1 = get_char(); 640 uint c2 = get_char(); 641 m_bit_buf = (m_bit_buf & 0xFFFF0000) | (c1 << 8) | c2; 642 m_bit_buf <<= -m_bits_left; 643 m_bits_left += 16; 644 assert(m_bits_left >= 0); 645 } else { 646 m_bit_buf <<= num_bits; 647 } 648 return i; 649 } 650 651 // 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. 652 uint get_bits_no_markers (int num_bits) { 653 if (!num_bits) return 0; 654 uint i = m_bit_buf >> (32 - num_bits); 655 if ((m_bits_left -= num_bits) <= 0) { 656 m_bit_buf <<= (num_bits += m_bits_left); 657 if (m_in_buf_left < 2 || m_pIn_buf_ofs[0] == 0xFF || m_pIn_buf_ofs[1] == 0xFF) { 658 uint c1 = get_octet(); 659 uint c2 = get_octet(); 660 m_bit_buf |= (c1 << 8) | c2; 661 } else { 662 m_bit_buf |= (cast(uint)m_pIn_buf_ofs[0] << 8) | m_pIn_buf_ofs[1]; 663 m_in_buf_left -= 2; 664 m_pIn_buf_ofs += 2; 665 } 666 m_bit_buf <<= -m_bits_left; 667 m_bits_left += 16; 668 assert(m_bits_left >= 0); 669 } else { 670 m_bit_buf <<= num_bits; 671 } 672 return i; 673 } 674 675 // Decodes a Huffman encoded symbol. 676 int huff_decode (huff_tables *pH) { 677 int symbol; 678 // Check first 8-bits: do we have a complete symbol? 679 if ((symbol = pH.look_up.ptr[m_bit_buf >> 24]) < 0) { 680 // Decode more bits, use a tree traversal to find symbol. 681 int ofs = 23; 682 do { 683 symbol = pH.tree.ptr[-cast(int)(symbol + ((m_bit_buf >> ofs) & 1))]; 684 --ofs; 685 } while (symbol < 0); 686 get_bits_no_markers(8 + (23 - ofs)); 687 } else { 688 get_bits_no_markers(pH.code_size.ptr[symbol]); 689 } 690 return symbol; 691 } 692 693 // Decodes a Huffman encoded symbol. 694 int huff_decode (huff_tables *pH, ref int extra_bits) { 695 int symbol; 696 // Check first 8-bits: do we have a complete symbol? 697 if ((symbol = pH.look_up2.ptr[m_bit_buf >> 24]) < 0) { 698 // Use a tree traversal to find symbol. 699 int ofs = 23; 700 do { 701 symbol = pH.tree.ptr[-cast(int)(symbol + ((m_bit_buf >> ofs) & 1))]; 702 --ofs; 703 } while (symbol < 0); 704 get_bits_no_markers(8 + (23 - ofs)); 705 extra_bits = get_bits_no_markers(symbol & 0xF); 706 } else { 707 assert(((symbol >> 8) & 31) == pH.code_size.ptr[symbol & 255] + ((symbol & 0x8000) ? (symbol & 15) : 0)); 708 if (symbol & 0x8000) { 709 get_bits_no_markers((symbol >> 8) & 31); 710 extra_bits = symbol >> 16; 711 } else { 712 int code_size = (symbol >> 8) & 31; 713 int num_extra_bits = symbol & 0xF; 714 int bits = code_size + num_extra_bits; 715 if (bits <= (m_bits_left + 16)) { 716 extra_bits = get_bits_no_markers(bits) & ((1 << num_extra_bits) - 1); 717 } else { 718 get_bits_no_markers(code_size); 719 extra_bits = get_bits_no_markers(num_extra_bits); 720 } 721 } 722 symbol &= 0xFF; 723 } 724 return symbol; 725 } 726 727 // Tables and macro used to fully decode the DPCM differences. 728 static immutable int[16] s_extend_test = [ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 ]; 729 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 ]; 730 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) ]; 731 // 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) 732 //#define JPGD_HUFF_EXTEND(x, s) (((x) < s_extend_test[s & 15]) ? ((x) + s_extend_offset[s & 15]) : (x)) 733 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)); } 734 735 // Clamps a value between 0-255. 736 //static ubyte clamp (int i) { if (cast(uint)(i) > 255) i = (((~i) >> 31) & 0xFF); return cast(ubyte)(i); } 737 alias clamp = CLAMP; 738 739 static struct DCT_Upsample { 740 static: 741 static struct Matrix44 { 742 pure nothrow @trusted @nogc: 743 alias Element_Type = int; 744 enum { NUM_ROWS = 4, NUM_COLS = 4 } 745 746 Element_Type[NUM_COLS][NUM_ROWS] v; 747 748 this() (in auto ref Matrix44 m) { 749 foreach (immutable r; 0..NUM_ROWS) v[r][] = m.v[r][]; 750 } 751 752 //@property int rows () const { pragma(inline, true); return NUM_ROWS; } 753 //@property int cols () const { pragma(inline, true); return NUM_COLS; } 754 755 ref inout(Element_Type) at (int r, int c) inout { pragma(inline, true); return v.ptr[r].ptr[c]; } 756 757 ref Matrix44 opOpAssign(string op:"+") (in auto ref Matrix44 a) { 758 foreach (int r; 0..NUM_ROWS) { 759 at(r, 0) += a.at(r, 0); 760 at(r, 1) += a.at(r, 1); 761 at(r, 2) += a.at(r, 2); 762 at(r, 3) += a.at(r, 3); 763 } 764 return this; 765 } 766 767 ref Matrix44 opOpAssign(string op:"-") (in auto ref Matrix44 a) { 768 foreach (int r; 0..NUM_ROWS) { 769 at(r, 0) -= a.at(r, 0); 770 at(r, 1) -= a.at(r, 1); 771 at(r, 2) -= a.at(r, 2); 772 at(r, 3) -= a.at(r, 3); 773 } 774 return this; 775 } 776 777 Matrix44 opBinary(string op:"+") (in auto ref Matrix44 b) const { 778 alias a = this; 779 Matrix44 ret; 780 foreach (int r; 0..NUM_ROWS) { 781 ret.at(r, 0) = a.at(r, 0) + b.at(r, 0); 782 ret.at(r, 1) = a.at(r, 1) + b.at(r, 1); 783 ret.at(r, 2) = a.at(r, 2) + b.at(r, 2); 784 ret.at(r, 3) = a.at(r, 3) + b.at(r, 3); 785 } 786 return ret; 787 } 788 789 Matrix44 opBinary(string op:"-") (in auto ref Matrix44 b) const { 790 alias a = this; 791 Matrix44 ret; 792 foreach (int r; 0..NUM_ROWS) { 793 ret.at(r, 0) = a.at(r, 0) - b.at(r, 0); 794 ret.at(r, 1) = a.at(r, 1) - b.at(r, 1); 795 ret.at(r, 2) = a.at(r, 2) - b.at(r, 2); 796 ret.at(r, 3) = a.at(r, 3) - b.at(r, 3); 797 } 798 return ret; 799 } 800 801 static void add_and_store() (jpgd_block_t* pDst, in auto ref Matrix44 a, in auto ref Matrix44 b) { 802 foreach (int r; 0..4) { 803 pDst[0*8 + r] = cast(jpgd_block_t)(a.at(r, 0) + b.at(r, 0)); 804 pDst[1*8 + r] = cast(jpgd_block_t)(a.at(r, 1) + b.at(r, 1)); 805 pDst[2*8 + r] = cast(jpgd_block_t)(a.at(r, 2) + b.at(r, 2)); 806 pDst[3*8 + r] = cast(jpgd_block_t)(a.at(r, 3) + b.at(r, 3)); 807 } 808 } 809 810 static void sub_and_store() (jpgd_block_t* pDst, in auto ref Matrix44 a, in auto ref Matrix44 b) { 811 foreach (int r; 0..4) { 812 pDst[0*8 + r] = cast(jpgd_block_t)(a.at(r, 0) - b.at(r, 0)); 813 pDst[1*8 + r] = cast(jpgd_block_t)(a.at(r, 1) - b.at(r, 1)); 814 pDst[2*8 + r] = cast(jpgd_block_t)(a.at(r, 2) - b.at(r, 2)); 815 pDst[3*8 + r] = cast(jpgd_block_t)(a.at(r, 3) - b.at(r, 3)); 816 } 817 } 818 } 819 820 enum FRACT_BITS = 10; 821 enum SCALE = 1 << FRACT_BITS; 822 823 alias Temp_Type = int; 824 //TODO: convert defines to mixins 825 //#define D(i) (((i) + (SCALE >> 1)) >> FRACT_BITS) 826 //#define F(i) ((int)((i) * SCALE + .5f)) 827 // Any decent C++ compiler will optimize this at compile time to a 0, or an array access. 828 //#define AT(c, r) ((((c)>=NUM_COLS)||((r)>=NUM_ROWS)) ? 0 : pSrc[(c)+(r)*8]) 829 830 static int D(T) (T i) { pragma(inline, true); return (((i) + (SCALE >> 1)) >> FRACT_BITS); } 831 enum F(float i) = (cast(int)((i) * SCALE + 0.5f)); 832 833 // NUM_ROWS/NUM_COLS = # of non-zero rows/cols in input matrix 834 static struct P_Q(int NUM_ROWS, int NUM_COLS) { 835 static void calc (ref Matrix44 P, ref Matrix44 Q, const(jpgd_block_t)* pSrc) { 836 //auto AT (int c, int r) nothrow @trusted @nogc { return (c >= NUM_COLS || r >= NUM_ROWS ? 0 : pSrc[c+r*8]); } 837 template AT(int c, int r) { 838 static if (c >= NUM_COLS || r >= NUM_ROWS) enum AT = "0"; else enum AT = "pSrc["~c.stringof~"+"~r.stringof~"*8]"; 839 } 840 // 4x8 = 4x8 times 8x8, matrix 0 is constant 841 immutable Temp_Type X000 = mixin(AT!(0, 0)); 842 immutable Temp_Type X001 = mixin(AT!(0, 1)); 843 immutable Temp_Type X002 = mixin(AT!(0, 2)); 844 immutable Temp_Type X003 = mixin(AT!(0, 3)); 845 immutable Temp_Type X004 = mixin(AT!(0, 4)); 846 immutable Temp_Type X005 = mixin(AT!(0, 5)); 847 immutable Temp_Type X006 = mixin(AT!(0, 6)); 848 immutable Temp_Type X007 = mixin(AT!(0, 7)); 849 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))); 850 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))); 851 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))); 852 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))); 853 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))); 854 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))); 855 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))); 856 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))); 857 immutable Temp_Type X020 = mixin(AT!(4, 0)); 858 immutable Temp_Type X021 = mixin(AT!(4, 1)); 859 immutable Temp_Type X022 = mixin(AT!(4, 2)); 860 immutable Temp_Type X023 = mixin(AT!(4, 3)); 861 immutable Temp_Type X024 = mixin(AT!(4, 4)); 862 immutable Temp_Type X025 = mixin(AT!(4, 5)); 863 immutable Temp_Type X026 = mixin(AT!(4, 6)); 864 immutable Temp_Type X027 = mixin(AT!(4, 7)); 865 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))); 866 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))); 867 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))); 868 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))); 869 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))); 870 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))); 871 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))); 872 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))); 873 874 // 4x4 = 4x8 times 8x4, matrix 1 is constant 875 P.at(0, 0) = X000; 876 P.at(0, 1) = D(X001 * F!(0.415735f) + X003 * F!(0.791065f) + X005 * F!(-0.352443f) + X007 * F!(0.277785f)); 877 P.at(0, 2) = X004; 878 P.at(0, 3) = D(X001 * F!(0.022887f) + X003 * F!(-0.097545f) + X005 * F!(0.490393f) + X007 * F!(0.865723f)); 879 P.at(1, 0) = X010; 880 P.at(1, 1) = D(X011 * F!(0.415735f) + X013 * F!(0.791065f) + X015 * F!(-0.352443f) + X017 * F!(0.277785f)); 881 P.at(1, 2) = X014; 882 P.at(1, 3) = D(X011 * F!(0.022887f) + X013 * F!(-0.097545f) + X015 * F!(0.490393f) + X017 * F!(0.865723f)); 883 P.at(2, 0) = X020; 884 P.at(2, 1) = D(X021 * F!(0.415735f) + X023 * F!(0.791065f) + X025 * F!(-0.352443f) + X027 * F!(0.277785f)); 885 P.at(2, 2) = X024; 886 P.at(2, 3) = D(X021 * F!(0.022887f) + X023 * F!(-0.097545f) + X025 * F!(0.490393f) + X027 * F!(0.865723f)); 887 P.at(3, 0) = X030; 888 P.at(3, 1) = D(X031 * F!(0.415735f) + X033 * F!(0.791065f) + X035 * F!(-0.352443f) + X037 * F!(0.277785f)); 889 P.at(3, 2) = X034; 890 P.at(3, 3) = D(X031 * F!(0.022887f) + X033 * F!(-0.097545f) + X035 * F!(0.490393f) + X037 * F!(0.865723f)); 891 // 40 muls 24 adds 892 893 // 4x4 = 4x8 times 8x4, matrix 1 is constant 894 Q.at(0, 0) = D(X001 * F!(0.906127f) + X003 * F!(-0.318190f) + X005 * F!(0.212608f) + X007 * F!(-0.180240f)); 895 Q.at(0, 1) = X002; 896 Q.at(0, 2) = D(X001 * F!(-0.074658f) + X003 * F!(0.513280f) + X005 * F!(0.768178f) + X007 * F!(-0.375330f)); 897 Q.at(0, 3) = X006; 898 Q.at(1, 0) = D(X011 * F!(0.906127f) + X013 * F!(-0.318190f) + X015 * F!(0.212608f) + X017 * F!(-0.180240f)); 899 Q.at(1, 1) = X012; 900 Q.at(1, 2) = D(X011 * F!(-0.074658f) + X013 * F!(0.513280f) + X015 * F!(0.768178f) + X017 * F!(-0.375330f)); 901 Q.at(1, 3) = X016; 902 Q.at(2, 0) = D(X021 * F!(0.906127f) + X023 * F!(-0.318190f) + X025 * F!(0.212608f) + X027 * F!(-0.180240f)); 903 Q.at(2, 1) = X022; 904 Q.at(2, 2) = D(X021 * F!(-0.074658f) + X023 * F!(0.513280f) + X025 * F!(0.768178f) + X027 * F!(-0.375330f)); 905 Q.at(2, 3) = X026; 906 Q.at(3, 0) = D(X031 * F!(0.906127f) + X033 * F!(-0.318190f) + X035 * F!(0.212608f) + X037 * F!(-0.180240f)); 907 Q.at(3, 1) = X032; 908 Q.at(3, 2) = D(X031 * F!(-0.074658f) + X033 * F!(0.513280f) + X035 * F!(0.768178f) + X037 * F!(-0.375330f)); 909 Q.at(3, 3) = X036; 910 // 40 muls 24 adds 911 } 912 } 913 914 static struct R_S(int NUM_ROWS, int NUM_COLS) { 915 static void calc(ref Matrix44 R, ref Matrix44 S, const(jpgd_block_t)* pSrc) { 916 //auto AT (int c, int r) nothrow @trusted @nogc { return (c >= NUM_COLS || r >= NUM_ROWS ? 0 : pSrc[c+r*8]); } 917 template AT(int c, int r) { 918 static if (c >= NUM_COLS || r >= NUM_ROWS) enum AT = "0"; else enum AT = "pSrc["~c.stringof~"+"~r.stringof~"*8]"; 919 } 920 // 4x8 = 4x8 times 8x8, matrix 0 is constant 921 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))); 922 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))); 923 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))); 924 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))); 925 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))); 926 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))); 927 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))); 928 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))); 929 immutable Temp_Type X110 = mixin(AT!(2, 0)); 930 immutable Temp_Type X111 = mixin(AT!(2, 1)); 931 immutable Temp_Type X112 = mixin(AT!(2, 2)); 932 immutable Temp_Type X113 = mixin(AT!(2, 3)); 933 immutable Temp_Type X114 = mixin(AT!(2, 4)); 934 immutable Temp_Type X115 = mixin(AT!(2, 5)); 935 immutable Temp_Type X116 = mixin(AT!(2, 6)); 936 immutable Temp_Type X117 = mixin(AT!(2, 7)); 937 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))); 938 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))); 939 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))); 940 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))); 941 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))); 942 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))); 943 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))); 944 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))); 945 immutable Temp_Type X130 = mixin(AT!(6, 0)); 946 immutable Temp_Type X131 = mixin(AT!(6, 1)); 947 immutable Temp_Type X132 = mixin(AT!(6, 2)); 948 immutable Temp_Type X133 = mixin(AT!(6, 3)); 949 immutable Temp_Type X134 = mixin(AT!(6, 4)); 950 immutable Temp_Type X135 = mixin(AT!(6, 5)); 951 immutable Temp_Type X136 = mixin(AT!(6, 6)); 952 immutable Temp_Type X137 = mixin(AT!(6, 7)); 953 // 80 muls 48 adds 954 955 // 4x4 = 4x8 times 8x4, matrix 1 is constant 956 R.at(0, 0) = X100; 957 R.at(0, 1) = D(X101 * F!(0.415735f) + X103 * F!(0.791065f) + X105 * F!(-0.352443f) + X107 * F!(0.277785f)); 958 R.at(0, 2) = X104; 959 R.at(0, 3) = D(X101 * F!(0.022887f) + X103 * F!(-0.097545f) + X105 * F!(0.490393f) + X107 * F!(0.865723f)); 960 R.at(1, 0) = X110; 961 R.at(1, 1) = D(X111 * F!(0.415735f) + X113 * F!(0.791065f) + X115 * F!(-0.352443f) + X117 * F!(0.277785f)); 962 R.at(1, 2) = X114; 963 R.at(1, 3) = D(X111 * F!(0.022887f) + X113 * F!(-0.097545f) + X115 * F!(0.490393f) + X117 * F!(0.865723f)); 964 R.at(2, 0) = X120; 965 R.at(2, 1) = D(X121 * F!(0.415735f) + X123 * F!(0.791065f) + X125 * F!(-0.352443f) + X127 * F!(0.277785f)); 966 R.at(2, 2) = X124; 967 R.at(2, 3) = D(X121 * F!(0.022887f) + X123 * F!(-0.097545f) + X125 * F!(0.490393f) + X127 * F!(0.865723f)); 968 R.at(3, 0) = X130; 969 R.at(3, 1) = D(X131 * F!(0.415735f) + X133 * F!(0.791065f) + X135 * F!(-0.352443f) + X137 * F!(0.277785f)); 970 R.at(3, 2) = X134; 971 R.at(3, 3) = D(X131 * F!(0.022887f) + X133 * F!(-0.097545f) + X135 * F!(0.490393f) + X137 * F!(0.865723f)); 972 // 40 muls 24 adds 973 // 4x4 = 4x8 times 8x4, matrix 1 is constant 974 S.at(0, 0) = D(X101 * F!(0.906127f) + X103 * F!(-0.318190f) + X105 * F!(0.212608f) + X107 * F!(-0.180240f)); 975 S.at(0, 1) = X102; 976 S.at(0, 2) = D(X101 * F!(-0.074658f) + X103 * F!(0.513280f) + X105 * F!(0.768178f) + X107 * F!(-0.375330f)); 977 S.at(0, 3) = X106; 978 S.at(1, 0) = D(X111 * F!(0.906127f) + X113 * F!(-0.318190f) + X115 * F!(0.212608f) + X117 * F!(-0.180240f)); 979 S.at(1, 1) = X112; 980 S.at(1, 2) = D(X111 * F!(-0.074658f) + X113 * F!(0.513280f) + X115 * F!(0.768178f) + X117 * F!(-0.375330f)); 981 S.at(1, 3) = X116; 982 S.at(2, 0) = D(X121 * F!(0.906127f) + X123 * F!(-0.318190f) + X125 * F!(0.212608f) + X127 * F!(-0.180240f)); 983 S.at(2, 1) = X122; 984 S.at(2, 2) = D(X121 * F!(-0.074658f) + X123 * F!(0.513280f) + X125 * F!(0.768178f) + X127 * F!(-0.375330f)); 985 S.at(2, 3) = X126; 986 S.at(3, 0) = D(X131 * F!(0.906127f) + X133 * F!(-0.318190f) + X135 * F!(0.212608f) + X137 * F!(-0.180240f)); 987 S.at(3, 1) = X132; 988 S.at(3, 2) = D(X131 * F!(-0.074658f) + X133 * F!(0.513280f) + X135 * F!(0.768178f) + X137 * F!(-0.375330f)); 989 S.at(3, 3) = X136; 990 // 40 muls 24 adds 991 } 992 } 993 } // end namespace DCT_Upsample 994 995 // Unconditionally frees all allocated m_blocks. 996 void free_all_blocks () { 997 //m_pStream = null; 998 readfn = null; 999 for (mem_block *b = m_pMem_blocks; b; ) { 1000 mem_block* n = b.m_pNext; 1001 jpgd_free(b); 1002 b = n; 1003 } 1004 m_pMem_blocks = null; 1005 } 1006 1007 // This method handles all errors. It will never return. 1008 // It could easily be changed to use C++ exceptions. 1009 /*JPGD_NORETURN*/ void stop_decoding (jpgd_status status, size_t line=__LINE__) { 1010 m_error_code = status; 1011 free_all_blocks(); 1012 //longjmp(m_jmp_state, status); 1013 throw new Exception("jpeg decoding error", __FILE__, line); 1014 } 1015 1016 void* alloc (size_t nSize, bool zero=false) { 1017 nSize = (JPGD_MAX(nSize, 1) + 3) & ~3; 1018 char *rv = null; 1019 for (mem_block *b = m_pMem_blocks; b; b = b.m_pNext) 1020 { 1021 if ((b.m_used_count + nSize) <= b.m_size) 1022 { 1023 rv = b.m_data.ptr + b.m_used_count; 1024 b.m_used_count += nSize; 1025 break; 1026 } 1027 } 1028 if (!rv) 1029 { 1030 size_t capacity = JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047); 1031 mem_block *b = cast(mem_block*)jpgd_malloc(mem_block.sizeof + capacity); 1032 if (!b) { stop_decoding(JPGD_NOTENOUGHMEM); } 1033 b.m_pNext = m_pMem_blocks; m_pMem_blocks = b; 1034 b.m_used_count = nSize; 1035 b.m_size = capacity; 1036 rv = b.m_data.ptr; 1037 } 1038 if (zero) memset(rv, 0, nSize); 1039 return rv; 1040 } 1041 1042 void word_clear (void *p, ushort c, uint n) { 1043 ubyte *pD = cast(ubyte*)p; 1044 immutable ubyte l = c & 0xFF, h = (c >> 8) & 0xFF; 1045 while (n) 1046 { 1047 pD[0] = l; pD[1] = h; pD += 2; 1048 n--; 1049 } 1050 } 1051 1052 // Refill the input buffer. 1053 // This method will sit in a loop until (A) the buffer is full or (B) 1054 // the stream's read() method reports and end of file condition. 1055 void prep_in_buffer () { 1056 m_in_buf_left = 0; 1057 m_pIn_buf_ofs = m_in_buf.ptr; 1058 1059 if (m_eof_flag) 1060 return; 1061 1062 do 1063 { 1064 int bytes_read = readfn(m_in_buf.ptr + m_in_buf_left, JPGD_IN_BUF_SIZE - m_in_buf_left, &m_eof_flag); 1065 if (bytes_read == -1) 1066 stop_decoding(JPGD_STREAM_READ); 1067 1068 m_in_buf_left += bytes_read; 1069 } while ((m_in_buf_left < JPGD_IN_BUF_SIZE) && (!m_eof_flag)); 1070 1071 m_total_bytes_read += m_in_buf_left; 1072 1073 // Pad the end of the block with M_EOI (prevents the decompressor from going off the rails if the stream is invalid). 1074 // (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.) 1075 word_clear(m_pIn_buf_ofs + m_in_buf_left, 0xD9FF, 64); 1076 } 1077 1078 // Read a Huffman code table. 1079 void read_dht_marker () { 1080 int i, index, count; 1081 ubyte[17] huff_num; 1082 ubyte[256] huff_val; 1083 1084 uint num_left = get_bits(16); 1085 1086 if (num_left < 2) 1087 stop_decoding(JPGD_BAD_DHT_MARKER); 1088 1089 num_left -= 2; 1090 1091 while (num_left) 1092 { 1093 index = get_bits(8); 1094 1095 huff_num.ptr[0] = 0; 1096 1097 count = 0; 1098 1099 for (i = 1; i <= 16; i++) 1100 { 1101 huff_num.ptr[i] = cast(ubyte)(get_bits(8)); 1102 count += huff_num.ptr[i]; 1103 } 1104 1105 if (count > 255) 1106 stop_decoding(JPGD_BAD_DHT_COUNTS); 1107 1108 for (i = 0; i < count; i++) 1109 huff_val.ptr[i] = cast(ubyte)(get_bits(8)); 1110 1111 i = 1 + 16 + count; 1112 1113 if (num_left < cast(uint)i) 1114 stop_decoding(JPGD_BAD_DHT_MARKER); 1115 1116 num_left -= i; 1117 1118 if ((index & 0x10) > 0x10) 1119 stop_decoding(JPGD_BAD_DHT_INDEX); 1120 1121 index = (index & 0x0F) + ((index & 0x10) >> 4) * (JPGD_MAX_HUFF_TABLES >> 1); 1122 1123 if (index >= JPGD_MAX_HUFF_TABLES) 1124 stop_decoding(JPGD_BAD_DHT_INDEX); 1125 1126 if (!m_huff_num.ptr[index]) 1127 m_huff_num.ptr[index] = cast(ubyte*)alloc(17); 1128 1129 if (!m_huff_val.ptr[index]) 1130 m_huff_val.ptr[index] = cast(ubyte*)alloc(256); 1131 1132 m_huff_ac.ptr[index] = (index & 0x10) != 0; 1133 memcpy(m_huff_num.ptr[index], huff_num.ptr, 17); 1134 memcpy(m_huff_val.ptr[index], huff_val.ptr, 256); 1135 } 1136 } 1137 1138 // Read a quantization table. 1139 void read_dqt_marker () { 1140 int n, i, prec; 1141 uint num_left; 1142 uint temp; 1143 1144 num_left = get_bits(16); 1145 1146 if (num_left < 2) 1147 stop_decoding(JPGD_BAD_DQT_MARKER); 1148 1149 num_left -= 2; 1150 1151 while (num_left) 1152 { 1153 n = get_bits(8); 1154 prec = n >> 4; 1155 n &= 0x0F; 1156 1157 if (n >= JPGD_MAX_QUANT_TABLES) 1158 stop_decoding(JPGD_BAD_DQT_TABLE); 1159 1160 if (!m_quant.ptr[n]) 1161 m_quant.ptr[n] = cast(jpgd_quant_t*)alloc(64 * jpgd_quant_t.sizeof); 1162 1163 // read quantization entries, in zag order 1164 for (i = 0; i < 64; i++) 1165 { 1166 temp = get_bits(8); 1167 1168 if (prec) 1169 temp = (temp << 8) + get_bits(8); 1170 1171 m_quant.ptr[n][i] = cast(jpgd_quant_t)(temp); 1172 } 1173 1174 i = 64 + 1; 1175 1176 if (prec) 1177 i += 64; 1178 1179 if (num_left < cast(uint)i) 1180 stop_decoding(JPGD_BAD_DQT_LENGTH); 1181 1182 num_left -= i; 1183 } 1184 } 1185 1186 // Read the start of frame (SOF) marker. 1187 void read_sof_marker () { 1188 int i; 1189 uint num_left; 1190 1191 num_left = get_bits(16); 1192 1193 if (get_bits(8) != 8) /* precision: sorry, only 8-bit precision is supported right now */ 1194 stop_decoding(JPGD_BAD_PRECISION); 1195 1196 m_image_y_size = get_bits(16); 1197 1198 if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT)) 1199 stop_decoding(JPGD_BAD_HEIGHT); 1200 1201 m_image_x_size = get_bits(16); 1202 1203 if ((m_image_x_size < 1) || (m_image_x_size > JPGD_MAX_WIDTH)) 1204 stop_decoding(JPGD_BAD_WIDTH); 1205 1206 m_comps_in_frame = get_bits(8); 1207 1208 if (m_comps_in_frame > JPGD_MAX_COMPONENTS) 1209 stop_decoding(JPGD_TOO_MANY_COMPONENTS); 1210 1211 if (num_left != cast(uint)(m_comps_in_frame * 3 + 8)) 1212 stop_decoding(JPGD_BAD_SOF_LENGTH); 1213 1214 for (i = 0; i < m_comps_in_frame; i++) 1215 { 1216 m_comp_ident.ptr[i] = get_bits(8); 1217 m_comp_h_samp.ptr[i] = get_bits(4); 1218 m_comp_v_samp.ptr[i] = get_bits(4); 1219 m_comp_quant.ptr[i] = get_bits(8); 1220 } 1221 } 1222 1223 // Used to skip unrecognized markers. 1224 void skip_variable_marker () { 1225 uint num_left; 1226 1227 num_left = get_bits(16); 1228 1229 if (num_left < 2) 1230 stop_decoding(JPGD_BAD_VARIABLE_MARKER); 1231 1232 num_left -= 2; 1233 1234 while (num_left) 1235 { 1236 get_bits(8); 1237 num_left--; 1238 } 1239 } 1240 1241 // Read a define restart interval (DRI) marker. 1242 void read_dri_marker () { 1243 if (get_bits(16) != 4) 1244 stop_decoding(JPGD_BAD_DRI_LENGTH); 1245 1246 m_restart_interval = get_bits(16); 1247 } 1248 1249 // Read a start of scan (SOS) marker. 1250 void read_sos_marker () { 1251 uint num_left; 1252 int i, ci, n, c, cc; 1253 1254 num_left = get_bits(16); 1255 1256 n = get_bits(8); 1257 1258 m_comps_in_scan = n; 1259 1260 num_left -= 3; 1261 1262 if ( (num_left != cast(uint)(n * 2 + 3)) || (n < 1) || (n > JPGD_MAX_COMPS_IN_SCAN) ) 1263 stop_decoding(JPGD_BAD_SOS_LENGTH); 1264 1265 for (i = 0; i < n; i++) 1266 { 1267 cc = get_bits(8); 1268 c = get_bits(8); 1269 num_left -= 2; 1270 1271 for (ci = 0; ci < m_comps_in_frame; ci++) 1272 if (cc == m_comp_ident.ptr[ci]) 1273 break; 1274 1275 if (ci >= m_comps_in_frame) 1276 stop_decoding(JPGD_BAD_SOS_COMP_ID); 1277 1278 m_comp_list.ptr[i] = ci; 1279 m_comp_dc_tab.ptr[ci] = (c >> 4) & 15; 1280 m_comp_ac_tab.ptr[ci] = (c & 15) + (JPGD_MAX_HUFF_TABLES >> 1); 1281 } 1282 1283 m_spectral_start = get_bits(8); 1284 m_spectral_end = get_bits(8); 1285 m_successive_high = get_bits(4); 1286 m_successive_low = get_bits(4); 1287 1288 if (!m_progressive_flag) 1289 { 1290 m_spectral_start = 0; 1291 m_spectral_end = 63; 1292 } 1293 1294 num_left -= 3; 1295 1296 /* read past whatever is num_left */ 1297 while (num_left) 1298 { 1299 get_bits(8); 1300 num_left--; 1301 } 1302 } 1303 1304 // Finds the next marker. 1305 int next_marker () { 1306 uint c, bytes; 1307 1308 bytes = 0; 1309 1310 do 1311 { 1312 do 1313 { 1314 bytes++; 1315 c = get_bits(8); 1316 } while (c != 0xFF); 1317 1318 do 1319 { 1320 c = get_bits(8); 1321 } while (c == 0xFF); 1322 1323 } while (c == 0); 1324 1325 // If bytes > 0 here, there where extra bytes before the marker (not good). 1326 1327 return c; 1328 } 1329 1330 // Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is 1331 // encountered. 1332 int process_markers () { 1333 int c; 1334 1335 for ( ; ; ) { 1336 c = next_marker(); 1337 1338 switch (c) 1339 { 1340 case M_SOF0: 1341 case M_SOF1: 1342 case M_SOF2: 1343 case M_SOF3: 1344 case M_SOF5: 1345 case M_SOF6: 1346 case M_SOF7: 1347 //case M_JPG: 1348 case M_SOF9: 1349 case M_SOF10: 1350 case M_SOF11: 1351 case M_SOF13: 1352 case M_SOF14: 1353 case M_SOF15: 1354 case M_SOI: 1355 case M_EOI: 1356 case M_SOS: 1357 return c; 1358 case M_DHT: 1359 read_dht_marker(); 1360 break; 1361 // No arithmitic support - dumb patents! 1362 case M_DAC: 1363 stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT); 1364 break; 1365 case M_DQT: 1366 read_dqt_marker(); 1367 break; 1368 case M_DRI: 1369 read_dri_marker(); 1370 break; 1371 //case M_APP0: /* no need to read the JFIF marker */ 1372 1373 case M_JPG: 1374 case M_RST0: /* no parameters */ 1375 case M_RST1: 1376 case M_RST2: 1377 case M_RST3: 1378 case M_RST4: 1379 case M_RST5: 1380 case M_RST6: 1381 case M_RST7: 1382 case M_TEM: 1383 stop_decoding(JPGD_UNEXPECTED_MARKER); 1384 break; 1385 default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */ 1386 skip_variable_marker(); 1387 break; 1388 } 1389 } 1390 } 1391 1392 // Finds the start of image (SOI) marker. 1393 // This code is rather defensive: it only checks the first 512 bytes to avoid 1394 // false positives. 1395 void locate_soi_marker () { 1396 uint lastchar, thischar; 1397 uint bytesleft; 1398 1399 lastchar = get_bits(8); 1400 1401 thischar = get_bits(8); 1402 1403 /* ok if it's a normal JPEG file without a special header */ 1404 1405 if ((lastchar == 0xFF) && (thischar == M_SOI)) 1406 return; 1407 1408 bytesleft = 4096; //512; 1409 1410 for ( ; ; ) 1411 { 1412 if (--bytesleft == 0) 1413 stop_decoding(JPGD_NOT_JPEG); 1414 1415 lastchar = thischar; 1416 1417 thischar = get_bits(8); 1418 1419 if (lastchar == 0xFF) 1420 { 1421 if (thischar == M_SOI) 1422 break; 1423 else if (thischar == M_EOI) // get_bits will keep returning M_EOI if we read past the end 1424 stop_decoding(JPGD_NOT_JPEG); 1425 } 1426 } 1427 1428 // 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. 1429 thischar = (m_bit_buf >> 24) & 0xFF; 1430 1431 if (thischar != 0xFF) 1432 stop_decoding(JPGD_NOT_JPEG); 1433 } 1434 1435 // Find a start of frame (SOF) marker. 1436 void locate_sof_marker () { 1437 locate_soi_marker(); 1438 1439 int c = process_markers(); 1440 1441 switch (c) 1442 { 1443 case M_SOF2: 1444 m_progressive_flag = true; 1445 goto case; 1446 case M_SOF0: /* baseline DCT */ 1447 case M_SOF1: /* extended sequential DCT */ 1448 read_sof_marker(); 1449 break; 1450 case M_SOF9: /* Arithmitic coding */ 1451 stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT); 1452 break; 1453 default: 1454 stop_decoding(JPGD_UNSUPPORTED_MARKER); 1455 break; 1456 } 1457 } 1458 1459 // Find a start of scan (SOS) marker. 1460 int locate_sos_marker () { 1461 int c; 1462 1463 c = process_markers(); 1464 1465 if (c == M_EOI) 1466 return false; 1467 else if (c != M_SOS) 1468 stop_decoding(JPGD_UNEXPECTED_MARKER); 1469 1470 read_sos_marker(); 1471 1472 return true; 1473 } 1474 1475 // Reset everything to default/uninitialized state. 1476 void initit (JpegStreamReadFunc rfn) { 1477 m_pMem_blocks = null; 1478 m_error_code = JPGD_SUCCESS; 1479 m_ready_flag = false; 1480 m_image_x_size = m_image_y_size = 0; 1481 readfn = rfn; 1482 m_progressive_flag = false; 1483 1484 memset(m_huff_ac.ptr, 0, m_huff_ac.sizeof); 1485 memset(m_huff_num.ptr, 0, m_huff_num.sizeof); 1486 memset(m_huff_val.ptr, 0, m_huff_val.sizeof); 1487 memset(m_quant.ptr, 0, m_quant.sizeof); 1488 1489 m_scan_type = 0; 1490 m_comps_in_frame = 0; 1491 1492 memset(m_comp_h_samp.ptr, 0, m_comp_h_samp.sizeof); 1493 memset(m_comp_v_samp.ptr, 0, m_comp_v_samp.sizeof); 1494 memset(m_comp_quant.ptr, 0, m_comp_quant.sizeof); 1495 memset(m_comp_ident.ptr, 0, m_comp_ident.sizeof); 1496 memset(m_comp_h_blocks.ptr, 0, m_comp_h_blocks.sizeof); 1497 memset(m_comp_v_blocks.ptr, 0, m_comp_v_blocks.sizeof); 1498 1499 m_comps_in_scan = 0; 1500 memset(m_comp_list.ptr, 0, m_comp_list.sizeof); 1501 memset(m_comp_dc_tab.ptr, 0, m_comp_dc_tab.sizeof); 1502 memset(m_comp_ac_tab.ptr, 0, m_comp_ac_tab.sizeof); 1503 1504 m_spectral_start = 0; 1505 m_spectral_end = 0; 1506 m_successive_low = 0; 1507 m_successive_high = 0; 1508 m_max_mcu_x_size = 0; 1509 m_max_mcu_y_size = 0; 1510 m_blocks_per_mcu = 0; 1511 m_max_blocks_per_row = 0; 1512 m_mcus_per_row = 0; 1513 m_mcus_per_col = 0; 1514 m_expanded_blocks_per_component = 0; 1515 m_expanded_blocks_per_mcu = 0; 1516 m_expanded_blocks_per_row = 0; 1517 m_freq_domain_chroma_upsample = false; 1518 1519 memset(m_mcu_org.ptr, 0, m_mcu_org.sizeof); 1520 1521 m_total_lines_left = 0; 1522 m_mcu_lines_left = 0; 1523 m_real_dest_bytes_per_scan_line = 0; 1524 m_dest_bytes_per_scan_line = 0; 1525 m_dest_bytes_per_pixel = 0; 1526 1527 memset(m_pHuff_tabs.ptr, 0, m_pHuff_tabs.sizeof); 1528 1529 memset(m_dc_coeffs.ptr, 0, m_dc_coeffs.sizeof); 1530 memset(m_ac_coeffs.ptr, 0, m_ac_coeffs.sizeof); 1531 memset(m_block_y_mcu.ptr, 0, m_block_y_mcu.sizeof); 1532 1533 m_eob_run = 0; 1534 1535 memset(m_block_y_mcu.ptr, 0, m_block_y_mcu.sizeof); 1536 1537 m_pIn_buf_ofs = m_in_buf.ptr; 1538 m_in_buf_left = 0; 1539 m_eof_flag = false; 1540 m_tem_flag = 0; 1541 1542 memset(m_in_buf_pad_start.ptr, 0, m_in_buf_pad_start.sizeof); 1543 memset(m_in_buf.ptr, 0, m_in_buf.sizeof); 1544 memset(m_in_buf_pad_end.ptr, 0, m_in_buf_pad_end.sizeof); 1545 1546 m_restart_interval = 0; 1547 m_restarts_left = 0; 1548 m_next_restart_num = 0; 1549 1550 m_max_mcus_per_row = 0; 1551 m_max_blocks_per_mcu = 0; 1552 m_max_mcus_per_col = 0; 1553 1554 memset(m_last_dc_val.ptr, 0, m_last_dc_val.sizeof); 1555 m_pMCU_coefficients = null; 1556 m_pSample_buf = null; 1557 1558 m_total_bytes_read = 0; 1559 1560 m_pScan_line_0 = null; 1561 m_pScan_line_1 = null; 1562 1563 // Ready the input buffer. 1564 prep_in_buffer(); 1565 1566 // Prime the bit buffer. 1567 m_bits_left = 16; 1568 m_bit_buf = 0; 1569 1570 get_bits(16); 1571 get_bits(16); 1572 1573 for (int i = 0; i < JPGD_MAX_BLOCKS_PER_MCU; i++) 1574 m_mcu_block_max_zag.ptr[i] = 64; 1575 } 1576 1577 enum SCALEBITS = 16; 1578 enum ONE_HALF = (cast(int) 1 << (SCALEBITS-1)); 1579 enum FIX(float x) = (cast(int)((x) * (1L<<SCALEBITS) + 0.5f)); 1580 1581 // Create a few tables that allow us to quickly convert YCbCr to RGB. 1582 void create_look_ups () { 1583 for (int i = 0; i <= 255; i++) 1584 { 1585 int k = i - 128; 1586 m_crr.ptr[i] = ( FIX!(1.40200f) * k + ONE_HALF) >> SCALEBITS; 1587 m_cbb.ptr[i] = ( FIX!(1.77200f) * k + ONE_HALF) >> SCALEBITS; 1588 m_crg.ptr[i] = (-FIX!(0.71414f)) * k; 1589 m_cbg.ptr[i] = (-FIX!(0.34414f)) * k + ONE_HALF; 1590 } 1591 } 1592 1593 // This method throws back into the stream any bytes that where read 1594 // into the bit buffer during initial marker scanning. 1595 void fix_in_buffer () { 1596 // In case any 0xFF's where pulled into the buffer during marker scanning. 1597 assert((m_bits_left & 7) == 0); 1598 1599 if (m_bits_left == 16) 1600 stuff_char(cast(ubyte)(m_bit_buf & 0xFF)); 1601 1602 if (m_bits_left >= 8) 1603 stuff_char(cast(ubyte)((m_bit_buf >> 8) & 0xFF)); 1604 1605 stuff_char(cast(ubyte)((m_bit_buf >> 16) & 0xFF)); 1606 stuff_char(cast(ubyte)((m_bit_buf >> 24) & 0xFF)); 1607 1608 m_bits_left = 16; 1609 get_bits_no_markers(16); 1610 get_bits_no_markers(16); 1611 } 1612 1613 void transform_mcu (int mcu_row) { 1614 jpgd_block_t* pSrc_ptr = m_pMCU_coefficients; 1615 ubyte* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64; 1616 1617 for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++) 1618 { 1619 idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag.ptr[mcu_block]); 1620 pSrc_ptr += 64; 1621 pDst_ptr += 64; 1622 } 1623 } 1624 1625 static immutable ubyte[64] s_max_rc = [ 1626 17, 18, 34, 50, 50, 51, 52, 52, 52, 68, 84, 84, 84, 84, 85, 86, 86, 86, 86, 86, 1627 102, 118, 118, 118, 118, 118, 118, 119, 120, 120, 120, 120, 120, 120, 120, 136, 1628 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 1629 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136 1630 ]; 1631 1632 void transform_mcu_expand (int mcu_row) { 1633 jpgd_block_t* pSrc_ptr = m_pMCU_coefficients; 1634 ubyte* pDst_ptr = m_pSample_buf + mcu_row * m_expanded_blocks_per_mcu * 64; 1635 1636 // Y IDCT 1637 int mcu_block; 1638 for (mcu_block = 0; mcu_block < m_expanded_blocks_per_component; mcu_block++) 1639 { 1640 idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag.ptr[mcu_block]); 1641 pSrc_ptr += 64; 1642 pDst_ptr += 64; 1643 } 1644 1645 // Chroma IDCT, with upsampling 1646 jpgd_block_t[64] temp_block; 1647 1648 for (int i = 0; i < 2; i++) 1649 { 1650 DCT_Upsample.Matrix44 P, Q, R, S; 1651 1652 assert(m_mcu_block_max_zag.ptr[mcu_block] >= 1); 1653 assert(m_mcu_block_max_zag.ptr[mcu_block] <= 64); 1654 1655 int max_zag = m_mcu_block_max_zag.ptr[mcu_block++] - 1; 1656 if (max_zag <= 0) max_zag = 0; // should never happen, only here to shut up static analysis 1657 switch (s_max_rc.ptr[max_zag]) 1658 { 1659 case 1*16+1: 1660 DCT_Upsample.P_Q!(1, 1).calc(P, Q, pSrc_ptr); 1661 DCT_Upsample.R_S!(1, 1).calc(R, S, pSrc_ptr); 1662 break; 1663 case 1*16+2: 1664 DCT_Upsample.P_Q!(1, 2).calc(P, Q, pSrc_ptr); 1665 DCT_Upsample.R_S!(1, 2).calc(R, S, pSrc_ptr); 1666 break; 1667 case 2*16+2: 1668 DCT_Upsample.P_Q!(2, 2).calc(P, Q, pSrc_ptr); 1669 DCT_Upsample.R_S!(2, 2).calc(R, S, pSrc_ptr); 1670 break; 1671 case 3*16+2: 1672 DCT_Upsample.P_Q!(3, 2).calc(P, Q, pSrc_ptr); 1673 DCT_Upsample.R_S!(3, 2).calc(R, S, pSrc_ptr); 1674 break; 1675 case 3*16+3: 1676 DCT_Upsample.P_Q!(3, 3).calc(P, Q, pSrc_ptr); 1677 DCT_Upsample.R_S!(3, 3).calc(R, S, pSrc_ptr); 1678 break; 1679 case 3*16+4: 1680 DCT_Upsample.P_Q!(3, 4).calc(P, Q, pSrc_ptr); 1681 DCT_Upsample.R_S!(3, 4).calc(R, S, pSrc_ptr); 1682 break; 1683 case 4*16+4: 1684 DCT_Upsample.P_Q!(4, 4).calc(P, Q, pSrc_ptr); 1685 DCT_Upsample.R_S!(4, 4).calc(R, S, pSrc_ptr); 1686 break; 1687 case 5*16+4: 1688 DCT_Upsample.P_Q!(5, 4).calc(P, Q, pSrc_ptr); 1689 DCT_Upsample.R_S!(5, 4).calc(R, S, pSrc_ptr); 1690 break; 1691 case 5*16+5: 1692 DCT_Upsample.P_Q!(5, 5).calc(P, Q, pSrc_ptr); 1693 DCT_Upsample.R_S!(5, 5).calc(R, S, pSrc_ptr); 1694 break; 1695 case 5*16+6: 1696 DCT_Upsample.P_Q!(5, 6).calc(P, Q, pSrc_ptr); 1697 DCT_Upsample.R_S!(5, 6).calc(R, S, pSrc_ptr); 1698 break; 1699 case 6*16+6: 1700 DCT_Upsample.P_Q!(6, 6).calc(P, Q, pSrc_ptr); 1701 DCT_Upsample.R_S!(6, 6).calc(R, S, pSrc_ptr); 1702 break; 1703 case 7*16+6: 1704 DCT_Upsample.P_Q!(7, 6).calc(P, Q, pSrc_ptr); 1705 DCT_Upsample.R_S!(7, 6).calc(R, S, pSrc_ptr); 1706 break; 1707 case 7*16+7: 1708 DCT_Upsample.P_Q!(7, 7).calc(P, Q, pSrc_ptr); 1709 DCT_Upsample.R_S!(7, 7).calc(R, S, pSrc_ptr); 1710 break; 1711 case 7*16+8: 1712 DCT_Upsample.P_Q!(7, 8).calc(P, Q, pSrc_ptr); 1713 DCT_Upsample.R_S!(7, 8).calc(R, S, pSrc_ptr); 1714 break; 1715 case 8*16+8: 1716 DCT_Upsample.P_Q!(8, 8).calc(P, Q, pSrc_ptr); 1717 DCT_Upsample.R_S!(8, 8).calc(R, S, pSrc_ptr); 1718 break; 1719 default: 1720 assert(false); 1721 } 1722 1723 auto a = DCT_Upsample.Matrix44(P + Q); 1724 P -= Q; 1725 DCT_Upsample.Matrix44* b = &P; 1726 auto c = DCT_Upsample.Matrix44(R + S); 1727 R -= S; 1728 DCT_Upsample.Matrix44* d = &R; 1729 1730 DCT_Upsample.Matrix44.add_and_store(temp_block.ptr, a, c); 1731 idct_4x4(temp_block.ptr, pDst_ptr); 1732 pDst_ptr += 64; 1733 1734 DCT_Upsample.Matrix44.sub_and_store(temp_block.ptr, a, c); 1735 idct_4x4(temp_block.ptr, pDst_ptr); 1736 pDst_ptr += 64; 1737 1738 DCT_Upsample.Matrix44.add_and_store(temp_block.ptr, *b, *d); 1739 idct_4x4(temp_block.ptr, pDst_ptr); 1740 pDst_ptr += 64; 1741 1742 DCT_Upsample.Matrix44.sub_and_store(temp_block.ptr, *b, *d); 1743 idct_4x4(temp_block.ptr, pDst_ptr); 1744 pDst_ptr += 64; 1745 1746 pSrc_ptr += 64; 1747 } 1748 } 1749 1750 // Loads and dequantizes the next row of (already decoded) coefficients. 1751 // Progressive images only. 1752 void load_next_row () { 1753 int i; 1754 jpgd_block_t *p; 1755 jpgd_quant_t *q; 1756 int mcu_row, mcu_block, row_block = 0; 1757 int component_num, component_id; 1758 int[JPGD_MAX_COMPONENTS] block_x_mcu; 1759 1760 memset(block_x_mcu.ptr, 0, JPGD_MAX_COMPONENTS * int.sizeof); 1761 1762 for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++) 1763 { 1764 int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0; 1765 1766 for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++) 1767 { 1768 component_id = m_mcu_org.ptr[mcu_block]; 1769 q = m_quant.ptr[m_comp_quant.ptr[component_id]]; 1770 1771 p = m_pMCU_coefficients + 64 * mcu_block; 1772 1773 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); 1774 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); 1775 p[0] = pDC[0]; 1776 memcpy(&p[1], &pAC[1], 63 * jpgd_block_t.sizeof); 1777 1778 for (i = 63; i > 0; i--) 1779 if (p[g_ZAG[i]]) 1780 break; 1781 1782 m_mcu_block_max_zag.ptr[mcu_block] = i + 1; 1783 1784 for ( ; i >= 0; i--) 1785 if (p[g_ZAG[i]]) 1786 p[g_ZAG[i]] = cast(jpgd_block_t)(p[g_ZAG[i]] * q[i]); 1787 1788 row_block++; 1789 1790 if (m_comps_in_scan == 1) 1791 block_x_mcu.ptr[component_id]++; 1792 else 1793 { 1794 if (++block_x_mcu_ofs == m_comp_h_samp.ptr[component_id]) 1795 { 1796 block_x_mcu_ofs = 0; 1797 1798 if (++block_y_mcu_ofs == m_comp_v_samp.ptr[component_id]) 1799 { 1800 block_y_mcu_ofs = 0; 1801 1802 block_x_mcu.ptr[component_id] += m_comp_h_samp.ptr[component_id]; 1803 } 1804 } 1805 } 1806 } 1807 1808 if (m_freq_domain_chroma_upsample) 1809 transform_mcu_expand(mcu_row); 1810 else 1811 transform_mcu(mcu_row); 1812 } 1813 1814 if (m_comps_in_scan == 1) 1815 m_block_y_mcu.ptr[m_comp_list.ptr[0]]++; 1816 else 1817 { 1818 for (component_num = 0; component_num < m_comps_in_scan; component_num++) 1819 { 1820 component_id = m_comp_list.ptr[component_num]; 1821 1822 m_block_y_mcu.ptr[component_id] += m_comp_v_samp.ptr[component_id]; 1823 } 1824 } 1825 } 1826 1827 // Restart interval processing. 1828 void process_restart () { 1829 int i; 1830 int c = 0; 1831 1832 // Align to a byte boundry 1833 // FIXME: Is this really necessary? get_bits_no_markers() never reads in markers! 1834 //get_bits_no_markers(m_bits_left & 7); 1835 1836 // Let's scan a little bit to find the marker, but not _too_ far. 1837 // 1536 is a "fudge factor" that determines how much to scan. 1838 for (i = 1536; i > 0; i--) 1839 if (get_char() == 0xFF) 1840 break; 1841 1842 if (i == 0) 1843 stop_decoding(JPGD_BAD_RESTART_MARKER); 1844 1845 for ( ; i > 0; i--) 1846 if ((c = get_char()) != 0xFF) 1847 break; 1848 1849 if (i == 0) 1850 stop_decoding(JPGD_BAD_RESTART_MARKER); 1851 1852 // Is it the expected marker? If not, something bad happened. 1853 if (c != (m_next_restart_num + M_RST0)) 1854 stop_decoding(JPGD_BAD_RESTART_MARKER); 1855 1856 // Reset each component's DC prediction values. 1857 memset(&m_last_dc_val, 0, m_comps_in_frame * uint.sizeof); 1858 1859 m_eob_run = 0; 1860 1861 m_restarts_left = m_restart_interval; 1862 1863 m_next_restart_num = (m_next_restart_num + 1) & 7; 1864 1865 // Get the bit buffer going again... 1866 1867 m_bits_left = 16; 1868 get_bits_no_markers(16); 1869 get_bits_no_markers(16); 1870 } 1871 1872 static int dequantize_ac (int c, int q) { pragma(inline, true); c *= q; return c; } 1873 1874 // Decodes and dequantizes the next row of coefficients. 1875 void decode_next_row () { 1876 int row_block = 0; 1877 1878 for (int mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++) 1879 { 1880 if ((m_restart_interval) && (m_restarts_left == 0)) 1881 process_restart(); 1882 1883 jpgd_block_t* p = m_pMCU_coefficients; 1884 for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++, p += 64) 1885 { 1886 int component_id = m_mcu_org.ptr[mcu_block]; 1887 jpgd_quant_t* q = m_quant.ptr[m_comp_quant.ptr[component_id]]; 1888 1889 int r, s; 1890 s = huff_decode(m_pHuff_tabs.ptr[m_comp_dc_tab.ptr[component_id]], r); 1891 s = JPGD_HUFF_EXTEND(r, s); 1892 1893 m_last_dc_val.ptr[component_id] = (s += m_last_dc_val.ptr[component_id]); 1894 1895 p[0] = cast(jpgd_block_t)(s * q[0]); 1896 1897 int prev_num_set = m_mcu_block_max_zag.ptr[mcu_block]; 1898 1899 huff_tables *pH = m_pHuff_tabs.ptr[m_comp_ac_tab.ptr[component_id]]; 1900 1901 int k; 1902 for (k = 1; k < 64; k++) 1903 { 1904 int extra_bits; 1905 s = huff_decode(pH, extra_bits); 1906 1907 r = s >> 4; 1908 s &= 15; 1909 1910 if (s) 1911 { 1912 if (r) 1913 { 1914 if ((k + r) > 63) 1915 stop_decoding(JPGD_DECODE_ERROR); 1916 1917 if (k < prev_num_set) 1918 { 1919 int n = JPGD_MIN(r, prev_num_set - k); 1920 int kt = k; 1921 while (n--) 1922 p[g_ZAG[kt++]] = 0; 1923 } 1924 1925 k += r; 1926 } 1927 1928 s = JPGD_HUFF_EXTEND(extra_bits, s); 1929 1930 assert(k < 64); 1931 1932 p[g_ZAG[k]] = cast(jpgd_block_t)(dequantize_ac(s, q[k])); //s * q[k]; 1933 } 1934 else 1935 { 1936 if (r == 15) 1937 { 1938 if ((k + 16) > 64) 1939 stop_decoding(JPGD_DECODE_ERROR); 1940 1941 if (k < prev_num_set) 1942 { 1943 int n = JPGD_MIN(16, prev_num_set - k); 1944 int kt = k; 1945 while (n--) 1946 { 1947 assert(kt <= 63); 1948 p[g_ZAG[kt++]] = 0; 1949 } 1950 } 1951 1952 k += 16 - 1; // - 1 because the loop counter is k 1953 assert(p[g_ZAG[k]] == 0); 1954 } 1955 else 1956 break; 1957 } 1958 } 1959 1960 if (k < prev_num_set) 1961 { 1962 int kt = k; 1963 while (kt < prev_num_set) 1964 p[g_ZAG[kt++]] = 0; 1965 } 1966 1967 m_mcu_block_max_zag.ptr[mcu_block] = k; 1968 1969 row_block++; 1970 } 1971 1972 if (m_freq_domain_chroma_upsample) 1973 transform_mcu_expand(mcu_row); 1974 else 1975 transform_mcu(mcu_row); 1976 1977 m_restarts_left--; 1978 } 1979 } 1980 1981 // YCbCr H1V1 (1x1:1:1, 3 m_blocks per MCU) to RGB 1982 void H1V1Convert () { 1983 int row = m_max_mcu_y_size - m_mcu_lines_left; 1984 ubyte *d = m_pScan_line_0; 1985 ubyte *s = m_pSample_buf + row * 8; 1986 1987 for (int i = m_max_mcus_per_row; i > 0; i--) 1988 { 1989 for (int j = 0; j < 8; j++) 1990 { 1991 int y = s[j]; 1992 int cb = s[64+j]; 1993 int cr = s[128+j]; 1994 1995 d[0] = clamp(y + m_crr.ptr[cr]); 1996 d[1] = clamp(y + ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16)); 1997 d[2] = clamp(y + m_cbb.ptr[cb]); 1998 d[3] = 255; 1999 2000 d += 4; 2001 } 2002 2003 s += 64*3; 2004 } 2005 } 2006 2007 // YCbCr H2V1 (2x1:1:1, 4 m_blocks per MCU) to RGB 2008 void H2V1Convert () { 2009 int row = m_max_mcu_y_size - m_mcu_lines_left; 2010 ubyte *d0 = m_pScan_line_0; 2011 ubyte *y = m_pSample_buf + row * 8; 2012 ubyte *c = m_pSample_buf + 2*64 + row * 8; 2013 2014 for (int i = m_max_mcus_per_row; i > 0; i--) 2015 { 2016 for (int l = 0; l < 2; l++) 2017 { 2018 for (int j = 0; j < 4; j++) 2019 { 2020 int cb = c[0]; 2021 int cr = c[64]; 2022 2023 int rc = m_crr.ptr[cr]; 2024 int gc = ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16); 2025 int bc = m_cbb.ptr[cb]; 2026 2027 int yy = y[j<<1]; 2028 d0[0] = clamp(yy+rc); 2029 d0[1] = clamp(yy+gc); 2030 d0[2] = clamp(yy+bc); 2031 d0[3] = 255; 2032 2033 yy = y[(j<<1)+1]; 2034 d0[4] = clamp(yy+rc); 2035 d0[5] = clamp(yy+gc); 2036 d0[6] = clamp(yy+bc); 2037 d0[7] = 255; 2038 2039 d0 += 8; 2040 2041 c++; 2042 } 2043 y += 64; 2044 } 2045 2046 y += 64*4 - 64*2; 2047 c += 64*4 - 8; 2048 } 2049 } 2050 2051 // YCbCr H2V1 (1x2:1:1, 4 m_blocks per MCU) to RGB 2052 void H1V2Convert () { 2053 int row = m_max_mcu_y_size - m_mcu_lines_left; 2054 ubyte *d0 = m_pScan_line_0; 2055 ubyte *d1 = m_pScan_line_1; 2056 ubyte *y; 2057 ubyte *c; 2058 2059 if (row < 8) 2060 y = m_pSample_buf + row * 8; 2061 else 2062 y = m_pSample_buf + 64*1 + (row & 7) * 8; 2063 2064 c = m_pSample_buf + 64*2 + (row >> 1) * 8; 2065 2066 for (int i = m_max_mcus_per_row; i > 0; i--) 2067 { 2068 for (int j = 0; j < 8; j++) 2069 { 2070 int cb = c[0+j]; 2071 int cr = c[64+j]; 2072 2073 int rc = m_crr.ptr[cr]; 2074 int gc = ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16); 2075 int bc = m_cbb.ptr[cb]; 2076 2077 int yy = y[j]; 2078 d0[0] = clamp(yy+rc); 2079 d0[1] = clamp(yy+gc); 2080 d0[2] = clamp(yy+bc); 2081 d0[3] = 255; 2082 2083 yy = y[8+j]; 2084 d1[0] = clamp(yy+rc); 2085 d1[1] = clamp(yy+gc); 2086 d1[2] = clamp(yy+bc); 2087 d1[3] = 255; 2088 2089 d0 += 4; 2090 d1 += 4; 2091 } 2092 2093 y += 64*4; 2094 c += 64*4; 2095 } 2096 } 2097 2098 // YCbCr H2V2 (2x2:1:1, 6 m_blocks per MCU) to RGB 2099 void H2V2Convert () { 2100 int row = m_max_mcu_y_size - m_mcu_lines_left; 2101 ubyte *d0 = m_pScan_line_0; 2102 ubyte *d1 = m_pScan_line_1; 2103 ubyte *y; 2104 ubyte *c; 2105 2106 if (row < 8) 2107 y = m_pSample_buf + row * 8; 2108 else 2109 y = m_pSample_buf + 64*2 + (row & 7) * 8; 2110 2111 c = m_pSample_buf + 64*4 + (row >> 1) * 8; 2112 2113 for (int i = m_max_mcus_per_row; i > 0; i--) 2114 { 2115 for (int l = 0; l < 2; l++) 2116 { 2117 for (int j = 0; j < 8; j += 2) 2118 { 2119 int cb = c[0]; 2120 int cr = c[64]; 2121 2122 int rc = m_crr.ptr[cr]; 2123 int gc = ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16); 2124 int bc = m_cbb.ptr[cb]; 2125 2126 int yy = y[j]; 2127 d0[0] = clamp(yy+rc); 2128 d0[1] = clamp(yy+gc); 2129 d0[2] = clamp(yy+bc); 2130 d0[3] = 255; 2131 2132 yy = y[j+1]; 2133 d0[4] = clamp(yy+rc); 2134 d0[5] = clamp(yy+gc); 2135 d0[6] = clamp(yy+bc); 2136 d0[7] = 255; 2137 2138 yy = y[j+8]; 2139 d1[0] = clamp(yy+rc); 2140 d1[1] = clamp(yy+gc); 2141 d1[2] = clamp(yy+bc); 2142 d1[3] = 255; 2143 2144 yy = y[j+8+1]; 2145 d1[4] = clamp(yy+rc); 2146 d1[5] = clamp(yy+gc); 2147 d1[6] = clamp(yy+bc); 2148 d1[7] = 255; 2149 2150 d0 += 8; 2151 d1 += 8; 2152 2153 c++; 2154 } 2155 y += 64; 2156 } 2157 2158 y += 64*6 - 64*2; 2159 c += 64*6 - 8; 2160 } 2161 } 2162 2163 // Y (1 block per MCU) to 8-bit grayscale 2164 void gray_convert () { 2165 int row = m_max_mcu_y_size - m_mcu_lines_left; 2166 ubyte *d = m_pScan_line_0; 2167 ubyte *s = m_pSample_buf + row * 8; 2168 2169 for (int i = m_max_mcus_per_row; i > 0; i--) 2170 { 2171 *cast(uint*)d = *cast(uint*)s; 2172 *cast(uint*)(&d[4]) = *cast(uint*)(&s[4]); 2173 2174 s += 64; 2175 d += 8; 2176 } 2177 } 2178 2179 void expanded_convert () { 2180 int row = m_max_mcu_y_size - m_mcu_lines_left; 2181 2182 ubyte* Py = m_pSample_buf + (row / 8) * 64 * m_comp_h_samp.ptr[0] + (row & 7) * 8; 2183 2184 ubyte* d = m_pScan_line_0; 2185 2186 for (int i = m_max_mcus_per_row; i > 0; i--) 2187 { 2188 for (int k = 0; k < m_max_mcu_x_size; k += 8) 2189 { 2190 immutable int Y_ofs = k * 8; 2191 immutable int Cb_ofs = Y_ofs + 64 * m_expanded_blocks_per_component; 2192 immutable int Cr_ofs = Y_ofs + 64 * m_expanded_blocks_per_component * 2; 2193 for (int j = 0; j < 8; j++) 2194 { 2195 int y = Py[Y_ofs + j]; 2196 int cb = Py[Cb_ofs + j]; 2197 int cr = Py[Cr_ofs + j]; 2198 2199 d[0] = clamp(y + m_crr.ptr[cr]); 2200 d[1] = clamp(y + ((m_crg.ptr[cr] + m_cbg.ptr[cb]) >> 16)); 2201 d[2] = clamp(y + m_cbb.ptr[cb]); 2202 d[3] = 255; 2203 2204 d += 4; 2205 } 2206 } 2207 2208 Py += 64 * m_expanded_blocks_per_mcu; 2209 } 2210 } 2211 2212 // Find end of image (EOI) marker, so we can return to the user the exact size of the input stream. 2213 void find_eoi () { 2214 if (!m_progressive_flag) 2215 { 2216 // Attempt to read the EOI marker. 2217 //get_bits_no_markers(m_bits_left & 7); 2218 2219 // Prime the bit buffer 2220 m_bits_left = 16; 2221 get_bits(16); 2222 get_bits(16); 2223 2224 // The next marker _should_ be EOI 2225 process_markers(); 2226 } 2227 2228 m_total_bytes_read -= m_in_buf_left; 2229 } 2230 2231 // Creates the tables needed for efficient Huffman decoding. 2232 void make_huff_table (int index, huff_tables *pH) { 2233 int p, i, l, si; 2234 ubyte[257] huffsize; 2235 uint[257] huffcode; 2236 uint code; 2237 uint subtree; 2238 int code_size; 2239 int lastp; 2240 int nextfreeentry; 2241 int currententry; 2242 2243 pH.ac_table = m_huff_ac.ptr[index] != 0; 2244 2245 p = 0; 2246 2247 for (l = 1; l <= 16; l++) 2248 { 2249 for (i = 1; i <= m_huff_num.ptr[index][l]; i++) 2250 huffsize.ptr[p++] = cast(ubyte)(l); 2251 } 2252 2253 huffsize.ptr[p] = 0; 2254 2255 lastp = p; 2256 2257 code = 0; 2258 si = huffsize.ptr[0]; 2259 p = 0; 2260 2261 while (huffsize.ptr[p]) 2262 { 2263 while (huffsize.ptr[p] == si) 2264 { 2265 huffcode.ptr[p++] = code; 2266 code++; 2267 } 2268 2269 code <<= 1; 2270 si++; 2271 } 2272 2273 memset(pH.look_up.ptr, 0, pH.look_up.sizeof); 2274 memset(pH.look_up2.ptr, 0, pH.look_up2.sizeof); 2275 memset(pH.tree.ptr, 0, pH.tree.sizeof); 2276 memset(pH.code_size.ptr, 0, pH.code_size.sizeof); 2277 2278 nextfreeentry = -1; 2279 2280 p = 0; 2281 2282 while (p < lastp) 2283 { 2284 i = m_huff_val.ptr[index][p]; 2285 code = huffcode.ptr[p]; 2286 code_size = huffsize.ptr[p]; 2287 2288 pH.code_size.ptr[i] = cast(ubyte)(code_size); 2289 2290 if (code_size <= 8) 2291 { 2292 code <<= (8 - code_size); 2293 2294 for (l = 1 << (8 - code_size); l > 0; l--) 2295 { 2296 assert(i < 256); 2297 2298 pH.look_up.ptr[code] = i; 2299 2300 bool has_extrabits = false; 2301 int extra_bits = 0; 2302 int num_extra_bits = i & 15; 2303 2304 int bits_to_fetch = code_size; 2305 if (num_extra_bits) 2306 { 2307 int total_codesize = code_size + num_extra_bits; 2308 if (total_codesize <= 8) 2309 { 2310 has_extrabits = true; 2311 extra_bits = ((1 << num_extra_bits) - 1) & (code >> (8 - total_codesize)); 2312 assert(extra_bits <= 0x7FFF); 2313 bits_to_fetch += num_extra_bits; 2314 } 2315 } 2316 2317 if (!has_extrabits) 2318 pH.look_up2.ptr[code] = i | (bits_to_fetch << 8); 2319 else 2320 pH.look_up2.ptr[code] = i | 0x8000 | (extra_bits << 16) | (bits_to_fetch << 8); 2321 2322 code++; 2323 } 2324 } 2325 else 2326 { 2327 subtree = (code >> (code_size - 8)) & 0xFF; 2328 2329 currententry = pH.look_up.ptr[subtree]; 2330 2331 if (currententry == 0) 2332 { 2333 pH.look_up.ptr[subtree] = currententry = nextfreeentry; 2334 pH.look_up2.ptr[subtree] = currententry = nextfreeentry; 2335 2336 nextfreeentry -= 2; 2337 } 2338 2339 code <<= (16 - (code_size - 8)); 2340 2341 for (l = code_size; l > 9; l--) 2342 { 2343 if ((code & 0x8000) == 0) 2344 currententry--; 2345 2346 if (pH.tree.ptr[-currententry - 1] == 0) 2347 { 2348 pH.tree.ptr[-currententry - 1] = nextfreeentry; 2349 2350 currententry = nextfreeentry; 2351 2352 nextfreeentry -= 2; 2353 } 2354 else 2355 currententry = pH.tree.ptr[-currententry - 1]; 2356 2357 code <<= 1; 2358 } 2359 2360 if ((code & 0x8000) == 0) 2361 currententry--; 2362 2363 pH.tree.ptr[-currententry - 1] = i; 2364 } 2365 2366 p++; 2367 } 2368 } 2369 2370 // Verifies the quantization tables needed for this scan are available. 2371 void check_quant_tables () { 2372 for (int i = 0; i < m_comps_in_scan; i++) 2373 if (m_quant.ptr[m_comp_quant.ptr[m_comp_list.ptr[i]]] == null) 2374 stop_decoding(JPGD_UNDEFINED_QUANT_TABLE); 2375 } 2376 2377 // Verifies that all the Huffman tables needed for this scan are available. 2378 void check_huff_tables () { 2379 for (int i = 0; i < m_comps_in_scan; i++) 2380 { 2381 if ((m_spectral_start == 0) && (m_huff_num.ptr[m_comp_dc_tab.ptr[m_comp_list.ptr[i]]] == null)) 2382 stop_decoding(JPGD_UNDEFINED_HUFF_TABLE); 2383 2384 if ((m_spectral_end > 0) && (m_huff_num.ptr[m_comp_ac_tab.ptr[m_comp_list.ptr[i]]] == null)) 2385 stop_decoding(JPGD_UNDEFINED_HUFF_TABLE); 2386 } 2387 2388 for (int i = 0; i < JPGD_MAX_HUFF_TABLES; i++) 2389 if (m_huff_num.ptr[i]) 2390 { 2391 if (!m_pHuff_tabs.ptr[i]) 2392 m_pHuff_tabs.ptr[i] = cast(huff_tables*)alloc(huff_tables.sizeof); 2393 2394 make_huff_table(i, m_pHuff_tabs.ptr[i]); 2395 } 2396 } 2397 2398 // Determines the component order inside each MCU. 2399 // Also calcs how many MCU's are on each row, etc. 2400 void calc_mcu_block_order () { 2401 int component_num, component_id; 2402 int max_h_samp = 0, max_v_samp = 0; 2403 2404 for (component_id = 0; component_id < m_comps_in_frame; component_id++) 2405 { 2406 if (m_comp_h_samp.ptr[component_id] > max_h_samp) 2407 max_h_samp = m_comp_h_samp.ptr[component_id]; 2408 2409 if (m_comp_v_samp.ptr[component_id] > max_v_samp) 2410 max_v_samp = m_comp_v_samp.ptr[component_id]; 2411 } 2412 2413 for (component_id = 0; component_id < m_comps_in_frame; component_id++) 2414 { 2415 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; 2416 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; 2417 } 2418 2419 if (m_comps_in_scan == 1) 2420 { 2421 m_mcus_per_row = m_comp_h_blocks.ptr[m_comp_list.ptr[0]]; 2422 m_mcus_per_col = m_comp_v_blocks.ptr[m_comp_list.ptr[0]]; 2423 } 2424 else 2425 { 2426 m_mcus_per_row = (((m_image_x_size + 7) / 8) + (max_h_samp - 1)) / max_h_samp; 2427 m_mcus_per_col = (((m_image_y_size + 7) / 8) + (max_v_samp - 1)) / max_v_samp; 2428 } 2429 2430 if (m_comps_in_scan == 1) 2431 { 2432 m_mcu_org.ptr[0] = m_comp_list.ptr[0]; 2433 2434 m_blocks_per_mcu = 1; 2435 } 2436 else 2437 { 2438 m_blocks_per_mcu = 0; 2439 2440 for (component_num = 0; component_num < m_comps_in_scan; component_num++) 2441 { 2442 int num_blocks; 2443 2444 component_id = m_comp_list.ptr[component_num]; 2445 2446 num_blocks = m_comp_h_samp.ptr[component_id] * m_comp_v_samp.ptr[component_id]; 2447 2448 while (num_blocks--) 2449 m_mcu_org.ptr[m_blocks_per_mcu++] = component_id; 2450 } 2451 } 2452 } 2453 2454 // Starts a new scan. 2455 int init_scan () { 2456 if (!locate_sos_marker()) 2457 return false; 2458 2459 calc_mcu_block_order(); 2460 2461 check_huff_tables(); 2462 2463 check_quant_tables(); 2464 2465 memset(m_last_dc_val.ptr, 0, m_comps_in_frame * uint.sizeof); 2466 2467 m_eob_run = 0; 2468 2469 if (m_restart_interval) 2470 { 2471 m_restarts_left = m_restart_interval; 2472 m_next_restart_num = 0; 2473 } 2474 2475 fix_in_buffer(); 2476 2477 return true; 2478 } 2479 2480 // Starts a frame. Determines if the number of components or sampling factors 2481 // are supported. 2482 void init_frame () { 2483 int i; 2484 2485 if (m_comps_in_frame == 1) 2486 { 2487 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]); }} 2488 2489 //if ((m_comp_h_samp.ptr[0] != 1) || (m_comp_v_samp.ptr[0] != 1)) 2490 // stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); 2491 2492 if ((m_comp_h_samp.ptr[0] == 1) && (m_comp_v_samp.ptr[0] == 1)) 2493 { 2494 m_scan_type = JPGD_GRAYSCALE; 2495 m_max_blocks_per_mcu = 1; 2496 m_max_mcu_x_size = 8; 2497 m_max_mcu_y_size = 8; 2498 } 2499 else if ((m_comp_h_samp.ptr[0] == 2) && (m_comp_v_samp.ptr[0] == 2)) 2500 { 2501 //k8: i added this, and i absolutely don't know what it means; but it decoded two sample images i found 2502 m_scan_type = JPGD_GRAYSCALE; 2503 m_max_blocks_per_mcu = 4; 2504 m_max_mcu_x_size = 8; 2505 m_max_mcu_y_size = 8; 2506 } 2507 else 2508 stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); 2509 } 2510 else if (m_comps_in_frame == 3) 2511 { 2512 if ( ((m_comp_h_samp.ptr[1] != 1) || (m_comp_v_samp.ptr[1] != 1)) || 2513 ((m_comp_h_samp.ptr[2] != 1) || (m_comp_v_samp.ptr[2] != 1)) ) 2514 stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); 2515 2516 if ((m_comp_h_samp.ptr[0] == 1) && (m_comp_v_samp.ptr[0] == 1)) 2517 { 2518 m_scan_type = JPGD_YH1V1; 2519 2520 m_max_blocks_per_mcu = 3; 2521 m_max_mcu_x_size = 8; 2522 m_max_mcu_y_size = 8; 2523 } 2524 else if ((m_comp_h_samp.ptr[0] == 2) && (m_comp_v_samp.ptr[0] == 1)) 2525 { 2526 m_scan_type = JPGD_YH2V1; 2527 m_max_blocks_per_mcu = 4; 2528 m_max_mcu_x_size = 16; 2529 m_max_mcu_y_size = 8; 2530 } 2531 else if ((m_comp_h_samp.ptr[0] == 1) && (m_comp_v_samp.ptr[0] == 2)) 2532 { 2533 m_scan_type = JPGD_YH1V2; 2534 m_max_blocks_per_mcu = 4; 2535 m_max_mcu_x_size = 8; 2536 m_max_mcu_y_size = 16; 2537 } 2538 else if ((m_comp_h_samp.ptr[0] == 2) && (m_comp_v_samp.ptr[0] == 2)) 2539 { 2540 m_scan_type = JPGD_YH2V2; 2541 m_max_blocks_per_mcu = 6; 2542 m_max_mcu_x_size = 16; 2543 m_max_mcu_y_size = 16; 2544 } 2545 else 2546 stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); 2547 } 2548 else 2549 stop_decoding(JPGD_UNSUPPORTED_COLORSPACE); 2550 2551 m_max_mcus_per_row = (m_image_x_size + (m_max_mcu_x_size - 1)) / m_max_mcu_x_size; 2552 m_max_mcus_per_col = (m_image_y_size + (m_max_mcu_y_size - 1)) / m_max_mcu_y_size; 2553 2554 // These values are for the *destination* pixels: after conversion. 2555 if (m_scan_type == JPGD_GRAYSCALE) 2556 m_dest_bytes_per_pixel = 1; 2557 else 2558 m_dest_bytes_per_pixel = 4; 2559 2560 m_dest_bytes_per_scan_line = ((m_image_x_size + 15) & 0xFFF0) * m_dest_bytes_per_pixel; 2561 2562 m_real_dest_bytes_per_scan_line = (m_image_x_size * m_dest_bytes_per_pixel); 2563 2564 // Initialize two scan line buffers. 2565 m_pScan_line_0 = cast(ubyte*)alloc(m_dest_bytes_per_scan_line, true); 2566 if ((m_scan_type == JPGD_YH1V2) || (m_scan_type == JPGD_YH2V2)) 2567 m_pScan_line_1 = cast(ubyte*)alloc(m_dest_bytes_per_scan_line, true); 2568 2569 m_max_blocks_per_row = m_max_mcus_per_row * m_max_blocks_per_mcu; 2570 2571 // Should never happen 2572 if (m_max_blocks_per_row > JPGD_MAX_BLOCKS_PER_ROW) 2573 stop_decoding(JPGD_ASSERTION_ERROR); 2574 2575 // Allocate the coefficient buffer, enough for one MCU 2576 m_pMCU_coefficients = cast(jpgd_block_t*)alloc(m_max_blocks_per_mcu * 64 * jpgd_block_t.sizeof); 2577 2578 for (i = 0; i < m_max_blocks_per_mcu; i++) 2579 m_mcu_block_max_zag.ptr[i] = 64; 2580 2581 m_expanded_blocks_per_component = m_comp_h_samp.ptr[0] * m_comp_v_samp.ptr[0]; 2582 m_expanded_blocks_per_mcu = m_expanded_blocks_per_component * m_comps_in_frame; 2583 m_expanded_blocks_per_row = m_max_mcus_per_row * m_expanded_blocks_per_mcu; 2584 // Freq. domain chroma upsampling is only supported for H2V2 subsampling factor (the most common one I've seen). 2585 m_freq_domain_chroma_upsample = false; 2586 version(JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING) { 2587 m_freq_domain_chroma_upsample = (m_expanded_blocks_per_mcu == 4*3); 2588 } 2589 2590 if (m_freq_domain_chroma_upsample) 2591 m_pSample_buf = cast(ubyte*)alloc(m_expanded_blocks_per_row * 64); 2592 else 2593 m_pSample_buf = cast(ubyte*)alloc(m_max_blocks_per_row * 64); 2594 2595 m_total_lines_left = m_image_y_size; 2596 2597 m_mcu_lines_left = 0; 2598 2599 create_look_ups(); 2600 } 2601 2602 // The coeff_buf series of methods originally stored the coefficients 2603 // into a "virtual" file which was located in EMS, XMS, or a disk file. A cache 2604 // was used to make this process more efficient. Now, we can store the entire 2605 // thing in RAM. 2606 coeff_buf* coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y) { 2607 coeff_buf* cb = cast(coeff_buf*)alloc(coeff_buf.sizeof); 2608 2609 cb.block_num_x = block_num_x; 2610 cb.block_num_y = block_num_y; 2611 cb.block_len_x = block_len_x; 2612 cb.block_len_y = block_len_y; 2613 cb.block_size = cast(int)((block_len_x * block_len_y) * jpgd_block_t.sizeof); 2614 cb.pData = cast(ubyte*)alloc(cb.block_size * block_num_x * block_num_y, true); 2615 return cb; 2616 } 2617 2618 jpgd_block_t* coeff_buf_getp (coeff_buf *cb, int block_x, int block_y) { 2619 assert((block_x < cb.block_num_x) && (block_y < cb.block_num_y)); 2620 return cast(jpgd_block_t*)(cb.pData + block_x * cb.block_size + block_y * (cb.block_size * cb.block_num_x)); 2621 } 2622 2623 // The following methods decode the various types of m_blocks encountered 2624 // in progressively encoded images. 2625 static void decode_block_dc_first (ref jpeg_decoder pD, int component_id, int block_x, int block_y) { 2626 int s, r; 2627 jpgd_block_t *p = pD.coeff_buf_getp(pD.m_dc_coeffs.ptr[component_id], block_x, block_y); 2628 2629 if ((s = pD.huff_decode(pD.m_pHuff_tabs.ptr[pD.m_comp_dc_tab.ptr[component_id]])) != 0) 2630 { 2631 r = pD.get_bits_no_markers(s); 2632 s = JPGD_HUFF_EXTEND(r, s); 2633 } 2634 2635 pD.m_last_dc_val.ptr[component_id] = (s += pD.m_last_dc_val.ptr[component_id]); 2636 2637 p[0] = cast(jpgd_block_t)(s << pD.m_successive_low); 2638 } 2639 2640 static void decode_block_dc_refine (ref jpeg_decoder pD, int component_id, int block_x, int block_y) { 2641 if (pD.get_bits_no_markers(1)) 2642 { 2643 jpgd_block_t *p = pD.coeff_buf_getp(pD.m_dc_coeffs.ptr[component_id], block_x, block_y); 2644 2645 p[0] |= (1 << pD.m_successive_low); 2646 } 2647 } 2648 2649 static void decode_block_ac_first (ref jpeg_decoder pD, int component_id, int block_x, int block_y) { 2650 int k, s, r; 2651 2652 if (pD.m_eob_run) 2653 { 2654 pD.m_eob_run--; 2655 return; 2656 } 2657 2658 jpgd_block_t *p = pD.coeff_buf_getp(pD.m_ac_coeffs.ptr[component_id], block_x, block_y); 2659 2660 for (k = pD.m_spectral_start; k <= pD.m_spectral_end; k++) 2661 { 2662 s = pD.huff_decode(pD.m_pHuff_tabs.ptr[pD.m_comp_ac_tab.ptr[component_id]]); 2663 2664 r = s >> 4; 2665 s &= 15; 2666 2667 if (s) 2668 { 2669 if ((k += r) > 63) 2670 pD.stop_decoding(JPGD_DECODE_ERROR); 2671 2672 r = pD.get_bits_no_markers(s); 2673 s = JPGD_HUFF_EXTEND(r, s); 2674 2675 p[g_ZAG[k]] = cast(jpgd_block_t)(s << pD.m_successive_low); 2676 } 2677 else 2678 { 2679 if (r == 15) 2680 { 2681 if ((k += 15) > 63) 2682 pD.stop_decoding(JPGD_DECODE_ERROR); 2683 } 2684 else 2685 { 2686 pD.m_eob_run = 1 << r; 2687 2688 if (r) 2689 pD.m_eob_run += pD.get_bits_no_markers(r); 2690 2691 pD.m_eob_run--; 2692 2693 break; 2694 } 2695 } 2696 } 2697 } 2698 2699 static void decode_block_ac_refine (ref jpeg_decoder pD, int component_id, int block_x, int block_y) { 2700 int s, k, r; 2701 int p1 = 1 << pD.m_successive_low; 2702 int m1 = (-1) << pD.m_successive_low; 2703 jpgd_block_t *p = pD.coeff_buf_getp(pD.m_ac_coeffs.ptr[component_id], block_x, block_y); 2704 2705 assert(pD.m_spectral_end <= 63); 2706 2707 k = pD.m_spectral_start; 2708 2709 if (pD.m_eob_run == 0) 2710 { 2711 for ( ; k <= pD.m_spectral_end; k++) 2712 { 2713 s = pD.huff_decode(pD.m_pHuff_tabs.ptr[pD.m_comp_ac_tab.ptr[component_id]]); 2714 2715 r = s >> 4; 2716 s &= 15; 2717 2718 if (s) 2719 { 2720 if (s != 1) 2721 pD.stop_decoding(JPGD_DECODE_ERROR); 2722 2723 if (pD.get_bits_no_markers(1)) 2724 s = p1; 2725 else 2726 s = m1; 2727 } 2728 else 2729 { 2730 if (r != 15) 2731 { 2732 pD.m_eob_run = 1 << r; 2733 2734 if (r) 2735 pD.m_eob_run += pD.get_bits_no_markers(r); 2736 2737 break; 2738 } 2739 } 2740 2741 do 2742 { 2743 jpgd_block_t *this_coef = p + g_ZAG[k & 63]; 2744 2745 if (*this_coef != 0) 2746 { 2747 if (pD.get_bits_no_markers(1)) 2748 { 2749 if ((*this_coef & p1) == 0) 2750 { 2751 if (*this_coef >= 0) 2752 *this_coef = cast(jpgd_block_t)(*this_coef + p1); 2753 else 2754 *this_coef = cast(jpgd_block_t)(*this_coef + m1); 2755 } 2756 } 2757 } 2758 else 2759 { 2760 if (--r < 0) 2761 break; 2762 } 2763 2764 k++; 2765 2766 } while (k <= pD.m_spectral_end); 2767 2768 if ((s) && (k < 64)) 2769 { 2770 p[g_ZAG[k]] = cast(jpgd_block_t)(s); 2771 } 2772 } 2773 } 2774 2775 if (pD.m_eob_run > 0) 2776 { 2777 for ( ; k <= pD.m_spectral_end; k++) 2778 { 2779 jpgd_block_t *this_coef = p + g_ZAG[k & 63]; // logical AND to shut up static code analysis 2780 2781 if (*this_coef != 0) 2782 { 2783 if (pD.get_bits_no_markers(1)) 2784 { 2785 if ((*this_coef & p1) == 0) 2786 { 2787 if (*this_coef >= 0) 2788 *this_coef = cast(jpgd_block_t)(*this_coef + p1); 2789 else 2790 *this_coef = cast(jpgd_block_t)(*this_coef + m1); 2791 } 2792 } 2793 } 2794 } 2795 2796 pD.m_eob_run--; 2797 } 2798 } 2799 2800 // Decode a scan in a progressively encoded image. 2801 void decode_scan (pDecode_block_func decode_block_func) { 2802 int mcu_row, mcu_col, mcu_block; 2803 int[JPGD_MAX_COMPONENTS] block_x_mcu; 2804 int[JPGD_MAX_COMPONENTS] m_block_y_mcu; 2805 2806 memset(m_block_y_mcu.ptr, 0, m_block_y_mcu.sizeof); 2807 2808 for (mcu_col = 0; mcu_col < m_mcus_per_col; mcu_col++) 2809 { 2810 int component_num, component_id; 2811 2812 memset(block_x_mcu.ptr, 0, block_x_mcu.sizeof); 2813 2814 for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++) 2815 { 2816 int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0; 2817 2818 if ((m_restart_interval) && (m_restarts_left == 0)) 2819 process_restart(); 2820 2821 for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++) 2822 { 2823 component_id = m_mcu_org.ptr[mcu_block]; 2824 2825 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); 2826 2827 if (m_comps_in_scan == 1) 2828 block_x_mcu.ptr[component_id]++; 2829 else 2830 { 2831 if (++block_x_mcu_ofs == m_comp_h_samp.ptr[component_id]) 2832 { 2833 block_x_mcu_ofs = 0; 2834 2835 if (++block_y_mcu_ofs == m_comp_v_samp.ptr[component_id]) 2836 { 2837 block_y_mcu_ofs = 0; 2838 block_x_mcu.ptr[component_id] += m_comp_h_samp.ptr[component_id]; 2839 } 2840 } 2841 } 2842 } 2843 2844 m_restarts_left--; 2845 } 2846 2847 if (m_comps_in_scan == 1) 2848 m_block_y_mcu.ptr[m_comp_list.ptr[0]]++; 2849 else 2850 { 2851 for (component_num = 0; component_num < m_comps_in_scan; component_num++) 2852 { 2853 component_id = m_comp_list.ptr[component_num]; 2854 m_block_y_mcu.ptr[component_id] += m_comp_v_samp.ptr[component_id]; 2855 } 2856 } 2857 } 2858 } 2859 2860 // Decode a progressively encoded image. 2861 void init_progressive () { 2862 int i; 2863 2864 if (m_comps_in_frame == 4) 2865 stop_decoding(JPGD_UNSUPPORTED_COLORSPACE); 2866 2867 // Allocate the coefficient buffers. 2868 for (i = 0; i < m_comps_in_frame; i++) 2869 { 2870 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); 2871 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); 2872 } 2873 2874 for ( ; ; ) 2875 { 2876 int dc_only_scan, refinement_scan; 2877 pDecode_block_func decode_block_func; 2878 2879 if (!init_scan()) 2880 break; 2881 2882 dc_only_scan = (m_spectral_start == 0); 2883 refinement_scan = (m_successive_high != 0); 2884 2885 if ((m_spectral_start > m_spectral_end) || (m_spectral_end > 63)) 2886 stop_decoding(JPGD_BAD_SOS_SPECTRAL); 2887 2888 if (dc_only_scan) 2889 { 2890 if (m_spectral_end) 2891 stop_decoding(JPGD_BAD_SOS_SPECTRAL); 2892 } 2893 else if (m_comps_in_scan != 1) /* AC scans can only contain one component */ 2894 stop_decoding(JPGD_BAD_SOS_SPECTRAL); 2895 2896 if ((refinement_scan) && (m_successive_low != m_successive_high - 1)) 2897 stop_decoding(JPGD_BAD_SOS_SUCCESSIVE); 2898 2899 if (dc_only_scan) 2900 { 2901 if (refinement_scan) 2902 decode_block_func = &decode_block_dc_refine; 2903 else 2904 decode_block_func = &decode_block_dc_first; 2905 } 2906 else 2907 { 2908 if (refinement_scan) 2909 decode_block_func = &decode_block_ac_refine; 2910 else 2911 decode_block_func = &decode_block_ac_first; 2912 } 2913 2914 decode_scan(decode_block_func); 2915 2916 m_bits_left = 16; 2917 get_bits(16); 2918 get_bits(16); 2919 } 2920 2921 m_comps_in_scan = m_comps_in_frame; 2922 2923 for (i = 0; i < m_comps_in_frame; i++) 2924 m_comp_list.ptr[i] = i; 2925 2926 calc_mcu_block_order(); 2927 } 2928 2929 void init_sequential () { 2930 if (!init_scan()) 2931 stop_decoding(JPGD_UNEXPECTED_MARKER); 2932 } 2933 2934 void decode_start () { 2935 init_frame(); 2936 2937 if (m_progressive_flag) 2938 init_progressive(); 2939 else 2940 init_sequential(); 2941 } 2942 2943 void decode_init (JpegStreamReadFunc rfn) { 2944 initit(rfn); 2945 locate_sof_marker(); 2946 } 2947 } 2948 2949 2950 // ////////////////////////////////////////////////////////////////////////// // 2951 /// read JPEG image header, determine dimensions and number of components. 2952 /// return `false` if image is not JPEG (i hope). 2953 public bool detect_jpeg_image_from_stream (scope JpegStreamReadFunc rfn, out int width, out int height, out int actual_comps) { 2954 if (rfn is null) return false; 2955 auto decoder = jpeg_decoder(rfn); 2956 version(jpegd_test) { import core.stdc.stdio : printf; printf("%u bytes read.\n", cast(uint)decoder.total_bytes_read); } 2957 if (decoder.error_code != JPGD_SUCCESS) return false; 2958 width = decoder.width; 2959 height = decoder.height; 2960 actual_comps = decoder.num_components; 2961 return true; 2962 } 2963 2964 2965 // ////////////////////////////////////////////////////////////////////////// // 2966 /// read JPEG image header, determine dimensions and number of components. 2967 /// return `false` if image is not JPEG (i hope). 2968 public bool detect_jpeg_image_from_file (const(char)[] filename, out int width, out int height, out int actual_comps) { 2969 import core.stdc.stdio; 2970 2971 FILE* m_pFile; 2972 bool m_eof_flag, m_error_flag; 2973 2974 if (filename.length == 0) throw new Exception("cannot open unnamed file"); 2975 if (filename.length < 512) { 2976 char[513] buffer; 2977 //import core.stdc.stdlib : alloca; 2978 auto tfn = buffer[0 .. filename.length + 1]; // (cast(char*)alloca(filename.length+1))[0..filename.length+1]; 2979 tfn[0..filename.length] = filename[]; 2980 tfn[filename.length] = 0; 2981 m_pFile = fopen(tfn.ptr, "rb"); 2982 } else { 2983 import core.stdc.stdlib : malloc, free; 2984 auto tfn = (cast(char*)malloc(filename.length+1))[0..filename.length+1]; 2985 if (tfn !is null) { 2986 scope(exit) free(tfn.ptr); 2987 m_pFile = fopen(tfn.ptr, "rb"); 2988 } 2989 } 2990 if (m_pFile is null) throw new Exception("cannot open file '"~filename.idup~"'"); 2991 scope(exit) if (m_pFile) fclose(m_pFile); 2992 2993 return detect_jpeg_image_from_stream( 2994 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 2995 if (m_pFile is null) return -1; 2996 if (m_eof_flag) { 2997 *pEOF_flag = true; 2998 return 0; 2999 } 3000 if (m_error_flag) return -1; 3001 int bytes_read = cast(int)(fread(pBuf, 1, max_bytes_to_read, m_pFile)); 3002 if (bytes_read < max_bytes_to_read) { 3003 if (ferror(m_pFile)) { 3004 m_error_flag = true; 3005 return -1; 3006 } 3007 m_eof_flag = true; 3008 *pEOF_flag = true; 3009 } 3010 return bytes_read; 3011 }, 3012 width, height, actual_comps); 3013 } 3014 3015 3016 // ////////////////////////////////////////////////////////////////////////// // 3017 /// read JPEG image header, determine dimensions and number of components. 3018 /// return `false` if image is not JPEG (i hope). 3019 public bool detect_jpeg_image_from_memory (const(void)[] buf, out int width, out int height, out int actual_comps) { 3020 size_t bufpos; 3021 return detect_jpeg_image_from_stream( 3022 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3023 import core.stdc.string : memcpy; 3024 if (bufpos >= buf.length) { 3025 *pEOF_flag = true; 3026 return 0; 3027 } 3028 if (buf.length-bufpos < max_bytes_to_read) max_bytes_to_read = cast(int)(buf.length-bufpos); 3029 memcpy(pBuf, (cast(const(ubyte)*)buf.ptr)+bufpos, max_bytes_to_read); 3030 bufpos += max_bytes_to_read; 3031 return max_bytes_to_read; 3032 }, 3033 width, height, actual_comps); 3034 } 3035 3036 3037 // ////////////////////////////////////////////////////////////////////////// // 3038 /// decompress JPEG image, what else? 3039 /// 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. 3040 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) { 3041 import core.stdc.string : memcpy; 3042 3043 //actual_comps = 0; 3044 if (rfn is null) return null; 3045 if (req_comps != -1 && req_comps != 1 && req_comps != 3 && req_comps != 4) return null; 3046 3047 auto decoder = jpeg_decoder(rfn); 3048 if (decoder.error_code != JPGD_SUCCESS) return null; 3049 version(jpegd_test) scope(exit) { import core.stdc.stdio : printf; printf("%u bytes read.\n", cast(uint)decoder.total_bytes_read); } 3050 3051 immutable int image_width = decoder.width; 3052 immutable int image_height = decoder.height; 3053 width = image_width; 3054 height = image_height; 3055 actual_comps = decoder.num_components; 3056 if (req_comps < 0) req_comps = decoder.num_components; 3057 3058 if (decoder.begin_decoding() != JPGD_SUCCESS) return null; 3059 3060 immutable int dst_bpl = image_width*req_comps; 3061 3062 static if (useMalloc) { 3063 ubyte* pImage_data = cast(ubyte*)jpgd_malloc(dst_bpl*image_height); 3064 if (pImage_data is null) return null; 3065 auto idata = pImage_data[0..dst_bpl*image_height]; 3066 } else { 3067 auto idata = new ubyte[](dst_bpl*image_height); 3068 auto pImage_data = idata.ptr; 3069 } 3070 3071 scope(failure) { 3072 static if (useMalloc) { 3073 jpgd_free(pImage_data); 3074 } else { 3075 import core.memory : GC; 3076 GC.free(idata.ptr); 3077 idata = null; 3078 } 3079 } 3080 3081 for (int y = 0; y < image_height; ++y) { 3082 const(ubyte)* pScan_line; 3083 uint scan_line_len; 3084 if (decoder.decode(/*(const void**)*/cast(void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS) { 3085 static if (useMalloc) { 3086 jpgd_free(pImage_data); 3087 } else { 3088 import core.memory : GC; 3089 GC.free(idata.ptr); 3090 idata = null; 3091 } 3092 return null; 3093 } 3094 3095 ubyte* pDst = pImage_data+y*dst_bpl; 3096 3097 if ((req_comps == 1 && decoder.num_components == 1) || (req_comps == 4 && decoder.num_components == 3)) { 3098 memcpy(pDst, pScan_line, dst_bpl); 3099 } else if (decoder.num_components == 1) { 3100 if (req_comps == 3) { 3101 for (int x = 0; x < image_width; ++x) { 3102 ubyte luma = pScan_line[x]; 3103 pDst[0] = luma; 3104 pDst[1] = luma; 3105 pDst[2] = luma; 3106 pDst += 3; 3107 } 3108 } else { 3109 for (int x = 0; x < image_width; ++x) { 3110 ubyte luma = pScan_line[x]; 3111 pDst[0] = luma; 3112 pDst[1] = luma; 3113 pDst[2] = luma; 3114 pDst[3] = 255; 3115 pDst += 4; 3116 } 3117 } 3118 } else if (decoder.num_components == 3) { 3119 if (req_comps == 1) { 3120 immutable int YR = 19595, YG = 38470, YB = 7471; 3121 for (int x = 0; x < image_width; ++x) { 3122 int r = pScan_line[x*4+0]; 3123 int g = pScan_line[x*4+1]; 3124 int b = pScan_line[x*4+2]; 3125 *pDst++ = cast(ubyte)((r * YR + g * YG + b * YB + 32768) >> 16); 3126 } 3127 } else { 3128 for (int x = 0; x < image_width; ++x) { 3129 pDst[0] = pScan_line[x*4+0]; 3130 pDst[1] = pScan_line[x*4+1]; 3131 pDst[2] = pScan_line[x*4+2]; 3132 pDst += 3; 3133 } 3134 } 3135 } 3136 } 3137 3138 return idata; 3139 } 3140 3141 3142 // ////////////////////////////////////////////////////////////////////////// // 3143 /// decompress JPEG image from disk file. 3144 /// 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. 3145 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) { 3146 import core.stdc.stdio; 3147 3148 FILE* m_pFile; 3149 bool m_eof_flag, m_error_flag; 3150 3151 if (filename.length == 0) throw new Exception("cannot open unnamed file"); 3152 if (filename.length < 512) { 3153 char[513] buffer; 3154 //import core.stdc.stdlib : alloca; 3155 auto tfn = buffer[0 .. filename.length + 1]; // (cast(char*)alloca(filename.length+1))[0..filename.length+1]; 3156 tfn[0..filename.length] = filename[]; 3157 tfn[filename.length] = 0; 3158 m_pFile = fopen(tfn.ptr, "rb"); 3159 } else { 3160 import core.stdc.stdlib : malloc, free; 3161 auto tfn = (cast(char*)malloc(filename.length+1))[0..filename.length+1]; 3162 if (tfn !is null) { 3163 scope(exit) free(tfn.ptr); 3164 m_pFile = fopen(tfn.ptr, "rb"); 3165 } 3166 } 3167 if (m_pFile is null) throw new Exception("cannot open file '"~filename.idup~"'"); 3168 scope(exit) if (m_pFile) fclose(m_pFile); 3169 3170 return decompress_jpeg_image_from_stream!useMalloc( 3171 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3172 if (m_pFile is null) return -1; 3173 if (m_eof_flag) { 3174 *pEOF_flag = true; 3175 return 0; 3176 } 3177 if (m_error_flag) return -1; 3178 int bytes_read = cast(int)(fread(pBuf, 1, max_bytes_to_read, m_pFile)); 3179 if (bytes_read < max_bytes_to_read) { 3180 if (ferror(m_pFile)) { 3181 m_error_flag = true; 3182 return -1; 3183 } 3184 m_eof_flag = true; 3185 *pEOF_flag = true; 3186 } 3187 return bytes_read; 3188 }, 3189 width, height, actual_comps, req_comps); 3190 } 3191 3192 3193 // ////////////////////////////////////////////////////////////////////////// // 3194 /// decompress JPEG image from memory buffer. 3195 /// 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. 3196 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) { 3197 size_t bufpos; 3198 return decompress_jpeg_image_from_stream!useMalloc( 3199 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3200 import core.stdc.string : memcpy; 3201 if (bufpos >= buf.length) { 3202 *pEOF_flag = true; 3203 return 0; 3204 } 3205 if (buf.length-bufpos < max_bytes_to_read) max_bytes_to_read = cast(int)(buf.length-bufpos); 3206 memcpy(pBuf, (cast(const(ubyte)*)buf.ptr)+bufpos, max_bytes_to_read); 3207 bufpos += max_bytes_to_read; 3208 return max_bytes_to_read; 3209 }, 3210 width, height, actual_comps, req_comps); 3211 } 3212 3213 3214 // ////////////////////////////////////////////////////////////////////////// // 3215 // if we have access "iv.vfs", add some handy API 3216 static if (__traits(compiles, { import iv.vfs; })) enum JpegHasIVVFS = true; else enum JpegHasIVVFS = false; 3217 3218 static if (JpegHasIVVFS) { 3219 import iv.vfs; 3220 3221 // ////////////////////////////////////////////////////////////////////////// // 3222 /// decompress JPEG image from disk file. 3223 /// 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. 3224 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) { 3225 return decompress_jpeg_image_from_stream!useMalloc( 3226 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3227 if (!fl.isOpen) return -1; 3228 if (fl.eof) { 3229 *pEOF_flag = true; 3230 return 0; 3231 } 3232 auto rd = fl.rawRead(pBuf[0..max_bytes_to_read]); 3233 if (fl.eof) *pEOF_flag = true; 3234 return cast(int)rd.length; 3235 }, 3236 width, height, actual_comps, req_comps); 3237 } 3238 // vfs API 3239 } 3240 3241 3242 // ////////////////////////////////////////////////////////////////////////// // 3243 // if we have access "arsd.color", add some handy API 3244 static if (__traits(compiles, { import arsd.color; })) enum JpegHasArsd = true; else enum JpegHasArsd = false; 3245 3246 static if (JpegHasArsd) { 3247 import arsd.color; 3248 3249 // ////////////////////////////////////////////////////////////////////////// // 3250 /// decompress JPEG image, what else? 3251 public MemoryImage readJpegFromStream (scope JpegStreamReadFunc rfn) { 3252 import core.stdc.string : memcpy; 3253 enum req_comps = 4; 3254 3255 if (rfn is null) return null; 3256 3257 auto decoder = jpeg_decoder(rfn); 3258 if (decoder.error_code != JPGD_SUCCESS) return null; 3259 version(jpegd_test) scope(exit) { import core.stdc.stdio : printf; printf("%u bytes read.\n", cast(uint)decoder.total_bytes_read); } 3260 3261 immutable int image_width = decoder.width; 3262 immutable int image_height = decoder.height; 3263 //width = image_width; 3264 //height = image_height; 3265 //actual_comps = decoder.num_components; 3266 3267 version(jpegd_test) {{ import core.stdc.stdio; stderr.fprintf("starting (%dx%d)...\n", image_width, image_height); }} 3268 3269 if (decoder.begin_decoding() != JPGD_SUCCESS || image_width < 1 || image_height < 1) return null; 3270 3271 immutable int dst_bpl = image_width*req_comps; 3272 auto img = new TrueColorImage(image_width, image_height); 3273 scope(failure) { img.clearInternal(); img = null; } 3274 ubyte* pImage_data = img.imageData.bytes.ptr; 3275 3276 for (int y = 0; y < image_height; ++y) { 3277 //version(jpegd_test) {{ import core.stdc.stdio; stderr.fprintf("loading line %d...\n", y); }} 3278 3279 const(ubyte)* pScan_line; 3280 uint scan_line_len; 3281 if (decoder.decode(/*(const void**)*/cast(void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS) { 3282 img.clearInternal(); 3283 img = null; 3284 //jpgd_free(pImage_data); 3285 return null; 3286 } 3287 3288 ubyte* pDst = pImage_data+y*dst_bpl; 3289 3290 if ((req_comps == 1 && decoder.num_components == 1) || (req_comps == 4 && decoder.num_components == 3)) { 3291 memcpy(pDst, pScan_line, dst_bpl); 3292 } else if (decoder.num_components == 1) { 3293 if (req_comps == 3) { 3294 for (int x = 0; x < image_width; ++x) { 3295 ubyte luma = pScan_line[x]; 3296 pDst[0] = luma; 3297 pDst[1] = luma; 3298 pDst[2] = luma; 3299 pDst += 3; 3300 } 3301 } else { 3302 for (int x = 0; x < image_width; ++x) { 3303 ubyte luma = pScan_line[x]; 3304 pDst[0] = luma; 3305 pDst[1] = luma; 3306 pDst[2] = luma; 3307 pDst[3] = 255; 3308 pDst += 4; 3309 } 3310 } 3311 } else if (decoder.num_components == 3) { 3312 if (req_comps == 1) { 3313 immutable int YR = 19595, YG = 38470, YB = 7471; 3314 for (int x = 0; x < image_width; ++x) { 3315 int r = pScan_line[x*4+0]; 3316 int g = pScan_line[x*4+1]; 3317 int b = pScan_line[x*4+2]; 3318 *pDst++ = cast(ubyte)((r * YR + g * YG + b * YB + 32768) >> 16); 3319 } 3320 } else { 3321 for (int x = 0; x < image_width; ++x) { 3322 pDst[0] = pScan_line[x*4+0]; 3323 pDst[1] = pScan_line[x*4+1]; 3324 pDst[2] = pScan_line[x*4+2]; 3325 pDst += 3; 3326 } 3327 } 3328 } 3329 } 3330 3331 return img; 3332 } 3333 3334 3335 // ////////////////////////////////////////////////////////////////////////// // 3336 /// decompress JPEG image from disk file. 3337 public MemoryImage readJpeg (const(char)[] filename) { 3338 import core.stdc.stdio; 3339 3340 FILE* m_pFile; 3341 bool m_eof_flag, m_error_flag; 3342 3343 if (filename.length == 0) throw new Exception("cannot open unnamed file"); 3344 if (filename.length < 512) { 3345 char[513] buffer; 3346 //import core.stdc.stdlib : alloca; 3347 auto tfn = buffer[0 .. filename.length + 1]; // (cast(char*)alloca(filename.length+1))[0..filename.length+1]; 3348 tfn[0..filename.length] = filename[]; 3349 tfn[filename.length] = 0; 3350 m_pFile = fopen(tfn.ptr, "rb"); 3351 } else { 3352 import core.stdc.stdlib : malloc, free; 3353 auto tfn = (cast(char*)malloc(filename.length+1))[0..filename.length+1]; 3354 if (tfn !is null) { 3355 scope(exit) free(tfn.ptr); 3356 m_pFile = fopen(tfn.ptr, "rb"); 3357 } 3358 } 3359 if (m_pFile is null) throw new Exception("cannot open file '"~filename.idup~"'"); 3360 scope(exit) if (m_pFile) fclose(m_pFile); 3361 3362 return readJpegFromStream( 3363 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3364 if (m_pFile is null) return -1; 3365 if (m_eof_flag) { 3366 *pEOF_flag = true; 3367 return 0; 3368 } 3369 if (m_error_flag) return -1; 3370 int bytes_read = cast(int)(fread(pBuf, 1, max_bytes_to_read, m_pFile)); 3371 if (bytes_read < max_bytes_to_read) { 3372 if (ferror(m_pFile)) { 3373 m_error_flag = true; 3374 return -1; 3375 } 3376 m_eof_flag = true; 3377 *pEOF_flag = true; 3378 } 3379 return bytes_read; 3380 } 3381 ); 3382 } 3383 3384 /++ 3385 History: 3386 Added January 22, 2021 (release version 9.2) 3387 +/ 3388 public void writeJpeg(const(char)[] filename, TrueColorImage img, JpegParams params = JpegParams.init) { 3389 if(!compress_image_to_jpeg_file(filename, img.width, img.height, 4, img.imageData.bytes, params)) 3390 throw new Exception("jpeg write failed"); // FIXME: check errno? 3391 } 3392 3393 /++ 3394 Encodes an image as jpeg in memory. 3395 3396 History: 3397 Added January 22, 2021 (release version 9.2) 3398 +/ 3399 public ubyte[] encodeJpeg(TrueColorImage img, JpegParams params = JpegParams.init) { 3400 ubyte[] data; 3401 encodeJpeg((const scope ubyte[] i) { 3402 data ~= i; 3403 return true; 3404 }, img, params); 3405 3406 return data; 3407 } 3408 3409 /// ditto 3410 public void encodeJpeg(scope bool delegate(const scope ubyte[]) dg, TrueColorImage img, JpegParams params = JpegParams.init) { 3411 if(!compress_image_to_jpeg_stream( 3412 dg, 3413 img.width, img.height, 4, img.imageData.bytes, params)) 3414 throw new Exception("encode"); 3415 } 3416 3417 3418 // ////////////////////////////////////////////////////////////////////////// // 3419 /// decompress JPEG image from memory buffer. 3420 public MemoryImage readJpegFromMemory (const(void)[] buf) { 3421 size_t bufpos; 3422 return readJpegFromStream( 3423 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3424 import core.stdc.string : memcpy; 3425 if (bufpos >= buf.length) { 3426 *pEOF_flag = true; 3427 return 0; 3428 } 3429 if (buf.length-bufpos < max_bytes_to_read) max_bytes_to_read = cast(int)(buf.length-bufpos); 3430 memcpy(pBuf, (cast(const(ubyte)*)buf.ptr)+bufpos, max_bytes_to_read); 3431 bufpos += max_bytes_to_read; 3432 return max_bytes_to_read; 3433 } 3434 ); 3435 } 3436 // done with arsd API 3437 } 3438 3439 3440 static if (JpegHasIVVFS) { 3441 public MemoryImage readJpeg (VFile fl) { 3442 return readJpegFromStream( 3443 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3444 if (!fl.isOpen) return -1; 3445 if (fl.eof) { 3446 *pEOF_flag = true; 3447 return 0; 3448 } 3449 auto rd = fl.rawRead(pBuf[0..max_bytes_to_read]); 3450 if (fl.eof) *pEOF_flag = true; 3451 return cast(int)rd.length; 3452 } 3453 ); 3454 } 3455 3456 public bool detectJpeg (VFile fl, out int width, out int height, out int actual_comps) { 3457 return detect_jpeg_image_from_stream( 3458 delegate int (void* pBuf, int max_bytes_to_read, bool *pEOF_flag) { 3459 if (!fl.isOpen) return -1; 3460 if (fl.eof) { 3461 *pEOF_flag = true; 3462 return 0; 3463 } 3464 auto rd = fl.rawRead(pBuf[0..max_bytes_to_read]); 3465 if (fl.eof) *pEOF_flag = true; 3466 return cast(int)rd.length; 3467 }, 3468 width, height, actual_comps); 3469 } 3470 // vfs API 3471 } 3472 3473 3474 // ////////////////////////////////////////////////////////////////////////// // 3475 version(jpegd_test) { 3476 import arsd.color; 3477 import arsd.png; 3478 3479 void main (string[] args) { 3480 import std.stdio; 3481 int width, height, comps; 3482 { 3483 assert(detect_jpeg_image_from_file((args.length > 1 ? args[1] : "image.jpg"), width, height, comps)); 3484 writeln(width, "x", height, "x", comps); 3485 auto img = readJpeg((args.length > 1 ? args[1] : "image.jpg")); 3486 writeln(img.width, "x", img.height); 3487 writePng("z00.png", img); 3488 } 3489 { 3490 ubyte[] file; 3491 { 3492 auto fl = File(args.length > 1 ? args[1] : "image.jpg"); 3493 file.length = cast(int)fl.size; 3494 fl.rawRead(file[]); 3495 } 3496 assert(detect_jpeg_image_from_memory(file[], width, height, comps)); 3497 writeln(width, "x", height, "x", comps); 3498 auto img = readJpegFromMemory(file[]); 3499 writeln(img.width, "x", img.height); 3500 writePng("z01.png", img); 3501 } 3502 } 3503 } 3504 3505 // jpge.cpp - C++ class for JPEG compression. 3506 // Public domain, Rich Geldreich <richgel99@gmail.com> 3507 // Alex Evans: Added RGBA support, linear memory allocator. 3508 // v1.01, Dec. 18, 2010 - Initial release 3509 // v1.02, Apr. 6, 2011 - Removed 2x2 ordered dither in H2V1 chroma subsampling method load_block_16_8_8(). (The rounding factor was 2, when it should have been 1. Either way, it wasn't helping.) 3510 // v1.03, Apr. 16, 2011 - Added support for optimized Huffman code tables, optimized dynamic memory allocation down to only 1 alloc. 3511 // Also from Alex Evans: Added RGBA support, linear memory allocator (no longer needed in v1.03). 3512 // v1.04, May. 19, 2012: Forgot to set m_pFile ptr to null in cfile_stream::close(). Thanks to Owen Kaluza for reporting this bug. 3513 // Code tweaks to fix VS2008 static code analysis warnings (all looked harmless). 3514 // Code review revealed method load_block_16_8_8() (used for the non-default H2V1 sampling mode to downsample chroma) somehow didn't get the rounding factor fix from v1.02. 3515 // D translation by Ketmar // Invisible Vector 3516 // 3517 // This is free and unencumbered software released into the public domain. 3518 // 3519 // Anyone is free to copy, modify, publish, use, compile, sell, or 3520 // distribute this software, either in source code form or as a compiled 3521 // binary, for any purpose, commercial or non-commercial, and by any 3522 // means. 3523 // 3524 // In jurisdictions that recognize copyright laws, the author or authors 3525 // of this software dedicate any and all copyright interest in the 3526 // software to the public domain. We make this dedication for the benefit 3527 // of the public at large and to the detriment of our heirs and 3528 // successors. We intend this dedication to be an overt act of 3529 // relinquishment in perpetuity of all present and future rights to this 3530 // software under copyright law. 3531 // 3532 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 3533 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 3534 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 3535 // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 3536 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 3537 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 3538 // OTHER DEALINGS IN THE SOFTWARE. 3539 // 3540 // For more information, please refer to <http://unlicense.org/> 3541 /** 3542 * Writes a JPEG image to a file or stream. 3543 * num_channels must be 1 (Y), 3 (RGB), 4 (RGBA), image pitch must be width*num_channels. 3544 * note that alpha will not be stored in jpeg file. 3545 */ 3546 3547 public: 3548 // ////////////////////////////////////////////////////////////////////////// // 3549 // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common. 3550 enum JpegSubsampling { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 } 3551 3552 /// JPEG compression parameters structure. 3553 public struct JpegParams { 3554 /// Quality: 1-100, higher is better. Typical values are around 50-95. 3555 int quality = 85; 3556 3557 /// subsampling: 3558 /// 0 = Y (grayscale) only 3559 /// 1 = YCbCr, no subsampling (H1V1, YCbCr 1x1x1, 3 blocks per MCU) 3560 /// 2 = YCbCr, H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU) 3561 /// 3 = YCbCr, H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common) 3562 JpegSubsampling subsampling = JpegSubsampling.H2V2; 3563 3564 /// Disables CbCr discrimination - only intended for testing. 3565 /// If true, the Y quantization table is also used for the CbCr channels. 3566 bool noChromaDiscrimFlag = false; 3567 3568 /// 3569 bool twoPass = true; 3570 3571 /// 3572 bool check () const pure nothrow @safe @nogc { 3573 if (quality < 1 || quality > 100) return false; 3574 if (cast(uint)subsampling > cast(uint)JpegSubsampling.H2V2) return false; 3575 return true; 3576 } 3577 } 3578 3579 3580 // ////////////////////////////////////////////////////////////////////////// // 3581 /// Writes JPEG image to file. 3582 /// num_channels must be 1 (Y), 3 (RGB), 4 (RGBA), image pitch must be width*num_channels. 3583 /// note that alpha will not be stored in jpeg file. 3584 bool compress_image_to_jpeg_stream (scope jpeg_encoder.WriteFunc wfn, int width, int height, int num_channels, const(ubyte)[] pImage_data) { return compress_image_to_jpeg_stream(wfn, width, height, num_channels, pImage_data, JpegParams()); } 3585 3586 /// Writes JPEG image to file. 3587 /// num_channels must be 1 (Y), 3 (RGB), 4 (RGBA), image pitch must be width*num_channels. 3588 /// note that alpha will not be stored in jpeg file. 3589 bool compress_image_to_jpeg_stream (scope jpeg_encoder.WriteFunc wfn, int width, int height, int num_channels, const(ubyte)[] pImage_data, in JpegParams comp_params) { 3590 jpeg_encoder dst_image; 3591 if (!dst_image.setup(wfn, width, height, num_channels, comp_params)) return false; 3592 for (uint pass_index = 0; pass_index < dst_image.total_passes(); pass_index++) { 3593 for (int i = 0; i < height; i++) { 3594 const(ubyte)* pBuf = pImage_data.ptr+i*width*num_channels; 3595 if (!dst_image.process_scanline(pBuf)) return false; 3596 } 3597 if (!dst_image.process_scanline(null)) return false; 3598 } 3599 dst_image.deinit(); 3600 //return dst_stream.close(); 3601 return true; 3602 } 3603 3604 3605 /// Writes JPEG image to file. 3606 /// num_channels must be 1 (Y), 3 (RGB), 4 (RGBA), image pitch must be width*num_channels. 3607 /// note that alpha will not be stored in jpeg file. 3608 bool compress_image_to_jpeg_file (const(char)[] fname, int width, int height, int num_channels, const(ubyte)[] pImage_data) { return compress_image_to_jpeg_file(fname, width, height, num_channels, pImage_data, JpegParams()); } 3609 3610 /// Writes JPEG image to file. 3611 /// num_channels must be 1 (Y), 3 (RGB), 4 (RGBA), image pitch must be width*num_channels. 3612 /// note that alpha will not be stored in jpeg file. 3613 bool compress_image_to_jpeg_file() (const(char)[] fname, int width, int height, int num_channels, const(ubyte)[] pImage_data, in auto ref JpegParams comp_params) { 3614 import std.internal.cstring; 3615 import core.stdc.stdio : FILE, fopen, fclose, fwrite; 3616 FILE* fl = fopen(fname.tempCString, "wb"); 3617 if (fl is null) return false; 3618 scope(exit) if (fl !is null) fclose(fl); 3619 auto res = compress_image_to_jpeg_stream( 3620 delegate bool (scope const(ubyte)[] buf) { 3621 if (fwrite(buf.ptr, 1, buf.length, fl) != buf.length) return false; 3622 return true; 3623 }, width, height, num_channels, pImage_data, comp_params); 3624 if (res) { 3625 if (fclose(fl) != 0) res = false; 3626 fl = null; 3627 } 3628 return res; 3629 } 3630 3631 3632 // ////////////////////////////////////////////////////////////////////////// // 3633 private: 3634 nothrow @trusted @nogc { 3635 auto JPGE_MIN(T) (T a, T b) pure nothrow @safe @nogc { pragma(inline, true); return (a < b ? a : b); } 3636 auto JPGE_MAX(T) (T a, T b) pure nothrow @safe @nogc { pragma(inline, true); return (a > b ? a : b); } 3637 3638 void *jpge_malloc (size_t nSize) { import core.stdc.stdlib : malloc; return malloc(nSize); } 3639 void jpge_free (void *p) { import core.stdc.stdlib : free; if (p !is null) free(p); } 3640 3641 3642 // Various JPEG enums and tables. 3643 enum { DC_LUM_CODES = 12, AC_LUM_CODES = 256, DC_CHROMA_CODES = 12, AC_CHROMA_CODES = 256, MAX_HUFF_SYMBOLS = 257, MAX_HUFF_CODESIZE = 32 } 3644 3645 static immutable ubyte[64] s_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 ]; 3646 static immutable short[64] s_std_lum_quant = [ 16,11,12,14,12,10,16,14,13,14,18,17,16,19,24,40,26,24,22,22,24,49,35,37,29,40,58,51,61,60,57,51,56,55,64,72,92,78,64,68,87,69,55,56,80,109,81,87,95,98,103,104,103,62,77,113,121,112,100,120,92,101,103,99 ]; 3647 static immutable short[64] s_std_croma_quant = [ 17,18,18,24,21,24,47,26,26,47,99,66,56,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99 ]; 3648 static immutable ubyte[17] s_dc_lum_bits = [ 0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0 ]; 3649 static immutable ubyte[DC_LUM_CODES] s_dc_lum_val = [ 0,1,2,3,4,5,6,7,8,9,10,11 ]; 3650 static immutable ubyte[17] s_ac_lum_bits = [ 0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d ]; 3651 static immutable ubyte[AC_LUM_CODES] s_ac_lum_val = [ 3652 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0, 3653 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49, 3654 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, 3655 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5, 3656 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, 3657 0xf9,0xfa 3658 ]; 3659 static immutable ubyte[17] s_dc_chroma_bits = [ 0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0 ]; 3660 static immutable ubyte[DC_CHROMA_CODES] s_dc_chroma_val = [ 0,1,2,3,4,5,6,7,8,9,10,11 ]; 3661 static immutable ubyte[17] s_ac_chroma_bits = [ 0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77 ]; 3662 static immutable ubyte[AC_CHROMA_CODES] s_ac_chroma_val = [ 3663 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0, 3664 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48, 3665 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, 3666 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3, 3667 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, 3668 0xf9,0xfa 3669 ]; 3670 3671 // Low-level helper functions. 3672 //template <class T> inline void clear_obj(T &obj) { memset(&obj, 0, sizeof(obj)); } 3673 3674 enum YR = 19595, YG = 38470, YB = 7471, CB_R = -11059, CB_G = -21709, CB_B = 32768, CR_R = 32768, CR_G = -27439, CR_B = -5329; // int 3675 //ubyte clamp (int i) { if (cast(uint)(i) > 255U) { if (i < 0) i = 0; else if (i > 255) i = 255; } return cast(ubyte)(i); } 3676 ubyte clamp() (int i) { pragma(inline, true); return cast(ubyte)(cast(uint)i > 255 ? (((~i)>>31)&0xFF) : i); } 3677 3678 void RGB_to_YCC (ubyte* pDst, const(ubyte)* pSrc, int num_pixels) { 3679 for (; num_pixels; pDst += 3, pSrc += 3, --num_pixels) { 3680 immutable int r = pSrc[0], g = pSrc[1], b = pSrc[2]; 3681 pDst[0] = cast(ubyte)((r*YR+g*YG+b*YB+32768)>>16); 3682 pDst[1] = clamp(128+((r*CB_R+g*CB_G+b*CB_B+32768)>>16)); 3683 pDst[2] = clamp(128+((r*CR_R+g*CR_G+b*CR_B+32768)>>16)); 3684 } 3685 } 3686 3687 void RGB_to_Y (ubyte* pDst, const(ubyte)* pSrc, int num_pixels) { 3688 for (; num_pixels; ++pDst, pSrc += 3, --num_pixels) { 3689 pDst[0] = cast(ubyte)((pSrc[0]*YR+pSrc[1]*YG+pSrc[2]*YB+32768)>>16); 3690 } 3691 } 3692 3693 void RGBA_to_YCC (ubyte* pDst, const(ubyte)* pSrc, int num_pixels) { 3694 for (; num_pixels; pDst += 3, pSrc += 4, --num_pixels) { 3695 immutable int r = pSrc[0], g = pSrc[1], b = pSrc[2]; 3696 pDst[0] = cast(ubyte)((r*YR+g*YG+b*YB+32768)>>16); 3697 pDst[1] = clamp(128+((r*CB_R+g*CB_G+b*CB_B+32768)>>16)); 3698 pDst[2] = clamp(128+((r*CR_R+g*CR_G+b*CR_B+32768)>>16)); 3699 } 3700 } 3701 3702 void RGBA_to_Y (ubyte* pDst, const(ubyte)* pSrc, int num_pixels) { 3703 for (; num_pixels; ++pDst, pSrc += 4, --num_pixels) { 3704 pDst[0] = cast(ubyte)((pSrc[0]*YR+pSrc[1]*YG+pSrc[2]*YB+32768)>>16); 3705 } 3706 } 3707 3708 void Y_to_YCC (ubyte* pDst, const(ubyte)* pSrc, int num_pixels) { 3709 for (; num_pixels; pDst += 3, ++pSrc, --num_pixels) { pDst[0] = pSrc[0]; pDst[1] = 128; pDst[2] = 128; } 3710 } 3711 3712 // Forward DCT - DCT derived from jfdctint. 3713 enum { ROW_BITS = 2 } 3714 //#define DCT_DESCALE(x, n) (((x)+(((int)1)<<((n)-1)))>>(n)) 3715 int DCT_DESCALE() (int x, int n) { pragma(inline, true); return (((x)+((cast(int)1)<<((n)-1)))>>(n)); } 3716 //#define DCT_MUL(var, c) (cast(short)(var)*cast(int)(c)) 3717 3718 //#define DCT1D(s0, s1, s2, s3, s4, s5, s6, s7) 3719 enum DCT1D = q{{ 3720 int t0 = s0+s7, t7 = s0-s7, t1 = s1+s6, t6 = s1-s6, t2 = s2+s5, t5 = s2-s5, t3 = s3+s4, t4 = s3-s4; 3721 int t10 = t0+t3, t13 = t0-t3, t11 = t1+t2, t12 = t1-t2; 3722 int u1 = (cast(short)(t12+t13)*cast(int)(4433)); 3723 s2 = u1+(cast(short)(t13)*cast(int)(6270)); 3724 s6 = u1+(cast(short)(t12)*cast(int)(-15137)); 3725 u1 = t4+t7; 3726 int u2 = t5+t6, u3 = t4+t6, u4 = t5+t7; 3727 int z5 = (cast(short)(u3+u4)*cast(int)(9633)); 3728 t4 = (cast(short)(t4)*cast(int)(2446)); t5 = (cast(short)(t5)*cast(int)(16819)); 3729 t6 = (cast(short)(t6)*cast(int)(25172)); t7 = (cast(short)(t7)*cast(int)(12299)); 3730 u1 = (cast(short)(u1)*cast(int)(-7373)); u2 = (cast(short)(u2)*cast(int)(-20995)); 3731 u3 = (cast(short)(u3)*cast(int)(-16069)); u4 = (cast(short)(u4)*cast(int)(-3196)); 3732 u3 += z5; u4 += z5; 3733 s0 = t10+t11; s1 = t7+u1+u4; s3 = t6+u2+u3; s4 = t10-t11; s5 = t5+u2+u4; s7 = t4+u1+u3; 3734 }}; 3735 3736 void DCT2D (int* p) { 3737 int c; 3738 int* q = p; 3739 for (c = 7; c >= 0; --c, q += 8) { 3740 int s0 = q[0], s1 = q[1], s2 = q[2], s3 = q[3], s4 = q[4], s5 = q[5], s6 = q[6], s7 = q[7]; 3741 //DCT1D(s0, s1, s2, s3, s4, s5, s6, s7); 3742 mixin(DCT1D); 3743 q[0] = s0<<ROW_BITS; q[1] = DCT_DESCALE(s1, CONST_BITS-ROW_BITS); q[2] = DCT_DESCALE(s2, CONST_BITS-ROW_BITS); q[3] = DCT_DESCALE(s3, CONST_BITS-ROW_BITS); 3744 q[4] = s4<<ROW_BITS; q[5] = DCT_DESCALE(s5, CONST_BITS-ROW_BITS); q[6] = DCT_DESCALE(s6, CONST_BITS-ROW_BITS); q[7] = DCT_DESCALE(s7, CONST_BITS-ROW_BITS); 3745 } 3746 for (q = p, c = 7; c >= 0; --c, ++q) { 3747 int s0 = q[0*8], s1 = q[1*8], s2 = q[2*8], s3 = q[3*8], s4 = q[4*8], s5 = q[5*8], s6 = q[6*8], s7 = q[7*8]; 3748 //DCT1D(s0, s1, s2, s3, s4, s5, s6, s7); 3749 mixin(DCT1D); 3750 q[0*8] = DCT_DESCALE(s0, ROW_BITS+3); q[1*8] = DCT_DESCALE(s1, CONST_BITS+ROW_BITS+3); q[2*8] = DCT_DESCALE(s2, CONST_BITS+ROW_BITS+3); q[3*8] = DCT_DESCALE(s3, CONST_BITS+ROW_BITS+3); 3751 q[4*8] = DCT_DESCALE(s4, ROW_BITS+3); q[5*8] = DCT_DESCALE(s5, CONST_BITS+ROW_BITS+3); q[6*8] = DCT_DESCALE(s6, CONST_BITS+ROW_BITS+3); q[7*8] = DCT_DESCALE(s7, CONST_BITS+ROW_BITS+3); 3752 } 3753 } 3754 3755 struct sym_freq { uint m_key, m_sym_index; } 3756 3757 // Radix sorts sym_freq[] array by 32-bit key m_key. Returns ptr to sorted values. 3758 sym_freq* radix_sort_syms (uint num_syms, sym_freq* pSyms0, sym_freq* pSyms1) { 3759 const uint cMaxPasses = 4; 3760 uint[256*cMaxPasses] hist; 3761 //clear_obj(hist); 3762 for (uint i = 0; i < num_syms; i++) { 3763 uint freq = pSyms0[i].m_key; 3764 ++hist[freq&0xFF]; 3765 ++hist[256+((freq>>8)&0xFF)]; 3766 ++hist[256*2+((freq>>16)&0xFF)]; 3767 ++hist[256*3+((freq>>24)&0xFF)]; 3768 } 3769 sym_freq* pCur_syms = pSyms0; 3770 sym_freq* pNew_syms = pSyms1; 3771 uint total_passes = cMaxPasses; while (total_passes > 1 && num_syms == hist[(total_passes-1)*256]) --total_passes; 3772 uint[256] offsets; 3773 for (uint pass_shift = 0, pass = 0; pass < total_passes; ++pass, pass_shift += 8) { 3774 const(uint)* pHist = &hist[pass<<8]; 3775 uint cur_ofs = 0; 3776 for (uint i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } 3777 for (uint i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key>>pass_shift)&0xFF]++] = pCur_syms[i]; 3778 sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; 3779 } 3780 return pCur_syms; 3781 } 3782 3783 // calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. 3784 void calculate_minimum_redundancy (sym_freq* A, int n) { 3785 int root, leaf, next, avbl, used, dpth; 3786 if (n == 0) return; 3787 if (n == 1) { A[0].m_key = 1; return; } 3788 A[0].m_key += A[1].m_key; root = 0; leaf = 2; 3789 for (next=1; next < n-1; next++) 3790 { 3791 if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = next; } else A[next].m_key = A[leaf++].m_key; 3792 if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key += A[root].m_key; A[root++].m_key = next; } else A[next].m_key += A[leaf++].m_key; 3793 } 3794 A[n-2].m_key = 0; 3795 for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; 3796 avbl = 1; used = dpth = 0; root = n-2; next = n-1; 3797 while (avbl>0) 3798 { 3799 while (root >= 0 && cast(int)A[root].m_key == dpth) { used++; root--; } 3800 while (avbl>used) { A[next--].m_key = dpth; avbl--; } 3801 avbl = 2*used; dpth++; used = 0; 3802 } 3803 } 3804 3805 // Limits canonical Huffman code table's max code size to max_code_size. 3806 void huffman_enforce_max_code_size (int* pNum_codes, int code_list_len, int max_code_size) { 3807 if (code_list_len <= 1) return; 3808 for (int i = max_code_size+1; i <= MAX_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; 3809 uint total = 0; 3810 for (int i = max_code_size; i > 0; i--) total += ((cast(uint)pNum_codes[i])<<(max_code_size-i)); 3811 while (total != (1UL<<max_code_size)) { 3812 pNum_codes[max_code_size]--; 3813 for (int i = max_code_size-1; i > 0; i--) { 3814 if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i+1] += 2; break; } 3815 } 3816 total--; 3817 } 3818 } 3819 } 3820 3821 3822 // ////////////////////////////////////////////////////////////////////////// // 3823 // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions. 3824 struct jpeg_encoder { 3825 public: 3826 alias WriteFunc = bool delegate (scope const(ubyte)[] buf); 3827 3828 nothrow /*@trusted @nogc*/: 3829 private: 3830 alias sample_array_t = int; 3831 3832 WriteFunc m_pStream; 3833 JpegParams m_params; 3834 ubyte m_num_components; 3835 ubyte[3] m_comp_h_samp; 3836 ubyte[3] m_comp_v_samp; 3837 int m_image_x, m_image_y, m_image_bpp, m_image_bpl; 3838 int m_image_x_mcu, m_image_y_mcu; 3839 int m_image_bpl_xlt, m_image_bpl_mcu; 3840 int m_mcus_per_row; 3841 int m_mcu_x, m_mcu_y; 3842 ubyte*[16] m_mcu_lines; 3843 ubyte m_mcu_y_ofs; 3844 sample_array_t[64] m_sample_array; 3845 short[64] m_coefficient_array; 3846 int[64][2] m_quantization_tables; 3847 uint[256][4] m_huff_codes; 3848 ubyte[256][4] m_huff_code_sizes; 3849 ubyte[17][4] m_huff_bits; 3850 ubyte[256][4] m_huff_val; 3851 uint[256][4] m_huff_count; 3852 int[3] m_last_dc_val; 3853 enum JPGE_OUT_BUF_SIZE = 2048; 3854 ubyte[JPGE_OUT_BUF_SIZE] m_out_buf; 3855 ubyte* m_pOut_buf; 3856 uint m_out_buf_left; 3857 uint m_bit_buffer; 3858 uint m_bits_in; 3859 ubyte m_pass_num; 3860 bool m_all_stream_writes_succeeded = true; 3861 3862 private: 3863 // Generates an optimized offman table. 3864 void optimize_huffman_table (int table_num, int table_len) { 3865 sym_freq[MAX_HUFF_SYMBOLS] syms0; 3866 sym_freq[MAX_HUFF_SYMBOLS] syms1; 3867 syms0[0].m_key = 1; syms0[0].m_sym_index = 0; // dummy symbol, assures that no valid code contains all 1's 3868 int num_used_syms = 1; 3869 const uint *pSym_count = &m_huff_count[table_num][0]; 3870 for (int i = 0; i < table_len; i++) { 3871 if (pSym_count[i]) { syms0[num_used_syms].m_key = pSym_count[i]; syms0[num_used_syms++].m_sym_index = i+1; } 3872 } 3873 sym_freq* pSyms = radix_sort_syms(num_used_syms, syms0.ptr, syms1.ptr); 3874 calculate_minimum_redundancy(pSyms, num_used_syms); 3875 3876 // Count the # of symbols of each code size. 3877 int[1+MAX_HUFF_CODESIZE] num_codes; 3878 //clear_obj(num_codes); 3879 for (int i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; 3880 3881 enum JPGE_CODE_SIZE_LIMIT = 16u; // the maximum possible size of a JPEG Huffman code (valid range is [9,16] - 9 vs. 8 because of the dummy symbol) 3882 huffman_enforce_max_code_size(num_codes.ptr, num_used_syms, JPGE_CODE_SIZE_LIMIT); 3883 3884 // Compute m_huff_bits array, which contains the # of symbols per code size. 3885 //clear_obj(m_huff_bits[table_num]); 3886 m_huff_bits[table_num][] = 0; 3887 for (int i = 1; i <= cast(int)JPGE_CODE_SIZE_LIMIT; i++) m_huff_bits[table_num][i] = cast(ubyte)(num_codes[i]); 3888 3889 // Remove the dummy symbol added above, which must be in largest bucket. 3890 for (int i = JPGE_CODE_SIZE_LIMIT; i >= 1; i--) { 3891 if (m_huff_bits[table_num][i]) { m_huff_bits[table_num][i]--; break; } 3892 } 3893 3894 // Compute the m_huff_val array, which contains the symbol indices sorted by code size (smallest to largest). 3895 for (int i = num_used_syms-1; i >= 1; i--) m_huff_val[table_num][num_used_syms-1-i] = cast(ubyte)(pSyms[i].m_sym_index-1); 3896 } 3897 3898 bool put_obj(T) (T v) { 3899 try { 3900 return (m_pStream !is null && m_pStream((&v)[0..1])); 3901 } catch (Exception) {} 3902 return false; 3903 } 3904 3905 bool put_buf() (const(void)* v, uint len) { 3906 try { 3907 return (m_pStream !is null && m_pStream((cast(ubyte*)v)[0..len])); 3908 } catch (Exception) {} 3909 return false; 3910 } 3911 3912 // JPEG marker generation. 3913 void emit_byte (ubyte i) { 3914 m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && put_obj(i); 3915 } 3916 3917 void emit_word(uint i) { 3918 emit_byte(cast(ubyte)(i>>8)); 3919 emit_byte(cast(ubyte)(i&0xFF)); 3920 } 3921 3922 void emit_marker (int marker) { 3923 emit_byte(cast(ubyte)(0xFF)); 3924 emit_byte(cast(ubyte)(marker)); 3925 } 3926 3927 // Emit JFIF marker 3928 void emit_jfif_app0 () { 3929 emit_marker(M_APP0); 3930 emit_word(2+4+1+2+1+2+2+1+1); 3931 emit_byte(0x4A); emit_byte(0x46); emit_byte(0x49); emit_byte(0x46); /* Identifier: ASCII "JFIF" */ 3932 emit_byte(0); 3933 emit_byte(1); /* Major version */ 3934 emit_byte(1); /* Minor version */ 3935 emit_byte(0); /* Density unit */ 3936 emit_word(1); 3937 emit_word(1); 3938 emit_byte(0); /* No thumbnail image */ 3939 emit_byte(0); 3940 } 3941 3942 // Emit quantization tables 3943 void emit_dqt () { 3944 for (int i = 0; i < (m_num_components == 3 ? 2 : 1); i++) { 3945 emit_marker(M_DQT); 3946 emit_word(64+1+2); 3947 emit_byte(cast(ubyte)(i)); 3948 for (int j = 0; j < 64; j++) emit_byte(cast(ubyte)(m_quantization_tables[i][j])); 3949 } 3950 } 3951 3952 // Emit start of frame marker 3953 void emit_sof () { 3954 emit_marker(M_SOF0); /* baseline */ 3955 emit_word(3*m_num_components+2+5+1); 3956 emit_byte(8); /* precision */ 3957 emit_word(m_image_y); 3958 emit_word(m_image_x); 3959 emit_byte(m_num_components); 3960 for (int i = 0; i < m_num_components; i++) { 3961 emit_byte(cast(ubyte)(i+1)); /* component ID */ 3962 emit_byte(cast(ubyte)((m_comp_h_samp[i]<<4)+m_comp_v_samp[i])); /* h and v sampling */ 3963 emit_byte(i > 0); /* quant. table num */ 3964 } 3965 } 3966 3967 // Emit Huffman table. 3968 void emit_dht (ubyte* bits, ubyte* val, int index, bool ac_flag) { 3969 emit_marker(M_DHT); 3970 int length = 0; 3971 for (int i = 1; i <= 16; i++) length += bits[i]; 3972 emit_word(length+2+1+16); 3973 emit_byte(cast(ubyte)(index+(ac_flag<<4))); 3974 for (int i = 1; i <= 16; i++) emit_byte(bits[i]); 3975 for (int i = 0; i < length; i++) emit_byte(val[i]); 3976 } 3977 3978 // Emit all Huffman tables. 3979 void emit_dhts () { 3980 emit_dht(m_huff_bits[0+0].ptr, m_huff_val[0+0].ptr, 0, false); 3981 emit_dht(m_huff_bits[2+0].ptr, m_huff_val[2+0].ptr, 0, true); 3982 if (m_num_components == 3) { 3983 emit_dht(m_huff_bits[0+1].ptr, m_huff_val[0+1].ptr, 1, false); 3984 emit_dht(m_huff_bits[2+1].ptr, m_huff_val[2+1].ptr, 1, true); 3985 } 3986 } 3987 3988 // emit start of scan 3989 void emit_sos () { 3990 emit_marker(M_SOS); 3991 emit_word(2*m_num_components+2+1+3); 3992 emit_byte(m_num_components); 3993 for (int i = 0; i < m_num_components; i++) { 3994 emit_byte(cast(ubyte)(i+1)); 3995 if (i == 0) 3996 emit_byte((0<<4)+0); 3997 else 3998 emit_byte((1<<4)+1); 3999 } 4000 emit_byte(0); /* spectral selection */ 4001 emit_byte(63); 4002 emit_byte(0); 4003 } 4004 4005 // Emit all markers at beginning of image file. 4006 void emit_markers () { 4007 emit_marker(M_SOI); 4008 emit_jfif_app0(); 4009 emit_dqt(); 4010 emit_sof(); 4011 emit_dhts(); 4012 emit_sos(); 4013 } 4014 4015 // Compute the actual canonical Huffman codes/code sizes given the JPEG huff bits and val arrays. 4016 void compute_huffman_table (uint* codes, ubyte* code_sizes, ubyte* bits, ubyte* val) { 4017 import core.stdc.string : memset; 4018 4019 int i, l, last_p, si; 4020 ubyte[257] huff_size; 4021 uint[257] huff_code; 4022 uint code; 4023 4024 int p = 0; 4025 for (l = 1; l <= 16; l++) 4026 for (i = 1; i <= bits[l]; i++) 4027 huff_size[p++] = cast(ubyte)l; 4028 4029 huff_size[p] = 0; last_p = p; // write sentinel 4030 4031 code = 0; si = huff_size[0]; p = 0; 4032 4033 while (huff_size[p]) 4034 { 4035 while (huff_size[p] == si) 4036 huff_code[p++] = code++; 4037 code <<= 1; 4038 si++; 4039 } 4040 4041 memset(codes, 0, codes[0].sizeof*256); 4042 memset(code_sizes, 0, code_sizes[0].sizeof*256); 4043 for (p = 0; p < last_p; p++) 4044 { 4045 codes[val[p]] = huff_code[p]; 4046 code_sizes[val[p]] = huff_size[p]; 4047 } 4048 } 4049 4050 // Quantization table generation. 4051 void compute_quant_table (int* pDst, const(short)* pSrc) { 4052 int q; 4053 if (m_params.quality < 50) 4054 q = 5000/m_params.quality; 4055 else 4056 q = 200-m_params.quality*2; 4057 for (int i = 0; i < 64; i++) { 4058 int j = *pSrc++; j = (j*q+50L)/100L; 4059 *pDst++ = JPGE_MIN(JPGE_MAX(j, 1), 255); 4060 } 4061 } 4062 4063 // Higher-level methods. 4064 void first_pass_init () { 4065 import core.stdc.string : memset; 4066 m_bit_buffer = 0; m_bits_in = 0; 4067 memset(m_last_dc_val.ptr, 0, 3*m_last_dc_val[0].sizeof); 4068 m_mcu_y_ofs = 0; 4069 m_pass_num = 1; 4070 } 4071 4072 bool second_pass_init () { 4073 compute_huffman_table(&m_huff_codes[0+0][0], &m_huff_code_sizes[0+0][0], m_huff_bits[0+0].ptr, m_huff_val[0+0].ptr); 4074 compute_huffman_table(&m_huff_codes[2+0][0], &m_huff_code_sizes[2+0][0], m_huff_bits[2+0].ptr, m_huff_val[2+0].ptr); 4075 if (m_num_components > 1) 4076 { 4077 compute_huffman_table(&m_huff_codes[0+1][0], &m_huff_code_sizes[0+1][0], m_huff_bits[0+1].ptr, m_huff_val[0+1].ptr); 4078 compute_huffman_table(&m_huff_codes[2+1][0], &m_huff_code_sizes[2+1][0], m_huff_bits[2+1].ptr, m_huff_val[2+1].ptr); 4079 } 4080 first_pass_init(); 4081 emit_markers(); 4082 m_pass_num = 2; 4083 return true; 4084 } 4085 4086 bool jpg_open (int p_x_res, int p_y_res, int src_channels) { 4087 m_num_components = 3; 4088 switch (m_params.subsampling) { 4089 case JpegSubsampling.Y_ONLY: 4090 m_num_components = 1; 4091 m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1; 4092 m_mcu_x = 8; m_mcu_y = 8; 4093 break; 4094 case JpegSubsampling.H1V1: 4095 m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1; 4096 m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; 4097 m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; 4098 m_mcu_x = 8; m_mcu_y = 8; 4099 break; 4100 case JpegSubsampling.H2V1: 4101 m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 1; 4102 m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; 4103 m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; 4104 m_mcu_x = 16; m_mcu_y = 8; 4105 break; 4106 case JpegSubsampling.H2V2: 4107 m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 2; 4108 m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; 4109 m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; 4110 m_mcu_x = 16; m_mcu_y = 16; 4111 break; 4112 default: assert(0); 4113 } 4114 4115 m_image_x = p_x_res; m_image_y = p_y_res; 4116 m_image_bpp = src_channels; 4117 m_image_bpl = m_image_x*src_channels; 4118 m_image_x_mcu = (m_image_x+m_mcu_x-1)&(~(m_mcu_x-1)); 4119 m_image_y_mcu = (m_image_y+m_mcu_y-1)&(~(m_mcu_y-1)); 4120 m_image_bpl_xlt = m_image_x*m_num_components; 4121 m_image_bpl_mcu = m_image_x_mcu*m_num_components; 4122 m_mcus_per_row = m_image_x_mcu/m_mcu_x; 4123 4124 if ((m_mcu_lines[0] = cast(ubyte*)(jpge_malloc(m_image_bpl_mcu*m_mcu_y))) is null) return false; 4125 for (int i = 1; i < m_mcu_y; i++) 4126 m_mcu_lines[i] = m_mcu_lines[i-1]+m_image_bpl_mcu; 4127 4128 compute_quant_table(m_quantization_tables[0].ptr, s_std_lum_quant.ptr); 4129 compute_quant_table(m_quantization_tables[1].ptr, (m_params.noChromaDiscrimFlag ? s_std_lum_quant.ptr : s_std_croma_quant.ptr)); 4130 4131 m_out_buf_left = JPGE_OUT_BUF_SIZE; 4132 m_pOut_buf = m_out_buf.ptr; 4133 4134 if (m_params.twoPass) 4135 { 4136 //clear_obj(m_huff_count); 4137 import core.stdc.string : memset; 4138 memset(m_huff_count.ptr, 0, m_huff_count.sizeof); 4139 first_pass_init(); 4140 } 4141 else 4142 { 4143 import core.stdc.string : memcpy; 4144 memcpy(m_huff_bits[0+0].ptr, s_dc_lum_bits.ptr, 17); memcpy(m_huff_val[0+0].ptr, s_dc_lum_val.ptr, DC_LUM_CODES); 4145 memcpy(m_huff_bits[2+0].ptr, s_ac_lum_bits.ptr, 17); memcpy(m_huff_val[2+0].ptr, s_ac_lum_val.ptr, AC_LUM_CODES); 4146 memcpy(m_huff_bits[0+1].ptr, s_dc_chroma_bits.ptr, 17); memcpy(m_huff_val[0+1].ptr, s_dc_chroma_val.ptr, DC_CHROMA_CODES); 4147 memcpy(m_huff_bits[2+1].ptr, s_ac_chroma_bits.ptr, 17); memcpy(m_huff_val[2+1].ptr, s_ac_chroma_val.ptr, AC_CHROMA_CODES); 4148 if (!second_pass_init()) return false; // in effect, skip over the first pass 4149 } 4150 return m_all_stream_writes_succeeded; 4151 } 4152 4153 void load_block_8_8_grey (int x) { 4154 ubyte *pSrc; 4155 sample_array_t *pDst = m_sample_array.ptr; 4156 x <<= 3; 4157 for (int i = 0; i < 8; i++, pDst += 8) 4158 { 4159 pSrc = m_mcu_lines[i]+x; 4160 pDst[0] = pSrc[0]-128; pDst[1] = pSrc[1]-128; pDst[2] = pSrc[2]-128; pDst[3] = pSrc[3]-128; 4161 pDst[4] = pSrc[4]-128; pDst[5] = pSrc[5]-128; pDst[6] = pSrc[6]-128; pDst[7] = pSrc[7]-128; 4162 } 4163 } 4164 4165 void load_block_8_8 (int x, int y, int c) { 4166 ubyte *pSrc; 4167 sample_array_t *pDst = m_sample_array.ptr; 4168 x = (x*(8*3))+c; 4169 y <<= 3; 4170 for (int i = 0; i < 8; i++, pDst += 8) 4171 { 4172 pSrc = m_mcu_lines[y+i]+x; 4173 pDst[0] = pSrc[0*3]-128; pDst[1] = pSrc[1*3]-128; pDst[2] = pSrc[2*3]-128; pDst[3] = pSrc[3*3]-128; 4174 pDst[4] = pSrc[4*3]-128; pDst[5] = pSrc[5*3]-128; pDst[6] = pSrc[6*3]-128; pDst[7] = pSrc[7*3]-128; 4175 } 4176 } 4177 4178 void load_block_16_8 (int x, int c) { 4179 ubyte* pSrc1; 4180 ubyte* pSrc2; 4181 sample_array_t *pDst = m_sample_array.ptr; 4182 x = (x*(16*3))+c; 4183 int a = 0, b = 2; 4184 for (int i = 0; i < 16; i += 2, pDst += 8) 4185 { 4186 pSrc1 = m_mcu_lines[i+0]+x; 4187 pSrc2 = m_mcu_lines[i+1]+x; 4188 pDst[0] = ((pSrc1[ 0*3]+pSrc1[ 1*3]+pSrc2[ 0*3]+pSrc2[ 1*3]+a)>>2)-128; pDst[1] = ((pSrc1[ 2*3]+pSrc1[ 3*3]+pSrc2[ 2*3]+pSrc2[ 3*3]+b)>>2)-128; 4189 pDst[2] = ((pSrc1[ 4*3]+pSrc1[ 5*3]+pSrc2[ 4*3]+pSrc2[ 5*3]+a)>>2)-128; pDst[3] = ((pSrc1[ 6*3]+pSrc1[ 7*3]+pSrc2[ 6*3]+pSrc2[ 7*3]+b)>>2)-128; 4190 pDst[4] = ((pSrc1[ 8*3]+pSrc1[ 9*3]+pSrc2[ 8*3]+pSrc2[ 9*3]+a)>>2)-128; pDst[5] = ((pSrc1[10*3]+pSrc1[11*3]+pSrc2[10*3]+pSrc2[11*3]+b)>>2)-128; 4191 pDst[6] = ((pSrc1[12*3]+pSrc1[13*3]+pSrc2[12*3]+pSrc2[13*3]+a)>>2)-128; pDst[7] = ((pSrc1[14*3]+pSrc1[15*3]+pSrc2[14*3]+pSrc2[15*3]+b)>>2)-128; 4192 int temp = a; a = b; b = temp; 4193 } 4194 } 4195 4196 void load_block_16_8_8 (int x, int c) { 4197 ubyte *pSrc1; 4198 sample_array_t *pDst = m_sample_array.ptr; 4199 x = (x*(16*3))+c; 4200 for (int i = 0; i < 8; i++, pDst += 8) { 4201 pSrc1 = m_mcu_lines[i+0]+x; 4202 pDst[0] = ((pSrc1[ 0*3]+pSrc1[ 1*3])>>1)-128; pDst[1] = ((pSrc1[ 2*3]+pSrc1[ 3*3])>>1)-128; 4203 pDst[2] = ((pSrc1[ 4*3]+pSrc1[ 5*3])>>1)-128; pDst[3] = ((pSrc1[ 6*3]+pSrc1[ 7*3])>>1)-128; 4204 pDst[4] = ((pSrc1[ 8*3]+pSrc1[ 9*3])>>1)-128; pDst[5] = ((pSrc1[10*3]+pSrc1[11*3])>>1)-128; 4205 pDst[6] = ((pSrc1[12*3]+pSrc1[13*3])>>1)-128; pDst[7] = ((pSrc1[14*3]+pSrc1[15*3])>>1)-128; 4206 } 4207 } 4208 4209 void load_quantized_coefficients (int component_num) { 4210 int *q = m_quantization_tables[component_num > 0].ptr; 4211 short *pDst = m_coefficient_array.ptr; 4212 for (int i = 0; i < 64; i++) 4213 { 4214 sample_array_t j = m_sample_array[s_zag[i]]; 4215 if (j < 0) 4216 { 4217 if ((j = -j+(*q>>1)) < *q) 4218 *pDst++ = 0; 4219 else 4220 *pDst++ = cast(short)(-(j/ *q)); 4221 } 4222 else 4223 { 4224 if ((j = j+(*q>>1)) < *q) 4225 *pDst++ = 0; 4226 else 4227 *pDst++ = cast(short)((j/ *q)); 4228 } 4229 q++; 4230 } 4231 } 4232 4233 void flush_output_buffer () { 4234 if (m_out_buf_left != JPGE_OUT_BUF_SIZE) m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && put_buf(m_out_buf.ptr, JPGE_OUT_BUF_SIZE-m_out_buf_left); 4235 m_pOut_buf = m_out_buf.ptr; 4236 m_out_buf_left = JPGE_OUT_BUF_SIZE; 4237 } 4238 4239 void put_bits (uint bits, uint len) { 4240 m_bit_buffer |= (cast(uint)bits<<(24-(m_bits_in += len))); 4241 while (m_bits_in >= 8) { 4242 ubyte c; 4243 //#define JPGE_PUT_BYTE(c) { *m_pOut_buf++ = (c); if (--m_out_buf_left == 0) flush_output_buffer(); } 4244 //JPGE_PUT_BYTE(c = (ubyte)((m_bit_buffer>>16)&0xFF)); 4245 //if (c == 0xFF) JPGE_PUT_BYTE(0); 4246 c = cast(ubyte)((m_bit_buffer>>16)&0xFF); 4247 *m_pOut_buf++ = c; 4248 if (--m_out_buf_left == 0) flush_output_buffer(); 4249 if (c == 0xFF) { 4250 *m_pOut_buf++ = 0; 4251 if (--m_out_buf_left == 0) flush_output_buffer(); 4252 } 4253 m_bit_buffer <<= 8; 4254 m_bits_in -= 8; 4255 } 4256 } 4257 4258 void code_coefficients_pass_one (int component_num) { 4259 if (component_num >= 3) return; // just to shut up static analysis 4260 int i, run_len, nbits, temp1; 4261 short *src = m_coefficient_array.ptr; 4262 uint *dc_count = (component_num ? m_huff_count[0+1].ptr : m_huff_count[0+0].ptr); 4263 uint *ac_count = (component_num ? m_huff_count[2+1].ptr : m_huff_count[2+0].ptr); 4264 4265 temp1 = src[0]-m_last_dc_val[component_num]; 4266 m_last_dc_val[component_num] = src[0]; 4267 if (temp1 < 0) temp1 = -temp1; 4268 4269 nbits = 0; 4270 while (temp1) 4271 { 4272 nbits++; temp1 >>= 1; 4273 } 4274 4275 dc_count[nbits]++; 4276 for (run_len = 0, i = 1; i < 64; i++) 4277 { 4278 if ((temp1 = m_coefficient_array[i]) == 0) 4279 run_len++; 4280 else 4281 { 4282 while (run_len >= 16) 4283 { 4284 ac_count[0xF0]++; 4285 run_len -= 16; 4286 } 4287 if (temp1 < 0) temp1 = -temp1; 4288 nbits = 1; 4289 while (temp1 >>= 1) nbits++; 4290 ac_count[(run_len<<4)+nbits]++; 4291 run_len = 0; 4292 } 4293 } 4294 if (run_len) ac_count[0]++; 4295 } 4296 4297 void code_coefficients_pass_two (int component_num) { 4298 int i, j, run_len, nbits, temp1, temp2; 4299 short *pSrc = m_coefficient_array.ptr; 4300 uint*[2] codes; 4301 ubyte*[2] code_sizes; 4302 4303 if (component_num == 0) 4304 { 4305 codes[0] = m_huff_codes[0+0].ptr; codes[1] = m_huff_codes[2+0].ptr; 4306 code_sizes[0] = m_huff_code_sizes[0+0].ptr; code_sizes[1] = m_huff_code_sizes[2+0].ptr; 4307 } 4308 else 4309 { 4310 codes[0] = m_huff_codes[0+1].ptr; codes[1] = m_huff_codes[2+1].ptr; 4311 code_sizes[0] = m_huff_code_sizes[0+1].ptr; code_sizes[1] = m_huff_code_sizes[2+1].ptr; 4312 } 4313 4314 temp1 = temp2 = pSrc[0]-m_last_dc_val[component_num]; 4315 m_last_dc_val[component_num] = pSrc[0]; 4316 4317 if (temp1 < 0) 4318 { 4319 temp1 = -temp1; temp2--; 4320 } 4321 4322 nbits = 0; 4323 while (temp1) 4324 { 4325 nbits++; temp1 >>= 1; 4326 } 4327 4328 put_bits(codes[0][nbits], code_sizes[0][nbits]); 4329 if (nbits) put_bits(temp2&((1<<nbits)-1), nbits); 4330 4331 for (run_len = 0, i = 1; i < 64; i++) 4332 { 4333 if ((temp1 = m_coefficient_array[i]) == 0) 4334 run_len++; 4335 else 4336 { 4337 while (run_len >= 16) 4338 { 4339 put_bits(codes[1][0xF0], code_sizes[1][0xF0]); 4340 run_len -= 16; 4341 } 4342 if ((temp2 = temp1) < 0) 4343 { 4344 temp1 = -temp1; 4345 temp2--; 4346 } 4347 nbits = 1; 4348 while (temp1 >>= 1) 4349 nbits++; 4350 j = (run_len<<4)+nbits; 4351 put_bits(codes[1][j], code_sizes[1][j]); 4352 put_bits(temp2&((1<<nbits)-1), nbits); 4353 run_len = 0; 4354 } 4355 } 4356 if (run_len) 4357 put_bits(codes[1][0], code_sizes[1][0]); 4358 } 4359 4360 void code_block (int component_num) { 4361 DCT2D(m_sample_array.ptr); 4362 load_quantized_coefficients(component_num); 4363 if (m_pass_num == 1) 4364 code_coefficients_pass_one(component_num); 4365 else 4366 code_coefficients_pass_two(component_num); 4367 } 4368 4369 void process_mcu_row () { 4370 if (m_num_components == 1) 4371 { 4372 for (int i = 0; i < m_mcus_per_row; i++) 4373 { 4374 load_block_8_8_grey(i); code_block(0); 4375 } 4376 } 4377 else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1)) 4378 { 4379 for (int i = 0; i < m_mcus_per_row; i++) 4380 { 4381 load_block_8_8(i, 0, 0); code_block(0); load_block_8_8(i, 0, 1); code_block(1); load_block_8_8(i, 0, 2); code_block(2); 4382 } 4383 } 4384 else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1)) 4385 { 4386 for (int i = 0; i < m_mcus_per_row; i++) 4387 { 4388 load_block_8_8(i*2+0, 0, 0); code_block(0); load_block_8_8(i*2+1, 0, 0); code_block(0); 4389 load_block_16_8_8(i, 1); code_block(1); load_block_16_8_8(i, 2); code_block(2); 4390 } 4391 } 4392 else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2)) 4393 { 4394 for (int i = 0; i < m_mcus_per_row; i++) 4395 { 4396 load_block_8_8(i*2+0, 0, 0); code_block(0); load_block_8_8(i*2+1, 0, 0); code_block(0); 4397 load_block_8_8(i*2+0, 1, 0); code_block(0); load_block_8_8(i*2+1, 1, 0); code_block(0); 4398 load_block_16_8(i, 1); code_block(1); load_block_16_8(i, 2); code_block(2); 4399 } 4400 } 4401 } 4402 4403 bool terminate_pass_one () { 4404 optimize_huffman_table(0+0, DC_LUM_CODES); optimize_huffman_table(2+0, AC_LUM_CODES); 4405 if (m_num_components > 1) 4406 { 4407 optimize_huffman_table(0+1, DC_CHROMA_CODES); optimize_huffman_table(2+1, AC_CHROMA_CODES); 4408 } 4409 return second_pass_init(); 4410 } 4411 4412 bool terminate_pass_two () { 4413 put_bits(0x7F, 7); 4414 flush_output_buffer(); 4415 emit_marker(M_EOI); 4416 m_pass_num++; // purposely bump up m_pass_num, for debugging 4417 return true; 4418 } 4419 4420 bool process_end_of_image () { 4421 if (m_mcu_y_ofs) 4422 { 4423 if (m_mcu_y_ofs < 16) // check here just to shut up static analysis 4424 { 4425 for (int i = m_mcu_y_ofs; i < m_mcu_y; i++) { 4426 import core.stdc.string : memcpy; 4427 memcpy(m_mcu_lines[i], m_mcu_lines[m_mcu_y_ofs-1], m_image_bpl_mcu); 4428 } 4429 } 4430 process_mcu_row(); 4431 } 4432 4433 if (m_pass_num == 1) 4434 return terminate_pass_one(); 4435 else 4436 return terminate_pass_two(); 4437 } 4438 4439 void load_mcu (const(void)* pSrc) { 4440 import core.stdc.string : memcpy; 4441 const(ubyte)* Psrc = cast(const(ubyte)*)(pSrc); 4442 4443 ubyte* pDst = m_mcu_lines[m_mcu_y_ofs]; // OK to write up to m_image_bpl_xlt bytes to pDst 4444 4445 if (m_num_components == 1) 4446 { 4447 if (m_image_bpp == 4) 4448 RGBA_to_Y(pDst, Psrc, m_image_x); 4449 else if (m_image_bpp == 3) 4450 RGB_to_Y(pDst, Psrc, m_image_x); 4451 else 4452 memcpy(pDst, Psrc, m_image_x); 4453 } 4454 else 4455 { 4456 if (m_image_bpp == 4) 4457 RGBA_to_YCC(pDst, Psrc, m_image_x); 4458 else if (m_image_bpp == 3) 4459 RGB_to_YCC(pDst, Psrc, m_image_x); 4460 else 4461 Y_to_YCC(pDst, Psrc, m_image_x); 4462 } 4463 4464 // Possibly duplicate pixels at end of scanline if not a multiple of 8 or 16 4465 if (m_num_components == 1) { 4466 import core.stdc.string : memset; 4467 memset(m_mcu_lines[m_mcu_y_ofs]+m_image_bpl_xlt, pDst[m_image_bpl_xlt-1], m_image_x_mcu-m_image_x); 4468 } else 4469 { 4470 const ubyte y = pDst[m_image_bpl_xlt-3+0], cb = pDst[m_image_bpl_xlt-3+1], cr = pDst[m_image_bpl_xlt-3+2]; 4471 ubyte *q = m_mcu_lines[m_mcu_y_ofs]+m_image_bpl_xlt; 4472 for (int i = m_image_x; i < m_image_x_mcu; i++) 4473 { 4474 *q++ = y; *q++ = cb; *q++ = cr; 4475 } 4476 } 4477 4478 if (++m_mcu_y_ofs == m_mcu_y) 4479 { 4480 process_mcu_row(); 4481 m_mcu_y_ofs = 0; 4482 } 4483 } 4484 4485 void clear() { 4486 m_mcu_lines[0] = null; 4487 m_pass_num = 0; 4488 m_all_stream_writes_succeeded = true; 4489 } 4490 4491 4492 public: 4493 //this () { clear(); } 4494 ~this () { deinit(); } 4495 4496 @disable this (this); // no copies 4497 4498 // Initializes the compressor. 4499 // pStream: The stream object to use for writing compressed data. 4500 // comp_params - Compression parameters structure, defined above. 4501 // width, height - Image dimensions. 4502 // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data. 4503 // Returns false on out of memory or if a stream write fails. 4504 bool setup() (WriteFunc pStream, int width, int height, int src_channels, in auto ref JpegParams comp_params) { 4505 deinit(); 4506 if ((pStream is null || width < 1 || height < 1) || (src_channels != 1 && src_channels != 3 && src_channels != 4) || !comp_params.check()) return false; 4507 m_pStream = pStream; 4508 m_params = comp_params; 4509 return jpg_open(width, height, src_channels); 4510 } 4511 4512 bool setup() (WriteFunc pStream, int width, int height, int src_channels) { return setup(pStream, width, height, src_channels, JpegParams()); } 4513 4514 @property ref inout(JpegParams) params () return inout pure nothrow @safe @nogc { pragma(inline, true); return m_params; } 4515 4516 // Deinitializes the compressor, freeing any allocated memory. May be called at any time. 4517 void deinit () { 4518 jpge_free(m_mcu_lines[0]); 4519 clear(); 4520 } 4521 4522 @property uint total_passes () const pure nothrow @safe @nogc { pragma(inline, true); return (m_params.twoPass ? 2 : 1); } 4523 @property uint cur_pass () const pure nothrow @safe @nogc { pragma(inline, true); return m_pass_num; } 4524 4525 // Call this method with each source scanline. 4526 // width*src_channels bytes per scanline is expected (RGB or Y format). 4527 // You must call with null after all scanlines are processed to finish compression. 4528 // Returns false on out of memory or if a stream write fails. 4529 bool process_scanline (const(void)* pScanline) { 4530 if (m_pass_num < 1 || m_pass_num > 2) return false; 4531 if (m_all_stream_writes_succeeded) { 4532 if (pScanline is null) { 4533 if (!process_end_of_image()) return false; 4534 } else { 4535 load_mcu(pScanline); 4536 } 4537 } 4538 return m_all_stream_writes_succeeded; 4539 } 4540 }