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:
Sun May 15 18:57:36 2016 +0000
Revision:
1:84fb3e9adaaf
Child:
3:533ced3d7c39
Working JPEG decoder using c functions external to the graphics library.

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