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