📄 png_decoder.c
字号:
}
// transparent control
if(png_dcb.flags & PNG_HAVE_tRNS)
{
reg = PNG_TRAN_CON_TRAN_ENABLE;
if(cfg->out_format == ARGB4444 || cfg->out_format == ARGB8888)
{
reg |= PNG_TRAN_CON_ARGB;
}
if(info->color_type == COLOR_TYPE_INDEX)
{
if(info->num_trans == 1)
{
DRV_WriteReg32(PNG_TRAN_KEY1, (info->trans.index<<16));
}
else
{
//DRV_WriteReg32(PNG_TRAN_TABLE, cfg->color_table_t);
reg |= PNG_TRAN_CON_TRAN_TABLE;
}
}
else if(info->color_type == COLOR_TYPE_GRAY)
{
DRV_WriteReg32(PNG_TRAN_KEY1, (info->trans.gray << 16));
}
else if(info->color_type == COLOR_TYPE_RGB)
{
DRV_WriteReg32(PNG_TRAN_KEY1, (info->trans.color.r));
DRV_WriteReg32(PNG_TRAN_KEY2, (info->trans.color.g << 16)|
(info->trans.color.g));
}
else
PNG_RAISE(1);
// background control
if(png_dcb.flags & PNG_HAVE_bKGD)
{
if(info->color_type == COLOR_TYPE_INDEX)
{
DRV_WriteReg32(PNG_BACK_GROUND, info->bKGD.index << 24);
}
else if(info->color_type == COLOR_TYPE_GRAY)
{
kal_uint32 gray;
gray = info->bKGD.gray;
if(info->bit_depth > 8)
gray = gray >> (8);
DRV_WriteReg32(PNG_BACK_GROUND, gray << 24);
}
else if(info->color_type == COLOR_TYPE_RGB)
{
kal_uint32 r,g,b;
r = info->bKGD.color.r;
g = info->bKGD.color.g;
b = info->bKGD.color.b;
if(info->bit_depth > 8)
{
r = r >> (info->bit_depth -8);
g = g >> (info->bit_depth -8);
b = b >> (info->bit_depth -8);
}
DRV_WriteReg32(PNG_BACK_GROUND, ((r<<16)|(g<<8)|b));
}
}
else
{ // no bKGD
if((info->color_type == COLOR_TYPE_GRAY || info->color_type ==
COLOR_TYPE_INDEX) && info->num_trans == 1)
{
info->use_work_buf = KAL_TRUE;
reg = 0;
}
else if(info->use_work_buf)
{
// without bKGD and output to working buffer
info->use_work_buf = KAL_TRUE;
reg = 0;
}
else
{
reg |= PNG_TRAN_CON_TRAN_OUT;
}
}
DRV_WriteReg32(PNG_TRAN_CON, reg);
}
else
{
DRV_WriteReg32(PNG_TRAN_CON, 0);
}
// configure the clipping
if(cfg->clip_en)
{
kal_int32 x, y;
out_format |= PNG_OUT_FORMAT_CLIP_EN;
if(info->use_work_buf)
{
DRV_WriteReg32(PNG_LCD_WH, ((info->wb_width<< 16)|info->wb_height));
DRV_WriteReg32(PNG_CLIP_XY, ((0 << 16)|0));
DRV_WriteReg32(PNG_CLIP_WH, ((info->wb_width)<< 16)|
(info->wb_height));
x = info->wb_dest_x;
y = info->wb_dest_y;
}
else
{
DRV_WriteReg32(PNG_LCD_WH, ((cfg->shadow_w << 16)|cfg->shadow_h));
DRV_WriteReg32(PNG_CLIP_XY, ((cfg->clip_x1 << 16)|cfg->clip_y1));
DRV_WriteReg32(PNG_CLIP_WH, ((cfg->clip_x2- cfg->clip_x1+ 1)<< 16)|
(cfg->clip_y2- cfg->clip_y1+ 1));
x = cfg->dest_x ;
y = cfg->dest_y ;
}
if(x < 0 )
{
x *= -1;
x |= 0x8000;
}
if(y < 0 )
{
y *= -1;
y |= 0x8000;
}
DRV_WriteReg32(PNG_IMG_XY, ((x<< 16)|(y & 0xffff)));
}
else
{
DRV_WriteReg32(PNG_IMG_XY, 0);
}
DRV_WriteReg8(PNG_OUT_FROMAT, out_format);
DRV_WriteReg8(PNG_IRQ_EN, PNG_IRQ_EN_ALL);
if(info->use_work_buf)
{
kal_uint8 r,g,b,bit_depth;
kal_uint32 *ct;
kal_uint16 gray;
kal_uint32 color, src_key=0,count,i;
DRV_WriteReg32(PNG_OUT_START, cfg->work_buffer_adrs);
DRV_WriteReg32(PNG_OUT_END, cfg->work_buffer_adrs+cfg->work_buffer_size-2);
if(info->color_type == COLOR_TYPE_GRAY)
{
gray = info->trans.gray;
bit_depth = info->bit_depth;
gray = png_get_gray_scale(bit_depth, gray);
r = g = b = gray;
if(cfg->out_format == RGB888)
src_key = (r<<16)|(g<<8)|b;
else
src_key = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);
}
else if(info->color_type == COLOR_TYPE_INDEX)
{
ct = (kal_uint32*)cfg->color_table;
color = ct[info->trans.index];
b = (color)&0xff;
g = (color>>8)&0xff;
r = (color>>16)&0xff;
if(cfg->out_format == RGB888)
src_key = (r<<16)|(g<<8)|b;
else
src_key = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);
count = png_dcb.info.num_plte;
// remove the color of differnet trans.index but the same with transparent color
for(i=0;i<=count;i++)
{
if(cfg->out_format == RGB888)
{
if(src_key == ct[i])
{
ct[i] ^= (1<<17); // xor R
}
}
else if(cfg->out_format == RGB565)
{
kal_uint32 r1,b1,g1;
b1 = (ct[i])&0xff;
g1 = (ct[i]>>8)&0xff;
r1 = (ct[i]>>16)&0xff;
if(((r1>>3)<<11)|((g1>>2)<<5)|(b1>>3) == src_key)
{
ct[i] ^= (1<<20); // xor R
}
}
}
ct[info->trans.index] = color;
//png_remove_srckey_color(info->trans.index);
}
// src_key for 2d engine to perform bitblit
png_dcb.info.src_key = src_key;
// not decode until the caller give the working buffer
}
else
{
DRV_WriteReg32(PNG_OUT_START, cfg->output_buffer_adrs);
DRV_WriteReg32(PNG_OUT_END, cfg->output_buffer_adrs+cfg->output_buffer_size-2);
}
PNG_DECODE_RUN();
}
/*************************************************************************
* FUNCTION
* png_crc_reset
*
* DESCRIPTION
* reset the crc value
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void png_crc_reset(void)
{
png_dcb.crc = 0xffffffffL;
}
/*************************************************************************
* FUNCTION
* png_crc_finish
*
* DESCRIPTION
* check the crc value is correct or not
*
* PARAMETERS
*
* RETURNS
* KAL_TRUE: the crc value is correct
* KAL_FALSE: the crc value is wrong
*
* GLOBALS AFFECTED
*
*************************************************************************/
static kal_bool png_crc_finish(void)
{
kal_uint32 crc;
crc = PNG_GET_U32();
if((crc ^ 0xffffffff) == png_dcb.crc)
return KAL_TRUE;
return KAL_FALSE;
}
/*************************************************************************
* FUNCTION
* png_crc_read
*
* DESCRIPTION
* 1. read the data into buffer
* 2. calculate the crc value
*
* PARAMETERS
* buf: buffer to contain the read data
* len: number to data to be read
*
* RETURNS
*
* GLOBALS AFFECTED
* png_dcb.crc
*
*************************************************************************/
static void png_crc_read(void *buf,kal_uint32 len)
{
extern kal_uint32 png_update_crc(kal_uint32 crc, kal_uint8 *buf,
kal_uint32 len);
PNG_GET_ARRAY(buf,len);
png_dcb.crc = png_update_crc(png_dcb.crc, (kal_uint8*)buf, len);
}
/*************************************************************************
* FUNCTION
* png_get_uint_32
*
* DESCRIPTION
* Grab an unsigned 32-bit integer from a buffer in big-endian format
*
* PARAMETERS
* buf: buffer containing data to be translated
*
* RETURNS
* unsigned 32-bit integer
*
* GLOBALS AFFECTED
*
*************************************************************************/
static kal_uint32 png_get_uint_32(kal_uint8* buf)
{
kal_uint32 i = ((kal_uint32)(*buf) << 24) +
((kal_uint32)(*(buf + 1)) << 16) +
((kal_uint32)(*(buf + 2)) << 8) +
(kal_uint32)(*(buf + 3));
return (i);
}
/*************************************************************************
* FUNCTION
* png_get_uint_16
*
* DESCRIPTION
* Grab an unsigned 16-bit integer from a buffer in big-endian format.
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static kal_uint16 png_get_uint_16(kal_uint8* buf)
{
kal_uint16 i = (kal_uint16)(((kal_uint16)(*buf) << 8) +
(kal_uint16)(*(buf + 1)));
return (i);
}
/*************************************************************************
* FUNCTION
* png_IHDR_Handler
*
* DESCRIPTION
* 1. parse the IHDR chunk
* 2. check if the line buffer is large enough
*
* PARAMETERS
* len: length of the IHDR
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void png_IHDR_Handler(kal_uint32 len)
{
kal_uint8 buf[13];
png_inform_struct *info = &png_dcb.info;
kal_uint32 size,byte;
if(png_dcb.flags & PNG_HAVE_IHDR)
{
PNG_RAISE(1);
}
else
png_dcb.flags |= PNG_HAVE_IHDR;
if(len != 13)
{
PNG_RAISE(1);
}
png_crc_read(buf,13);
if(!png_crc_finish())
{
PNG_RAISE(1);
}
info->img_w = png_get_uint_32(buf);
info->img_h = png_get_uint_32(buf+4);
info->bit_depth = buf[8];
info->color_type = buf[9];
info->interlaced = buf[12];
byte = (info->bit_depth > 8)?(2):(1);
size = png_type_channel[info->color_type]*byte*info->img_w;
if(size > BUFF0_LEN)
PNG_RAISE(1);
}
/*************************************************************************
* FUNCTION
* png_PLTE_Handler
*
* DESCRIPTION
* parse the PLTE chunk
*
* PARAMETERS
* len: length of the PLTE
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void png_PLTE_Handler(kal_uint32 len)
{
kal_uint32 *ct = png_dcb.cfg->color_table;
png_inform_struct *info = &png_dcb.info;
kal_uint32 count = (1 << info->bit_depth),i;
if(!(png_dcb.flags & PNG_HAVE_IHDR) ||
(png_dcb.flags & PNG_HAVE_PLTE)||
(png_dcb.flags & PNG_HAVE_IDAT))
{
PNG_RAISE(1);
}
else
png_dcb.flags |= PNG_HAVE_PLTE;
if(len > 3*count || (len%3))
{
PNG_RAISE(1);
}
count = len/3;
info->num_plte = count-1;
for(i=0;i<count;i++)
{
kal_uint8 buf[3];
kal_uint32 c;
png_crc_read(buf,3);
c = (buf[0]<<16)|(buf[1]<<8)|(buf[2]);
// replace MMI's source key color with XOR 1
if(png_dcb.cfg->out_format == RGB565)
{
kal_uint32 x;
x = ((buf[0]>>3)<<11)|((buf[1]>>2)<<5)|(buf[2]>>3);
if(x == png_dcb.cfg->src_key)
{
//png_dcb.src_hit = KAL_TRUE;
c ^= 0x8;
}
}
else if(png_dcb.cfg->out_format == RGB888)
{
if(c == png_dcb.cfg->src_key)
{
//png_dcb.src_hit = KAL_TRUE;
c ^= 1;
}
}
ct[i] = c;
}
if(!png_crc_finish())
{
PNG_RAISE(1);
}
}
/*************************************************************************
* FUNCTION
* png_tRNS_Handler
*
* DESCRIPTION
* parse the tRNS chunk
*
* PARAMETERS
* len: length of the tRNS chunk
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void png_tRNS_Handler(kal_uint32 len)
{
png_inform_struct *info = &png_dcb.info;
kal_uint32 count = (1 << info->bit_depth);
kal_uint8 buf[6];
if(!(png_dcb.flags & PNG_HAVE_IHDR) ||
(png_dcb.flags & PNG_HAVE_tRNS)||
(png_dcb.flags & PNG_HAVE_IDAT))
{
PNG_RAISE(1);
}
else
png_dcb.flags |= PNG_HAVE_tRNS;
if(info->color_type == COLOR_TYPE_INDEX)
{
if(len > count)
{
PNG_RAISE(1);
}
info->num_trans = len;
if(len ==1)
{
png_crc_read(&info->trans.index,1);
}
else
{
kal_uint8 *ptr = (kal_uint8*)png_dcb.cfg->color_table_t;
png_crc_read(ptr,len);
}
if(!png_crc_finish())
{
PNG_RAISE(1);
}
}
else if(info->color_type == COLOR_TYPE_GRAY)
{
if(len != 2)
{
PNG_RAISE(0);
}
png_crc_read(buf,2);
info->trans.gray = png_get_uint_16(buf);
if(!png_crc_finish())
{
PNG_RAISE(1);
}
info->num_trans = 1;
}
else if(info->color_type == COLOR_TYPE_RGB)
{
if(len != 6)
{
PNG_RAISE(0);
}
png_crc_read(buf,6);
if(!png_crc_finish())
{
PNG_RAISE(1);
}
info->num_trans = 1;
info->trans.color.r = png_get_uint_16(buf);
info->trans.color.g = png_get_uint_16(buf+2);
info->trans.color.b = png_get_uint_16(buf+4);
}
else
{
PNG_RAISE(1);
}
}
/*************************************************************************
* FUNCTION
* png_bKGD_Handler
*
* DESCRIPTION
* parse the bKGD chunk
*
* PARAMETERS
* len: length of the bKGD chunk
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void png_bKGD_Handler(kal_uint32 len)
{
png_inform_struct *info = &png_dcb.info;
if(!(png_dcb.flags & PNG_HAVE_IHDR) ||
(png_dcb.flags & PNG_HAVE_bKGD)||
(png_dcb.flags & PNG_HAVE_IDAT))
{
PNG_RAISE(1);
}
else
png_dcb.flags |= PNG_HAVE_bKGD;
if(info->color_type == COLOR_TYPE_INDEX)
{
if(len != 1)
PNG_RAISE(1);
png_crc_read(&info->bKGD.index,1);
}
else if(info->color_type == COLOR_TYPE_GRAY || info->color_type == COLOR_TYPE_GRAY_A)
{
if(len != 2)
PNG_RAISE(1);
png_crc_read(&info->bKGD.gray,2);
}
else if(info->color_type == COLOR_TYPE_RGB || info->color_type == COLOR_TYPE_RGB_A)
{
kal_uint8 buf[6];
if(len != 6)
PNG_RAISE(1);
png_crc_read(buf,6);
info->bKGD.color.r = png_get_uint_16(buf);
info->bKGD.color.g = png_get_uint_16(buf+2);
info->bKGD.color.b = png_get_uint_16(buf+4);
}
if(!png_crc_finish())
PNG_RAISE(1);
}
/*************************************************************************
* FUNCTION
* png_IDAT_Handler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -