This is the David Smart RA8875 Library with mods for working with FRDM-K64F
GraphicsDisplayJPEG.cpp@167:8aa3fb2a5a31, 2019-02-26 (annotated)
- Committer:
- WiredHome
- Date:
- Tue Feb 26 19:52:57 2019 +0000
- Revision:
- 167:8aa3fb2a5a31
- Parent:
- 136:224e03d5c31f
- Child:
- 197:853d08e2fb53
Documentation update to the script in the Fonts/FontMods.h file to improve the understanding of what it does.
Who changed what in which revision?
User | Revision | Line number | New 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 | 115:c9862fd0c689 | 13 | #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 115:c9862fd0c689 | 14 | #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 115:c9862fd0c689 | 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 | 118:34eb0b64fc61 | 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 | 115:c9862fd0c689 | 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 | 118:34eb0b64fc61 | 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 | 115:c9862fd0c689 | 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 | 136:224e03d5c31f | 847 | uint32_t pCount = pixelCount; |
WiredHome | 136:224e03d5c31f | 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 | 115:c9862fd0c689 | 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 | 115:c9862fd0c689 | 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 | 115:c9862fd0c689 | 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 | } |