Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of RA8875 by
GraphicsDisplayJPEG.cpp
00001 /*----------------------------------------------------------------------------/ 00002 / TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012 00003 /-----------------------------------------------------------------------------/ 00004 / The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. 00005 / This is a free software that opened for education, research and commercial 00006 / developments under license policy of following terms. 00007 / 00008 / Copyright (C) 2012, ChaN, all right reserved. 00009 / 00010 / * The TJpgDec module is a free software and there is NO WARRANTY. 00011 / * No restriction on use. You can use, modify and redistribute it for 00012 / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. 00013 / * Redistributions of source code must retain the above copyright notice. 00014 / 00015 /-----------------------------------------------------------------------------/ 00016 / Oct 04,'11 R0.01 First release. 00017 / Feb 19,'12 R0.01a Fixed decompression fails when scan starts with an escape seq. 00018 / Sep 03,'12 R0.01b Added JD_TBLCLIP option. 00019 /----------------------------------------------------------------------------*/ 00020 00021 #include "mbed.h" 00022 00023 #include "GraphicsDisplay.h" 00024 00025 //#define DEBUG "JPEG" 00026 // ... 00027 // INFO("Stuff to show %d", var); // new-line is automatically appended 00028 // 00029 #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) 00030 #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00031 #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00032 #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00033 static void HexDump(const char * title, const uint8_t * p, int count) 00034 { 00035 int i; 00036 char buf[100] = "0000: "; 00037 00038 if (*title) 00039 INFO("%s @%p", title, p); 00040 for (i=0; i<count; ) { 00041 sprintf(buf + strlen(buf), "%02X ", *(p+i)); 00042 if ((++i & 0x0F) == 0x00) { 00043 INFO("%s", buf); 00044 if (i < count) 00045 sprintf(buf, "%04X: ", i); 00046 else 00047 buf[0] = '\0'; 00048 } 00049 } 00050 if (strlen(buf)) 00051 INFO("%s", buf); 00052 } 00053 #else 00054 #define INFO(x, ...) 00055 #define WARN(x, ...) 00056 #define ERR(x, ...) 00057 #define HexDump(a, b, c) 00058 #endif 00059 00060 00061 /*-----------------------------------------------*/ 00062 /* Zigzag-order to raster-order conversion table */ 00063 /*-----------------------------------------------*/ 00064 00065 #define ZIG(n) Zig[n] 00066 00067 static 00068 const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */ 00069 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 00070 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 00071 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 00072 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 00073 }; 00074 00075 00076 00077 /*-------------------------------------------------*/ 00078 /* Input scale factor of Arai algorithm */ 00079 /* (scaled up 16 bits for fixed point operations) */ 00080 /*-------------------------------------------------*/ 00081 00082 #define IPSF(n) Ipsf[n] 00083 00084 static 00085 const uint16_t Ipsf[64] = { /* See also aa_idct.png */ 00086 (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), 00087 (uint16_t)(1.38704*8192), (uint16_t)(1.92388*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.08979*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.38268*8192), 00088 (uint16_t)(1.30656*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.70711*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.36048*8192), 00089 (uint16_t)(1.17588*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.38268*8192), (uint16_t)(1.17588*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.32442*8192), 00090 (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), 00091 (uint16_t)(0.78570*8192), (uint16_t)(1.08979*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.61732*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.21677*8192), 00092 (uint16_t)(0.54120*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.29290*8192), (uint16_t)(0.14932*8192), 00093 (uint16_t)(0.27590*8192), (uint16_t)(0.38268*8192), (uint16_t)(0.36048*8192), (uint16_t)(0.32442*8192), (uint16_t)(0.27590*8192), (uint16_t)(0.21678*8192), (uint16_t)(0.14932*8192), (uint16_t)(0.07612*8192) 00094 }; 00095 00096 00097 00098 /*---------------------------------------------*/ 00099 /* Conversion table for fast clipping process */ 00100 /*---------------------------------------------*/ 00101 00102 #if JD_TBLCLIP 00103 00104 #define BYTECLIP(v) Clip8[(uint16_t)(v) & 0x3FF] 00105 00106 static 00107 const uint8_t Clip8[1024] = { 00108 /* 0..255 */ 00109 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 00110 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 00111 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 00112 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 00113 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 00114 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 00115 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 00116 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 00117 /* 256..511 */ 00118 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 00119 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 00120 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 00121 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 00122 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 00123 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 00124 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 00125 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 00126 /* -512..-257 */ 00127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00135 /* -256..-1 */ 00136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00144 }; 00145 00146 #else /* JD_TBLCLIP */ 00147 00148 inline 00149 uint8_t BYTECLIP ( 00150 int16_t val 00151 ) 00152 { 00153 if (val < 0) val = 0; 00154 if (val > 255) val = 255; 00155 00156 return (uint8_t)val; 00157 } 00158 00159 #endif 00160 00161 00162 00163 /*-----------------------------------------------------------------------*/ 00164 /* Allocate a memory block from memory pool */ 00165 /*-----------------------------------------------------------------------*/ 00166 00167 static 00168 void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ 00169 JDEC * jd, /* Pointer to the decompressor object */ 00170 uint16_t nd /* Number of bytes to allocate */ 00171 ) 00172 { 00173 char *rp = 0; 00174 00175 INFO("alloc_pool(%p,%d) %p:%d", jd, nd, jd->pool, jd->sz_pool); 00176 nd = (nd + 3) & ~3; /* Align block size to the word boundary */ 00177 00178 if (jd->sz_pool >= nd) { 00179 jd->sz_pool -= nd; 00180 rp = (char*)jd->pool; /* Get start of available memory pool */ 00181 jd->pool = (void*)(rp + nd); /* Allocate requierd bytes */ 00182 //INFO("jd->pool %p", jd->pool); 00183 } 00184 INFO("rp %p", rp); 00185 return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */ 00186 } 00187 00188 00189 00190 00191 /*-----------------------------------------------------------------------*/ 00192 /* Create de-quantization and prescaling tables with a DQT segment */ 00193 /*-----------------------------------------------------------------------*/ 00194 00195 static 00196 uint16_t create_qt_tbl ( /* 0:OK, !0:Failed */ 00197 JDEC * jd, /* Pointer to the decompressor object */ 00198 const uint8_t * data, /* Pointer to the quantizer tables */ 00199 uint16_t ndata /* Size of input data */ 00200 ) 00201 { 00202 uint16_t i; 00203 uint8_t d, z; 00204 int32_t *pb; 00205 00206 INFO("create qt table (%p,%p,%d)", jd, data, ndata); 00207 HexDump("JDEC", (uint8_t *)jd, sizeof(JDEC)); 00208 while (ndata) { /* Process all tables in the segment */ 00209 if (ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */ 00210 ndata -= 65; 00211 d = *data++; /* Get table property */ 00212 if (d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */ 00213 i = d & 3; /* Get table ID */ 00214 pb = (int32_t *)alloc_pool(jd, 64 * sizeof (int32_t));/* Allocate a memory block for the table */ 00215 if (!pb) return JDR_MEM1; /* Err: not enough memory */ 00216 jd->qttbl[i] = pb; /* Register the table */ 00217 for (i = 0; i < 64; i++) { /* Load the table */ 00218 z = ZIG(i); /* Zigzag-order to raster-order conversion */ 00219 pb[z] = (int32_t)((uint32_t)*data++ * IPSF(z)); /* Apply scale factor of Arai algorithm to the de-quantizers */ 00220 } 00221 } 00222 00223 return JDR_OK; 00224 } 00225 00226 00227 00228 00229 /*-----------------------------------------------------------------------*/ 00230 /* Create huffman code tables with a DHT segment */ 00231 /*-----------------------------------------------------------------------*/ 00232 00233 static 00234 uint16_t create_huffman_tbl ( /* 0:OK, !0:Failed */ 00235 JDEC * jd, /* Pointer to the decompressor object */ 00236 const uint8_t * data, /* Pointer to the packed huffman tables */ 00237 uint16_t ndata /* Size of input data */ 00238 ) 00239 { 00240 uint16_t i, j, b, np, cls, num; 00241 uint8_t d, *pb, *pd; 00242 uint16_t hc, *ph; 00243 00244 INFO("create_huffman_tbl(%p,%p,%d)", jd, data, ndata); 00245 HexDump("JDEC - create_huffman_tbl entry", (uint8_t *)jd, sizeof(JDEC)); 00246 while (ndata) { /* Process all tables in the segment */ 00247 if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */ 00248 ndata -= 17; 00249 d = *data++; /* Get table number and class */ 00250 cls = (d >> 4); num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ 00251 if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ 00252 pb = (uint8_t *)alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */ 00253 if (!pb) { 00254 ERR("JDR_MEM1"); 00255 return JDR_MEM1; /* Err: not enough memory */ 00256 } 00257 jd->huffbits[num][cls] = pb; 00258 for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ 00259 pb[i] = b = *data++; 00260 np += b; /* Get sum of code words for each code */ 00261 } 00262 00263 ph = (uint16_t *)alloc_pool(jd, np * sizeof (uint16_t));/* Allocate a memory block for the code word table */ 00264 if (!ph) { 00265 ERR("JDR_MEM1"); 00266 return JDR_MEM1; /* Err: not enough memory */ 00267 } 00268 //INFO("jd->pool: %p", jd->pool); 00269 jd->huffcode[num][cls] = ph; 00270 //INFO("jd->pool: %p, %p", jd->pool, ph); 00271 hc = 0; 00272 for (j = i = 0; i < 16; i++) { /* Re-build huffman code word table */ 00273 b = pb[i]; 00274 while (b--) ph[j++] = hc++; 00275 hc <<= 1; 00276 INFO("jd->pool: %d: %p, %p", i, jd->pool, ph); 00277 } 00278 //INFO("jd->pool: %p", jd->pool); 00279 00280 if (ndata < np) return JDR_FMT1; /* Err: wrong data size */ 00281 ndata -= np; 00282 //INFO("jd->pool: %p", jd->pool); 00283 pd = (uint8_t *)alloc_pool(jd, np); /* Allocate a memory block for the decoded data */ 00284 //INFO("jd->pool: %p", jd->pool); 00285 if (!pd) { 00286 ERR("JDR_MEM1"); 00287 return JDR_MEM1; /* Err: not enough memory */ 00288 } 00289 jd->huffdata[num][cls] = pd; 00290 for (i = 0; i < np; i++) { /* Load decoded data corresponds to each code ward */ 00291 d = *data++; 00292 if (!cls && d > 11) return JDR_FMT1; 00293 *pd++ = d; 00294 } 00295 } 00296 00297 HexDump("JDEC - create_huffman_tbl exit", (uint8_t *)jd, sizeof(JDEC)); 00298 return JDR_OK; 00299 } 00300 00301 00302 00303 00304 /*-----------------------------------------------------------------------*/ 00305 /* Extract N bits from input stream */ 00306 /*-----------------------------------------------------------------------*/ 00307 00308 int16_t GraphicsDisplay::bitext ( /* >=0: extracted data, <0: error code */ 00309 JDEC * jd, /* Pointer to the decompressor object */ 00310 uint16_t nbit /* Number of bits to extract (1 to 11) */ 00311 ) 00312 { 00313 uint8_t msk, s, *dp; 00314 uint16_t dc, v, f; 00315 00316 00317 msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ 00318 s = *dp; v = f = 0; 00319 do { 00320 if (!msk) { /* Next byte? */ 00321 if (!dc) { /* No input data is available, re-fill input buffer */ 00322 dp = jd->inbuf; /* Top of input buffer */ 00323 dc = getJpegData(jd, dp, JD_SZBUF); 00324 if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */ 00325 } else { 00326 dp++; /* Next data ptr */ 00327 } 00328 dc--; /* Decrement number of available bytes */ 00329 if (f) { /* In flag sequence? */ 00330 f = 0; /* Exit flag sequence */ 00331 if (*dp != 0) return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ 00332 *dp = s = 0xFF; /* The flag is a data 0xFF */ 00333 } else { 00334 s = *dp; /* Get next data byte */ 00335 if (s == 0xFF) { /* Is start of flag sequence? */ 00336 f = 1; continue; /* Enter flag sequence */ 00337 } 00338 } 00339 msk = 0x80; /* Read from MSB */ 00340 } 00341 v <<= 1; /* Get a bit */ 00342 if (s & msk) v++; 00343 msk >>= 1; 00344 nbit--; 00345 } while (nbit); 00346 jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp; 00347 00348 return (int16_t)v; 00349 } 00350 00351 00352 00353 00354 /*-----------------------------------------------------------------------*/ 00355 /* Extract a huffman decoded data from input stream */ 00356 /*-----------------------------------------------------------------------*/ 00357 00358 int16_t GraphicsDisplay::huffext ( /* >=0: decoded data, <0: error code */ 00359 JDEC * jd, /* Pointer to the decompressor object */ 00360 const uint8_t * hbits, /* Pointer to the bit distribution table */ 00361 const uint16_t * hcode, /* Pointer to the code word table */ 00362 const uint8_t * hdata /* Pointer to the data table */ 00363 ) 00364 { 00365 uint8_t msk, s, *dp; 00366 uint16_t dc, v, f, bl, nd; 00367 00368 00369 msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ 00370 s = *dp; v = f = 0; 00371 bl = 16; /* Max code length */ 00372 do { 00373 if (!msk) { /* Next byte? */ 00374 if (!dc) { /* No input data is available, re-fill input buffer */ 00375 dp = jd->inbuf; /* Top of input buffer */ 00376 dc = getJpegData(jd, dp, JD_SZBUF); 00377 if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */ 00378 } else { 00379 dp++; /* Next data ptr */ 00380 } 00381 dc--; /* Decrement number of available bytes */ 00382 if (f) { /* In flag sequence? */ 00383 f = 0; /* Exit flag sequence */ 00384 if (*dp != 0) 00385 return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ 00386 *dp = s = 0xFF; /* The flag is a data 0xFF */ 00387 } else { 00388 s = *dp; /* Get next data byte */ 00389 if (s == 0xFF) { /* Is start of flag sequence? */ 00390 f = 1; continue; /* Enter flag sequence, get trailing byte */ 00391 } 00392 } 00393 msk = 0x80; /* Read from MSB */ 00394 } 00395 v <<= 1; /* Get a bit */ 00396 if (s & msk) v++; 00397 msk >>= 1; 00398 00399 for (nd = *hbits++; nd; nd--) { /* Search the code word in this bit length */ 00400 if (v == *hcode++) { /* Matched? */ 00401 jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp; 00402 return *hdata; /* Return the decoded data */ 00403 } 00404 hdata++; 00405 } 00406 bl--; 00407 } while (bl); 00408 00409 return 0 - (int16_t)JDR_FMT1; /* Err: code not found (may be collapted data) */ 00410 } 00411 00412 00413 00414 00415 /*-----------------------------------------------------------------------*/ 00416 /* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ 00417 /*-----------------------------------------------------------------------*/ 00418 00419 static 00420 void block_idct ( 00421 int32_t * src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ 00422 uint8_t * dst /* Pointer to the destination to store the block as byte array */ 00423 ) 00424 { 00425 const int32_t M13 = (int32_t)(1.41421*4096), M2 = (int32_t)(1.08239*4096), M4 = (int32_t)(2.61313*4096), M5 = (int32_t)(1.84776*4096); 00426 int32_t v0, v1, v2, v3, v4, v5, v6, v7; 00427 int32_t t10, t11, t12, t13; 00428 uint16_t i; 00429 00430 /* Process columns */ 00431 for (i = 0; i < 8; i++) { 00432 v0 = src[8 * 0]; /* Get even elements */ 00433 v1 = src[8 * 2]; 00434 v2 = src[8 * 4]; 00435 v3 = src[8 * 6]; 00436 00437 t10 = v0 + v2; /* Process the even elements */ 00438 t12 = v0 - v2; 00439 t11 = (v1 - v3) * M13 >> 12; 00440 v3 += v1; 00441 t11 -= v3; 00442 v0 = t10 + v3; 00443 v3 = t10 - v3; 00444 v1 = t11 + t12; 00445 v2 = t12 - t11; 00446 00447 v4 = src[8 * 7]; /* Get odd elements */ 00448 v5 = src[8 * 1]; 00449 v6 = src[8 * 5]; 00450 v7 = src[8 * 3]; 00451 00452 t10 = v5 - v4; /* Process the odd elements */ 00453 t11 = v5 + v4; 00454 t12 = v6 - v7; 00455 v7 += v6; 00456 v5 = (t11 - v7) * M13 >> 12; 00457 v7 += t11; 00458 t13 = (t10 + t12) * M5 >> 12; 00459 v4 = t13 - (t10 * M2 >> 12); 00460 v6 = t13 - (t12 * M4 >> 12) - v7; 00461 v5 -= v6; 00462 v4 -= v5; 00463 00464 src[8 * 0] = v0 + v7; /* Write-back transformed values */ 00465 src[8 * 7] = v0 - v7; 00466 src[8 * 1] = v1 + v6; 00467 src[8 * 6] = v1 - v6; 00468 src[8 * 2] = v2 + v5; 00469 src[8 * 5] = v2 - v5; 00470 src[8 * 3] = v3 + v4; 00471 src[8 * 4] = v3 - v4; 00472 00473 src++; /* Next column */ 00474 } 00475 00476 /* Process rows */ 00477 src -= 8; 00478 for (i = 0; i < 8; i++) { 00479 v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */ 00480 v1 = src[2]; 00481 v2 = src[4]; 00482 v3 = src[6]; 00483 00484 t10 = v0 + v2; /* Process the even elements */ 00485 t12 = v0 - v2; 00486 t11 = (v1 - v3) * M13 >> 12; 00487 v3 += v1; 00488 t11 -= v3; 00489 v0 = t10 + v3; 00490 v3 = t10 - v3; 00491 v1 = t11 + t12; 00492 v2 = t12 - t11; 00493 00494 v4 = src[7]; /* Get odd elements */ 00495 v5 = src[1]; 00496 v6 = src[5]; 00497 v7 = src[3]; 00498 00499 t10 = v5 - v4; /* Process the odd elements */ 00500 t11 = v5 + v4; 00501 t12 = v6 - v7; 00502 v7 += v6; 00503 v5 = (t11 - v7) * M13 >> 12; 00504 v7 += t11; 00505 t13 = (t10 + t12) * M5 >> 12; 00506 v4 = t13 - (t10 * M2 >> 12); 00507 v6 = t13 - (t12 * M4 >> 12) - v7; 00508 v5 -= v6; 00509 v4 -= v5; 00510 00511 dst[0] = BYTECLIP((v0 + v7) >> 8); /* Descale the transformed values 8 bits and output */ 00512 dst[7] = BYTECLIP((v0 - v7) >> 8); 00513 dst[1] = BYTECLIP((v1 + v6) >> 8); 00514 dst[6] = BYTECLIP((v1 - v6) >> 8); 00515 dst[2] = BYTECLIP((v2 + v5) >> 8); 00516 dst[5] = BYTECLIP((v2 - v5) >> 8); 00517 dst[3] = BYTECLIP((v3 + v4) >> 8); 00518 dst[4] = BYTECLIP((v3 - v4) >> 8); 00519 dst += 8; 00520 00521 src += 8; /* Next row */ 00522 } 00523 } 00524 00525 00526 00527 00528 /*-----------------------------------------------------------------------*/ 00529 /* Load all blocks in the MCU into working buffer */ 00530 /*-----------------------------------------------------------------------*/ 00531 00532 JRESULT GraphicsDisplay::mcu_load ( 00533 JDEC * jd /* Pointer to the decompressor object */ 00534 ) 00535 { 00536 int32_t *tmp = (int32_t *)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ 00537 uint16_t blk, nby, nbc, i, z, id, cmp; 00538 int16_t b, d, e; 00539 uint8_t *bp; 00540 const uint8_t *hb, *hd; 00541 const uint16_t *hc; 00542 const int32_t *dqf; 00543 00544 INFO("mcu_load"); 00545 HexDump("JDEC", (uint8_t *)jd, sizeof(JDEC)); 00546 00547 nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */ 00548 nbc = 2; /* Number of C blocks (2) */ 00549 bp = jd->mcubuf; /* Pointer to the first block */ 00550 00551 for (blk = 0; blk < nby + nbc; blk++) { 00552 cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */ 00553 id = cmp ? 1 : 0; /* Huffman table ID of the component */ 00554 00555 /* Extract a DC element from input stream */ 00556 hb = jd->huffbits[id][0]; /* Huffman table for the DC element */ 00557 hc = jd->huffcode[id][0]; 00558 hd = jd->huffdata[id][0]; 00559 b = huffext(jd, hb, hc, hd); /* Extract a huffman coded data (bit length) */ 00560 if (b < 0) return (JRESULT)(0 - b); /* Err: invalid code or input */ 00561 d = jd->dcv[cmp]; /* DC value of previous block */ 00562 if (b) { /* If there is any difference from previous block */ 00563 e = bitext(jd, b); /* Extract data bits */ 00564 if (e < 0) return (JRESULT)(0 - e); /* Err: input */ 00565 b = 1 << (b - 1); /* MSB position */ 00566 if (!(e & b)) e -= (b << 1) - 1; /* Restore sign if needed */ 00567 d += e; /* Get current value */ 00568 jd->dcv[cmp] = (int16_t)d; /* Save current DC value for next block */ 00569 } 00570 dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */ 00571 tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ 00572 00573 /* Extract following 63 AC elements from input stream */ 00574 for (i = 1; i < 64; i++) tmp[i] = 0; /* Clear rest of elements */ 00575 hb = jd->huffbits[id][1]; /* Huffman table for the AC elements */ 00576 hc = jd->huffcode[id][1]; 00577 hd = jd->huffdata[id][1]; 00578 i = 1; /* Top of the AC elements */ 00579 do { 00580 b = huffext(jd, hb, hc, hd); /* Extract a huffman coded value (zero runs and bit length) */ 00581 if (b == 0) break; /* EOB? */ 00582 if (b < 0) return (JRESULT)(0 - b); /* Err: invalid code or input error */ 00583 z = (uint16_t)b >> 4; /* Number of leading zero elements */ 00584 if (z) { 00585 i += z; /* Skip zero elements */ 00586 if (i >= 64) return JDR_FMT1; /* Too long zero run */ 00587 } 00588 if (b &= 0x0F) { /* Bit length */ 00589 d = bitext(jd, b); /* Extract data bits */ 00590 if (d < 0) return (JRESULT)(0 - d); /* Err: input device */ 00591 b = 1 << (b - 1); /* MSB position */ 00592 if (!(d & b)) d -= (b << 1) - 1;/* Restore negative value if needed */ 00593 z = ZIG(i); /* Zigzag-order to raster-order converted index */ 00594 tmp[z] = d * dqf[z] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ 00595 } 00596 } while (++i < 64); /* Next AC element */ 00597 00598 if (JD_USE_SCALE && jd->scale == 3) 00599 *bp = (*tmp / 256) + 128; /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */ 00600 else 00601 block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ 00602 00603 bp += 64; /* Next block */ 00604 } 00605 00606 return JDR_OK; /* All blocks have been loaded successfully */ 00607 } 00608 00609 00610 00611 00612 /*-----------------------------------------------------------------------*/ 00613 /* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ 00614 /*-----------------------------------------------------------------------*/ 00615 00616 JRESULT GraphicsDisplay::mcu_output ( 00617 JDEC * jd, /* Pointer to the decompressor object */ 00618 uint16_t (* outfunc)(JDEC * jd, void * stream, JRECT * rect), /* RGB output function */ 00619 uint16_t x, /* MCU position in the image (left of the MCU) */ 00620 uint16_t y /* MCU position in the image (top of the MCU) */ 00621 ) 00622 { 00623 const int16_t CVACC = (sizeof (int16_t) > 2) ? 1024 : 128; 00624 uint16_t ix, iy, mx, my, rx, ry; 00625 int16_t yy, cb, cr; 00626 uint8_t *py, *pc, *rgb24; 00627 JRECT rect; 00628 00629 INFO("mcu_output(%p,%p,%d,%d)", jd, outfunc, x, y); 00630 HexDump("JDEC", (uint8_t *)jd, sizeof(JDEC)); 00631 00632 mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */ 00633 rx = (x + mx <= jd->width) ? mx : jd->width - x; /* Output rectangular size (it may be clipped at right/bottom end) */ 00634 ry = (y + my <= jd->height) ? my : jd->height - y; 00635 if (JD_USE_SCALE) { 00636 rx >>= jd->scale; ry >>= jd->scale; 00637 if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */ 00638 x >>= jd->scale; y >>= jd->scale; 00639 } 00640 rect.left = x; rect.right = x + rx - 1; /* Rectangular area in the frame buffer */ 00641 rect.top = y; rect.bottom = y + ry - 1; 00642 00643 00644 if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */ 00645 00646 /* Build an RGB MCU from discrete comopnents */ 00647 rgb24 = (uint8_t *)jd->workbuf; 00648 for (iy = 0; iy < my; iy++) { 00649 pc = jd->mcubuf; 00650 py = pc + iy * 8; 00651 if (my == 16) { /* Double block height? */ 00652 pc += 64 * 4 + (iy >> 1) * 8; 00653 if (iy >= 8) py += 64; 00654 } else { /* Single block height */ 00655 pc += mx * 8 + iy * 8; 00656 } 00657 for (ix = 0; ix < mx; ix++) { 00658 cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ 00659 cr = pc[64] - 128; 00660 if (mx == 16) { /* Double block width? */ 00661 if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */ 00662 pc += ix & 1; /* Increase chroma pointer every two pixels */ 00663 } else { /* Single block width */ 00664 pc++; /* Increase chroma pointer every pixel */ 00665 } 00666 yy = *py++; /* Get Y component */ 00667 00668 /* Convert YCbCr to RGB */ 00669 *rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr) / CVACC); 00670 *rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC); 00671 *rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb) / CVACC); 00672 } 00673 } 00674 00675 /* Descale the MCU rectangular if needed */ 00676 if (JD_USE_SCALE && jd->scale) { 00677 uint16_t x, y, r, g, b, s, w, a; 00678 uint8_t *op; 00679 00680 /* Get averaged RGB value of each square correcponds to a pixel */ 00681 s = jd->scale * 2; /* Bumber of shifts for averaging */ 00682 w = 1 << jd->scale; /* Width of square */ 00683 a = (mx - w) * 3; /* Bytes to skip for next line in the square */ 00684 op = (uint8_t *)jd->workbuf; 00685 for (iy = 0; iy < my; iy += w) { 00686 for (ix = 0; ix < mx; ix += w) { 00687 rgb24 = (uint8_t *)jd->workbuf + (iy * mx + ix) * 3; 00688 r = g = b = 0; 00689 for (y = 0; y < w; y++) { /* Accumulate RGB value in the square */ 00690 for (x = 0; x < w; x++) { 00691 r += *rgb24++; 00692 g += *rgb24++; 00693 b += *rgb24++; 00694 } 00695 rgb24 += a; 00696 } /* Put the averaged RGB value as a pixel */ 00697 *op++ = (uint8_t)(r >> s); 00698 *op++ = (uint8_t)(g >> s); 00699 *op++ = (uint8_t)(b >> s); 00700 } 00701 } 00702 } 00703 00704 } else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */ 00705 00706 /* Build a 1/8 descaled RGB MCU from discrete comopnents */ 00707 rgb24 = (uint8_t *)jd->workbuf; 00708 pc = jd->mcubuf + mx * my; 00709 cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ 00710 cr = pc[64] - 128; 00711 for (iy = 0; iy < my; iy += 8) { 00712 py = jd->mcubuf; 00713 if (iy == 8) py += 64 * 2; 00714 for (ix = 0; ix < mx; ix += 8) { 00715 yy = *py; /* Get Y component */ 00716 py += 64; 00717 00718 /* Convert YCbCr to RGB */ 00719 *rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr / CVACC)); 00720 *rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC); 00721 *rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb / CVACC)); 00722 } 00723 } 00724 } 00725 00726 /* Squeeze up pixel table if a part of MCU is to be truncated */ 00727 mx >>= jd->scale; 00728 if (rx < mx) { 00729 uint8_t *s, *d; 00730 uint16_t x, y; 00731 00732 s = d = (uint8_t *)jd->workbuf; 00733 for (y = 0; y < ry; y++) { 00734 for (x = 0; x < rx; x++) { /* Copy effective pixels */ 00735 *d++ = *s++; 00736 *d++ = *s++; 00737 *d++ = *s++; 00738 } 00739 s += (mx - rx) * 3; /* Skip truncated pixels */ 00740 } 00741 } 00742 00743 /* Convert RGB888 to RGB565 if needed */ 00744 if (JD_FORMAT == 1) { 00745 uint8_t *s = (uint8_t *)jd->workbuf; 00746 uint16_t w, *d = (uint16_t *)s; 00747 uint16_t n = rx * ry; 00748 00749 do { 00750 w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ 00751 w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */ 00752 w |= *s++ >> 3; /* -----------BBBBB */ 00753 *d++ = w; 00754 } while (--n); 00755 } 00756 00757 /* Output the RGB rectangular */ 00758 INFO("call outfunc"); 00759 if (outfunc) 00760 return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; 00761 else 00762 return privOutFunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; 00763 } 00764 00765 00766 00767 00768 /*-----------------------------------------------------------------------*/ 00769 /* Process restart interval */ 00770 /*-----------------------------------------------------------------------*/ 00771 00772 JRESULT GraphicsDisplay::restart ( 00773 JDEC * jd, /* Pointer to the decompressor object */ 00774 uint16_t rstn /* Expected restert sequense number */ 00775 ) 00776 { 00777 uint16_t i, dc; 00778 uint16_t d; 00779 uint8_t *dp; 00780 00781 INFO("restart(%p,%d)", jd, rstn); 00782 00783 /* Discard padding bits and get two bytes from the input stream */ 00784 dp = jd->dptr; dc = jd->dctr; 00785 d = 0; 00786 for (i = 0; i < 2; i++) { 00787 if (!dc) { /* No input data is available, re-fill input buffer */ 00788 dp = jd->inbuf; 00789 dc = getJpegData(jd, dp, JD_SZBUF); 00790 if (!dc) return JDR_INP; 00791 } else { 00792 dp++; 00793 } 00794 dc--; 00795 d = (d << 8) | *dp; /* Get a byte */ 00796 } 00797 jd->dptr = dp; jd->dctr = dc; jd->dmsk = 0; 00798 00799 /* Check the marker */ 00800 if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) 00801 return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ 00802 00803 /* Reset DC offset */ 00804 jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; 00805 00806 return JDR_OK; 00807 } 00808 00809 00810 00811 00812 /*-----------------------------------------------------------------------*/ 00813 /* Analyze the JPEG image and Initialize decompressor object */ 00814 /*-----------------------------------------------------------------------*/ 00815 00816 #define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t *)(ptr))<<8)|(uint16_t)*(uint8_t *)((ptr)+1)) 00817 00818 uint16_t GraphicsDisplay::privInFunc(JDEC * jd, uint8_t * buff, uint16_t ndata) 00819 { 00820 //INFO("Read in %p count %d", buff, ndata); 00821 if (buff) { 00822 size_t n = fread(buff, 1, ndata, (FILE *)jd->device); 00823 INFO("fread returned %d of %d", n, ndata); 00824 HexDump("buf", buff, (ndata > 32) ? 32 : ndata); 00825 return n == (size_t)-1 ? 0 : n; 00826 } else { 00827 off_t t = fseek((FILE *)jd->device, ndata, SEEK_CUR); 00828 INFO("Seek returned %d", t); 00829 return t == (off_t)-1 ? 0 : ndata; 00830 } 00831 } 00832 00833 uint16_t GraphicsDisplay::getJpegData(JDEC * jd, uint8_t * buff, uint16_t ndata) 00834 { 00835 //INFO("getJpegData(%p, %p, %d)", jd, buff, ndata); 00836 if (jd->infunc) 00837 return jd->infunc(jd, buff, ndata); 00838 else 00839 return privInFunc(jd, buff, ndata); 00840 } 00841 00842 // RGB565 if JD_FORMAT == 1 00843 // RGB888 if JD_FORMAT == 0 00844 uint16_t GraphicsDisplay::privOutFunc(JDEC * jd, void * bitmap, JRECT * rect) 00845 { 00846 int x0 = rect->left; 00847 int x1 = rect->right; 00848 int y0 = rect->top; 00849 int y1 = rect->bottom; 00850 00851 INFO("privOutFunc: (%d,%d)-(%d,%d) : (%d,%d)", x0,y0, x1,y1, width(), height()); 00852 if (y0 >= height() || x0 >= width()) 00853 return 1; // off the right || bottom of screen 00854 if (x1 > width()-1) x1 = width() - 1; // clip to width 00855 if (y1 > height()-1) y1 = height() - 1; // clip to height 00856 00857 int w = x1 - x0 + 1; 00858 00859 #if 1 00860 uint32_t pixelCount = (1 + (y1-y0)) * (1+x1-x0); 00861 #if JD_FORMAT == 0 00862 uint8_t *s = (uint8_t *)bitmap; 00863 uint16_t rgb565, *d = (uint16_t *)s; 00864 uint32_t pCount = pixelCount; 00865 00866 do { 00867 rgb565 = (*s++ & 0xF8) << 8; /* RRRRR----------- */ 00868 rgb565 |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */ 00869 rgb565 |= *s++ >> 3; /* -----------BBBBB */ 00870 *d++ = rgb565; 00871 } while (--pCount); 00872 #endif 00873 // 00874 window(x0+img_x, y0+img_y, w, y1 - y0 + 2); 00875 uint16_t *src = (uint16_t *)bitmap; // pointer to RGB565 format 00876 pixelStream(src, pixelCount, x0+img_x, y0+img_y); 00877 window(); 00878 #else 00879 for (int y= y0; y <= y1; y++) { 00880 SetGraphicsCursor(x0+img_x, y+img_y); 00881 _StartGraphicsStream(); 00882 #if JD_FORMAT == 1 00883 uint16_t *p = src + w * (y - y0); 00884 #else 00885 uint8_t *p = src + 3 * (w * (y - y0)); 00886 #endif 00887 for (int x=x0; x <= x1; x++) { 00888 #if JD_FORMAT == 1 00889 _putp(*p++); 00890 #else 00891 _putp(RGB(*p, *(p+1), *(p+2))); 00892 p += 3; 00893 #endif 00894 } 00895 _EndGraphicsStream(); 00896 } 00897 #endif 00898 return 1; 00899 } 00900 00901 JRESULT GraphicsDisplay::jd_prepare ( 00902 JDEC * jd, /* Blank decompressor object */ 00903 uint16_t (*infunc)(JDEC *, uint8_t *, uint16_t), /* JPEG strem input function */ 00904 void* pool, /* Working buffer for the decompression session */ 00905 uint16_t sz_pool, /* Size of working buffer */ 00906 void* dev /* I/O device identifier for the session */ 00907 ) 00908 { 00909 uint8_t *seg, b; 00910 uint16_t marker; 00911 uint32_t ofs; 00912 uint16_t n, i, j, len; 00913 JRESULT rc; 00914 00915 INFO("jd_prepare(%p,%p,%p,%d,%p)", jd, infunc, pool, sz_pool, dev); 00916 HexDump("JDEC 1", (uint8_t *)jd, sizeof(JDEC)); 00917 00918 if (!pool) { 00919 ERR("JDR_PAR"); 00920 return JDR_PAR; 00921 } 00922 00923 //INFO("pool is at %p", pool); 00924 jd->pool = pool; /* Work memroy */ 00925 jd->sz_pool = sz_pool; /* Size of given work memory */ 00926 jd->infunc = infunc; /* Stream input function */ 00927 jd->device = dev; /* I/O device identifier */ 00928 jd->nrst = 0; /* No restart interval (default) */ 00929 00930 for (i = 0; i < 2; i++) { /* Nulls pointers */ 00931 for (j = 0; j < 2; j++) { 00932 jd->huffbits[i][j] = 0; 00933 jd->huffcode[i][j] = 0; 00934 jd->huffdata[i][j] = 0; 00935 } 00936 } 00937 for (i = 0; i < 4; i++) jd->qttbl[i] = 0; 00938 HexDump("JDEC 2", (uint8_t *)jd, sizeof(JDEC)); 00939 00940 jd->inbuf = seg = (uint8_t *)alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */ 00941 if (!seg) { 00942 ERR("JDR_MEM1"); 00943 return JDR_MEM1; 00944 } 00945 HexDump("JDEC 3", (uint8_t *)jd, sizeof(JDEC)); 00946 00947 if (getJpegData(jd, seg, 2) != 2) { 00948 ERR("JDR_INP"); 00949 return JDR_INP;/* Check SOI marker */ 00950 } 00951 INFO("Checkpoint"); 00952 HexDump("SOI marker", seg, 2); 00953 if (LDB_WORD(seg) != 0xFFD8) { 00954 ERR("JDR_FMT1"); 00955 return JDR_FMT1; /* Err: SOI is not detected */ 00956 } 00957 ofs = 2; 00958 00959 for (;;) { 00960 /* Get a JPEG marker */ 00961 if (getJpegData(jd, seg, 4) != 4) { 00962 ERR("JDR_INP"); 00963 return JDR_INP; 00964 } 00965 marker = LDB_WORD(seg); /* Marker */ 00966 len = LDB_WORD(seg + 2); /* Length field */ 00967 if (len <= 2 || (marker >> 8) != 0xFF) { 00968 ERR("JDR_FMT1"); 00969 return JDR_FMT1; 00970 } 00971 len -= 2; /* Content size excluding length field */ 00972 ofs += 4 + len; /* Number of bytes loaded */ 00973 00974 switch (marker & 0xFF) { 00975 case 0xC0: /* SOF0 (baseline JPEG) */ 00976 /* Load segment data */ 00977 if (len > JD_SZBUF) { 00978 ERR("JDR_MEM2"); 00979 return JDR_MEM2; 00980 } 00981 if (getJpegData(jd, seg, len) != len) { 00982 ERR("JDR_INP"); 00983 return JDR_INP; 00984 } 00985 00986 jd->width = LDB_WORD(seg+3); /* Image width in unit of pixel */ 00987 jd->height = LDB_WORD(seg+1); /* Image height in unit of pixel */ 00988 INFO("Image size(%d,%d)", jd->width, jd->height); 00989 00990 if (seg[5] != 3) { 00991 ERR("JDR_FMT3"); 00992 return JDR_FMT3; /* Err: Supports only Y/Cb/Cr format */ 00993 } 00994 00995 /* Check three image components */ 00996 for (i = 0; i < 3; i++) { 00997 b = seg[7 + 3 * i]; /* Get sampling factor */ 00998 if (!i) { /* Y component */ 00999 if (b != 0x11 && b != 0x22 && b != 0x21) {/* Check sampling factor */ 01000 ERR("JDR_FMT3"); 01001 return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ 01002 } 01003 jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */ 01004 } else { /* Cb/Cr component */ 01005 if (b != 0x11) { 01006 ERR("JDR_FMT3"); 01007 return JDR_FMT3; /* Err: Sampling factor of Cr/Cb must be 1 */ 01008 } 01009 } 01010 b = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */ 01011 if (b > 3) { 01012 ERR("JDR_FMT3"); 01013 return JDR_FMT3; /* Err: Invalid ID */ 01014 } 01015 jd->qtid[i] = b; 01016 } 01017 break; 01018 01019 case 0xDD: /* DRI */ 01020 /* Load segment data */ 01021 if (len > JD_SZBUF) { 01022 ERR("JDR_MEM2"); 01023 return JDR_MEM2; 01024 } 01025 if (getJpegData(jd, seg, len) != len) { 01026 ERR("JDR_INP"); 01027 return JDR_INP; 01028 } 01029 01030 /* Get restart interval (MCUs) */ 01031 jd->nrst = LDB_WORD(seg); 01032 break; 01033 01034 case 0xC4: /* DHT */ 01035 /* Load segment data */ 01036 if (len > JD_SZBUF) { 01037 ERR("JDR_MEM2"); 01038 return JDR_MEM2; 01039 } 01040 if (getJpegData(jd, seg, len) != len) { 01041 ERR("JDR_INP"); 01042 return JDR_INP; 01043 } 01044 01045 /* Create huffman tables */ 01046 INFO("next - create_huffman_tbl()"); 01047 rc = (JRESULT)create_huffman_tbl(jd, seg, len); 01048 if (rc) { 01049 ERR("rc = %d", rc); 01050 return rc; 01051 } 01052 break; 01053 01054 case 0xDB: /* DQT */ 01055 /* Load segment data */ 01056 if (len > JD_SZBUF) { 01057 ERR("JDR_MEM2"); 01058 return JDR_MEM2; 01059 } 01060 if (getJpegData(jd, seg, len) != len) { 01061 ERR("JDR_INP"); 01062 return JDR_INP; 01063 } 01064 01065 /* Create de-quantizer tables */ 01066 rc = (JRESULT)create_qt_tbl(jd, seg, len); 01067 if (rc) { 01068 ERR("rc = %d", rc); 01069 return rc; 01070 } 01071 break; 01072 01073 case 0xDA: /* SOS */ 01074 /* Load segment data */ 01075 if (len > JD_SZBUF) { 01076 ERR("JDR_MEM2"); 01077 return JDR_MEM2; 01078 } 01079 if (getJpegData(jd, seg, len) != len) { 01080 ERR("JDR_INP"); 01081 return JDR_INP; 01082 } 01083 01084 if (!jd->width || !jd->height) { 01085 ERR("JDR_FMT1"); 01086 return JDR_FMT1; /* Err: Invalid image size */ 01087 } 01088 01089 if (seg[0] != 3) { 01090 ERR("JDR_FMT3"); 01091 return JDR_FMT3; /* Err: Supports only three color components format */ 01092 } 01093 01094 /* Check if all tables corresponding to each components have been loaded */ 01095 for (i = 0; i < 3; i++) { 01096 b = seg[2 + 2 * i]; /* Get huffman table ID */ 01097 if (b != 0x00 && b != 0x11) { 01098 ERR("JDR_FMT3"); 01099 return JDR_FMT3; /* Err: Different table number for DC/AC element */ 01100 } 01101 b = i ? 1 : 0; 01102 if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) { /* Check huffman table for this component */ 01103 ERR("JDR_FMT1"); 01104 return JDR_FMT1; /* Err: Huffman table not loaded */ 01105 } 01106 if (!jd->qttbl[jd->qtid[i]]) { 01107 ERR("JDR_FMT1"); 01108 return JDR_FMT1; /* Err: Dequantizer table not loaded */ 01109 } 01110 } 01111 01112 /* Allocate working buffer for MCU and RGB */ 01113 n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */ 01114 if (!n) { 01115 ERR("JDR_FMT1"); 01116 return JDR_FMT1; /* Err: SOF0 has not been loaded */ 01117 } 01118 len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */ 01119 if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */ 01120 jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */ 01121 if (!jd->workbuf) { 01122 ERR("JDR_MEM1"); 01123 return JDR_MEM1; /* Err: not enough memory */ 01124 } 01125 jd->mcubuf = (uint8_t *)alloc_pool(jd, (n + 2) * 64); /* Allocate MCU working buffer */ 01126 if (!jd->mcubuf) { 01127 ERR("JDR_MEM1"); 01128 return JDR_MEM1; /* Err: not enough memory */ 01129 } 01130 01131 /* Pre-load the JPEG data to extract it from the bit stream */ 01132 jd->dptr = seg; jd->dctr = 0; jd->dmsk = 0; /* Prepare to read bit stream */ 01133 if (ofs %= JD_SZBUF) { /* Align read offset to JD_SZBUF */ 01134 jd->dctr = getJpegData(jd, seg + ofs, JD_SZBUF - (uint16_t)ofs); 01135 jd->dptr = seg + ofs - 1; 01136 } 01137 01138 return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */ 01139 01140 case 0xC1: /* SOF1 */ 01141 case 0xC2: /* SOF2 */ 01142 case 0xC3: /* SOF3 */ 01143 case 0xC5: /* SOF5 */ 01144 case 0xC6: /* SOF6 */ 01145 case 0xC7: /* SOF7 */ 01146 case 0xC9: /* SOF9 */ 01147 case 0xCA: /* SOF10 */ 01148 case 0xCB: /* SOF11 */ 01149 case 0xCD: /* SOF13 */ 01150 case 0xCE: /* SOF14 */ 01151 case 0xCF: /* SOF15 */ 01152 case 0xD9: /* EOI */ 01153 return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */ 01154 01155 default: /* Unknown segment (comment, exif or etc..) */ 01156 /* Skip segment data */ 01157 if (getJpegData(jd, 0, len) != len) { /* Null pointer specifies to skip bytes of stream */ 01158 INFO("Unknown segment"); 01159 return JDR_INP; 01160 } 01161 } 01162 } 01163 } 01164 01165 01166 01167 01168 /*-----------------------------------------------------------------------*/ 01169 /* Start to decompress the JPEG picture */ 01170 /*-----------------------------------------------------------------------*/ 01171 01172 JRESULT GraphicsDisplay::jd_decomp ( 01173 JDEC * jd, /* Initialized decompression object */ 01174 uint16_t (*outfunc)(JDEC * jd, void * stream, JRECT * rect), /* RGB output function */ 01175 uint8_t scale /* Output de-scaling factor (0 to 3) */ 01176 ) 01177 { 01178 uint16_t x, y, mx, my; 01179 uint16_t rst, rsc; 01180 JRESULT rc; 01181 01182 INFO("jd_decomp(%p,%p,%d)", jd, outfunc, scale); 01183 HexDump("JDEC", (uint8_t *)jd, sizeof(JDEC)); 01184 01185 if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; 01186 jd->scale = scale; 01187 01188 mx = jd->msx * 8; my = jd->msy * 8; /* Size of the MCU (pixel) */ 01189 01190 jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ 01191 rst = rsc = 0; 01192 01193 rc = JDR_OK; 01194 for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */ 01195 for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */ 01196 if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */ 01197 rc = restart(jd, rsc++); 01198 if (rc != JDR_OK) return rc; 01199 rst = 1; 01200 } 01201 rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream and apply IDCT) */ 01202 if (rc != JDR_OK) return rc; 01203 rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (color space conversion, scaling and output) */ 01204 if (rc != JDR_OK) return rc; 01205 } 01206 } 01207 return rc; 01208 }
Generated on Tue Jul 12 2022 19:25:30 by
