Demonstration of the Bitmap rendering - reads BMP and JPG files in many format variants and renders to the screen.

Dependencies:   FlashFileSystem mbed RA8875

Bitmap and JPEG Demo

This demo publishes each graphic file from a list of files to the display. The graphic files can be BMP, JPG, or ICO. On the terminal it displays the filename and the return-code (in case of an error). This demo works as intended on the 480x272 display in either 8 or 16 bit per pixel mode and it should work on larger displays.

Items of interest to change and rebuild/test:

// Not all systems have the LocalFileSystem. Plug in the library and driver for yours.
LocalFileSystem local("local");             // Image source

TestImage_T TestImage[] = {
    { 0, 0, "/local/01601602.bmp"},
    { 0, 0, "/local/48027202.bmp"},
    { 0, 0, "/local/48027204.bmp"},
    { 0, 0, "/local/48027208.bmp"},
    { 0, 0, "/local/48027224.bmp"},
    { 0, 0, "/local/p480272.jpg"},
    { 0, 0, "/local/p480272.bmp"}
};

// deefine your screen size and color depth. 
#define SCREEN_W 480
#define SCREEN_H 272
#define SCREEN_BPP 16

LocalFileSystem may need to be altered to SDFileSystem (for example) and the corresponding paths in the TestImage array.

Also, the Screen size and bit per pixel color depth.

Images

The following image files are saved in different resolution and color depth. The first, and smallest, was simply for developing the monochrome support. Others are 4-bit color, 8-bit color, 24-bit color, and a mislabeled 1-bit color (shown as 02).

/media/uploads/WiredHome/testimages.zip

Committer:
WiredHome
Date:
Tue May 17 10:45:59 2016 +0000
Revision:
11:0c2ff405c1c1
Parent:
9:092f7ac73c03
working - adding instrumentation

Who changed what in which revision?

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