This is the David Smart RA8875 Library with mods for working with FRDM-K64F

Committer:
lamell
Date:
Tue Mar 10 21:28:18 2020 -0400
Revision:
199:08eb9e55567b
Parent:
197:853d08e2fb53
Subtle changes in the way the library behaves.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 167:8aa3fb2a5a31 1 // Wrapping ChaN's TJpgDec into this graphics engine
WiredHome 167:8aa3fb2a5a31 2 //
WiredHome 115:c9862fd0c689 3
WiredHome 115:c9862fd0c689 4 #include "mbed.h"
WiredHome 115:c9862fd0c689 5
WiredHome 115:c9862fd0c689 6 #include "GraphicsDisplay.h"
WiredHome 115:c9862fd0c689 7
WiredHome 121:6bc4911f5e55 8 //#define DEBUG "JPEG"
WiredHome 115:c9862fd0c689 9 // ...
WiredHome 115:c9862fd0c689 10 // INFO("Stuff to show %d", var); // new-line is automatically appended
WiredHome 115:c9862fd0c689 11 //
WiredHome 115:c9862fd0c689 12 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 197:853d08e2fb53 13 #define INFO(x, ...) std::printf("[INF %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 197:853d08e2fb53 14 #define WARN(x, ...) std::printf("[WRN %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 197:853d08e2fb53 15 #define ERR(x, ...) std::printf("[ERR %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 115:c9862fd0c689 16 static void HexDump(const char * title, const uint8_t * p, int count)
WiredHome 115:c9862fd0c689 17 {
WiredHome 115:c9862fd0c689 18 int i;
WiredHome 115:c9862fd0c689 19 char buf[100] = "0000: ";
WiredHome 115:c9862fd0c689 20
WiredHome 115:c9862fd0c689 21 if (*title)
WiredHome 121:6bc4911f5e55 22 INFO("%s @%p", title, p);
WiredHome 115:c9862fd0c689 23 for (i=0; i<count; ) {
WiredHome 115:c9862fd0c689 24 sprintf(buf + strlen(buf), "%02X ", *(p+i));
WiredHome 115:c9862fd0c689 25 if ((++i & 0x0F) == 0x00) {
WiredHome 115:c9862fd0c689 26 INFO("%s", buf);
WiredHome 115:c9862fd0c689 27 if (i < count)
WiredHome 115:c9862fd0c689 28 sprintf(buf, "%04X: ", i);
WiredHome 115:c9862fd0c689 29 else
WiredHome 115:c9862fd0c689 30 buf[0] = '\0';
WiredHome 115:c9862fd0c689 31 }
WiredHome 115:c9862fd0c689 32 }
WiredHome 115:c9862fd0c689 33 if (strlen(buf))
WiredHome 115:c9862fd0c689 34 INFO("%s", buf);
WiredHome 115:c9862fd0c689 35 }
WiredHome 115:c9862fd0c689 36 #else
WiredHome 115:c9862fd0c689 37 #define INFO(x, ...)
WiredHome 115:c9862fd0c689 38 #define WARN(x, ...)
WiredHome 115:c9862fd0c689 39 #define ERR(x, ...)
WiredHome 115:c9862fd0c689 40 #define HexDump(a, b, c)
WiredHome 115:c9862fd0c689 41 #endif
WiredHome 115:c9862fd0c689 42
WiredHome 115:c9862fd0c689 43
WiredHome 115:c9862fd0c689 44 /*-----------------------------------------------*/
WiredHome 115:c9862fd0c689 45 /* Zigzag-order to raster-order conversion table */
WiredHome 115:c9862fd0c689 46 /*-----------------------------------------------*/
WiredHome 115:c9862fd0c689 47
WiredHome 115:c9862fd0c689 48 #define ZIG(n) Zig[n]
WiredHome 115:c9862fd0c689 49
WiredHome 115:c9862fd0c689 50 static
WiredHome 115:c9862fd0c689 51 const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */
WiredHome 115:c9862fd0c689 52 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
WiredHome 115:c9862fd0c689 53 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
WiredHome 115:c9862fd0c689 54 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
WiredHome 115:c9862fd0c689 55 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
WiredHome 115:c9862fd0c689 56 };
WiredHome 115:c9862fd0c689 57
WiredHome 115:c9862fd0c689 58
WiredHome 115:c9862fd0c689 59
WiredHome 115:c9862fd0c689 60 /*-------------------------------------------------*/
WiredHome 115:c9862fd0c689 61 /* Input scale factor of Arai algorithm */
WiredHome 115:c9862fd0c689 62 /* (scaled up 16 bits for fixed point operations) */
WiredHome 115:c9862fd0c689 63 /*-------------------------------------------------*/
WiredHome 115:c9862fd0c689 64
WiredHome 115:c9862fd0c689 65 #define IPSF(n) Ipsf[n]
WiredHome 115:c9862fd0c689 66
WiredHome 115:c9862fd0c689 67 static
WiredHome 115:c9862fd0c689 68 const uint16_t Ipsf[64] = { /* See also aa_idct.png */
WiredHome 115:c9862fd0c689 69 (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),
WiredHome 115:c9862fd0c689 70 (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),
WiredHome 115:c9862fd0c689 71 (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),
WiredHome 115:c9862fd0c689 72 (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),
WiredHome 115:c9862fd0c689 73 (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),
WiredHome 115:c9862fd0c689 74 (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),
WiredHome 115:c9862fd0c689 75 (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),
WiredHome 115:c9862fd0c689 76 (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)
WiredHome 115:c9862fd0c689 77 };
WiredHome 115:c9862fd0c689 78
WiredHome 115:c9862fd0c689 79
WiredHome 115:c9862fd0c689 80
WiredHome 115:c9862fd0c689 81 /*---------------------------------------------*/
WiredHome 115:c9862fd0c689 82 /* Conversion table for fast clipping process */
WiredHome 115:c9862fd0c689 83 /*---------------------------------------------*/
WiredHome 115:c9862fd0c689 84
WiredHome 115:c9862fd0c689 85 #if JD_TBLCLIP
WiredHome 115:c9862fd0c689 86
WiredHome 115:c9862fd0c689 87 #define BYTECLIP(v) Clip8[(uint16_t)(v) & 0x3FF]
WiredHome 115:c9862fd0c689 88
WiredHome 115:c9862fd0c689 89 static
WiredHome 115:c9862fd0c689 90 const uint8_t Clip8[1024] = {
WiredHome 115:c9862fd0c689 91 /* 0..255 */
WiredHome 115:c9862fd0c689 92 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,
WiredHome 115:c9862fd0c689 93 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,
WiredHome 115:c9862fd0c689 94 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,
WiredHome 115:c9862fd0c689 95 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,
WiredHome 115:c9862fd0c689 96 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,
WiredHome 115:c9862fd0c689 97 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,
WiredHome 115:c9862fd0c689 98 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,
WiredHome 115:c9862fd0c689 99 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,
WiredHome 115:c9862fd0c689 100 /* 256..511 */
WiredHome 115:c9862fd0c689 101 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,
WiredHome 115:c9862fd0c689 102 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,
WiredHome 115:c9862fd0c689 103 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,
WiredHome 115:c9862fd0c689 104 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,
WiredHome 115:c9862fd0c689 105 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,
WiredHome 115:c9862fd0c689 106 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,
WiredHome 115:c9862fd0c689 107 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,
WiredHome 115:c9862fd0c689 108 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,
WiredHome 115:c9862fd0c689 109 /* -512..-257 */
WiredHome 115:c9862fd0c689 110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 118 /* -256..-1 */
WiredHome 115:c9862fd0c689 119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
WiredHome 115:c9862fd0c689 126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
WiredHome 115:c9862fd0c689 127 };
WiredHome 115:c9862fd0c689 128
WiredHome 115:c9862fd0c689 129 #else /* JD_TBLCLIP */
WiredHome 115:c9862fd0c689 130
WiredHome 115:c9862fd0c689 131 inline
WiredHome 115:c9862fd0c689 132 uint8_t BYTECLIP (
WiredHome 115:c9862fd0c689 133 int16_t val
WiredHome 115:c9862fd0c689 134 )
WiredHome 115:c9862fd0c689 135 {
WiredHome 115:c9862fd0c689 136 if (val < 0) val = 0;
WiredHome 115:c9862fd0c689 137 if (val > 255) val = 255;
WiredHome 115:c9862fd0c689 138
WiredHome 115:c9862fd0c689 139 return (uint8_t)val;
WiredHome 115:c9862fd0c689 140 }
WiredHome 115:c9862fd0c689 141
WiredHome 115:c9862fd0c689 142 #endif
WiredHome 115:c9862fd0c689 143
WiredHome 115:c9862fd0c689 144
WiredHome 115:c9862fd0c689 145
WiredHome 115:c9862fd0c689 146 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 147 /* Allocate a memory block from memory pool */
WiredHome 115:c9862fd0c689 148 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 149
WiredHome 115:c9862fd0c689 150 static
WiredHome 115:c9862fd0c689 151 void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */
WiredHome 115:c9862fd0c689 152 JDEC * jd, /* Pointer to the decompressor object */
WiredHome 115:c9862fd0c689 153 uint16_t nd /* Number of bytes to allocate */
WiredHome 115:c9862fd0c689 154 )
WiredHome 115:c9862fd0c689 155 {
WiredHome 115:c9862fd0c689 156 char *rp = 0;
WiredHome 115:c9862fd0c689 157
WiredHome 115:c9862fd0c689 158 INFO("alloc_pool(%p,%d) %p:%d", jd, nd, jd->pool, jd->sz_pool);
WiredHome 115:c9862fd0c689 159 nd = (nd + 3) & ~3; /* Align block size to the word boundary */
WiredHome 115:c9862fd0c689 160
WiredHome 115:c9862fd0c689 161 if (jd->sz_pool >= nd) {
WiredHome 115:c9862fd0c689 162 jd->sz_pool -= nd;
WiredHome 115:c9862fd0c689 163 rp = (char*)jd->pool; /* Get start of available memory pool */
WiredHome 115:c9862fd0c689 164 jd->pool = (void*)(rp + nd); /* Allocate requierd bytes */
WiredHome 120:be2aaa3adf72 165 //INFO("jd->pool %p", jd->pool);
WiredHome 115:c9862fd0c689 166 }
WiredHome 115:c9862fd0c689 167 INFO("rp %p", rp);
WiredHome 115:c9862fd0c689 168 return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */
WiredHome 115:c9862fd0c689 169 }
WiredHome 115:c9862fd0c689 170
WiredHome 115:c9862fd0c689 171
WiredHome 115:c9862fd0c689 172
WiredHome 115:c9862fd0c689 173
WiredHome 115:c9862fd0c689 174 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 175 /* Create de-quantization and prescaling tables with a DQT segment */
WiredHome 115:c9862fd0c689 176 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 177
WiredHome 115:c9862fd0c689 178 static
WiredHome 115:c9862fd0c689 179 uint16_t create_qt_tbl ( /* 0:OK, !0:Failed */
WiredHome 115:c9862fd0c689 180 JDEC * jd, /* Pointer to the decompressor object */
WiredHome 115:c9862fd0c689 181 const uint8_t * data, /* Pointer to the quantizer tables */
WiredHome 115:c9862fd0c689 182 uint16_t ndata /* Size of input data */
WiredHome 115:c9862fd0c689 183 )
WiredHome 115:c9862fd0c689 184 {
WiredHome 115:c9862fd0c689 185 uint16_t i;
WiredHome 115:c9862fd0c689 186 uint8_t d, z;
WiredHome 115:c9862fd0c689 187 int32_t *pb;
WiredHome 115:c9862fd0c689 188
WiredHome 120:be2aaa3adf72 189 INFO("create qt table (%p,%p,%d)", jd, data, ndata);
WiredHome 120:be2aaa3adf72 190 HexDump("JDEC", (uint8_t *)jd, sizeof(JDEC));
WiredHome 115:c9862fd0c689 191 while (ndata) { /* Process all tables in the segment */
WiredHome 115:c9862fd0c689 192 if (ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */
WiredHome 115:c9862fd0c689 193 ndata -= 65;
WiredHome 115:c9862fd0c689 194 d = *data++; /* Get table property */
WiredHome 115:c9862fd0c689 195 if (d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */
WiredHome 115:c9862fd0c689 196 i = d & 3; /* Get table ID */
WiredHome 115:c9862fd0c689 197 pb = (int32_t *)alloc_pool(jd, 64 * sizeof (int32_t));/* Allocate a memory block for the table */
WiredHome 115:c9862fd0c689 198 if (!pb) return JDR_MEM1; /* Err: not enough memory */
WiredHome 115:c9862fd0c689 199 jd->qttbl[i] = pb; /* Register the table */
WiredHome 115:c9862fd0c689 200 for (i = 0; i < 64; i++) { /* Load the table */
WiredHome 115:c9862fd0c689 201 z = ZIG(i); /* Zigzag-order to raster-order conversion */
WiredHome 115:c9862fd0c689 202 pb[z] = (int32_t)((uint32_t)*data++ * IPSF(z)); /* Apply scale factor of Arai algorithm to the de-quantizers */
WiredHome 115:c9862fd0c689 203 }
WiredHome 115:c9862fd0c689 204 }
WiredHome 115:c9862fd0c689 205
WiredHome 115:c9862fd0c689 206 return JDR_OK;
WiredHome 115:c9862fd0c689 207 }
WiredHome 115:c9862fd0c689 208
WiredHome 115:c9862fd0c689 209
WiredHome 115:c9862fd0c689 210
WiredHome 115:c9862fd0c689 211
WiredHome 115:c9862fd0c689 212 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 213 /* Create huffman code tables with a DHT segment */
WiredHome 115:c9862fd0c689 214 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 215
WiredHome 115:c9862fd0c689 216 static
WiredHome 115:c9862fd0c689 217 uint16_t create_huffman_tbl ( /* 0:OK, !0:Failed */
WiredHome 115:c9862fd0c689 218 JDEC * jd, /* Pointer to the decompressor object */
WiredHome 115:c9862fd0c689 219 const uint8_t * data, /* Pointer to the packed huffman tables */
WiredHome 115:c9862fd0c689 220 uint16_t ndata /* Size of input data */
WiredHome 115:c9862fd0c689 221 )
WiredHome 115:c9862fd0c689 222 {
WiredHome 115:c9862fd0c689 223 uint16_t i, j, b, np, cls, num;
WiredHome 115:c9862fd0c689 224 uint8_t d, *pb, *pd;
WiredHome 115:c9862fd0c689 225 uint16_t hc, *ph;
WiredHome 115:c9862fd0c689 226
WiredHome 117:6710b8e196f0 227 INFO("create_huffman_tbl(%p,%p,%d)", jd, data, ndata);
WiredHome 121:6bc4911f5e55 228 HexDump("JDEC - create_huffman_tbl entry", (uint8_t *)jd, sizeof(JDEC));
WiredHome 115:c9862fd0c689 229 while (ndata) { /* Process all tables in the segment */
WiredHome 115:c9862fd0c689 230 if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */
WiredHome 115:c9862fd0c689 231 ndata -= 17;
WiredHome 115:c9862fd0c689 232 d = *data++; /* Get table number and class */
WiredHome 115:c9862fd0c689 233 cls = (d >> 4); num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */
WiredHome 115:c9862fd0c689 234 if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */
WiredHome 115:c9862fd0c689 235 pb = (uint8_t *)alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */
WiredHome 115:c9862fd0c689 236 if (!pb) {
WiredHome 115:c9862fd0c689 237 ERR("JDR_MEM1");
WiredHome 115:c9862fd0c689 238 return JDR_MEM1; /* Err: not enough memory */
WiredHome 115:c9862fd0c689 239 }
WiredHome 115:c9862fd0c689 240 jd->huffbits[num][cls] = pb;
WiredHome 115:c9862fd0c689 241 for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */
WiredHome 115:c9862fd0c689 242 pb[i] = b = *data++;
WiredHome 115:c9862fd0c689 243 np += b; /* Get sum of code words for each code */
WiredHome 115:c9862fd0c689 244 }
WiredHome 115:c9862fd0c689 245
WiredHome 115:c9862fd0c689 246 ph = (uint16_t *)alloc_pool(jd, np * sizeof (uint16_t));/* Allocate a memory block for the code word table */
WiredHome 115:c9862fd0c689 247 if (!ph) {
WiredHome 115:c9862fd0c689 248 ERR("JDR_MEM1");
WiredHome 115:c9862fd0c689 249 return JDR_MEM1; /* Err: not enough memory */
WiredHome 115:c9862fd0c689 250 }
WiredHome 118:34eb0b64fc61 251 //INFO("jd->pool: %p", jd->pool);
WiredHome 115:c9862fd0c689 252 jd->huffcode[num][cls] = ph;
WiredHome 118:34eb0b64fc61 253 //INFO("jd->pool: %p, %p", jd->pool, ph);
WiredHome 115:c9862fd0c689 254 hc = 0;
WiredHome 115:c9862fd0c689 255 for (j = i = 0; i < 16; i++) { /* Re-build huffman code word table */
WiredHome 115:c9862fd0c689 256 b = pb[i];
WiredHome 115:c9862fd0c689 257 while (b--) ph[j++] = hc++;
WiredHome 115:c9862fd0c689 258 hc <<= 1;
WiredHome 115:c9862fd0c689 259 INFO("jd->pool: %d: %p, %p", i, jd->pool, ph);
WiredHome 115:c9862fd0c689 260 }
WiredHome 118:34eb0b64fc61 261 //INFO("jd->pool: %p", jd->pool);
WiredHome 115:c9862fd0c689 262
WiredHome 115:c9862fd0c689 263 if (ndata < np) return JDR_FMT1; /* Err: wrong data size */
WiredHome 115:c9862fd0c689 264 ndata -= np;
WiredHome 118:34eb0b64fc61 265 //INFO("jd->pool: %p", jd->pool);
WiredHome 115:c9862fd0c689 266 pd = (uint8_t *)alloc_pool(jd, np); /* Allocate a memory block for the decoded data */
WiredHome 118:34eb0b64fc61 267 //INFO("jd->pool: %p", jd->pool);
WiredHome 115:c9862fd0c689 268 if (!pd) {
WiredHome 115:c9862fd0c689 269 ERR("JDR_MEM1");
WiredHome 115:c9862fd0c689 270 return JDR_MEM1; /* Err: not enough memory */
WiredHome 115:c9862fd0c689 271 }
WiredHome 115:c9862fd0c689 272 jd->huffdata[num][cls] = pd;
WiredHome 115:c9862fd0c689 273 for (i = 0; i < np; i++) { /* Load decoded data corresponds to each code ward */
WiredHome 115:c9862fd0c689 274 d = *data++;
WiredHome 115:c9862fd0c689 275 if (!cls && d > 11) return JDR_FMT1;
WiredHome 115:c9862fd0c689 276 *pd++ = d;
WiredHome 115:c9862fd0c689 277 }
WiredHome 115:c9862fd0c689 278 }
WiredHome 115:c9862fd0c689 279
WiredHome 121:6bc4911f5e55 280 HexDump("JDEC - create_huffman_tbl exit", (uint8_t *)jd, sizeof(JDEC));
WiredHome 115:c9862fd0c689 281 return JDR_OK;
WiredHome 115:c9862fd0c689 282 }
WiredHome 115:c9862fd0c689 283
WiredHome 115:c9862fd0c689 284
WiredHome 115:c9862fd0c689 285
WiredHome 115:c9862fd0c689 286
WiredHome 115:c9862fd0c689 287 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 288 /* Extract N bits from input stream */
WiredHome 115:c9862fd0c689 289 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 290
WiredHome 115:c9862fd0c689 291 int16_t GraphicsDisplay::bitext ( /* >=0: extracted data, <0: error code */
WiredHome 115:c9862fd0c689 292 JDEC * jd, /* Pointer to the decompressor object */
WiredHome 115:c9862fd0c689 293 uint16_t nbit /* Number of bits to extract (1 to 11) */
WiredHome 115:c9862fd0c689 294 )
WiredHome 115:c9862fd0c689 295 {
WiredHome 115:c9862fd0c689 296 uint8_t msk, s, *dp;
WiredHome 115:c9862fd0c689 297 uint16_t dc, v, f;
WiredHome 115:c9862fd0c689 298
WiredHome 115:c9862fd0c689 299
WiredHome 115:c9862fd0c689 300 msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */
WiredHome 115:c9862fd0c689 301 s = *dp; v = f = 0;
WiredHome 115:c9862fd0c689 302 do {
WiredHome 115:c9862fd0c689 303 if (!msk) { /* Next byte? */
WiredHome 115:c9862fd0c689 304 if (!dc) { /* No input data is available, re-fill input buffer */
WiredHome 115:c9862fd0c689 305 dp = jd->inbuf; /* Top of input buffer */
WiredHome 115:c9862fd0c689 306 dc = getJpegData(jd, dp, JD_SZBUF);
WiredHome 115:c9862fd0c689 307 if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */
WiredHome 115:c9862fd0c689 308 } else {
WiredHome 115:c9862fd0c689 309 dp++; /* Next data ptr */
WiredHome 115:c9862fd0c689 310 }
WiredHome 115:c9862fd0c689 311 dc--; /* Decrement number of available bytes */
WiredHome 115:c9862fd0c689 312 if (f) { /* In flag sequence? */
WiredHome 115:c9862fd0c689 313 f = 0; /* Exit flag sequence */
WiredHome 115:c9862fd0c689 314 if (*dp != 0) return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
WiredHome 115:c9862fd0c689 315 *dp = s = 0xFF; /* The flag is a data 0xFF */
WiredHome 115:c9862fd0c689 316 } else {
WiredHome 115:c9862fd0c689 317 s = *dp; /* Get next data byte */
WiredHome 115:c9862fd0c689 318 if (s == 0xFF) { /* Is start of flag sequence? */
WiredHome 115:c9862fd0c689 319 f = 1; continue; /* Enter flag sequence */
WiredHome 115:c9862fd0c689 320 }
WiredHome 115:c9862fd0c689 321 }
WiredHome 115:c9862fd0c689 322 msk = 0x80; /* Read from MSB */
WiredHome 115:c9862fd0c689 323 }
WiredHome 115:c9862fd0c689 324 v <<= 1; /* Get a bit */
WiredHome 115:c9862fd0c689 325 if (s & msk) v++;
WiredHome 115:c9862fd0c689 326 msk >>= 1;
WiredHome 115:c9862fd0c689 327 nbit--;
WiredHome 115:c9862fd0c689 328 } while (nbit);
WiredHome 115:c9862fd0c689 329 jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp;
WiredHome 115:c9862fd0c689 330
WiredHome 115:c9862fd0c689 331 return (int16_t)v;
WiredHome 115:c9862fd0c689 332 }
WiredHome 115:c9862fd0c689 333
WiredHome 115:c9862fd0c689 334
WiredHome 115:c9862fd0c689 335
WiredHome 115:c9862fd0c689 336
WiredHome 115:c9862fd0c689 337 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 338 /* Extract a huffman decoded data from input stream */
WiredHome 115:c9862fd0c689 339 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 340
WiredHome 115:c9862fd0c689 341 int16_t GraphicsDisplay::huffext ( /* >=0: decoded data, <0: error code */
WiredHome 115:c9862fd0c689 342 JDEC * jd, /* Pointer to the decompressor object */
WiredHome 115:c9862fd0c689 343 const uint8_t * hbits, /* Pointer to the bit distribution table */
WiredHome 115:c9862fd0c689 344 const uint16_t * hcode, /* Pointer to the code word table */
WiredHome 115:c9862fd0c689 345 const uint8_t * hdata /* Pointer to the data table */
WiredHome 115:c9862fd0c689 346 )
WiredHome 115:c9862fd0c689 347 {
WiredHome 115:c9862fd0c689 348 uint8_t msk, s, *dp;
WiredHome 115:c9862fd0c689 349 uint16_t dc, v, f, bl, nd;
WiredHome 115:c9862fd0c689 350
WiredHome 115:c9862fd0c689 351
WiredHome 115:c9862fd0c689 352 msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */
WiredHome 115:c9862fd0c689 353 s = *dp; v = f = 0;
WiredHome 115:c9862fd0c689 354 bl = 16; /* Max code length */
WiredHome 115:c9862fd0c689 355 do {
WiredHome 115:c9862fd0c689 356 if (!msk) { /* Next byte? */
WiredHome 115:c9862fd0c689 357 if (!dc) { /* No input data is available, re-fill input buffer */
WiredHome 115:c9862fd0c689 358 dp = jd->inbuf; /* Top of input buffer */
WiredHome 115:c9862fd0c689 359 dc = getJpegData(jd, dp, JD_SZBUF);
WiredHome 115:c9862fd0c689 360 if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */
WiredHome 115:c9862fd0c689 361 } else {
WiredHome 115:c9862fd0c689 362 dp++; /* Next data ptr */
WiredHome 115:c9862fd0c689 363 }
WiredHome 115:c9862fd0c689 364 dc--; /* Decrement number of available bytes */
WiredHome 115:c9862fd0c689 365 if (f) { /* In flag sequence? */
WiredHome 115:c9862fd0c689 366 f = 0; /* Exit flag sequence */
WiredHome 115:c9862fd0c689 367 if (*dp != 0)
WiredHome 115:c9862fd0c689 368 return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
WiredHome 115:c9862fd0c689 369 *dp = s = 0xFF; /* The flag is a data 0xFF */
WiredHome 115:c9862fd0c689 370 } else {
WiredHome 115:c9862fd0c689 371 s = *dp; /* Get next data byte */
WiredHome 115:c9862fd0c689 372 if (s == 0xFF) { /* Is start of flag sequence? */
WiredHome 115:c9862fd0c689 373 f = 1; continue; /* Enter flag sequence, get trailing byte */
WiredHome 115:c9862fd0c689 374 }
WiredHome 115:c9862fd0c689 375 }
WiredHome 115:c9862fd0c689 376 msk = 0x80; /* Read from MSB */
WiredHome 115:c9862fd0c689 377 }
WiredHome 115:c9862fd0c689 378 v <<= 1; /* Get a bit */
WiredHome 115:c9862fd0c689 379 if (s & msk) v++;
WiredHome 115:c9862fd0c689 380 msk >>= 1;
WiredHome 115:c9862fd0c689 381
WiredHome 115:c9862fd0c689 382 for (nd = *hbits++; nd; nd--) { /* Search the code word in this bit length */
WiredHome 115:c9862fd0c689 383 if (v == *hcode++) { /* Matched? */
WiredHome 115:c9862fd0c689 384 jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp;
WiredHome 115:c9862fd0c689 385 return *hdata; /* Return the decoded data */
WiredHome 115:c9862fd0c689 386 }
WiredHome 115:c9862fd0c689 387 hdata++;
WiredHome 115:c9862fd0c689 388 }
WiredHome 115:c9862fd0c689 389 bl--;
WiredHome 115:c9862fd0c689 390 } while (bl);
WiredHome 115:c9862fd0c689 391
WiredHome 115:c9862fd0c689 392 return 0 - (int16_t)JDR_FMT1; /* Err: code not found (may be collapted data) */
WiredHome 115:c9862fd0c689 393 }
WiredHome 115:c9862fd0c689 394
WiredHome 115:c9862fd0c689 395
WiredHome 115:c9862fd0c689 396
WiredHome 115:c9862fd0c689 397
WiredHome 115:c9862fd0c689 398 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 399 /* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */
WiredHome 115:c9862fd0c689 400 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 401
WiredHome 115:c9862fd0c689 402 static
WiredHome 115:c9862fd0c689 403 void block_idct (
WiredHome 115:c9862fd0c689 404 int32_t * src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */
WiredHome 115:c9862fd0c689 405 uint8_t * dst /* Pointer to the destination to store the block as byte array */
WiredHome 115:c9862fd0c689 406 )
WiredHome 115:c9862fd0c689 407 {
WiredHome 115:c9862fd0c689 408 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);
WiredHome 115:c9862fd0c689 409 int32_t v0, v1, v2, v3, v4, v5, v6, v7;
WiredHome 115:c9862fd0c689 410 int32_t t10, t11, t12, t13;
WiredHome 115:c9862fd0c689 411 uint16_t i;
WiredHome 115:c9862fd0c689 412
WiredHome 115:c9862fd0c689 413 /* Process columns */
WiredHome 115:c9862fd0c689 414 for (i = 0; i < 8; i++) {
WiredHome 115:c9862fd0c689 415 v0 = src[8 * 0]; /* Get even elements */
WiredHome 115:c9862fd0c689 416 v1 = src[8 * 2];
WiredHome 115:c9862fd0c689 417 v2 = src[8 * 4];
WiredHome 115:c9862fd0c689 418 v3 = src[8 * 6];
WiredHome 115:c9862fd0c689 419
WiredHome 115:c9862fd0c689 420 t10 = v0 + v2; /* Process the even elements */
WiredHome 115:c9862fd0c689 421 t12 = v0 - v2;
WiredHome 115:c9862fd0c689 422 t11 = (v1 - v3) * M13 >> 12;
WiredHome 115:c9862fd0c689 423 v3 += v1;
WiredHome 115:c9862fd0c689 424 t11 -= v3;
WiredHome 115:c9862fd0c689 425 v0 = t10 + v3;
WiredHome 115:c9862fd0c689 426 v3 = t10 - v3;
WiredHome 115:c9862fd0c689 427 v1 = t11 + t12;
WiredHome 115:c9862fd0c689 428 v2 = t12 - t11;
WiredHome 115:c9862fd0c689 429
WiredHome 115:c9862fd0c689 430 v4 = src[8 * 7]; /* Get odd elements */
WiredHome 115:c9862fd0c689 431 v5 = src[8 * 1];
WiredHome 115:c9862fd0c689 432 v6 = src[8 * 5];
WiredHome 115:c9862fd0c689 433 v7 = src[8 * 3];
WiredHome 115:c9862fd0c689 434
WiredHome 115:c9862fd0c689 435 t10 = v5 - v4; /* Process the odd elements */
WiredHome 115:c9862fd0c689 436 t11 = v5 + v4;
WiredHome 115:c9862fd0c689 437 t12 = v6 - v7;
WiredHome 115:c9862fd0c689 438 v7 += v6;
WiredHome 115:c9862fd0c689 439 v5 = (t11 - v7) * M13 >> 12;
WiredHome 115:c9862fd0c689 440 v7 += t11;
WiredHome 115:c9862fd0c689 441 t13 = (t10 + t12) * M5 >> 12;
WiredHome 115:c9862fd0c689 442 v4 = t13 - (t10 * M2 >> 12);
WiredHome 115:c9862fd0c689 443 v6 = t13 - (t12 * M4 >> 12) - v7;
WiredHome 115:c9862fd0c689 444 v5 -= v6;
WiredHome 115:c9862fd0c689 445 v4 -= v5;
WiredHome 115:c9862fd0c689 446
WiredHome 115:c9862fd0c689 447 src[8 * 0] = v0 + v7; /* Write-back transformed values */
WiredHome 115:c9862fd0c689 448 src[8 * 7] = v0 - v7;
WiredHome 115:c9862fd0c689 449 src[8 * 1] = v1 + v6;
WiredHome 115:c9862fd0c689 450 src[8 * 6] = v1 - v6;
WiredHome 115:c9862fd0c689 451 src[8 * 2] = v2 + v5;
WiredHome 115:c9862fd0c689 452 src[8 * 5] = v2 - v5;
WiredHome 115:c9862fd0c689 453 src[8 * 3] = v3 + v4;
WiredHome 115:c9862fd0c689 454 src[8 * 4] = v3 - v4;
WiredHome 115:c9862fd0c689 455
WiredHome 115:c9862fd0c689 456 src++; /* Next column */
WiredHome 115:c9862fd0c689 457 }
WiredHome 115:c9862fd0c689 458
WiredHome 115:c9862fd0c689 459 /* Process rows */
WiredHome 115:c9862fd0c689 460 src -= 8;
WiredHome 115:c9862fd0c689 461 for (i = 0; i < 8; i++) {
WiredHome 115:c9862fd0c689 462 v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */
WiredHome 115:c9862fd0c689 463 v1 = src[2];
WiredHome 115:c9862fd0c689 464 v2 = src[4];
WiredHome 115:c9862fd0c689 465 v3 = src[6];
WiredHome 115:c9862fd0c689 466
WiredHome 115:c9862fd0c689 467 t10 = v0 + v2; /* Process the even elements */
WiredHome 115:c9862fd0c689 468 t12 = v0 - v2;
WiredHome 115:c9862fd0c689 469 t11 = (v1 - v3) * M13 >> 12;
WiredHome 115:c9862fd0c689 470 v3 += v1;
WiredHome 115:c9862fd0c689 471 t11 -= v3;
WiredHome 115:c9862fd0c689 472 v0 = t10 + v3;
WiredHome 115:c9862fd0c689 473 v3 = t10 - v3;
WiredHome 115:c9862fd0c689 474 v1 = t11 + t12;
WiredHome 115:c9862fd0c689 475 v2 = t12 - t11;
WiredHome 115:c9862fd0c689 476
WiredHome 115:c9862fd0c689 477 v4 = src[7]; /* Get odd elements */
WiredHome 115:c9862fd0c689 478 v5 = src[1];
WiredHome 115:c9862fd0c689 479 v6 = src[5];
WiredHome 115:c9862fd0c689 480 v7 = src[3];
WiredHome 115:c9862fd0c689 481
WiredHome 115:c9862fd0c689 482 t10 = v5 - v4; /* Process the odd elements */
WiredHome 115:c9862fd0c689 483 t11 = v5 + v4;
WiredHome 115:c9862fd0c689 484 t12 = v6 - v7;
WiredHome 115:c9862fd0c689 485 v7 += v6;
WiredHome 115:c9862fd0c689 486 v5 = (t11 - v7) * M13 >> 12;
WiredHome 115:c9862fd0c689 487 v7 += t11;
WiredHome 115:c9862fd0c689 488 t13 = (t10 + t12) * M5 >> 12;
WiredHome 115:c9862fd0c689 489 v4 = t13 - (t10 * M2 >> 12);
WiredHome 115:c9862fd0c689 490 v6 = t13 - (t12 * M4 >> 12) - v7;
WiredHome 115:c9862fd0c689 491 v5 -= v6;
WiredHome 115:c9862fd0c689 492 v4 -= v5;
WiredHome 115:c9862fd0c689 493
WiredHome 115:c9862fd0c689 494 dst[0] = BYTECLIP((v0 + v7) >> 8); /* Descale the transformed values 8 bits and output */
WiredHome 115:c9862fd0c689 495 dst[7] = BYTECLIP((v0 - v7) >> 8);
WiredHome 115:c9862fd0c689 496 dst[1] = BYTECLIP((v1 + v6) >> 8);
WiredHome 115:c9862fd0c689 497 dst[6] = BYTECLIP((v1 - v6) >> 8);
WiredHome 115:c9862fd0c689 498 dst[2] = BYTECLIP((v2 + v5) >> 8);
WiredHome 115:c9862fd0c689 499 dst[5] = BYTECLIP((v2 - v5) >> 8);
WiredHome 115:c9862fd0c689 500 dst[3] = BYTECLIP((v3 + v4) >> 8);
WiredHome 115:c9862fd0c689 501 dst[4] = BYTECLIP((v3 - v4) >> 8);
WiredHome 115:c9862fd0c689 502 dst += 8;
WiredHome 115:c9862fd0c689 503
WiredHome 115:c9862fd0c689 504 src += 8; /* Next row */
WiredHome 115:c9862fd0c689 505 }
WiredHome 115:c9862fd0c689 506 }
WiredHome 115:c9862fd0c689 507
WiredHome 115:c9862fd0c689 508
WiredHome 115:c9862fd0c689 509
WiredHome 115:c9862fd0c689 510
WiredHome 115:c9862fd0c689 511 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 512 /* Load all blocks in the MCU into working buffer */
WiredHome 115:c9862fd0c689 513 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 514
WiredHome 115:c9862fd0c689 515 JRESULT GraphicsDisplay::mcu_load (
WiredHome 115:c9862fd0c689 516 JDEC * jd /* Pointer to the decompressor object */
WiredHome 115:c9862fd0c689 517 )
WiredHome 115:c9862fd0c689 518 {
WiredHome 115:c9862fd0c689 519 int32_t *tmp = (int32_t *)jd->workbuf; /* Block working buffer for de-quantize and IDCT */
WiredHome 115:c9862fd0c689 520 uint16_t blk, nby, nbc, i, z, id, cmp;
WiredHome 115:c9862fd0c689 521 int16_t b, d, e;
WiredHome 115:c9862fd0c689 522 uint8_t *bp;
WiredHome 115:c9862fd0c689 523 const uint8_t *hb, *hd;
WiredHome 115:c9862fd0c689 524 const uint16_t *hc;
WiredHome 115:c9862fd0c689 525 const int32_t *dqf;
WiredHome 115:c9862fd0c689 526
WiredHome 118:34eb0b64fc61 527 INFO("mcu_load");
WiredHome 118:34eb0b64fc61 528 HexDump("JDEC", (uint8_t *)jd, sizeof(JDEC));
WiredHome 197:853d08e2fb53 529
WiredHome 115:c9862fd0c689 530 nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */
WiredHome 115:c9862fd0c689 531 nbc = 2; /* Number of C blocks (2) */
WiredHome 115:c9862fd0c689 532 bp = jd->mcubuf; /* Pointer to the first block */
WiredHome 115:c9862fd0c689 533
WiredHome 115:c9862fd0c689 534 for (blk = 0; blk < nby + nbc; blk++) {
WiredHome 115:c9862fd0c689 535 cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */
WiredHome 115:c9862fd0c689 536 id = cmp ? 1 : 0; /* Huffman table ID of the component */
WiredHome 115:c9862fd0c689 537
WiredHome 115:c9862fd0c689 538 /* Extract a DC element from input stream */
WiredHome 115:c9862fd0c689 539 hb = jd->huffbits[id][0]; /* Huffman table for the DC element */
WiredHome 115:c9862fd0c689 540 hc = jd->huffcode[id][0];
WiredHome 115:c9862fd0c689 541 hd = jd->huffdata[id][0];
WiredHome 115:c9862fd0c689 542 b = huffext(jd, hb, hc, hd); /* Extract a huffman coded data (bit length) */
WiredHome 115:c9862fd0c689 543 if (b < 0) return (JRESULT)(0 - b); /* Err: invalid code or input */
WiredHome 115:c9862fd0c689 544 d = jd->dcv[cmp]; /* DC value of previous block */
WiredHome 115:c9862fd0c689 545 if (b) { /* If there is any difference from previous block */
WiredHome 115:c9862fd0c689 546 e = bitext(jd, b); /* Extract data bits */
WiredHome 115:c9862fd0c689 547 if (e < 0) return (JRESULT)(0 - e); /* Err: input */
WiredHome 115:c9862fd0c689 548 b = 1 << (b - 1); /* MSB position */
WiredHome 115:c9862fd0c689 549 if (!(e & b)) e -= (b << 1) - 1; /* Restore sign if needed */
WiredHome 115:c9862fd0c689 550 d += e; /* Get current value */
WiredHome 115:c9862fd0c689 551 jd->dcv[cmp] = (int16_t)d; /* Save current DC value for next block */
WiredHome 115:c9862fd0c689 552 }
WiredHome 115:c9862fd0c689 553 dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */
WiredHome 115:c9862fd0c689 554 tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */
WiredHome 115:c9862fd0c689 555
WiredHome 115:c9862fd0c689 556 /* Extract following 63 AC elements from input stream */
WiredHome 115:c9862fd0c689 557 for (i = 1; i < 64; i++) tmp[i] = 0; /* Clear rest of elements */
WiredHome 115:c9862fd0c689 558 hb = jd->huffbits[id][1]; /* Huffman table for the AC elements */
WiredHome 115:c9862fd0c689 559 hc = jd->huffcode[id][1];
WiredHome 115:c9862fd0c689 560 hd = jd->huffdata[id][1];
WiredHome 115:c9862fd0c689 561 i = 1; /* Top of the AC elements */
WiredHome 115:c9862fd0c689 562 do {
WiredHome 115:c9862fd0c689 563 b = huffext(jd, hb, hc, hd); /* Extract a huffman coded value (zero runs and bit length) */
WiredHome 115:c9862fd0c689 564 if (b == 0) break; /* EOB? */
WiredHome 115:c9862fd0c689 565 if (b < 0) return (JRESULT)(0 - b); /* Err: invalid code or input error */
WiredHome 115:c9862fd0c689 566 z = (uint16_t)b >> 4; /* Number of leading zero elements */
WiredHome 115:c9862fd0c689 567 if (z) {
WiredHome 115:c9862fd0c689 568 i += z; /* Skip zero elements */
WiredHome 115:c9862fd0c689 569 if (i >= 64) return JDR_FMT1; /* Too long zero run */
WiredHome 115:c9862fd0c689 570 }
WiredHome 115:c9862fd0c689 571 if (b &= 0x0F) { /* Bit length */
WiredHome 115:c9862fd0c689 572 d = bitext(jd, b); /* Extract data bits */
WiredHome 115:c9862fd0c689 573 if (d < 0) return (JRESULT)(0 - d); /* Err: input device */
WiredHome 115:c9862fd0c689 574 b = 1 << (b - 1); /* MSB position */
WiredHome 115:c9862fd0c689 575 if (!(d & b)) d -= (b << 1) - 1;/* Restore negative value if needed */
WiredHome 115:c9862fd0c689 576 z = ZIG(i); /* Zigzag-order to raster-order converted index */
WiredHome 115:c9862fd0c689 577 tmp[z] = d * dqf[z] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */
WiredHome 115:c9862fd0c689 578 }
WiredHome 115:c9862fd0c689 579 } while (++i < 64); /* Next AC element */
WiredHome 115:c9862fd0c689 580
WiredHome 115:c9862fd0c689 581 if (JD_USE_SCALE && jd->scale == 3)
WiredHome 115:c9862fd0c689 582 *bp = (*tmp / 256) + 128; /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */
WiredHome 115:c9862fd0c689 583 else
WiredHome 115:c9862fd0c689 584 block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */
WiredHome 115:c9862fd0c689 585
WiredHome 115:c9862fd0c689 586 bp += 64; /* Next block */
WiredHome 115:c9862fd0c689 587 }
WiredHome 115:c9862fd0c689 588
WiredHome 115:c9862fd0c689 589 return JDR_OK; /* All blocks have been loaded successfully */
WiredHome 115:c9862fd0c689 590 }
WiredHome 115:c9862fd0c689 591
WiredHome 115:c9862fd0c689 592
WiredHome 115:c9862fd0c689 593
WiredHome 115:c9862fd0c689 594
WiredHome 115:c9862fd0c689 595 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 596 /* Output an MCU: Convert YCrCb to RGB and output it in RGB form */
WiredHome 115:c9862fd0c689 597 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 598
WiredHome 115:c9862fd0c689 599 JRESULT GraphicsDisplay::mcu_output (
WiredHome 115:c9862fd0c689 600 JDEC * jd, /* Pointer to the decompressor object */
WiredHome 115:c9862fd0c689 601 uint16_t (* outfunc)(JDEC * jd, void * stream, JRECT * rect), /* RGB output function */
WiredHome 115:c9862fd0c689 602 uint16_t x, /* MCU position in the image (left of the MCU) */
WiredHome 115:c9862fd0c689 603 uint16_t y /* MCU position in the image (top of the MCU) */
WiredHome 115:c9862fd0c689 604 )
WiredHome 115:c9862fd0c689 605 {
WiredHome 115:c9862fd0c689 606 const int16_t CVACC = (sizeof (int16_t) > 2) ? 1024 : 128;
WiredHome 115:c9862fd0c689 607 uint16_t ix, iy, mx, my, rx, ry;
WiredHome 115:c9862fd0c689 608 int16_t yy, cb, cr;
WiredHome 115:c9862fd0c689 609 uint8_t *py, *pc, *rgb24;
WiredHome 115:c9862fd0c689 610 JRECT rect;
WiredHome 115:c9862fd0c689 611
WiredHome 118:34eb0b64fc61 612 INFO("mcu_output(%p,%p,%d,%d)", jd, outfunc, x, y);
WiredHome 118:34eb0b64fc61 613 HexDump("JDEC", (uint8_t *)jd, sizeof(JDEC));
WiredHome 118:34eb0b64fc61 614
WiredHome 115:c9862fd0c689 615 mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */
WiredHome 115:c9862fd0c689 616 rx = (x + mx <= jd->width) ? mx : jd->width - x; /* Output rectangular size (it may be clipped at right/bottom end) */
WiredHome 115:c9862fd0c689 617 ry = (y + my <= jd->height) ? my : jd->height - y;
WiredHome 115:c9862fd0c689 618 if (JD_USE_SCALE) {
WiredHome 115:c9862fd0c689 619 rx >>= jd->scale; ry >>= jd->scale;
WiredHome 115:c9862fd0c689 620 if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */
WiredHome 115:c9862fd0c689 621 x >>= jd->scale; y >>= jd->scale;
WiredHome 115:c9862fd0c689 622 }
WiredHome 115:c9862fd0c689 623 rect.left = x; rect.right = x + rx - 1; /* Rectangular area in the frame buffer */
WiredHome 115:c9862fd0c689 624 rect.top = y; rect.bottom = y + ry - 1;
WiredHome 115:c9862fd0c689 625
WiredHome 115:c9862fd0c689 626
WiredHome 115:c9862fd0c689 627 if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */
WiredHome 115:c9862fd0c689 628
WiredHome 115:c9862fd0c689 629 /* Build an RGB MCU from discrete comopnents */
WiredHome 115:c9862fd0c689 630 rgb24 = (uint8_t *)jd->workbuf;
WiredHome 115:c9862fd0c689 631 for (iy = 0; iy < my; iy++) {
WiredHome 115:c9862fd0c689 632 pc = jd->mcubuf;
WiredHome 115:c9862fd0c689 633 py = pc + iy * 8;
WiredHome 115:c9862fd0c689 634 if (my == 16) { /* Double block height? */
WiredHome 115:c9862fd0c689 635 pc += 64 * 4 + (iy >> 1) * 8;
WiredHome 115:c9862fd0c689 636 if (iy >= 8) py += 64;
WiredHome 115:c9862fd0c689 637 } else { /* Single block height */
WiredHome 115:c9862fd0c689 638 pc += mx * 8 + iy * 8;
WiredHome 115:c9862fd0c689 639 }
WiredHome 115:c9862fd0c689 640 for (ix = 0; ix < mx; ix++) {
WiredHome 115:c9862fd0c689 641 cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */
WiredHome 115:c9862fd0c689 642 cr = pc[64] - 128;
WiredHome 115:c9862fd0c689 643 if (mx == 16) { /* Double block width? */
WiredHome 115:c9862fd0c689 644 if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */
WiredHome 115:c9862fd0c689 645 pc += ix & 1; /* Increase chroma pointer every two pixels */
WiredHome 115:c9862fd0c689 646 } else { /* Single block width */
WiredHome 115:c9862fd0c689 647 pc++; /* Increase chroma pointer every pixel */
WiredHome 115:c9862fd0c689 648 }
WiredHome 115:c9862fd0c689 649 yy = *py++; /* Get Y component */
WiredHome 115:c9862fd0c689 650
WiredHome 115:c9862fd0c689 651 /* Convert YCbCr to RGB */
WiredHome 115:c9862fd0c689 652 *rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr) / CVACC);
WiredHome 115:c9862fd0c689 653 *rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC);
WiredHome 115:c9862fd0c689 654 *rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb) / CVACC);
WiredHome 115:c9862fd0c689 655 }
WiredHome 115:c9862fd0c689 656 }
WiredHome 115:c9862fd0c689 657
WiredHome 115:c9862fd0c689 658 /* Descale the MCU rectangular if needed */
WiredHome 115:c9862fd0c689 659 if (JD_USE_SCALE && jd->scale) {
WiredHome 115:c9862fd0c689 660 uint16_t x, y, r, g, b, s, w, a;
WiredHome 115:c9862fd0c689 661 uint8_t *op;
WiredHome 115:c9862fd0c689 662
WiredHome 115:c9862fd0c689 663 /* Get averaged RGB value of each square correcponds to a pixel */
WiredHome 115:c9862fd0c689 664 s = jd->scale * 2; /* Bumber of shifts for averaging */
WiredHome 115:c9862fd0c689 665 w = 1 << jd->scale; /* Width of square */
WiredHome 115:c9862fd0c689 666 a = (mx - w) * 3; /* Bytes to skip for next line in the square */
WiredHome 115:c9862fd0c689 667 op = (uint8_t *)jd->workbuf;
WiredHome 115:c9862fd0c689 668 for (iy = 0; iy < my; iy += w) {
WiredHome 115:c9862fd0c689 669 for (ix = 0; ix < mx; ix += w) {
WiredHome 115:c9862fd0c689 670 rgb24 = (uint8_t *)jd->workbuf + (iy * mx + ix) * 3;
WiredHome 115:c9862fd0c689 671 r = g = b = 0;
WiredHome 115:c9862fd0c689 672 for (y = 0; y < w; y++) { /* Accumulate RGB value in the square */
WiredHome 115:c9862fd0c689 673 for (x = 0; x < w; x++) {
WiredHome 115:c9862fd0c689 674 r += *rgb24++;
WiredHome 115:c9862fd0c689 675 g += *rgb24++;
WiredHome 115:c9862fd0c689 676 b += *rgb24++;
WiredHome 115:c9862fd0c689 677 }
WiredHome 115:c9862fd0c689 678 rgb24 += a;
WiredHome 115:c9862fd0c689 679 } /* Put the averaged RGB value as a pixel */
WiredHome 115:c9862fd0c689 680 *op++ = (uint8_t)(r >> s);
WiredHome 115:c9862fd0c689 681 *op++ = (uint8_t)(g >> s);
WiredHome 115:c9862fd0c689 682 *op++ = (uint8_t)(b >> s);
WiredHome 115:c9862fd0c689 683 }
WiredHome 115:c9862fd0c689 684 }
WiredHome 115:c9862fd0c689 685 }
WiredHome 115:c9862fd0c689 686
WiredHome 115:c9862fd0c689 687 } else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */
WiredHome 115:c9862fd0c689 688
WiredHome 115:c9862fd0c689 689 /* Build a 1/8 descaled RGB MCU from discrete comopnents */
WiredHome 115:c9862fd0c689 690 rgb24 = (uint8_t *)jd->workbuf;
WiredHome 115:c9862fd0c689 691 pc = jd->mcubuf + mx * my;
WiredHome 115:c9862fd0c689 692 cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */
WiredHome 115:c9862fd0c689 693 cr = pc[64] - 128;
WiredHome 115:c9862fd0c689 694 for (iy = 0; iy < my; iy += 8) {
WiredHome 115:c9862fd0c689 695 py = jd->mcubuf;
WiredHome 115:c9862fd0c689 696 if (iy == 8) py += 64 * 2;
WiredHome 115:c9862fd0c689 697 for (ix = 0; ix < mx; ix += 8) {
WiredHome 115:c9862fd0c689 698 yy = *py; /* Get Y component */
WiredHome 115:c9862fd0c689 699 py += 64;
WiredHome 115:c9862fd0c689 700
WiredHome 115:c9862fd0c689 701 /* Convert YCbCr to RGB */
WiredHome 115:c9862fd0c689 702 *rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr / CVACC));
WiredHome 115:c9862fd0c689 703 *rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC);
WiredHome 115:c9862fd0c689 704 *rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb / CVACC));
WiredHome 115:c9862fd0c689 705 }
WiredHome 115:c9862fd0c689 706 }
WiredHome 115:c9862fd0c689 707 }
WiredHome 115:c9862fd0c689 708
WiredHome 115:c9862fd0c689 709 /* Squeeze up pixel table if a part of MCU is to be truncated */
WiredHome 115:c9862fd0c689 710 mx >>= jd->scale;
WiredHome 115:c9862fd0c689 711 if (rx < mx) {
WiredHome 115:c9862fd0c689 712 uint8_t *s, *d;
WiredHome 115:c9862fd0c689 713 uint16_t x, y;
WiredHome 115:c9862fd0c689 714
WiredHome 115:c9862fd0c689 715 s = d = (uint8_t *)jd->workbuf;
WiredHome 115:c9862fd0c689 716 for (y = 0; y < ry; y++) {
WiredHome 115:c9862fd0c689 717 for (x = 0; x < rx; x++) { /* Copy effective pixels */
WiredHome 115:c9862fd0c689 718 *d++ = *s++;
WiredHome 115:c9862fd0c689 719 *d++ = *s++;
WiredHome 115:c9862fd0c689 720 *d++ = *s++;
WiredHome 115:c9862fd0c689 721 }
WiredHome 115:c9862fd0c689 722 s += (mx - rx) * 3; /* Skip truncated pixels */
WiredHome 115:c9862fd0c689 723 }
WiredHome 115:c9862fd0c689 724 }
WiredHome 115:c9862fd0c689 725
WiredHome 115:c9862fd0c689 726 /* Convert RGB888 to RGB565 if needed */
WiredHome 115:c9862fd0c689 727 if (JD_FORMAT == 1) {
WiredHome 115:c9862fd0c689 728 uint8_t *s = (uint8_t *)jd->workbuf;
WiredHome 115:c9862fd0c689 729 uint16_t w, *d = (uint16_t *)s;
WiredHome 115:c9862fd0c689 730 uint16_t n = rx * ry;
WiredHome 115:c9862fd0c689 731
WiredHome 115:c9862fd0c689 732 do {
WiredHome 115:c9862fd0c689 733 w = (*s++ & 0xF8) << 8; /* RRRRR----------- */
WiredHome 115:c9862fd0c689 734 w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */
WiredHome 115:c9862fd0c689 735 w |= *s++ >> 3; /* -----------BBBBB */
WiredHome 115:c9862fd0c689 736 *d++ = w;
WiredHome 115:c9862fd0c689 737 } while (--n);
WiredHome 115:c9862fd0c689 738 }
WiredHome 115:c9862fd0c689 739
WiredHome 115:c9862fd0c689 740 /* Output the RGB rectangular */
WiredHome 119:d129b798f82f 741 INFO("call outfunc");
WiredHome 115:c9862fd0c689 742 if (outfunc)
WiredHome 197:853d08e2fb53 743 return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR;
WiredHome 115:c9862fd0c689 744 else
WiredHome 115:c9862fd0c689 745 return privOutFunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR;
WiredHome 115:c9862fd0c689 746 }
WiredHome 115:c9862fd0c689 747
WiredHome 115:c9862fd0c689 748
WiredHome 115:c9862fd0c689 749
WiredHome 115:c9862fd0c689 750
WiredHome 115:c9862fd0c689 751 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 752 /* Process restart interval */
WiredHome 115:c9862fd0c689 753 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 754
WiredHome 115:c9862fd0c689 755 JRESULT GraphicsDisplay::restart (
WiredHome 115:c9862fd0c689 756 JDEC * jd, /* Pointer to the decompressor object */
WiredHome 115:c9862fd0c689 757 uint16_t rstn /* Expected restert sequense number */
WiredHome 115:c9862fd0c689 758 )
WiredHome 115:c9862fd0c689 759 {
WiredHome 115:c9862fd0c689 760 uint16_t i, dc;
WiredHome 115:c9862fd0c689 761 uint16_t d;
WiredHome 115:c9862fd0c689 762 uint8_t *dp;
WiredHome 197:853d08e2fb53 763
WiredHome 116:43e5bd2d7302 764 INFO("restart(%p,%d)", jd, rstn);
WiredHome 115:c9862fd0c689 765
WiredHome 115:c9862fd0c689 766 /* Discard padding bits and get two bytes from the input stream */
WiredHome 115:c9862fd0c689 767 dp = jd->dptr; dc = jd->dctr;
WiredHome 115:c9862fd0c689 768 d = 0;
WiredHome 115:c9862fd0c689 769 for (i = 0; i < 2; i++) {
WiredHome 115:c9862fd0c689 770 if (!dc) { /* No input data is available, re-fill input buffer */
WiredHome 115:c9862fd0c689 771 dp = jd->inbuf;
WiredHome 115:c9862fd0c689 772 dc = getJpegData(jd, dp, JD_SZBUF);
WiredHome 115:c9862fd0c689 773 if (!dc) return JDR_INP;
WiredHome 115:c9862fd0c689 774 } else {
WiredHome 115:c9862fd0c689 775 dp++;
WiredHome 115:c9862fd0c689 776 }
WiredHome 115:c9862fd0c689 777 dc--;
WiredHome 115:c9862fd0c689 778 d = (d << 8) | *dp; /* Get a byte */
WiredHome 115:c9862fd0c689 779 }
WiredHome 115:c9862fd0c689 780 jd->dptr = dp; jd->dctr = dc; jd->dmsk = 0;
WiredHome 115:c9862fd0c689 781
WiredHome 115:c9862fd0c689 782 /* Check the marker */
WiredHome 115:c9862fd0c689 783 if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7))
WiredHome 115:c9862fd0c689 784 return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */
WiredHome 115:c9862fd0c689 785
WiredHome 115:c9862fd0c689 786 /* Reset DC offset */
WiredHome 115:c9862fd0c689 787 jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0;
WiredHome 115:c9862fd0c689 788
WiredHome 115:c9862fd0c689 789 return JDR_OK;
WiredHome 115:c9862fd0c689 790 }
WiredHome 115:c9862fd0c689 791
WiredHome 115:c9862fd0c689 792
WiredHome 115:c9862fd0c689 793
WiredHome 115:c9862fd0c689 794
WiredHome 115:c9862fd0c689 795 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 796 /* Analyze the JPEG image and Initialize decompressor object */
WiredHome 115:c9862fd0c689 797 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 798
WiredHome 115:c9862fd0c689 799 #define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t *)(ptr))<<8)|(uint16_t)*(uint8_t *)((ptr)+1))
WiredHome 115:c9862fd0c689 800
WiredHome 115:c9862fd0c689 801 uint16_t GraphicsDisplay::privInFunc(JDEC * jd, uint8_t * buff, uint16_t ndata)
WiredHome 115:c9862fd0c689 802 {
WiredHome 120:be2aaa3adf72 803 //INFO("Read in %p count %d", buff, ndata);
WiredHome 115:c9862fd0c689 804 if (buff) {
WiredHome 115:c9862fd0c689 805 size_t n = fread(buff, 1, ndata, (FILE *)jd->device);
WiredHome 115:c9862fd0c689 806 INFO("fread returned %d of %d", n, ndata);
WiredHome 115:c9862fd0c689 807 HexDump("buf", buff, (ndata > 32) ? 32 : ndata);
WiredHome 115:c9862fd0c689 808 return n == (size_t)-1 ? 0 : n;
WiredHome 115:c9862fd0c689 809 } else {
WiredHome 115:c9862fd0c689 810 off_t t = fseek((FILE *)jd->device, ndata, SEEK_CUR);
WiredHome 115:c9862fd0c689 811 INFO("Seek returned %d", t);
WiredHome 115:c9862fd0c689 812 return t == (off_t)-1 ? 0 : ndata;
WiredHome 115:c9862fd0c689 813 }
WiredHome 115:c9862fd0c689 814 }
WiredHome 115:c9862fd0c689 815
WiredHome 115:c9862fd0c689 816 uint16_t GraphicsDisplay::getJpegData(JDEC * jd, uint8_t * buff, uint16_t ndata)
WiredHome 115:c9862fd0c689 817 {
WiredHome 120:be2aaa3adf72 818 //INFO("getJpegData(%p, %p, %d)", jd, buff, ndata);
WiredHome 115:c9862fd0c689 819 if (jd->infunc)
WiredHome 115:c9862fd0c689 820 return jd->infunc(jd, buff, ndata);
WiredHome 115:c9862fd0c689 821 else
WiredHome 115:c9862fd0c689 822 return privInFunc(jd, buff, ndata);
WiredHome 115:c9862fd0c689 823 }
WiredHome 115:c9862fd0c689 824
WiredHome 136:224e03d5c31f 825 // RGB565 if JD_FORMAT == 1
WiredHome 136:224e03d5c31f 826 // RGB888 if JD_FORMAT == 0
WiredHome 115:c9862fd0c689 827 uint16_t GraphicsDisplay::privOutFunc(JDEC * jd, void * bitmap, JRECT * rect)
WiredHome 115:c9862fd0c689 828 {
WiredHome 115:c9862fd0c689 829 int x0 = rect->left;
WiredHome 115:c9862fd0c689 830 int x1 = rect->right;
WiredHome 115:c9862fd0c689 831 int y0 = rect->top;
WiredHome 115:c9862fd0c689 832 int y1 = rect->bottom;
WiredHome 197:853d08e2fb53 833
WiredHome 115:c9862fd0c689 834 INFO("privOutFunc: (%d,%d)-(%d,%d) : (%d,%d)", x0,y0, x1,y1, width(), height());
WiredHome 115:c9862fd0c689 835 if (y0 >= height() || x0 >= width())
WiredHome 136:224e03d5c31f 836 return 1; // off the right || bottom of screen
WiredHome 136:224e03d5c31f 837 if (x1 > width()-1) x1 = width() - 1; // clip to width
WiredHome 136:224e03d5c31f 838 if (y1 > height()-1) y1 = height() - 1; // clip to height
WiredHome 136:224e03d5c31f 839
WiredHome 115:c9862fd0c689 840 int w = x1 - x0 + 1;
WiredHome 136:224e03d5c31f 841
WiredHome 136:224e03d5c31f 842 #if 1
WiredHome 136:224e03d5c31f 843 uint32_t pixelCount = (1 + (y1-y0)) * (1+x1-x0);
WiredHome 136:224e03d5c31f 844 #if JD_FORMAT == 0
WiredHome 136:224e03d5c31f 845 uint8_t *s = (uint8_t *)bitmap;
WiredHome 136:224e03d5c31f 846 uint16_t rgb565, *d = (uint16_t *)s;
WiredHome 197:853d08e2fb53 847 uint32_t pCount = pixelCount;
WiredHome 197:853d08e2fb53 848
WiredHome 136:224e03d5c31f 849 do {
WiredHome 136:224e03d5c31f 850 rgb565 = (*s++ & 0xF8) << 8; /* RRRRR----------- */
WiredHome 136:224e03d5c31f 851 rgb565 |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */
WiredHome 136:224e03d5c31f 852 rgb565 |= *s++ >> 3; /* -----------BBBBB */
WiredHome 136:224e03d5c31f 853 *d++ = rgb565;
WiredHome 136:224e03d5c31f 854 } while (--pCount);
WiredHome 136:224e03d5c31f 855 #endif
WiredHome 136:224e03d5c31f 856 //
WiredHome 136:224e03d5c31f 857 window(x0+img_x, y0+img_y, w, y1 - y0 + 2);
WiredHome 136:224e03d5c31f 858 uint16_t *src = (uint16_t *)bitmap; // pointer to RGB565 format
WiredHome 136:224e03d5c31f 859 pixelStream(src, pixelCount, x0+img_x, y0+img_y);
WiredHome 136:224e03d5c31f 860 window();
WiredHome 136:224e03d5c31f 861 #else
WiredHome 115:c9862fd0c689 862 for (int y= y0; y <= y1; y++) {
WiredHome 136:224e03d5c31f 863 SetGraphicsCursor(x0+img_x, y+img_y);
WiredHome 115:c9862fd0c689 864 _StartGraphicsStream();
WiredHome 115:c9862fd0c689 865 #if JD_FORMAT == 1
WiredHome 115:c9862fd0c689 866 uint16_t *p = src + w * (y - y0);
WiredHome 115:c9862fd0c689 867 #else
WiredHome 115:c9862fd0c689 868 uint8_t *p = src + 3 * (w * (y - y0));
WiredHome 115:c9862fd0c689 869 #endif
WiredHome 115:c9862fd0c689 870 for (int x=x0; x <= x1; x++) {
WiredHome 115:c9862fd0c689 871 #if JD_FORMAT == 1
WiredHome 115:c9862fd0c689 872 _putp(*p++);
WiredHome 115:c9862fd0c689 873 #else
WiredHome 115:c9862fd0c689 874 _putp(RGB(*p, *(p+1), *(p+2)));
WiredHome 115:c9862fd0c689 875 p += 3;
WiredHome 115:c9862fd0c689 876 #endif
WiredHome 115:c9862fd0c689 877 }
WiredHome 115:c9862fd0c689 878 _EndGraphicsStream();
WiredHome 115:c9862fd0c689 879 }
WiredHome 136:224e03d5c31f 880 #endif
WiredHome 115:c9862fd0c689 881 return 1;
WiredHome 115:c9862fd0c689 882 }
WiredHome 115:c9862fd0c689 883
WiredHome 115:c9862fd0c689 884 JRESULT GraphicsDisplay::jd_prepare (
WiredHome 115:c9862fd0c689 885 JDEC * jd, /* Blank decompressor object */
WiredHome 115:c9862fd0c689 886 uint16_t (*infunc)(JDEC *, uint8_t *, uint16_t), /* JPEG strem input function */
WiredHome 115:c9862fd0c689 887 void* pool, /* Working buffer for the decompression session */
WiredHome 115:c9862fd0c689 888 uint16_t sz_pool, /* Size of working buffer */
WiredHome 115:c9862fd0c689 889 void* dev /* I/O device identifier for the session */
WiredHome 115:c9862fd0c689 890 )
WiredHome 115:c9862fd0c689 891 {
WiredHome 115:c9862fd0c689 892 uint8_t *seg, b;
WiredHome 115:c9862fd0c689 893 uint16_t marker;
WiredHome 115:c9862fd0c689 894 uint32_t ofs;
WiredHome 115:c9862fd0c689 895 uint16_t n, i, j, len;
WiredHome 115:c9862fd0c689 896 JRESULT rc;
WiredHome 115:c9862fd0c689 897
WiredHome 120:be2aaa3adf72 898 INFO("jd_prepare(%p,%p,%p,%d,%p)", jd, infunc, pool, sz_pool, dev);
WiredHome 121:6bc4911f5e55 899 HexDump("JDEC 1", (uint8_t *)jd, sizeof(JDEC));
WiredHome 118:34eb0b64fc61 900
WiredHome 115:c9862fd0c689 901 if (!pool) {
WiredHome 115:c9862fd0c689 902 ERR("JDR_PAR");
WiredHome 115:c9862fd0c689 903 return JDR_PAR;
WiredHome 115:c9862fd0c689 904 }
WiredHome 115:c9862fd0c689 905
WiredHome 120:be2aaa3adf72 906 //INFO("pool is at %p", pool);
WiredHome 115:c9862fd0c689 907 jd->pool = pool; /* Work memroy */
WiredHome 115:c9862fd0c689 908 jd->sz_pool = sz_pool; /* Size of given work memory */
WiredHome 115:c9862fd0c689 909 jd->infunc = infunc; /* Stream input function */
WiredHome 115:c9862fd0c689 910 jd->device = dev; /* I/O device identifier */
WiredHome 115:c9862fd0c689 911 jd->nrst = 0; /* No restart interval (default) */
WiredHome 115:c9862fd0c689 912
WiredHome 115:c9862fd0c689 913 for (i = 0; i < 2; i++) { /* Nulls pointers */
WiredHome 115:c9862fd0c689 914 for (j = 0; j < 2; j++) {
WiredHome 115:c9862fd0c689 915 jd->huffbits[i][j] = 0;
WiredHome 115:c9862fd0c689 916 jd->huffcode[i][j] = 0;
WiredHome 115:c9862fd0c689 917 jd->huffdata[i][j] = 0;
WiredHome 115:c9862fd0c689 918 }
WiredHome 115:c9862fd0c689 919 }
WiredHome 115:c9862fd0c689 920 for (i = 0; i < 4; i++) jd->qttbl[i] = 0;
WiredHome 121:6bc4911f5e55 921 HexDump("JDEC 2", (uint8_t *)jd, sizeof(JDEC));
WiredHome 115:c9862fd0c689 922
WiredHome 115:c9862fd0c689 923 jd->inbuf = seg = (uint8_t *)alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */
WiredHome 115:c9862fd0c689 924 if (!seg) {
WiredHome 115:c9862fd0c689 925 ERR("JDR_MEM1");
WiredHome 115:c9862fd0c689 926 return JDR_MEM1;
WiredHome 115:c9862fd0c689 927 }
WiredHome 121:6bc4911f5e55 928 HexDump("JDEC 3", (uint8_t *)jd, sizeof(JDEC));
WiredHome 115:c9862fd0c689 929
WiredHome 115:c9862fd0c689 930 if (getJpegData(jd, seg, 2) != 2) {
WiredHome 115:c9862fd0c689 931 ERR("JDR_INP");
WiredHome 115:c9862fd0c689 932 return JDR_INP;/* Check SOI marker */
WiredHome 115:c9862fd0c689 933 }
WiredHome 120:be2aaa3adf72 934 INFO("Checkpoint");
WiredHome 115:c9862fd0c689 935 HexDump("SOI marker", seg, 2);
WiredHome 115:c9862fd0c689 936 if (LDB_WORD(seg) != 0xFFD8) {
WiredHome 115:c9862fd0c689 937 ERR("JDR_FMT1");
WiredHome 115:c9862fd0c689 938 return JDR_FMT1; /* Err: SOI is not detected */
WiredHome 115:c9862fd0c689 939 }
WiredHome 115:c9862fd0c689 940 ofs = 2;
WiredHome 115:c9862fd0c689 941
WiredHome 115:c9862fd0c689 942 for (;;) {
WiredHome 115:c9862fd0c689 943 /* Get a JPEG marker */
WiredHome 115:c9862fd0c689 944 if (getJpegData(jd, seg, 4) != 4) {
WiredHome 115:c9862fd0c689 945 ERR("JDR_INP");
WiredHome 115:c9862fd0c689 946 return JDR_INP;
WiredHome 115:c9862fd0c689 947 }
WiredHome 115:c9862fd0c689 948 marker = LDB_WORD(seg); /* Marker */
WiredHome 115:c9862fd0c689 949 len = LDB_WORD(seg + 2); /* Length field */
WiredHome 115:c9862fd0c689 950 if (len <= 2 || (marker >> 8) != 0xFF) {
WiredHome 115:c9862fd0c689 951 ERR("JDR_FMT1");
WiredHome 115:c9862fd0c689 952 return JDR_FMT1;
WiredHome 115:c9862fd0c689 953 }
WiredHome 115:c9862fd0c689 954 len -= 2; /* Content size excluding length field */
WiredHome 115:c9862fd0c689 955 ofs += 4 + len; /* Number of bytes loaded */
WiredHome 115:c9862fd0c689 956
WiredHome 115:c9862fd0c689 957 switch (marker & 0xFF) {
WiredHome 115:c9862fd0c689 958 case 0xC0: /* SOF0 (baseline JPEG) */
WiredHome 115:c9862fd0c689 959 /* Load segment data */
WiredHome 115:c9862fd0c689 960 if (len > JD_SZBUF) {
WiredHome 115:c9862fd0c689 961 ERR("JDR_MEM2");
WiredHome 115:c9862fd0c689 962 return JDR_MEM2;
WiredHome 115:c9862fd0c689 963 }
WiredHome 115:c9862fd0c689 964 if (getJpegData(jd, seg, len) != len) {
WiredHome 115:c9862fd0c689 965 ERR("JDR_INP");
WiredHome 115:c9862fd0c689 966 return JDR_INP;
WiredHome 115:c9862fd0c689 967 }
WiredHome 115:c9862fd0c689 968
WiredHome 115:c9862fd0c689 969 jd->width = LDB_WORD(seg+3); /* Image width in unit of pixel */
WiredHome 115:c9862fd0c689 970 jd->height = LDB_WORD(seg+1); /* Image height in unit of pixel */
WiredHome 115:c9862fd0c689 971 INFO("Image size(%d,%d)", jd->width, jd->height);
WiredHome 197:853d08e2fb53 972
WiredHome 115:c9862fd0c689 973 if (seg[5] != 3) {
WiredHome 115:c9862fd0c689 974 ERR("JDR_FMT3");
WiredHome 115:c9862fd0c689 975 return JDR_FMT3; /* Err: Supports only Y/Cb/Cr format */
WiredHome 115:c9862fd0c689 976 }
WiredHome 115:c9862fd0c689 977
WiredHome 115:c9862fd0c689 978 /* Check three image components */
WiredHome 197:853d08e2fb53 979 for (i = 0; i < 3; i++) {
WiredHome 115:c9862fd0c689 980 b = seg[7 + 3 * i]; /* Get sampling factor */
WiredHome 115:c9862fd0c689 981 if (!i) { /* Y component */
WiredHome 115:c9862fd0c689 982 if (b != 0x11 && b != 0x22 && b != 0x21) {/* Check sampling factor */
WiredHome 115:c9862fd0c689 983 ERR("JDR_FMT3");
WiredHome 115:c9862fd0c689 984 return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */
WiredHome 115:c9862fd0c689 985 }
WiredHome 115:c9862fd0c689 986 jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */
WiredHome 115:c9862fd0c689 987 } else { /* Cb/Cr component */
WiredHome 115:c9862fd0c689 988 if (b != 0x11) {
WiredHome 115:c9862fd0c689 989 ERR("JDR_FMT3");
WiredHome 115:c9862fd0c689 990 return JDR_FMT3; /* Err: Sampling factor of Cr/Cb must be 1 */
WiredHome 115:c9862fd0c689 991 }
WiredHome 115:c9862fd0c689 992 }
WiredHome 115:c9862fd0c689 993 b = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */
WiredHome 115:c9862fd0c689 994 if (b > 3) {
WiredHome 115:c9862fd0c689 995 ERR("JDR_FMT3");
WiredHome 115:c9862fd0c689 996 return JDR_FMT3; /* Err: Invalid ID */
WiredHome 115:c9862fd0c689 997 }
WiredHome 115:c9862fd0c689 998 jd->qtid[i] = b;
WiredHome 115:c9862fd0c689 999 }
WiredHome 115:c9862fd0c689 1000 break;
WiredHome 115:c9862fd0c689 1001
WiredHome 115:c9862fd0c689 1002 case 0xDD: /* DRI */
WiredHome 115:c9862fd0c689 1003 /* Load segment data */
WiredHome 115:c9862fd0c689 1004 if (len > JD_SZBUF) {
WiredHome 115:c9862fd0c689 1005 ERR("JDR_MEM2");
WiredHome 115:c9862fd0c689 1006 return JDR_MEM2;
WiredHome 115:c9862fd0c689 1007 }
WiredHome 115:c9862fd0c689 1008 if (getJpegData(jd, seg, len) != len) {
WiredHome 115:c9862fd0c689 1009 ERR("JDR_INP");
WiredHome 115:c9862fd0c689 1010 return JDR_INP;
WiredHome 115:c9862fd0c689 1011 }
WiredHome 115:c9862fd0c689 1012
WiredHome 115:c9862fd0c689 1013 /* Get restart interval (MCUs) */
WiredHome 115:c9862fd0c689 1014 jd->nrst = LDB_WORD(seg);
WiredHome 115:c9862fd0c689 1015 break;
WiredHome 115:c9862fd0c689 1016
WiredHome 115:c9862fd0c689 1017 case 0xC4: /* DHT */
WiredHome 115:c9862fd0c689 1018 /* Load segment data */
WiredHome 115:c9862fd0c689 1019 if (len > JD_SZBUF) {
WiredHome 115:c9862fd0c689 1020 ERR("JDR_MEM2");
WiredHome 115:c9862fd0c689 1021 return JDR_MEM2;
WiredHome 115:c9862fd0c689 1022 }
WiredHome 115:c9862fd0c689 1023 if (getJpegData(jd, seg, len) != len) {
WiredHome 115:c9862fd0c689 1024 ERR("JDR_INP");
WiredHome 115:c9862fd0c689 1025 return JDR_INP;
WiredHome 115:c9862fd0c689 1026 }
WiredHome 115:c9862fd0c689 1027
WiredHome 115:c9862fd0c689 1028 /* Create huffman tables */
WiredHome 115:c9862fd0c689 1029 INFO("next - create_huffman_tbl()");
WiredHome 115:c9862fd0c689 1030 rc = (JRESULT)create_huffman_tbl(jd, seg, len);
WiredHome 115:c9862fd0c689 1031 if (rc) {
WiredHome 115:c9862fd0c689 1032 ERR("rc = %d", rc);
WiredHome 115:c9862fd0c689 1033 return rc;
WiredHome 115:c9862fd0c689 1034 }
WiredHome 115:c9862fd0c689 1035 break;
WiredHome 115:c9862fd0c689 1036
WiredHome 115:c9862fd0c689 1037 case 0xDB: /* DQT */
WiredHome 115:c9862fd0c689 1038 /* Load segment data */
WiredHome 115:c9862fd0c689 1039 if (len > JD_SZBUF) {
WiredHome 115:c9862fd0c689 1040 ERR("JDR_MEM2");
WiredHome 115:c9862fd0c689 1041 return JDR_MEM2;
WiredHome 115:c9862fd0c689 1042 }
WiredHome 115:c9862fd0c689 1043 if (getJpegData(jd, seg, len) != len) {
WiredHome 115:c9862fd0c689 1044 ERR("JDR_INP");
WiredHome 115:c9862fd0c689 1045 return JDR_INP;
WiredHome 115:c9862fd0c689 1046 }
WiredHome 115:c9862fd0c689 1047
WiredHome 115:c9862fd0c689 1048 /* Create de-quantizer tables */
WiredHome 115:c9862fd0c689 1049 rc = (JRESULT)create_qt_tbl(jd, seg, len);
WiredHome 115:c9862fd0c689 1050 if (rc) {
WiredHome 115:c9862fd0c689 1051 ERR("rc = %d", rc);
WiredHome 115:c9862fd0c689 1052 return rc;
WiredHome 115:c9862fd0c689 1053 }
WiredHome 115:c9862fd0c689 1054 break;
WiredHome 115:c9862fd0c689 1055
WiredHome 115:c9862fd0c689 1056 case 0xDA: /* SOS */
WiredHome 115:c9862fd0c689 1057 /* Load segment data */
WiredHome 115:c9862fd0c689 1058 if (len > JD_SZBUF) {
WiredHome 115:c9862fd0c689 1059 ERR("JDR_MEM2");
WiredHome 115:c9862fd0c689 1060 return JDR_MEM2;
WiredHome 115:c9862fd0c689 1061 }
WiredHome 115:c9862fd0c689 1062 if (getJpegData(jd, seg, len) != len) {
WiredHome 115:c9862fd0c689 1063 ERR("JDR_INP");
WiredHome 115:c9862fd0c689 1064 return JDR_INP;
WiredHome 115:c9862fd0c689 1065 }
WiredHome 115:c9862fd0c689 1066
WiredHome 115:c9862fd0c689 1067 if (!jd->width || !jd->height) {
WiredHome 115:c9862fd0c689 1068 ERR("JDR_FMT1");
WiredHome 115:c9862fd0c689 1069 return JDR_FMT1; /* Err: Invalid image size */
WiredHome 115:c9862fd0c689 1070 }
WiredHome 115:c9862fd0c689 1071
WiredHome 115:c9862fd0c689 1072 if (seg[0] != 3) {
WiredHome 115:c9862fd0c689 1073 ERR("JDR_FMT3");
WiredHome 115:c9862fd0c689 1074 return JDR_FMT3; /* Err: Supports only three color components format */
WiredHome 115:c9862fd0c689 1075 }
WiredHome 197:853d08e2fb53 1076
WiredHome 115:c9862fd0c689 1077 /* Check if all tables corresponding to each components have been loaded */
WiredHome 115:c9862fd0c689 1078 for (i = 0; i < 3; i++) {
WiredHome 115:c9862fd0c689 1079 b = seg[2 + 2 * i]; /* Get huffman table ID */
WiredHome 115:c9862fd0c689 1080 if (b != 0x00 && b != 0x11) {
WiredHome 115:c9862fd0c689 1081 ERR("JDR_FMT3");
WiredHome 115:c9862fd0c689 1082 return JDR_FMT3; /* Err: Different table number for DC/AC element */
WiredHome 115:c9862fd0c689 1083 }
WiredHome 115:c9862fd0c689 1084 b = i ? 1 : 0;
WiredHome 115:c9862fd0c689 1085 if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) { /* Check huffman table for this component */
WiredHome 115:c9862fd0c689 1086 ERR("JDR_FMT1");
WiredHome 115:c9862fd0c689 1087 return JDR_FMT1; /* Err: Huffman table not loaded */
WiredHome 115:c9862fd0c689 1088 }
WiredHome 115:c9862fd0c689 1089 if (!jd->qttbl[jd->qtid[i]]) {
WiredHome 115:c9862fd0c689 1090 ERR("JDR_FMT1");
WiredHome 115:c9862fd0c689 1091 return JDR_FMT1; /* Err: Dequantizer table not loaded */
WiredHome 115:c9862fd0c689 1092 }
WiredHome 115:c9862fd0c689 1093 }
WiredHome 115:c9862fd0c689 1094
WiredHome 115:c9862fd0c689 1095 /* Allocate working buffer for MCU and RGB */
WiredHome 115:c9862fd0c689 1096 n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */
WiredHome 115:c9862fd0c689 1097 if (!n) {
WiredHome 115:c9862fd0c689 1098 ERR("JDR_FMT1");
WiredHome 115:c9862fd0c689 1099 return JDR_FMT1; /* Err: SOF0 has not been loaded */
WiredHome 115:c9862fd0c689 1100 }
WiredHome 115:c9862fd0c689 1101 len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */
WiredHome 115:c9862fd0c689 1102 if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */
WiredHome 115:c9862fd0c689 1103 jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */
WiredHome 115:c9862fd0c689 1104 if (!jd->workbuf) {
WiredHome 115:c9862fd0c689 1105 ERR("JDR_MEM1");
WiredHome 115:c9862fd0c689 1106 return JDR_MEM1; /* Err: not enough memory */
WiredHome 115:c9862fd0c689 1107 }
WiredHome 115:c9862fd0c689 1108 jd->mcubuf = (uint8_t *)alloc_pool(jd, (n + 2) * 64); /* Allocate MCU working buffer */
WiredHome 115:c9862fd0c689 1109 if (!jd->mcubuf) {
WiredHome 115:c9862fd0c689 1110 ERR("JDR_MEM1");
WiredHome 115:c9862fd0c689 1111 return JDR_MEM1; /* Err: not enough memory */
WiredHome 115:c9862fd0c689 1112 }
WiredHome 115:c9862fd0c689 1113
WiredHome 115:c9862fd0c689 1114 /* Pre-load the JPEG data to extract it from the bit stream */
WiredHome 115:c9862fd0c689 1115 jd->dptr = seg; jd->dctr = 0; jd->dmsk = 0; /* Prepare to read bit stream */
WiredHome 115:c9862fd0c689 1116 if (ofs %= JD_SZBUF) { /* Align read offset to JD_SZBUF */
WiredHome 115:c9862fd0c689 1117 jd->dctr = getJpegData(jd, seg + ofs, JD_SZBUF - (uint16_t)ofs);
WiredHome 115:c9862fd0c689 1118 jd->dptr = seg + ofs - 1;
WiredHome 115:c9862fd0c689 1119 }
WiredHome 115:c9862fd0c689 1120
WiredHome 115:c9862fd0c689 1121 return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */
WiredHome 115:c9862fd0c689 1122
WiredHome 115:c9862fd0c689 1123 case 0xC1: /* SOF1 */
WiredHome 115:c9862fd0c689 1124 case 0xC2: /* SOF2 */
WiredHome 115:c9862fd0c689 1125 case 0xC3: /* SOF3 */
WiredHome 115:c9862fd0c689 1126 case 0xC5: /* SOF5 */
WiredHome 115:c9862fd0c689 1127 case 0xC6: /* SOF6 */
WiredHome 115:c9862fd0c689 1128 case 0xC7: /* SOF7 */
WiredHome 115:c9862fd0c689 1129 case 0xC9: /* SOF9 */
WiredHome 115:c9862fd0c689 1130 case 0xCA: /* SOF10 */
WiredHome 115:c9862fd0c689 1131 case 0xCB: /* SOF11 */
WiredHome 115:c9862fd0c689 1132 case 0xCD: /* SOF13 */
WiredHome 115:c9862fd0c689 1133 case 0xCE: /* SOF14 */
WiredHome 115:c9862fd0c689 1134 case 0xCF: /* SOF15 */
WiredHome 115:c9862fd0c689 1135 case 0xD9: /* EOI */
WiredHome 115:c9862fd0c689 1136 return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */
WiredHome 115:c9862fd0c689 1137
WiredHome 115:c9862fd0c689 1138 default: /* Unknown segment (comment, exif or etc..) */
WiredHome 115:c9862fd0c689 1139 /* Skip segment data */
WiredHome 115:c9862fd0c689 1140 if (getJpegData(jd, 0, len) != len) { /* Null pointer specifies to skip bytes of stream */
WiredHome 115:c9862fd0c689 1141 INFO("Unknown segment");
WiredHome 115:c9862fd0c689 1142 return JDR_INP;
WiredHome 115:c9862fd0c689 1143 }
WiredHome 115:c9862fd0c689 1144 }
WiredHome 115:c9862fd0c689 1145 }
WiredHome 115:c9862fd0c689 1146 }
WiredHome 115:c9862fd0c689 1147
WiredHome 115:c9862fd0c689 1148
WiredHome 115:c9862fd0c689 1149
WiredHome 115:c9862fd0c689 1150
WiredHome 115:c9862fd0c689 1151 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 1152 /* Start to decompress the JPEG picture */
WiredHome 115:c9862fd0c689 1153 /*-----------------------------------------------------------------------*/
WiredHome 115:c9862fd0c689 1154
WiredHome 115:c9862fd0c689 1155 JRESULT GraphicsDisplay::jd_decomp (
WiredHome 115:c9862fd0c689 1156 JDEC * jd, /* Initialized decompression object */
WiredHome 115:c9862fd0c689 1157 uint16_t (*outfunc)(JDEC * jd, void * stream, JRECT * rect), /* RGB output function */
WiredHome 115:c9862fd0c689 1158 uint8_t scale /* Output de-scaling factor (0 to 3) */
WiredHome 115:c9862fd0c689 1159 )
WiredHome 115:c9862fd0c689 1160 {
WiredHome 115:c9862fd0c689 1161 uint16_t x, y, mx, my;
WiredHome 115:c9862fd0c689 1162 uint16_t rst, rsc;
WiredHome 115:c9862fd0c689 1163 JRESULT rc;
WiredHome 115:c9862fd0c689 1164
WiredHome 118:34eb0b64fc61 1165 INFO("jd_decomp(%p,%p,%d)", jd, outfunc, scale);
WiredHome 118:34eb0b64fc61 1166 HexDump("JDEC", (uint8_t *)jd, sizeof(JDEC));
WiredHome 118:34eb0b64fc61 1167
WiredHome 115:c9862fd0c689 1168 if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR;
WiredHome 115:c9862fd0c689 1169 jd->scale = scale;
WiredHome 115:c9862fd0c689 1170
WiredHome 115:c9862fd0c689 1171 mx = jd->msx * 8; my = jd->msy * 8; /* Size of the MCU (pixel) */
WiredHome 115:c9862fd0c689 1172
WiredHome 115:c9862fd0c689 1173 jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */
WiredHome 115:c9862fd0c689 1174 rst = rsc = 0;
WiredHome 115:c9862fd0c689 1175
WiredHome 115:c9862fd0c689 1176 rc = JDR_OK;
WiredHome 115:c9862fd0c689 1177 for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */
WiredHome 115:c9862fd0c689 1178 for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */
WiredHome 115:c9862fd0c689 1179 if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */
WiredHome 115:c9862fd0c689 1180 rc = restart(jd, rsc++);
WiredHome 115:c9862fd0c689 1181 if (rc != JDR_OK) return rc;
WiredHome 115:c9862fd0c689 1182 rst = 1;
WiredHome 115:c9862fd0c689 1183 }
WiredHome 115:c9862fd0c689 1184 rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream and apply IDCT) */
WiredHome 115:c9862fd0c689 1185 if (rc != JDR_OK) return rc;
WiredHome 115:c9862fd0c689 1186 rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (color space conversion, scaling and output) */
WiredHome 115:c9862fd0c689 1187 if (rc != JDR_OK) return rc;
WiredHome 115:c9862fd0c689 1188 }
WiredHome 115:c9862fd0c689 1189 }
WiredHome 115:c9862fd0c689 1190 return rc;
WiredHome 115:c9862fd0c689 1191 }