project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp: Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem. sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately. sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades. sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for fastboot. Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
934 lines
24 KiB
C
934 lines
24 KiB
C
/**
|
|
* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef PACKAGE
|
|
#define PACKAGE "jbig2dec"
|
|
#endif
|
|
|
|
#include <rtthread.h>
|
|
#include <rtdevice.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#include "drv_display.h"
|
|
#include "drv_heap.h"
|
|
#include "image_info.h"
|
|
#include "jbig2dec.h"
|
|
|
|
#if !defined (UINT32_MAX)
|
|
#define UINT32_MAX 0xffffffff
|
|
#endif
|
|
|
|
#define get_uint16(bptr)\
|
|
(((bptr)[0] << 8) | (bptr)[1])
|
|
#define get_int16(bptr)\
|
|
(((int)get_uint16(bptr) ^ 0x8000) - 0x8000)
|
|
|
|
#define OPTI 1
|
|
|
|
#define CONTEXT_13 1
|
|
|
|
#if CONTEXT_13
|
|
#define CONTEXT_VALUE0 0x0efb
|
|
#define CONTEXT_VALUE1 0x0008
|
|
#define CONTEXT_VALUE2 0x0200
|
|
#define CONTEXT_VALUE3 1
|
|
#else //else CONTEXT = 16
|
|
#define CONTEXT_VALUE0 0x7bf7
|
|
#define CONTEXT_VALUE1 0x10
|
|
#define CONTEXT_VALUE2 0x800
|
|
#define CONTEXT_VALUE3 0
|
|
#endif
|
|
|
|
|
|
void
|
|
jbig2_free(Jbig2Allocator *allocator, void *p)
|
|
{
|
|
allocator->free(allocator, p);
|
|
}
|
|
|
|
int16_t
|
|
jbig2_get_int16(const unsigned char *bptr)
|
|
{
|
|
return get_int16(bptr);
|
|
}
|
|
|
|
int32_t
|
|
jbig2_get_int32(const unsigned char *bptr)
|
|
{
|
|
return ((int32_t)get_int16(bptr) << 16) | get_uint16(bptr + 2);
|
|
}
|
|
|
|
uint32_t
|
|
jbig2_get_uint32(const unsigned char *bptr)
|
|
{
|
|
return ((uint32_t)get_uint16(bptr) << 16) | get_uint16(bptr + 2);
|
|
}
|
|
|
|
/* could put bit fields in to minimize memory usage */
|
|
typedef struct
|
|
{
|
|
unsigned short Qe;
|
|
unsigned char mps_xor; /* mps_xor = index ^ NMPS */
|
|
unsigned char lps_xor; /* lps_xor = index ^ NLPS ^ (SWITCH << 7) */
|
|
} Jbig2ArithQe;
|
|
|
|
const Jbig2ArithQe jbig2_arith_Qe[47] =
|
|
{
|
|
{ 0x5601, 1 ^ 0, 1 ^ 0 ^ 0x80 },
|
|
{ 0x3401, 2 ^ 1, 6 ^ 1 },
|
|
{ 0x1801, 3 ^ 2, 9 ^ 2 },
|
|
{ 0x0AC1, 4 ^ 3, 12 ^ 3 },
|
|
{ 0x0521, 5 ^ 4, 29 ^ 4 },
|
|
{ 0x0221, 38 ^ 5, 33 ^ 5 },
|
|
{ 0x5601, 7 ^ 6, 6 ^ 6 ^ 0x80 },
|
|
{ 0x5401, 8 ^ 7, 14 ^ 7 },
|
|
{ 0x4801, 9 ^ 8, 14 ^ 8 },
|
|
{ 0x3801, 10 ^ 9, 14 ^ 9 },
|
|
{ 0x3001, 11 ^ 10, 17 ^ 10 },
|
|
{ 0x2401, 12 ^ 11, 18 ^ 11 },
|
|
{ 0x1C01, 13 ^ 12, 20 ^ 12 },
|
|
{ 0x1601, 29 ^ 13, 21 ^ 13 },
|
|
{ 0x5601, 15 ^ 14, 14 ^ 14 ^ 0x80 },
|
|
{ 0x5401, 16 ^ 15, 14 ^ 15 },
|
|
{ 0x5101, 17 ^ 16, 15 ^ 16 },
|
|
{ 0x4801, 18 ^ 17, 16 ^ 17 },
|
|
{ 0x3801, 19 ^ 18, 17 ^ 18 },
|
|
{ 0x3401, 20 ^ 19, 18 ^ 19 },
|
|
{ 0x3001, 21 ^ 20, 19 ^ 20 },
|
|
{ 0x2801, 22 ^ 21, 19 ^ 21 },
|
|
{ 0x2401, 23 ^ 22, 20 ^ 22 },
|
|
{ 0x2201, 24 ^ 23, 21 ^ 23 },
|
|
{ 0x1C01, 25 ^ 24, 22 ^ 24 },
|
|
{ 0x1801, 26 ^ 25, 23 ^ 25 },
|
|
{ 0x1601, 27 ^ 26, 24 ^ 26 },
|
|
{ 0x1401, 28 ^ 27, 25 ^ 27 },
|
|
{ 0x1201, 29 ^ 28, 26 ^ 28 },
|
|
{ 0x1101, 30 ^ 29, 27 ^ 29 },
|
|
{ 0x0AC1, 31 ^ 30, 28 ^ 30 },
|
|
{ 0x09C1, 32 ^ 31, 29 ^ 31 },
|
|
{ 0x08A1, 33 ^ 32, 30 ^ 32 },
|
|
{ 0x0521, 34 ^ 33, 31 ^ 33 },
|
|
{ 0x0441, 35 ^ 34, 32 ^ 34 },
|
|
{ 0x02A1, 36 ^ 35, 33 ^ 35 },
|
|
{ 0x0221, 37 ^ 36, 34 ^ 36 },
|
|
{ 0x0141, 38 ^ 37, 35 ^ 37 },
|
|
{ 0x0111, 39 ^ 38, 36 ^ 38 },
|
|
{ 0x0085, 40 ^ 39, 37 ^ 39 },
|
|
{ 0x0049, 41 ^ 40, 38 ^ 40 },
|
|
{ 0x0025, 42 ^ 41, 39 ^ 41 },
|
|
{ 0x0015, 43 ^ 42, 40 ^ 42 },
|
|
{ 0x0009, 44 ^ 43, 41 ^ 43 },
|
|
{ 0x0005, 45 ^ 44, 42 ^ 44 },
|
|
{ 0x0001, 45 ^ 45, 43 ^ 45 },
|
|
{ 0x5601, 46 ^ 46, 46 ^ 46 }
|
|
};
|
|
|
|
static void *
|
|
jbig2_default_alloc(Jbig2Allocator *allocator, size_t size)
|
|
{
|
|
return malloc(size);
|
|
}
|
|
|
|
static void
|
|
jbig2_default_free(Jbig2Allocator *allocator, void *p)
|
|
{
|
|
free(p);
|
|
}
|
|
|
|
static void *
|
|
jbig2_default_realloc(Jbig2Allocator *allocator, void *p, size_t size)
|
|
{
|
|
return realloc(p, size);
|
|
}
|
|
|
|
static Jbig2Allocator jbig2_default_allocator =
|
|
{
|
|
jbig2_default_alloc,
|
|
jbig2_default_free,
|
|
jbig2_default_realloc
|
|
};
|
|
|
|
void *
|
|
jbig2_alloc(Jbig2Allocator *allocator, size_t size, size_t num)
|
|
{
|
|
if (num > 0 && size > SIZE_MAX / num)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return allocator->alloc(allocator, size * num);
|
|
}
|
|
|
|
void *
|
|
jbig2_realloc(Jbig2Allocator *allocator, void *p, size_t size, size_t num)
|
|
{
|
|
/* check for integer multiplication overflow */
|
|
if (num > 0 && size >= SIZE_MAX / num)
|
|
{
|
|
return NULL;
|
|
}
|
|
return allocator->realloc(allocator, p, size * num);
|
|
}
|
|
|
|
Jbig2Ctx *
|
|
jbig2_ctx_new(Jbig2Allocator *allocator)
|
|
{
|
|
Jbig2Ctx *result;
|
|
|
|
if (allocator == NULL)
|
|
allocator = &jbig2_default_allocator;
|
|
|
|
result = (Jbig2Ctx *)jbig2_alloc(allocator, sizeof(Jbig2Ctx), 1);
|
|
if (NULL == result)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
result->allocator = allocator;
|
|
result->state = JBIG2_FILE_HEADER;
|
|
result->buf = NULL;
|
|
result->n_segments = 0;
|
|
result->segments = jbig2_new(result, Jbig2Segment *, 8);
|
|
if (NULL == result->segments)
|
|
{
|
|
rt_kprintf("malloc failed : fail to malloc result->segments\n");
|
|
return NULL;
|
|
}
|
|
result->segment_index = 0;
|
|
|
|
result->current_page = 0;
|
|
result->max_page_index = 4;
|
|
result->pages = jbig2_new(result, Jbig2Page, result->max_page_index);
|
|
if (NULL == result->pages)
|
|
{
|
|
jbig2_ctx_free(result);
|
|
rt_kprintf("malloc failed : fail to malloc result->pages\n");
|
|
return NULL;
|
|
}
|
|
{
|
|
int index;
|
|
|
|
for (index = 0; index < result->max_page_index; index++)
|
|
{
|
|
result->pages[index].state = JBIG2_PAGE_FREE;
|
|
result->pages[index].number = 0;
|
|
result->pages[index].width = 0;
|
|
result->pages[index].height = 0xffffffff;
|
|
result->pages[index].x_resolution = 0;
|
|
result->pages[index].y_resolution = 0;
|
|
result->pages[index].flags = 0;
|
|
result->pages[index].image = NULL;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
Jbig2WordStream super;
|
|
const unsigned char *data;
|
|
size_t size;
|
|
} Jbig2WordStreamBuf;//
|
|
|
|
static int//
|
|
jbig2_word_stream_buf_get_next_word(Jbig2WordStream *self, size_t offset, uint32_t *word)
|
|
{
|
|
Jbig2WordStreamBuf *z = (Jbig2WordStreamBuf *)self;
|
|
uint32_t val = 0;
|
|
int ret = 0;
|
|
|
|
if (self == NULL || word == NULL)
|
|
return -1;
|
|
if (offset >= z->size)
|
|
{
|
|
*word = 0;
|
|
return 0;
|
|
}
|
|
|
|
if (offset < z->size)
|
|
{
|
|
val |= z->data[offset] << 24;
|
|
ret++;
|
|
}
|
|
if (offset + 1 < z->size)
|
|
{
|
|
val |= z->data[offset + 1] << 16;
|
|
ret++;
|
|
}
|
|
if (offset + 2 < z->size)
|
|
{
|
|
val |= z->data[offset + 2] << 8;
|
|
ret++;
|
|
}
|
|
if (offset + 3 < z->size)
|
|
{
|
|
val |= z->data[offset + 3];
|
|
ret++;
|
|
}
|
|
*word = val;
|
|
return ret;
|
|
}
|
|
|
|
Jbig2WordStream *//
|
|
jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const unsigned char *data, size_t size)
|
|
{
|
|
Jbig2WordStreamBuf *result = jbig2_new(ctx, Jbig2WordStreamBuf, 1);
|
|
if (NULL == result)
|
|
{
|
|
rt_kprintf("malloc failed : fail to malloc result\n");
|
|
return NULL;
|
|
}
|
|
//Jbig2WordStreamBuf *result = (Jbig2WordStreamBuf *)malloc(sizeof(Jbig2WordStreamBuf) * 1);
|
|
|
|
if (result == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
result->super.get_next_word = jbig2_word_stream_buf_get_next_word;
|
|
result->data = data;
|
|
result->size = size;
|
|
|
|
return &result->super;
|
|
}
|
|
|
|
static void//
|
|
jbig2_arith_bytein(Jbig2ArithState *as)
|
|
{
|
|
int new_bytes;
|
|
unsigned char B;
|
|
|
|
/* invariant: as->next_word_bytes > 0 */
|
|
|
|
/* Figure G.3 */
|
|
B = (unsigned char)((as->next_word >> 24) & 0xFF);
|
|
if (B == 0xFF)
|
|
{
|
|
unsigned char B1;
|
|
|
|
if (as->next_word_bytes == 1)
|
|
{
|
|
Jbig2WordStream *ws = as->ws;
|
|
|
|
new_bytes = ws->get_next_word(ws, as->offset, &as->next_word);
|
|
as->next_word_bytes = new_bytes;
|
|
as->offset += new_bytes;
|
|
|
|
B1 = (unsigned char)((as->next_word >> 24) & 0xFF);
|
|
if (B1 > 0x8F)
|
|
{
|
|
as->C += 0xFF00;
|
|
as->CT = 8;
|
|
as->next_word = 0xFF000000 | (as->next_word >> 8);
|
|
as->next_word_bytes = 4;
|
|
as->offset--;
|
|
}
|
|
else
|
|
{
|
|
as->C += B1 << 9;
|
|
as->CT = 7;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
B1 = (unsigned char)((as->next_word >> 16) & 0xFF);
|
|
if (B1 > 0x8F)
|
|
{
|
|
as->C += 0xFF00;
|
|
as->CT = 8;
|
|
}
|
|
else
|
|
{
|
|
as->next_word_bytes--;
|
|
as->next_word <<= 8;
|
|
as->C += (B1 << 9);
|
|
as->CT = 7;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
as->CT = 8;
|
|
as->next_word <<= 8;
|
|
as->next_word_bytes--;
|
|
if (as->next_word_bytes == 0)
|
|
{
|
|
Jbig2WordStream *ws = as->ws;
|
|
|
|
new_bytes = ws->get_next_word(ws, as->offset, &as->next_word);
|
|
as->offset += new_bytes;
|
|
as->next_word_bytes = new_bytes;
|
|
}
|
|
B = (unsigned char)((as->next_word >> 24) & 0xFF);
|
|
as->C += (B << 8);
|
|
}
|
|
}
|
|
|
|
Jbig2ArithState *//
|
|
jbig2_arith_new(Jbig2Ctx *ctx, Jbig2WordStream *ws)
|
|
{
|
|
Jbig2ArithState *result;
|
|
int new_bytes;
|
|
|
|
result = jbig2_new(ctx, Jbig2ArithState, 1);
|
|
if (result == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
result->ws = ws;
|
|
|
|
new_bytes = ws->get_next_word(ws, 0, &result->next_word);
|
|
result->next_word_bytes = new_bytes;
|
|
result->offset = new_bytes;
|
|
result->C = (result->next_word >> 8) & 0xFF0000;
|
|
jbig2_arith_bytein(result);
|
|
result->C <<= 7;
|
|
result->CT -= 7;
|
|
result->A = 0x8000;
|
|
|
|
return result;
|
|
}
|
|
|
|
static void//
|
|
jbig2_arith_renormd(Jbig2ArithState *as)
|
|
{
|
|
/* Figure E.18 */
|
|
do
|
|
{
|
|
if (as->CT == 0)
|
|
jbig2_arith_bytein(as);
|
|
as->A <<= 1;
|
|
as->C <<= 1;
|
|
as->CT--;
|
|
}
|
|
while ((as->A & 0x8000) == 0);
|
|
}
|
|
|
|
#if OPTI
|
|
char
|
|
jbig2_arith_decode(Jbig2ArithState *as, uint8_t *pcx) // , int *code
|
|
{
|
|
uint8_t cx = *pcx;
|
|
const Jbig2ArithQe *pqe;
|
|
unsigned int index = cx & 0x7f;
|
|
char D;
|
|
|
|
if (index >= 47)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
pqe = &jbig2_arith_Qe[index];
|
|
}
|
|
|
|
/* Figure E.15 */
|
|
as->A -= pqe->Qe;
|
|
if (
|
|
!((as->C >> 16) < pqe->Qe)
|
|
)
|
|
{
|
|
as->C -= pqe->Qe << 16;
|
|
if ((as->A & 0x8000) == 0)
|
|
{
|
|
/* MPS_EXCHANGE, Figure E.16 */
|
|
if (as->A < pqe->Qe)
|
|
{
|
|
D = 1 - (cx >> 7);
|
|
*pcx ^= pqe->lps_xor;
|
|
}
|
|
else
|
|
{
|
|
D = cx >> 7;
|
|
*pcx ^= pqe->mps_xor;
|
|
}
|
|
|
|
#if 0 //OPTI
|
|
{
|
|
/* Figure E.18 */
|
|
do
|
|
{
|
|
if (as->CT == 0)
|
|
jbig2_arith_bytein(as);
|
|
as->A <<= 1;
|
|
as->C <<= 1;
|
|
as->CT--;
|
|
}
|
|
while ((as->A & 0x8000) == 0);
|
|
}
|
|
#else
|
|
jbig2_arith_renormd(as);
|
|
#endif
|
|
return D;
|
|
}
|
|
else
|
|
{
|
|
return cx >> 7;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* LPS_EXCHANGE, Figure E.17 */
|
|
if (as->A < pqe->Qe)
|
|
{
|
|
as->A = pqe->Qe;
|
|
D = cx >> 7;
|
|
*pcx ^= pqe->mps_xor;
|
|
}
|
|
else
|
|
{
|
|
as->A = pqe->Qe;
|
|
D = 1 - (cx >> 7);
|
|
*pcx ^= pqe->lps_xor;
|
|
}
|
|
#if 0 //OPTI
|
|
{
|
|
/* Figure E.18 */
|
|
do
|
|
{
|
|
if (as->CT == 0)
|
|
jbig2_arith_bytein(as);
|
|
as->A <<= 1;
|
|
as->C <<= 1;
|
|
as->CT--;
|
|
}
|
|
while ((as->A & 0x8000) == 0);
|
|
}
|
|
#else
|
|
jbig2_arith_renormd(as);
|
|
#endif
|
|
return D;
|
|
}
|
|
}
|
|
#else
|
|
char
|
|
jbig2_arith_decode(Jbig2ArithState *as, uint8_t *pcx, int *code)
|
|
{
|
|
uint8_t cx = *pcx;
|
|
const Jbig2ArithQe *pqe;
|
|
unsigned int index = cx & 0x7f;
|
|
char D;
|
|
|
|
if (index >= 47)
|
|
{
|
|
*code = -1;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
pqe = &jbig2_arith_Qe[index];
|
|
}
|
|
|
|
/* Figure E.15 */
|
|
as->A -= pqe->Qe;
|
|
if (
|
|
!((as->C >> 16) < pqe->Qe)
|
|
)
|
|
{
|
|
as->C -= pqe->Qe << 16;
|
|
if ((as->A & 0x8000) == 0)
|
|
{
|
|
/* MPS_EXCHANGE, Figure E.16 */
|
|
if (as->A < pqe->Qe)
|
|
{
|
|
D = 1 - (cx >> 7);
|
|
*pcx ^= pqe->lps_xor;
|
|
}
|
|
else
|
|
{
|
|
D = cx >> 7;
|
|
*pcx ^= pqe->mps_xor;
|
|
}
|
|
|
|
#if 0 //OPTI
|
|
{
|
|
/* Figure E.18 */
|
|
do
|
|
{
|
|
if (as->CT == 0)
|
|
jbig2_arith_bytein(as);
|
|
as->A <<= 1;
|
|
as->C <<= 1;
|
|
as->CT--;
|
|
}
|
|
while ((as->A & 0x8000) == 0);
|
|
}
|
|
#else
|
|
jbig2_arith_renormd(as);
|
|
#endif
|
|
*code = 0;
|
|
return D;
|
|
}
|
|
else
|
|
{
|
|
*code = 0;
|
|
return cx >> 7;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* LPS_EXCHANGE, Figure E.17 */
|
|
if (as->A < pqe->Qe)
|
|
{
|
|
as->A = pqe->Qe;
|
|
D = cx >> 7;
|
|
*pcx ^= pqe->mps_xor;
|
|
}
|
|
else
|
|
{
|
|
as->A = pqe->Qe;
|
|
D = 1 - (cx >> 7);
|
|
*pcx ^= pqe->lps_xor;
|
|
}
|
|
#if 0 //OPTI
|
|
{
|
|
/* Figure E.18 */
|
|
do
|
|
{
|
|
if (as->CT == 0)
|
|
jbig2_arith_bytein(as);
|
|
as->A <<= 1;
|
|
as->C <<= 1;
|
|
as->CT--;
|
|
}
|
|
while ((as->A & 0x8000) == 0);
|
|
}
|
|
#else
|
|
jbig2_arith_renormd(as);
|
|
#endif
|
|
*code = 0;
|
|
return D;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void//
|
|
jbig2_image_free(Jbig2Ctx *ctx, Jbig2Image *image)
|
|
{
|
|
if (image != NULL)
|
|
{
|
|
//jbig2_free(ctx->allocator, image->data);
|
|
jbig2_free(ctx->allocator, image);
|
|
}
|
|
}
|
|
|
|
void
|
|
jbig2_image_release(Jbig2Ctx *ctx, Jbig2Image *image)
|
|
{
|
|
if (image == NULL)
|
|
return;
|
|
image->refcount--;
|
|
if (image->refcount == 0)
|
|
jbig2_image_free(ctx, image);
|
|
}
|
|
|
|
Jbig2Allocator *
|
|
jbig2_ctx_free(Jbig2Ctx *ctx)
|
|
{
|
|
Jbig2Allocator *ca;
|
|
int i;
|
|
|
|
if (ctx == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
ca = ctx->allocator;
|
|
jbig2_free(ca, ctx->buf);
|
|
if (ctx->segments != NULL)
|
|
{
|
|
for (i = 0; i < ctx->n_segments; i++)
|
|
{
|
|
if (ctx->segments[i] == NULL)
|
|
continue;
|
|
jbig2_free(ctx->allocator, ctx->segments[i]->referred_to_segments);
|
|
if ((4 == (ctx->segments[i]->flags & 63) || 40 == (ctx->segments[i]->flags & 63)) && ctx->segments[i]->result != NULL)
|
|
{
|
|
jbig2_image_release(ctx, (Jbig2Image *)ctx->segments[i]->result);
|
|
}
|
|
jbig2_free(ctx->allocator, ctx->segments[i]);
|
|
}
|
|
jbig2_free(ca, ctx->segments);
|
|
}
|
|
|
|
if (ctx->pages != NULL)
|
|
{
|
|
for (i = 0; i <= ctx->current_page; i++)
|
|
if (ctx->pages[i].image != NULL)
|
|
jbig2_image_release(ctx, ctx->pages[i].image);
|
|
jbig2_free(ca, ctx->pages);
|
|
}
|
|
|
|
jbig2_free(ca, ctx);
|
|
|
|
return ca;
|
|
}
|
|
|
|
int jbig2_decompression(image_info_t *img_info, rt_uint8_t *fb, rt_int32_t xVir, rt_int32_t xoffset, rt_int32_t yoffset)
|
|
{
|
|
|
|
Jbig2Ctx *ctx = NULL;
|
|
Jbig2WordStream *ws = NULL;
|
|
Jbig2ArithState *as = NULL;
|
|
uint8_t *GB_stats = NULL;
|
|
int stats_size;
|
|
rt_int16_t width = img_info->w;
|
|
rt_int16_t height = img_info->h;
|
|
size_t length = img_info->size;
|
|
rt_uint8_t *headbuf = RT_NULL;
|
|
rt_uint8_t *tailbuf = RT_NULL;
|
|
rt_uint16_t align8_x1, align8_x2;
|
|
rt_uint8_t mod8_x1, mod8_x2;
|
|
|
|
// Initial buffer(clear)
|
|
align8_x1 = xoffset / 8;
|
|
align8_x2 = (xoffset + img_info->w + 7) / 8;
|
|
mod8_x1 = xoffset % 8;
|
|
mod8_x2 = (xoffset + img_info->w) % 8;
|
|
//rt_kprintf("xoffset = %d, width = %d\n", xoffset, width);
|
|
//rt_kprintf("align8_x1 = %d, align8_x2 = %d\n", align8_x1, align8_x2);
|
|
//rt_kprintf("mod8_x1 = %d, mod8_x2 = %d\n", mod8_x1, mod8_x2);
|
|
{
|
|
rt_uint16_t x, y;
|
|
|
|
if (mod8_x1 != 0)
|
|
{
|
|
headbuf = rt_malloc(height);
|
|
RT_ASSERT(headbuf != RT_NULL);
|
|
}
|
|
|
|
if (mod8_x2 != 0)
|
|
{
|
|
tailbuf = rt_malloc(height);
|
|
RT_ASSERT(tailbuf != RT_NULL);
|
|
}
|
|
|
|
for (y = yoffset; y < yoffset + height; y++)
|
|
{
|
|
// Backup left margin if not align8
|
|
if (mod8_x1 != 0)
|
|
{
|
|
headbuf[y - yoffset] = fb[y * (xVir >> 3) + align8_x1];
|
|
}
|
|
|
|
// Backup right margin if not align8
|
|
if (mod8_x2 != 0)
|
|
{
|
|
tailbuf[y - yoffset] = fb[y * (xVir >> 3) + (align8_x2 - 1)];
|
|
}
|
|
|
|
for (x = align8_x1; x < align8_x2; x++)
|
|
{
|
|
fb[y * (xVir >> 3) + x] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
ctx = jbig2_ctx_new(NULL);
|
|
if (NULL == ctx)
|
|
{
|
|
rt_kprintf("malloc failed : fail to malloc ctx\n");
|
|
return -1;
|
|
}
|
|
#if CONTEXT_13
|
|
stats_size = 1 << 13;
|
|
#else
|
|
stats_size = 1 << 16;
|
|
#endif
|
|
GB_stats = jbig2_new(ctx, uint8_t, stats_size);
|
|
if (NULL == GB_stats)
|
|
{
|
|
rt_kprintf("malloc failed : fail to malloc GB_stats\n");
|
|
return -1;
|
|
}
|
|
memset(GB_stats, 0, stats_size);
|
|
|
|
ws = jbig2_word_stream_buf_new(ctx, img_info->data, length);
|
|
if (NULL == ws)
|
|
{
|
|
rt_kprintf("malloc failed : fail to malloc ws\n");
|
|
return -1;
|
|
}
|
|
as = jbig2_arith_new(ctx, ws);
|
|
if (NULL == as)
|
|
{
|
|
rt_kprintf("malloc failed : fail to malloc as\n");
|
|
return -1;
|
|
}
|
|
|
|
if (1)
|
|
{
|
|
const uint32_t GBW = width;
|
|
const uint32_t GBH = height;
|
|
uint32_t x, y;
|
|
unsigned char *line2 = NULL;
|
|
unsigned char *line1 = NULL;
|
|
|
|
if (GBW <= 0 || GBH <= 0)
|
|
return -1;
|
|
|
|
for (y = 0; y < GBH; y++)
|
|
{
|
|
uint32_t CONTEXT;
|
|
uint32_t line_m1;
|
|
uint32_t line_m2;
|
|
uint32_t padded_width = (GBW + 7) & (-8);
|
|
int code_t = 0;
|
|
|
|
#if CONTEXT_13
|
|
line_m1 = line1 ? (line1[0]) : 0;
|
|
line_m2 = line2 ? line2[0] << 4 : 0;
|
|
CONTEXT = ((line_m1 >> 1) & 0x1f8) | (line_m2 & 0x1e00);
|
|
#else
|
|
line_m1 = line1 ? line1[0] : 0;
|
|
line_m2 = line2 ? line2[0] << 6 : 0;
|
|
CONTEXT = (line_m1 & 0x7f0) | (line_m2 & 0xf800);
|
|
#endif
|
|
|
|
for (x = 0; x < padded_width; x += 8)
|
|
{
|
|
#if OPTI
|
|
unsigned char result = 0;
|
|
#else
|
|
unsigned char result = 0;
|
|
#endif
|
|
int x_minor;
|
|
int minor_width = (GBW - x) > 8 ? 8 : GBW - x;
|
|
|
|
if (line1)
|
|
line_m1 = (line_m1 << 8) | (x + 8 < GBW ? line1[(x >> 3) + 1] : 0);
|
|
|
|
if (line2)
|
|
{
|
|
#if CONTEXT_13
|
|
line_m2 = (line_m2 << 8) | (x + 8 < GBW ? line2[(x >> 3) + 1] << 4 : 0);
|
|
#else
|
|
line_m2 = (line_m2 << 8) | (x + 8 < GBW ? line2[(x >> 3) + 1] << 6 : 0);
|
|
#endif
|
|
}
|
|
#if OPTI
|
|
{
|
|
if (minor_width == 8)
|
|
{
|
|
uint8_t bit;
|
|
// 0
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (7 + CONTEXT_VALUE3)) & CONTEXT_VALUE1) | ((line_m2 >> (7)) & CONTEXT_VALUE2);
|
|
result = (bit << 7);
|
|
// 1
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (6 + CONTEXT_VALUE3)) & CONTEXT_VALUE1) | ((line_m2 >> (6)) & CONTEXT_VALUE2);
|
|
result |= (bit << 6);
|
|
// 2
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (5 + CONTEXT_VALUE3)) & CONTEXT_VALUE1) | ((line_m2 >> (5)) & CONTEXT_VALUE2);
|
|
result |= (bit << 5);
|
|
// 3
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (4 + CONTEXT_VALUE3)) & CONTEXT_VALUE1) | ((line_m2 >> (4)) & CONTEXT_VALUE2);
|
|
result |= (bit << 4);
|
|
// 4
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (3 + CONTEXT_VALUE3)) & CONTEXT_VALUE1) | ((line_m2 >> (3)) & CONTEXT_VALUE2);
|
|
result |= (bit << 3);
|
|
// 5
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (2 + CONTEXT_VALUE3)) & CONTEXT_VALUE1) | ((line_m2 >> (2)) & CONTEXT_VALUE2);
|
|
result |= (bit << 2);
|
|
// 6
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (1 + CONTEXT_VALUE3)) & CONTEXT_VALUE1) | ((line_m2 >> (1)) & CONTEXT_VALUE2);
|
|
result |= (bit << 1);
|
|
// 7
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (0 + CONTEXT_VALUE3)) & CONTEXT_VALUE1) | ((line_m2)& CONTEXT_VALUE2);
|
|
result |= (bit);
|
|
}
|
|
else
|
|
{
|
|
for (x_minor = 0; x_minor < minor_width; x_minor++)
|
|
{
|
|
uint8_t bit;
|
|
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
|
|
if (code_t)
|
|
return -1;
|
|
result |= bit << (7 - x_minor);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (7 + CONTEXT_VALUE3 - x_minor)) & CONTEXT_VALUE1) | ((line_m2 >> (7 - x_minor)) & CONTEXT_VALUE2);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
for (x_minor = 0; x_minor < minor_width; x_minor++)
|
|
{
|
|
uint8_t bit;
|
|
|
|
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code_t);
|
|
if (code_t)
|
|
return -1;
|
|
result |= bit << (7 - x_minor);
|
|
CONTEXT = ((CONTEXT & CONTEXT_VALUE0) << 1) | bit | ((line_m1 >> (7 + CONTEXT_VALUE3 - x_minor)) & CONTEXT_VALUE3) | ((line_m2 >> (7 - x_minor)) & CONTEXT_VALUE2);
|
|
}
|
|
#endif
|
|
if (result != 0)
|
|
{
|
|
fb[(y + yoffset) * (xVir >> 3) + ((x + xoffset) >> 3)] = result;
|
|
}
|
|
}
|
|
line2 = line1;
|
|
line1 = fb + (xVir / 8) * (y + yoffset) + (xoffset >> 3);
|
|
}
|
|
|
|
}
|
|
|
|
// Restore left margin if not align8 & shift the decode result
|
|
if (mod8_x1 != 0)
|
|
{
|
|
rt_uint16_t x, y;
|
|
rt_uint8_t bitmask = 0xff >> (mod8_x1);
|
|
for (y = yoffset; y < yoffset + height; y++)
|
|
{
|
|
rt_uint8_t temp = 0;
|
|
rt_uint8_t shift = headbuf[y - yoffset] & (rt_uint8_t)(~bitmask);
|
|
for (x = align8_x1; x < align8_x2; x++)
|
|
{
|
|
temp = fb[y * (xVir >> 3) + x];
|
|
|
|
fb[y * (xVir >> 3) + x] >>= mod8_x1;
|
|
fb[y * (xVir >> 3) + x] |= shift;
|
|
|
|
shift = temp << (8 - mod8_x1);
|
|
|
|
}
|
|
}
|
|
rt_free(headbuf);
|
|
}
|
|
|
|
// Restore right margin if not align8
|
|
if (mod8_x2 != 0)
|
|
{
|
|
rt_uint16_t y;
|
|
for (y = yoffset; y < yoffset + height; y++)
|
|
{
|
|
rt_uint8_t bitmask = 0xff << (8 - mod8_x2);
|
|
tailbuf[y - yoffset] &= (~bitmask);
|
|
fb[y * (xVir >> 3) + (align8_x2 - 1)] &= bitmask;
|
|
fb[y * (xVir >> 3) + (align8_x2 - 1)] |= tailbuf[y - yoffset];
|
|
}
|
|
rt_free(tailbuf);
|
|
}
|
|
|
|
jbig2_free(ctx->allocator, as);
|
|
jbig2_free(ctx->allocator, ws);
|
|
jbig2_free(ctx->allocator, GB_stats);
|
|
jbig2_ctx_free(ctx);
|
|
return 0;
|
|
}
|