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