Add JPEG encoder

This commit is contained in:
iabdalkader 2014-09-17 21:39:19 +02:00
parent 9cb9c4b892
commit 8854f0a9d5
5 changed files with 502 additions and 0 deletions

View File

@ -135,6 +135,7 @@ OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/img/,\
freak.o \
template.o \
font.o \
jpeg.o \
)
OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/py/, \

View File

@ -43,6 +43,7 @@ SRCS += $(addprefix img/, \
freak.c \
template.c \
font.c \
jpeg.c \
)
SRCS += $(addprefix py/, \

View File

@ -211,6 +211,7 @@ void imlib_scale(struct image *src, struct image *dst, interp_t interp);
void imlib_blit(struct image *src, struct image *dst, int x_off, int y_off);
void imlib_blend(struct image *src, struct image *dst, int x_off, int y_off, uint8_t alpha);
void imlib_subimage(struct image *src, struct image *dst, int x_off, int y_off);
void jpeg_compress(image_t *src, image_t *dst, int quality);
/* Image file functions */
int ppm_read(image_t *img, const char *path);

482
src/omv/img/jpeg.c Normal file
View File

@ -0,0 +1,482 @@
/*
* This file is part of the OpenMV project.
* Copyright (c) 2013 Ibrahim Abd Elkader <i.abdalkader@gmail.com>
* This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/
*
* Public domain Minimalistic JPEG baseline encoder
*
* */
#include "ff.h"
#include "std.h"
#include "xalloc.h"
#include "imlib.h"
#include "mdefs.h"
#define R8(p) \
rb_tbl[((p>>3)&0x1F)]
#define G8(p) \
g_tbl[((p&0x07)<<3)|(p>>13)]
#define B8(p) \
rb_tbl[((p>>8)&0x1F)]
typedef struct {
int idx;
int length;
uint8_t *buf;
} jpeg_buf_t;
static float fdtbl_Y[64], fdtbl_UV[64];
static uint8_t YTable[64], UVTable[64];
static uint8_t rb_tbl []= {
0, 8, 16, 24, 32, 41, 49, 57, 65, 74,
82, 90, 98, 106, 115, 123, 131, 139,
148, 156, 164, 172, 180, 189, 197, 205,
213, 222, 230, 238, 246, 255
};
static uint8_t g_tbl []= {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44,
48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89,
93, 97, 101, 105, 109, 113, 117, 121, 125, 129,
133, 137, 141, 145, 149, 153, 157, 161, 165, 170,
174, 178, 182, 186, 190, 194, 198, 202, 206, 210,
214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 255
};
static const uint8_t s_jo_ZigZag[] = {
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63
};
static const uint8_t YQT[] = {
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
};
static const uint8_t UVQT[] = {
17,18,24,47,99,99,99,99,
18,21,26,66,99,99,99,99,
24,26,56,99,99,99,99,99,
47,66,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99
};
static const float aasf[] = {
1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f
};
static const uint8_t std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
static const uint8_t std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
static const uint8_t std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
static const uint8_t std_ac_luminance_values[] = {
0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
};
static const uint8_t std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
static const uint8_t std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
static const uint8_t std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
static const uint8_t std_ac_chrominance_values[] = {
0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
};
// Huffman tables
static const uint16_t YDC_HT[12][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}};
static const uint16_t UVDC_HT[12][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}};
static const uint16_t YAC_HT[256][2] = {
{0x000A, 0x0004},{0x0000, 0x0002},{0x0001, 0x0002},{0x0004, 0x0003},{0x000B, 0x0004},{0x001A, 0x0005},{0x0078, 0x0007},{0x00F8, 0x0008},
{0x03F6, 0x000A},{0xFF82, 0x0010},{0xFF83, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x000C, 0x0004},{0x001B, 0x0005},{0x0079, 0x0007},{0x01F6, 0x0009},{0x07F6, 0x000B},{0xFF84, 0x0010},{0xFF85, 0x0010},
{0xFF86, 0x0010},{0xFF87, 0x0010},{0xFF88, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x001C, 0x0005},{0x00F9, 0x0008},{0x03F7, 0x000A},{0x0FF4, 0x000C},{0xFF89, 0x0010},{0xFF8A, 0x0010},{0xFF8B, 0x0010},
{0xFF8C, 0x0010},{0xFF8D, 0x0010},{0xFF8E, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x003A, 0x0006},{0x01F7, 0x0009},{0x0FF5, 0x000C},{0xFF8F, 0x0010},{0xFF90, 0x0010},{0xFF91, 0x0010},{0xFF92, 0x0010},
{0xFF93, 0x0010},{0xFF94, 0x0010},{0xFF95, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x003B, 0x0006},{0x03F8, 0x000A},{0xFF96, 0x0010},{0xFF97, 0x0010},{0xFF98, 0x0010},{0xFF99, 0x0010},{0xFF9A, 0x0010},
{0xFF9B, 0x0010},{0xFF9C, 0x0010},{0xFF9D, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x007A, 0x0007},{0x07F7, 0x000B},{0xFF9E, 0x0010},{0xFF9F, 0x0010},{0xFFA0, 0x0010},{0xFFA1, 0x0010},{0xFFA2, 0x0010},
{0xFFA3, 0x0010},{0xFFA4, 0x0010},{0xFFA5, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x007B, 0x0007},{0x0FF6, 0x000C},{0xFFA6, 0x0010},{0xFFA7, 0x0010},{0xFFA8, 0x0010},{0xFFA9, 0x0010},{0xFFAA, 0x0010},
{0xFFAB, 0x0010},{0xFFAC, 0x0010},{0xFFAD, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x00FA, 0x0008},{0x0FF7, 0x000C},{0xFFAE, 0x0010},{0xFFAF, 0x0010},{0xFFB0, 0x0010},{0xFFB1, 0x0010},{0xFFB2, 0x0010},
{0xFFB3, 0x0010},{0xFFB4, 0x0010},{0xFFB5, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x01F8, 0x0009},{0x7FC0, 0x000F},{0xFFB6, 0x0010},{0xFFB7, 0x0010},{0xFFB8, 0x0010},{0xFFB9, 0x0010},{0xFFBA, 0x0010},
{0xFFBB, 0x0010},{0xFFBC, 0x0010},{0xFFBD, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x01F9, 0x0009},{0xFFBE, 0x0010},{0xFFBF, 0x0010},{0xFFC0, 0x0010},{0xFFC1, 0x0010},{0xFFC2, 0x0010},{0xFFC3, 0x0010},
{0xFFC4, 0x0010},{0xFFC5, 0x0010},{0xFFC6, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x01FA, 0x0009},{0xFFC7, 0x0010},{0xFFC8, 0x0010},{0xFFC9, 0x0010},{0xFFCA, 0x0010},{0xFFCB, 0x0010},{0xFFCC, 0x0010},
{0xFFCD, 0x0010},{0xFFCE, 0x0010},{0xFFCF, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x03F9, 0x000A},{0xFFD0, 0x0010},{0xFFD1, 0x0010},{0xFFD2, 0x0010},{0xFFD3, 0x0010},{0xFFD4, 0x0010},{0xFFD5, 0x0010},
{0xFFD6, 0x0010},{0xFFD7, 0x0010},{0xFFD8, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x03FA, 0x000A},{0xFFD9, 0x0010},{0xFFDA, 0x0010},{0xFFDB, 0x0010},{0xFFDC, 0x0010},{0xFFDD, 0x0010},{0xFFDE, 0x0010},
{0xFFDF, 0x0010},{0xFFE0, 0x0010},{0xFFE1, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x07F8, 0x000B},{0xFFE2, 0x0010},{0xFFE3, 0x0010},{0xFFE4, 0x0010},{0xFFE5, 0x0010},{0xFFE6, 0x0010},{0xFFE7, 0x0010},
{0xFFE8, 0x0010},{0xFFE9, 0x0010},{0xFFEA, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0xFFEB, 0x0010},{0xFFEC, 0x0010},{0xFFED, 0x0010},{0xFFEE, 0x0010},{0xFFEF, 0x0010},{0xFFF0, 0x0010},{0xFFF1, 0x0010},
{0xFFF2, 0x0010},{0xFFF3, 0x0010},{0xFFF4, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x07F9, 0x000B},{0xFFF5, 0x0010},{0xFFF6, 0x0010},{0xFFF7, 0x0010},{0xFFF8, 0x0010},{0xFFF9, 0x0010},{0xFFFA, 0x0010},{0xFFFB, 0x0010},
{0xFFFC, 0x0010},{0xFFFD, 0x0010},{0xFFFE, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
};
static const uint16_t UVAC_HT[256][2] = {
{0x0000, 0x0002},{0x0001, 0x0002},{0x0004, 0x0003},{0x000A, 0x0004},{0x0018, 0x0005},{0x0019, 0x0005},{0x0038, 0x0006},{0x0078, 0x0007},
{0x01F4, 0x0009},{0x03F6, 0x000A},{0x0FF4, 0x000C},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x000B, 0x0004},{0x0039, 0x0006},{0x00F6, 0x0008},{0x01F5, 0x0009},{0x07F6, 0x000B},{0x0FF5, 0x000C},{0xFF88, 0x0010},
{0xFF89, 0x0010},{0xFF8A, 0x0010},{0xFF8B, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x001A, 0x0005},{0x00F7, 0x0008},{0x03F7, 0x000A},{0x0FF6, 0x000C},{0x7FC2, 0x000F},{0xFF8C, 0x0010},{0xFF8D, 0x0010},
{0xFF8E, 0x0010},{0xFF8F, 0x0010},{0xFF90, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x001B, 0x0005},{0x00F8, 0x0008},{0x03F8, 0x000A},{0x0FF7, 0x000C},{0xFF91, 0x0010},{0xFF92, 0x0010},{0xFF93, 0x0010},
{0xFF94, 0x0010},{0xFF95, 0x0010},{0xFF96, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x003A, 0x0006},{0x01F6, 0x0009},{0xFF97, 0x0010},{0xFF98, 0x0010},{0xFF99, 0x0010},{0xFF9A, 0x0010},{0xFF9B, 0x0010},
{0xFF9C, 0x0010},{0xFF9D, 0x0010},{0xFF9E, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x003B, 0x0006},{0x03F9, 0x000A},{0xFF9F, 0x0010},{0xFFA0, 0x0010},{0xFFA1, 0x0010},{0xFFA2, 0x0010},{0xFFA3, 0x0010},
{0xFFA4, 0x0010},{0xFFA5, 0x0010},{0xFFA6, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x0079, 0x0007},{0x07F7, 0x000B},{0xFFA7, 0x0010},{0xFFA8, 0x0010},{0xFFA9, 0x0010},{0xFFAA, 0x0010},{0xFFAB, 0x0010},
{0xFFAC, 0x0010},{0xFFAD, 0x0010},{0xFFAE, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x007A, 0x0007},{0x07F8, 0x000B},{0xFFAF, 0x0010},{0xFFB0, 0x0010},{0xFFB1, 0x0010},{0xFFB2, 0x0010},{0xFFB3, 0x0010},
{0xFFB4, 0x0010},{0xFFB5, 0x0010},{0xFFB6, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x00F9, 0x0008},{0xFFB7, 0x0010},{0xFFB8, 0x0010},{0xFFB9, 0x0010},{0xFFBA, 0x0010},{0xFFBB, 0x0010},{0xFFBC, 0x0010},
{0xFFBD, 0x0010},{0xFFBE, 0x0010},{0xFFBF, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x01F7, 0x0009},{0xFFC0, 0x0010},{0xFFC1, 0x0010},{0xFFC2, 0x0010},{0xFFC3, 0x0010},{0xFFC4, 0x0010},{0xFFC5, 0x0010},
{0xFFC6, 0x0010},{0xFFC7, 0x0010},{0xFFC8, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x01F8, 0x0009},{0xFFC9, 0x0010},{0xFFCA, 0x0010},{0xFFCB, 0x0010},{0xFFCC, 0x0010},{0xFFCD, 0x0010},{0xFFCE, 0x0010},
{0xFFCF, 0x0010},{0xFFD0, 0x0010},{0xFFD1, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x01F9, 0x0009},{0xFFD2, 0x0010},{0xFFD3, 0x0010},{0xFFD4, 0x0010},{0xFFD5, 0x0010},{0xFFD6, 0x0010},{0xFFD7, 0x0010},
{0xFFD8, 0x0010},{0xFFD9, 0x0010},{0xFFDA, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x01FA, 0x0009},{0xFFDB, 0x0010},{0xFFDC, 0x0010},{0xFFDD, 0x0010},{0xFFDE, 0x0010},{0xFFDF, 0x0010},{0xFFE0, 0x0010},
{0xFFE1, 0x0010},{0xFFE2, 0x0010},{0xFFE3, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x07F9, 0x000B},{0xFFE4, 0x0010},{0xFFE5, 0x0010},{0xFFE6, 0x0010},{0xFFE7, 0x0010},{0xFFE8, 0x0010},{0xFFE9, 0x0010},
{0xFFEA, 0x0010},{0xFFEB, 0x0010},{0xFFEC, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x0000, 0x0000},{0x3FE0, 0x000E},{0xFFED, 0x0010},{0xFFEE, 0x0010},{0xFFEF, 0x0010},{0xFFF0, 0x0010},{0xFFF1, 0x0010},{0xFFF2, 0x0010},
{0xFFF3, 0x0010},{0xFFF4, 0x0010},{0xFFF5, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
{0x03FA, 0x000A},{0x7FC3, 0x000F},{0xFFF6, 0x0010},{0xFFF7, 0x0010},{0xFFF8, 0x0010},{0xFFF9, 0x0010},{0xFFFA, 0x0010},{0xFFFB, 0x0010},
{0xFFFC, 0x0010},{0xFFFD, 0x0010},{0xFFFE, 0x0010},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},{0x0000, 0x0000},
};
static void jpeg_put_char(jpeg_buf_t *jpeg_buf, char c)
{
if (jpeg_buf->idx == jpeg_buf->length) {
jpeg_buf->length += 1024;
jpeg_buf->buf = xrealloc(jpeg_buf->buf, jpeg_buf->length);
}
jpeg_buf->buf[jpeg_buf->idx++]=c;
}
static void jpeg_put_bytes(jpeg_buf_t *jpeg_buf, const void *data, int size)
{
if (jpeg_buf->idx+size == jpeg_buf->length) {
jpeg_buf->length += 1024;
jpeg_buf->buf = xrealloc(jpeg_buf->buf, jpeg_buf->length);
}
memcpy(jpeg_buf->buf+jpeg_buf->idx, data, size);
jpeg_buf->idx += size;
}
static void jo_writeBits(jpeg_buf_t *jpeg_buf, int *bitBuf, int *bitCnt, const uint16_t *bs)
{
int bitc = *bitCnt;
int bitb = *bitBuf;
bitc += bs[1];
bitb |= bs[0] << (24 - bitc);
while (bitc > 7) {
uint8_t c = (bitb >> 16) & 255;
jpeg_put_char(jpeg_buf, c);
if(c == 255) {
jpeg_put_char(jpeg_buf, 0);
}
bitb <<= 8;
bitc -= 8;
}
*bitCnt = bitc;
*bitBuf = bitb;
}
static void jo_calcBits(int val, uint16_t bits[2]) {
int tmp1 = val < 0 ? -val : val;
val = val < 0 ? val-1 : val;
bits[1] = 1;
while(tmp1 >>= 1) {
++bits[1];
}
bits[0] = val & ((1<<bits[1])-1);
}
static int jo_processDU(jpeg_buf_t *jpeg_buf, int *bitBuf, int *bitCnt, int *CDU,
float *fdtbl, int DC, const uint16_t (*HTDC)[2], const uint16_t (*HTAC)[2])
{
const uint16_t EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
const uint16_t M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
static int C0 =(int)(0.382683433f * 4096);
static int C1 =(int)(0.541196100f * 4096);
static int C2 =(int)(1.306562965f * 4096);
static int C3 =(int)(0.707106781f * 4096);
// DCT rows
for (int i=8; i>0; i--, CDU+=8) {
int tmp0 = CDU[0] + CDU[7];
int tmp1 = CDU[1] + CDU[6];
int tmp2 = CDU[2] + CDU[5];
int tmp3 = CDU[3] + CDU[4];
int tmp7 = CDU[0] - CDU[7];
int tmp6 = CDU[1] - CDU[6];
int tmp5 = CDU[2] - CDU[5];
int tmp4 = CDU[3] - CDU[4];
// Even part
int tmp10 = tmp0 + tmp3;
int tmp13 = tmp0 - tmp3;
int tmp11 = tmp1 + tmp2;
int tmp12 = tmp1 - tmp2;
int z1 = (tmp12 + tmp13) * C3>>12; // c4
CDU[0] = tmp10 + tmp11;
CDU[4] = tmp10 - tmp11;
CDU[2] = tmp13 + z1;
CDU[6] = tmp13 - z1;
// Odd part
tmp10 = tmp4 + tmp5;// phase 2
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
// The rotator is modified from fig 4-8 to avoid extra negations.
int z5 = (tmp10 - tmp12) * C0>>12; // c6
int z2 = (tmp10 * C1>>12) + z5; // c2-c6
int z4 = (tmp12 * C2>>12) + z5; // c2+c6
int z3 = (tmp11 * C3>>12); // c4
int z11 = tmp7 + z3; // phase 5
int z13 = tmp7 - z3;
CDU[5] = z13 + z2;// phase 6
CDU[3] = z13 - z2;
CDU[1] = z11 + z4;
CDU[7] = z11 - z4;
}
CDU -= 64;
// DCT columns
for (int i=8; i>0; i--, CDU++) {
int tmp0 = CDU[0] + CDU[56];
int tmp1 = CDU[8] + CDU[48];
int tmp2 = CDU[16] + CDU[40];
int tmp3 = CDU[24] + CDU[32];
int tmp7 = CDU[0] - CDU[56];
int tmp6 = CDU[8] - CDU[48];
int tmp5 = CDU[16] - CDU[40];
int tmp4 = CDU[24] - CDU[32];
// Even part
int tmp10 = tmp0 + tmp3; // phase 2
int tmp13 = tmp0 - tmp3;
int tmp11 = tmp1 + tmp2;
int tmp12 = tmp1 - tmp2;
int z1 = (tmp12 + tmp13) * C3>>12; // c4
CDU[0] = tmp10 + tmp11; // phase 3
CDU[32] = tmp10 - tmp11;
CDU[16] = tmp13 + z1; // phase 5
CDU[48] = tmp13 - z1;
// Odd part
tmp10 = tmp4 + tmp5; // phase 2
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
// The rotator is modified from fig 4-8 to avoid extra negations.
int z5 = (tmp10 - tmp12) * C0>>12; // c6
int z2 = (tmp10 * C1>>12) + z5; // c2-c6
int z4 = (tmp12 * C2>>12) + z5; // c2+c6
int z3 = (tmp11 * C3>>12); // c4
int z11 = tmp7 + z3; // phase 5
int z13 = tmp7 - z3;
CDU[40] = z13 + z2;// phase 6
CDU[24] = z13 - z2;
CDU[8] = z11 + z4;
CDU[56] = z11 - z4;
}
CDU-=8;
// Quantize/descale/zigzag the coefficients
int DU[64];
for(int i=0; i<64; ++i) {
DU[s_jo_ZigZag[i]] = fast_roundf(CDU[i]*fdtbl[i]);
}
// Encode DC
int diff = DU[0] - DC;
if (diff == 0) {
jo_writeBits(jpeg_buf, bitBuf, bitCnt, HTDC[0]);
} else {
uint16_t bits[2];
jo_calcBits(diff, bits);
jo_writeBits(jpeg_buf, bitBuf, bitCnt, HTDC[bits[1]]);
jo_writeBits(jpeg_buf, bitBuf, bitCnt, bits);
}
// Encode ACs
int end0pos = 63;
for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
}
// end0pos = first element in reverse order !=0
if(end0pos == 0) {
jo_writeBits(jpeg_buf, bitBuf, bitCnt, EOB);
return DU[0];
}
for(int i = 1; i <= end0pos; ++i) {
int startpos = i;
for (; DU[i]==0 && i<=end0pos; ++i) {
}
int nrzeroes = i-startpos;
if ( nrzeroes >= 16 ) {
int lng = nrzeroes>>4;
for (int nrmarker=1; nrmarker <= lng; ++nrmarker)
jo_writeBits(jpeg_buf, bitBuf, bitCnt, M16zeroes);
nrzeroes &= 15;
}
uint16_t bits[2];
jo_calcBits(DU[i], bits);
jo_writeBits(jpeg_buf, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
jo_writeBits(jpeg_buf, bitBuf, bitCnt, bits);
}
if(end0pos != 63) {
jo_writeBits(jpeg_buf, bitBuf, bitCnt, EOB);
}
return DU[0];
}
void jpeg_compress(image_t *src, image_t *dst, int quality)
{
static int q =0;
uint8_t head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
uint8_t head1[] = { 0xFF,0xC0,0,0x11,8,src->h>>8,src->h&0xFF,src->w>>8,src->w&0xFF,3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
uint8_t head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
jpeg_buf_t jpeg_buf = {
.idx =0,
.length=4096,
.buf = xalloc(4096)
};
// Write Headers
jpeg_put_bytes(&jpeg_buf, head0, sizeof(head0));
jpeg_put_bytes(&jpeg_buf, YTable, sizeof(YTable));
jpeg_put_char(&jpeg_buf, 1);
jpeg_put_bytes(&jpeg_buf, UVTable, sizeof(UVTable));
jpeg_put_bytes(&jpeg_buf, head1, sizeof(head1));
jpeg_put_bytes(&jpeg_buf, std_dc_luminance_nrcodes+1, sizeof(std_dc_luminance_nrcodes)-1);
jpeg_put_bytes(&jpeg_buf, std_dc_luminance_values, sizeof(std_dc_luminance_values));
jpeg_put_char(&jpeg_buf, 0x10); // HTYACinfo
jpeg_put_bytes(&jpeg_buf, std_ac_luminance_nrcodes+1, sizeof(std_ac_luminance_nrcodes)-1);
jpeg_put_bytes(&jpeg_buf, std_ac_luminance_values, sizeof(std_ac_luminance_values));
jpeg_put_char(&jpeg_buf, 1); // HTUDCinfo
jpeg_put_bytes(&jpeg_buf, std_dc_chrominance_nrcodes+1, sizeof(std_dc_chrominance_nrcodes)-1);
jpeg_put_bytes(&jpeg_buf, std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
jpeg_put_char(&jpeg_buf, 0x11); // HTUACinfo
jpeg_put_bytes(&jpeg_buf, std_ac_chrominance_nrcodes+1, sizeof(std_ac_chrominance_nrcodes)-1);
jpeg_put_bytes(&jpeg_buf, std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
jpeg_put_bytes(&jpeg_buf, head2, sizeof(head2));
quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
// If quality changed, update quantization matrix
if (q != quality) {
q = quality;
for(int i = 0; i < 64; ++i) {
int yti = (YQT[i]*quality+50)/100;
YTable[s_jo_ZigZag[i]] = yti < 1 ? 1 : yti > 255 ? 255 : yti;
int uvti = (UVQT[i]*quality+50)/100;
UVTable[s_jo_ZigZag[i]] = uvti < 1 ? 1 : uvti > 255 ? 255 : uvti;
}
for(int r = 0, k = 0; r < 8; ++r) {
for(int c = 0; c < 8; ++c, ++k) {
fdtbl_Y[k] = 1 / (YTable [s_jo_ZigZag[k]] * aasf[r] * aasf[c]);
fdtbl_UV[k] = 1 / (UVTable[s_jo_ZigZag[k]] * aasf[r] * aasf[c]);
}
}
}
// Encode 8x8 macroblocks
int bitBuf=0, bitCnt=0;
int DCY=0, DCU=0, DCV=0;
int YDU[64], UDU[64], VDU[64];
uint16_t *data = (uint16_t *)src->pixels;
uint32_t cv1 =__PKHBT(66, 129, 16);
uint32_t cv2 =__PKHBT(-38, -74, 16);
uint32_t cv3 =__PKHBT(112, -94, 16);
for (int y=0; y<src->h; y+=8) {
for (int x=0; x<src->w; x+=8) {
for (int r=y, pos=0; r<y+8; ++r) {
int ofs = r*src->w;
for (int c=x; c<x+8; ++c, ++pos) {
int p = ofs + c;
int b = B8(data[p]);
uint32_t v0 =__PKHBT(R8(data[p]), G8(data[p]), 16);
YDU[pos]=( __SMLAD(v0, cv1, 128+25 *b) >>8)-128;
UDU[pos]=((int)__SMLAD(v0, cv2, 128+112*b))>>8;
VDU[pos]=((int)__SMLAD(v0, cv3, 128-18 *b))>>8;
}
}
DCY = jo_processDU(&jpeg_buf, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCU = jo_processDU(&jpeg_buf, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
DCV = jo_processDU(&jpeg_buf, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
}
}
// Do the bit alignment of the EOI marker
static const uint16_t fillBits[] = {0x7F, 7};
jo_writeBits(&jpeg_buf, &bitBuf, &bitCnt, fillBits);
// EOI
jpeg_put_char(&jpeg_buf, 0xFF);
jpeg_put_char(&jpeg_buf, 0xD9);
dst->bpp = jpeg_buf.idx+1;
dst->data = jpeg_buf.buf;
}

View File

@ -367,6 +367,21 @@ static mp_obj_t py_image_rainbow(mp_obj_t src_image_obj)
return src_image_obj;
}
static mp_obj_t py_image_compress(mp_obj_t image_obj, mp_obj_t quality)
{
image_t *image = py_image_cobj(image_obj);
image_t cimage = {
.w=image->w,
.h=image->h,
.bpp=0,
.pixels= NULL
};
jpeg_compress(image, &cimage, mp_obj_get_int(quality));
return py_image_from_struct(&cimage);
}
static mp_obj_t py_image_draw_line(mp_obj_t image_obj, mp_obj_t line_obj)
{
/* get image pointer */
@ -811,6 +826,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_rainbow_obj, py_image_rainbow);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_erode_obj, py_image_erode);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_dilate_obj, py_image_dilate);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_morph_obj, py_image_morph);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_compress_obj, py_image_compress);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_draw_line_obj, py_image_draw_line);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_draw_circle_obj, py_image_draw_circle);
@ -841,6 +857,7 @@ static const mp_map_elem_t locals_dict_table[] = {
{MP_OBJ_NEW_QSTR(MP_QSTR_erode), (mp_obj_t)&py_image_erode_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_dilate), (mp_obj_t)&py_image_dilate_obj},
// {MP_OBJ_NEW_QSTR(MP_QSTR_morph), (mp_obj_t)&py_image_morph_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_compress), (mp_obj_t)&py_image_compress_obj},
/* drawing functions */
{MP_OBJ_NEW_QSTR(MP_QSTR_draw_line), (mp_obj_t)&py_image_draw_line_obj},