CUER / RA8875

Fork of RA8875 by David Smart

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GraphicsDisplayJPEG.cpp Source File

GraphicsDisplayJPEG.cpp

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