KSM edits to RA8875

Dependents:   Liz_Test_Code

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GraphicsDisplayJPEG.cpp Source File

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     window(x0+img_x, y0+img_y, w, y1 - y0 + 2);
00858     uint16_t *src = (uint16_t *)bitmap;     // pointer to RGB565 format
00859     pixelStream(src, pixelCount, x0+img_x, y0+img_y);
00860     window();
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 }