📄 jpeg.c
字号:
VISUAL_Register_HISR(VISUAL_JPEG_DEC_HISR_ID,jpeg_decoder_HISR);
VISUAL_Register_HISR(VISUAL_JPEG_ENC_HISR_ID,jpeg_encoder_HISR);
VISUAL_Register_HISR(VISUAL_JPEG_DEC_CB_HISR_ID,jpeg_decode_cb_HISR);
IRQUnmask(IRQ_JPEG_DEC_CODE);
IRQUnmask(IRQ_JPEG_ENC_CODE);
#endif
#ifndef __MAUI_BASIC__
if (jpeg_codec_sleep_mode_handler==0xFF)
jpeg_codec_sleep_mode_handler = L1SM_GetHandle();
#endif /* __MAUI_BASIC__ */
} /* jpeg_codec_init() */
kal_uint32 jpeg_decode_time_estimate(void)
{
kal_uint32 decode_time;
#if (defined(JPEG_DRV_V3))
if (jpeg_file_para.jpg_progressive == KAL_TRUE)
{
decode_time = ((300 * jpeg_file_para.jpg_decode_width * jpeg_file_para.jpg_decode_height)/1000000 +
(jpeg_decode_config_data.jpeg_file_size /2000 + 10))* jpeg_file_para.progressive_decode_times;
}
else
{
decode_time = ((300 * jpeg_file_para.jpg_decode_width * jpeg_file_para.jpg_decode_height)/1000000 +
(jpeg_decode_config_data.jpeg_file_size /2000 + 10));
}
#else
if (jpeg_file_para.jpg_progressive==KAL_TRUE)
{
decode_time = ((1000 * jpeg_file_para.jpg_decode_width * jpeg_file_para.jpg_decode_height)/1000000 +
(jpeg_decode_config_data.jpeg_file_size /2000 + 10))* jpeg_file_para.progressive_decode_times;
}
else
{
decode_time = ((1000 * jpeg_file_para.jpg_decode_width * jpeg_file_para.jpg_decode_height)/1000000 +
(jpeg_decode_config_data.jpeg_file_size /2000 + 10));
}
#endif
if (decode_time<1000)
decode_time=1000;
return decode_time;
}
/*************************************************************************
* FUNCTION
* jpeg_codec_deinit
*
* DESCRIPTION
* This function power down the jpeg codec and resizer (for MT6218B).
*
* PARAMETERS
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void jpeg_codec_deinit(void)
{
#if (defined(JPEG_DRV_V1))
IRQMask(IRQ_JPEG_CODE);
IRQMask(IRQ_RESZ_CODE);
jpeg_decoder_operation_state = JPEG_DECODER_IDLE_STATE;
#elif (defined(JPEG_DRV_V2))
jpeg_decoder_operation_state=JPEG_DECODER_IDLE_STATE;
jpeg_encoder_operation_state=JPEG_ENCODER_IDLE_STATE;
IRQMask(IRQ_JPEG_CODE);
#elif (defined(JPEG_DRV_V3))
jpeg_decoder_operation_state=JPEG_DECODER_IDLE_STATE;
jpeg_encoder_operation_state=JPEG_ENCODER_IDLE_STATE;
IRQMask(IRQ_JPEG_DEC_CODE);
IRQMask(IRQ_JPEG_ENC_CODE);
#endif
} /* jpeg_codec_deinit() */
/*************************************************************************
* FUNCTION
* parse_exif
*
* DESCRIPTION
* This function parse the EXIF in a JPEG file.
*
* PARAMETERS
* jpeg_file_handle the file handler of JPEG file, 0 stands for the
* JPEG stream is in buffer already.
* jpg_file_ptr the start address pointer for the parsed jpeg file
* jpeg_file_offset the EXIF data offset from the head of JPEG file or JPEG stream
* exif_size size of the EXIF data stream
*
* RETURNS
* 0 the EXIF data stream parsing success
* not 0 the EXIF data stream parsing fail
*
* GLOBALS AFFECTED
*
*************************************************************************/
kal_int32 parse_exif(kal_uint32 jpeg_file_handle, kal_uint8 *jpg_file_ptr, kal_uint32 jpeg_file_buffer_size,
kal_uint32 jpg_file_offset,kal_uint32 exif_size,kal_uint16 *exif_file_offset)
{
kal_uint32 index,exif_offset;
kal_uint32 fs_read_size;
kal_uint8 endian_flag,num_of_required_tag,num_of_current_tag,num_of_parsed_tag=0;
kal_uint16 num_of_ifd_tag, first_ifd_offset,tag_id,tag_value=0,tag_count,tag_type=0;
if (jpeg_file_handle!=0)
{
index=0;
jpeg_DRM_seek_file((FS_HANDLE) jpeg_file_handle, jpg_file_offset, FS_FILE_BEGIN);
jpeg_DRM_read_file((FS_HANDLE) jpeg_file_handle, jpg_file_ptr, 512, &fs_read_size);
}
else
{
index=jpg_file_offset;
}
exif_offset=jpg_file_offset;
/* parse TIFF header */
if ((jpg_file_ptr[index]==0x49) && (jpg_file_ptr[index+1]==0x49))
{
endian_flag=0; /* little endian */
if ((jpg_file_ptr[index+2]!=0x2A)||(jpg_file_ptr[index+3]!=0x00))
return -1;
index+=((jpg_file_ptr[index+7]<<24)|(jpg_file_ptr[index+6]<<16)|(jpg_file_ptr[index+5]<<8)|
jpg_file_ptr[index+4]);
}
else if ((jpg_file_ptr[index+0]==0x4D) && (jpg_file_ptr[index+1]==0x4D))
{
endian_flag=1; /* big endian */
if ((jpg_file_ptr[index+3]!=0x2A)||(jpg_file_ptr[index+2]!=0x00))
return -1;
index+=((jpg_file_ptr[index+4]<<24)|(jpg_file_ptr[index+5]<<16)|(jpg_file_ptr[index+6]<<8)|
jpg_file_ptr[index+7]);
}
else
return -1;
/* find the 1st IFD pointer */
if (endian_flag==0)
{
num_of_ifd_tag=(jpg_file_ptr[index+1]<<8)|(jpg_file_ptr[index]);
index+=(num_of_ifd_tag*12+2);
first_ifd_offset = ((jpg_file_ptr[index+3]<<24)|(jpg_file_ptr[index+2]<<16)|(jpg_file_ptr[index+1]<<8)|
jpg_file_ptr[index]);
}
else
{
num_of_ifd_tag=(jpg_file_ptr[index]<<8)|(jpg_file_ptr[index+1]);
index+=(num_of_ifd_tag*12+2);
first_ifd_offset=((jpg_file_ptr[index]<<24)|(jpg_file_ptr[index+1]<<16)|(jpg_file_ptr[index+2]<<8)|
jpg_file_ptr[index+3]);
}
if (first_ifd_offset==0)
return -1;
index=exif_offset+first_ifd_offset;
if (jpeg_file_handle!=0)
{
jpeg_DRM_seek_file((FS_HANDLE) jpeg_file_handle, index, FS_FILE_BEGIN);
jpeg_DRM_read_file((FS_HANDLE) jpeg_file_handle, jpg_file_ptr, 512, &fs_read_size);
index=0;
}
if (endian_flag==0)
{
num_of_ifd_tag=(jpg_file_ptr[index+1]<<8)|(jpg_file_ptr[index]);
}
else
{
num_of_ifd_tag=(jpg_file_ptr[index]<<8)|(jpg_file_ptr[index+1]);
}
index+=2;
num_of_required_tag=5;
num_of_current_tag=0;
do
{
if (endian_flag==0)
{
tag_id=(jpg_file_ptr[index+1]<<8)|(jpg_file_ptr[index]);
tag_type=(jpg_file_ptr[index+3]<<8)|(jpg_file_ptr[index+2]);
tag_count=((jpg_file_ptr[index+7]<<24)|(jpg_file_ptr[index+6]<<16)|
(jpg_file_ptr[index+5]<<8)|jpg_file_ptr[index+4]);
if (tag_type==EXIF_TAG_TYPE_SHORT)
{
tag_value=(jpg_file_ptr[index+9]<<8)|(jpg_file_ptr[index+8]);
}
else if (tag_type==EXIF_TAG_TYPE_LONG)
{
tag_value=((jpg_file_ptr[index+11]<<24)|(jpg_file_ptr[index+10]<<16)|
(jpg_file_ptr[index+9]<<8)|jpg_file_ptr[index+8]);
}
}
else
{
tag_id=(jpg_file_ptr[index]<<8)|(jpg_file_ptr[index+1]);
tag_type=(jpg_file_ptr[index+2]<<8)|(jpg_file_ptr[index+3]);
tag_count=((jpg_file_ptr[index+4]<<24)|(jpg_file_ptr[index+5]<<16)|
(jpg_file_ptr[index+6]<<8)|jpg_file_ptr[index+7]);
if (tag_type==EXIF_TAG_TYPE_SHORT)
{
tag_value=(jpg_file_ptr[index+8]<<8)|(jpg_file_ptr[index+9]);
}
else if (tag_type==EXIF_TAG_TYPE_LONG)
{
tag_value=((jpg_file_ptr[index+8]<<24)|(jpg_file_ptr[index+9]<<16)|
(jpg_file_ptr[index+10]<<8)|jpg_file_ptr[index+11]);
}
}
switch (tag_id)
{
case EXIF_TAG_COMPRESSION:
if (tag_value==EXIF_JPEG_COMPRESSED)
{
num_of_required_tag=2;
jpeg_thumb_para.jfif_mode= EXIF_MODE_JPEG;
}
num_of_current_tag++;
break;
case EXIF_TAG_IMAGE_WIDTH:
jpeg_thumb_para.jpg_width=tag_value;
num_of_current_tag++;
break;
case EXIF_TAG_IMAGE_HEIGHT:
jpeg_thumb_para.jpg_height=tag_value;
num_of_current_tag++;
break;
case EXIF_TAG_PIXEL_COMPOSITION:
if (tag_value==EXIF_NON_COMPRESSED_RGB)
jpeg_thumb_para.jfif_mode= EXIF_MODE_RGB;
else /* do not support YCbCr format thumbnail */
return -1;
num_of_current_tag++;
break;
case EXIF_TAG_STRIP_OFFSET:
case EXIF_TAG_JPEG_SOI_OFFSET:
*exif_file_offset=tag_value;
num_of_current_tag++;
break;
default:
break;
}
index+=12;
num_of_parsed_tag++;
} while ((num_of_required_tag!=num_of_current_tag) && (num_of_ifd_tag>num_of_parsed_tag));
if (num_of_required_tag==num_of_current_tag)
return 0;
else
return -1;
} /* parse_exif()*/
/*************************************************************************
* FUNCTION
* parse_jpeg_thumbnail
*
* DESCRIPTION
* This function parse the parameters of compressed type thumbnail of a JPEG file.
*
* PARAMETERS
* jpeg_file_handle the file handler of the parsed jpeg file
* jpg_file_ptr the start address pointer of the parsed jpeg file or
* the buffer pointer for temporary JPEG data buffer
* jpeg_file_buffer_size the size of the parsed jpeg file or JPEG data buffer
* jpg_file_offset the data offset from the beginning of the JPEG file.
* thumbnail_size the size of the thumbnail data
*
* RETURNS
* 0 if the compressed thumbnail data parse correctly.
* not 0 if the compressed thumbnail data parse failed.
*
* GLOBALS AFFECTED
*
*************************************************************************/
kal_int32 parse_jpeg_thumbnail(kal_uint32 jpeg_file_handle, kal_uint8 *jpg_file_ptr, kal_uint32 jpeg_file_buffer_size,
kal_uint32 jpg_file_offset,kal_uint32 thumbnail_size)
{
kal_uint8 byte,jpg_byte1,jpg_byte2;
kal_uint32 index,index_offset;
kal_uint16 marker_length;
kal_uint32 jpeg_file_index=0;
kal_uint32 fs_read_size;
kal_uint8 i;
kal_uint8 parse_end_flag=0;
kal_uint32 huffman_q_table_size=0;
kal_uint8 restart_marker_flag=0;
index=0;
if (jpeg_file_handle!=0)
{
jpeg_DRM_seek_file((FS_HANDLE) jpeg_file_handle, jpg_file_offset, FS_FILE_BEGIN);
jpeg_DRM_read_file((FS_HANDLE) jpeg_file_handle, jpg_file_ptr, 512, &fs_read_size);
}
jpg_byte1=jpg_file_ptr[index++];
jpg_byte2=jpg_file_ptr[index++];
jpeg_file_index=jpg_file_offset+2;
jpeg_thumb_para.jpg_height=0xFFFF;
jpeg_thumb_para.jpg_width=0xFFFF;
jpeg_thumb_para.thumbnail_offset=0;
jpeg_thumb_para.jpg_progressive=KAL_FALSE;
if ((jpg_byte1==0xFF) && (jpg_byte2==0xD8))
{
do
{
if (jpeg_file_handle!=0)
{
if (jpeg_file_index>=(thumbnail_size+jpg_file_offset))
break;
}
else
{
if (index>=jpeg_file_buffer_size)
break;
}
do
{
byte=jpg_file_ptr[index++];
if (jpeg_file_handle!=0)
{
jpeg_file_index++;
if (index>=(fs_read_size-30))
{
index=0;
jpeg_DRM_read_file((FS_HANDLE) jpeg_file_handle, jpg_file_ptr, 512, &fs_read_size);
}
}
} while (byte!=0xFF);
jpg_byte1=0xFF;
jpg_byte2=jpg_file_ptr[index++];
if (jpeg_file_handle!=0)
{
jpeg_file_index++;
if (index>=(fs_read_size-30))
{
index=0;
jpeg_DRM_read_file((FS_HANDLE) jpeg_file_handle, jpg_file_ptr, 512, &fs_read_size);
}
}
switch (jpg_byte2)
{
case JPEG_MARKER_SOF0:
case JPEG_MARKER_SOF2:
if (jpg_byte2==JPEG_MARKER_SOF2)
{
return -1;
}
marker_length=(jpg_file_ptr[index++]<<8);
marker_length += (int) (jpg_file_ptr[index++]-2);
jpeg_thumb_para.jpg_precision=jpg_file_ptr[index++];
jpeg_thumb_para.jpg_height=(jpg_file_ptr[index++]<<8);
jpeg_thumb_para.jpg_height|=jpg_file_ptr[index++];
jpeg_thumb_para.jpg_width=(jpg_file_ptr[index++]<<8);
jpeg_thumb_para.jpg_width|=jpg_file_ptr[index++];
jpeg_thumb_para.number_of_component=jpg_file_ptr[index++];
jpeg_thumb_para.component_id1=jpg_file_ptr[index++];
jpeg_thumb_para.y_h_sample_factor=(jpg_file_ptr[index]&0xF0)>>4;
jpeg_thumb_para.y_v_sample_factor=jpg_file_ptr[index++]&0x0F;
jpeg_thumb_para.q_table_id1=jpg_file_ptr[index++];
jpeg_file_index+=11;
if (jpeg_thumb_para.number_of_component>=2)
{
jpeg_thumb_para.component_id2=jpg_file_ptr[index++];
jpeg_thumb_para.u_h_sample_factor=(jpg_file_ptr[index]&0xF0)>>4;
jpeg_thumb_para.u_v_sample_factor=jpg_file_ptr[index++]&0x0F;
jpeg_thumb_para.q_table_id2=jpg_file_ptr[index++];
jpeg_file_index+=3;
if (jpeg_thumb_para.number_of_component>=3)
{
jpeg_thumb_para.component_id3=jpg_file_ptr[index++];
jpeg_thumb_para.v_h_sample_factor=(jpg_file_ptr[index]&0xF0)>>4;
jpeg_thumb_para.v_v_sample_factor=jpg_file_ptr[index++]&0x0F;
jpeg_thumb_para.q_table_id3=jpg_file_ptr[index++];
jpeg_file_index+=3;
}
else
{
jpeg_thumb_para.component_id3=0;
jpeg_thumb_para.v_h_sample_factor=0;
jpeg_thumb_para.v_v_sample_factor=0;
jpeg_thumb_para.q_table_id3=0;
}
}
else
{
jpeg_thumb_para.component_id2=0;
jpeg_thumb_para.u_h_sample_factor=0;
jpeg_thumb_para.u_v_sample_factor=0;
jpeg_thumb_para.q_table_id2=0;
jpeg_thumb_para.component_id3=0;
jpeg_thumb_para.v_h_sample_factor=0;
jpeg_thumb_para.v_v_sample_factor=0;
jpeg_thumb_para.q_table_id3=0;
}
parse_end_flag|=0x01;
break;
case JPEG_MARKER_SOS:
jpg_byte2=0xD9;
break;
case 0xC8:
case 0x00:
break;
case JPEG_MARKER_DQT:
case JPEG_MARKER_DHT:
if (jpeg_thumb_para.thumbnail_offset==0) /* set thumbnail_offset when first time met DQT or DHT */
jpeg_thumb_para.thumbnail_offset=jpeg_file_index-jpg_file_offset-2;
index_offset=(jpg_file_ptr[index++]<<8);
index_offset += (int) (jpg_file_ptr[index++]-2);
huffman_q_table_size+=index_offset;
index+=index_offset;
if (jpeg_file_handle!=0)
{
jpeg_file_index+=(index_offset+2);
}
if (jpg_byte2==JPEG_MARKER_DQT)
parse_end_flag|=0x02;
else
parse_end_flag|=0x04;
/* make sure DQT,DHT and SOF are read or table size overflow*/
if (huffman_q_table_size>=0x800)
jpg_byte2=0xD9;
break;
default:
if ((jpg_byte2==JPEG_MARKER_SOF1) || (jpg_byte2==JPEG_MARKER_DNL)||
((jpg_byte2>=JPEG_MARKER_SOF3) && (jpg_byte2<=JPEG_MARKER_SOF15))||
(jpg_byte2==JPEG_MARKER_DRI) || (jpg_byte2==JPEG_MARKER_DHP) ||
(jpg_byte2==JPEG_MARKER_EXP) || (jpg_byte2==JPEG_MARKER_COM) ||
((jpg_byte2>=JPEG_MARKER_APP0) && (jpg_byte2<=JPEG_MARKER_APP15)))
{
index_offset=(jpg_file_ptr[index++]<<8);
index_offset += (int) (jpg_file_ptr[index++]-2);
index+=index_offset;
if (jpeg_file_handle!=0)
{
jpeg_file_index+=(index_offset+2);
if (index>=(fs_read_size-30))
{
index=0;
jpeg_DRM_seek_file((FS_HANDLE) jpeg_file_handle, jpeg_file_index, FS_FILE_BEGIN);
jpeg_DRM_read_file((FS_HANDLE) jpeg_file_handle, jpg_file_ptr, 512, &fs_read_size);
}
}
if (jpg_byte2==JPEG_MARKER_DRI)
restart_marker_flag=1;
}
break;
}
} while (!((jpg_byte1==0xFF) && (jpg_byte2==0xD9)));
}
else
return -1;
if ((jpeg_thumb_para.y_h_sample_factor + jpeg_thumb_para.y_v_sample_factor +
jpeg_thumb_para.u_h_sample_factor + jpeg_thumb_para.u_v_sample_factor +
jpeg_thumb_para.v_h_sample_factor + jpeg_thumb_para.v_v_sample_factor)>10)
{
return -1;
}
if (jpeg_file_handle!=0)
{
jpeg_DRM_seek_file((FS_HANDLE) jpeg_file_handle, (thumbnail_size+jpg_file_offset-20),FS_FILE_BEGIN);
jpeg_DRM_read_file((FS_HANDLE) jpeg_file_handle, jpg_file_ptr,20, &fs_read_size);
for (i=1;i<20;i++)
{
jpg_byte2=jpg_file_ptr[fs_read_size-i];
if (jpg_byte2==0xD9)
{
jpg_byte1=jpg_file_ptr[fs_read_size-i-1];
if (jpg_byte1==0xFF)
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -