mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Optimize JPEG library.
This commit is contained in:
parent
726e3a8e21
commit
fd418576c0
@ -4,6 +4,7 @@
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* Minimalistic JPEG baseline encoder.
|
||||
* Ported from public domain JPEG writer by Jon Olick - http://jonolick.com
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
@ -13,39 +14,13 @@
|
||||
#include "xalloc.h"
|
||||
#include "imlib.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
|
||||
};
|
||||
extern const int8_t yuv_table[196608];
|
||||
|
||||
static const uint8_t s_jo_ZigZag[] = {
|
||||
0, 1, 5, 6, 14, 15, 27, 28,
|
||||
@ -195,10 +170,11 @@ static void jpeg_put_char(jpeg_buf_t *jpeg_buf, char c)
|
||||
|
||||
static void jpeg_put_bytes(jpeg_buf_t *jpeg_buf, const void *data, int size)
|
||||
{
|
||||
if (jpeg_buf->idx+size == jpeg_buf->length) {
|
||||
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;
|
||||
}
|
||||
@ -383,17 +359,25 @@ static int jo_processDU(jpeg_buf_t *jpeg_buf, int *bitBuf, int *bitCnt, int *CDU
|
||||
|
||||
void jpeg_compress(image_t *src, image_t *dst, int quality)
|
||||
{
|
||||
// Quality
|
||||
static int q =0;
|
||||
|
||||
// JPEG buffer
|
||||
jpeg_buf_t jpeg_buf = {
|
||||
.idx =0,
|
||||
.buf = dst->pixels,
|
||||
.length = dst->bpp,
|
||||
};
|
||||
|
||||
// Quantization tables
|
||||
float fdtbl_Y[64], fdtbl_UV[64];
|
||||
uint8_t YTable[64], UVTable[64];
|
||||
|
||||
// JPEG headers
|
||||
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)
|
||||
};
|
||||
|
||||
quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
|
||||
|
||||
// If quality changed, update quantization matrix
|
||||
@ -441,24 +425,43 @@ void jpeg_compress(image_t *src, image_t *dst, int quality)
|
||||
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);
|
||||
uint16_t *pixels = (uint16_t *)src->pixels;
|
||||
|
||||
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;
|
||||
}
|
||||
for (int r=y, pos=0; r<y+8; ++r, pos+=8) {
|
||||
int ofs = r*src->w+x;
|
||||
YDU[pos + 0] = yuv_table[pixels[ofs + 0] * 3 + 0];
|
||||
UDU[pos + 0] = yuv_table[pixels[ofs + 0] * 3 + 1];
|
||||
VDU[pos + 0] = yuv_table[pixels[ofs + 0] * 3 + 2];
|
||||
|
||||
YDU[pos + 1] = yuv_table[pixels[ofs + 1] * 3 + 0];
|
||||
UDU[pos + 1] = yuv_table[pixels[ofs + 1] * 3 + 1];
|
||||
VDU[pos + 1] = yuv_table[pixels[ofs + 1] * 3 + 2];
|
||||
|
||||
YDU[pos + 2] = yuv_table[pixels[ofs + 2] * 3 + 0];
|
||||
UDU[pos + 2] = yuv_table[pixels[ofs + 2] * 3 + 1];
|
||||
VDU[pos + 2] = yuv_table[pixels[ofs + 2] * 3 + 2];
|
||||
|
||||
YDU[pos + 3] = yuv_table[pixels[ofs + 3] * 3 + 0];
|
||||
UDU[pos + 3] = yuv_table[pixels[ofs + 3] * 3 + 1];
|
||||
VDU[pos + 3] = yuv_table[pixels[ofs + 3] * 3 + 2];
|
||||
|
||||
YDU[pos + 4] = yuv_table[pixels[ofs + 4] * 3 + 0];
|
||||
UDU[pos + 4] = yuv_table[pixels[ofs + 4] * 3 + 1];
|
||||
VDU[pos + 4] = yuv_table[pixels[ofs + 4] * 3 + 2];
|
||||
|
||||
YDU[pos + 5] = yuv_table[pixels[ofs + 5] * 3 + 0];
|
||||
UDU[pos + 5] = yuv_table[pixels[ofs + 5] * 3 + 1];
|
||||
VDU[pos + 5] = yuv_table[pixels[ofs + 5] * 3 + 2];
|
||||
|
||||
YDU[pos + 6] = yuv_table[pixels[ofs + 6] * 3 + 0];
|
||||
UDU[pos + 6] = yuv_table[pixels[ofs + 6] * 3 + 1];
|
||||
VDU[pos + 6] = yuv_table[pixels[ofs + 6] * 3 + 2];
|
||||
|
||||
YDU[pos + 7] = yuv_table[pixels[ofs + 7] * 3 + 0];
|
||||
UDU[pos + 7] = yuv_table[pixels[ofs + 7] * 3 + 1];
|
||||
VDU[pos + 7] = yuv_table[pixels[ofs + 7] * 3 + 2];
|
||||
}
|
||||
|
||||
DCY = jo_processDU(&jpeg_buf, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user